/* * FastLog.java * Eisenkraut * * Copyright (c) 2004-2016 Hanns Holger Rutz. All rights reserved. * * This software is published under the GNU General Public License v3+ * * * For further information, please contact Hanns Holger Rutz at * contact@sciss.de */ package de.sciss.eisenkraut.math; /** * Implementation of the ICSILog algorithm * as described in O. Vinyals, G. Friedland, N. Mirghafori * "Revisiting a basic function on current CPUs: A fast logarithm implementation * with adjustable accuracy" (2007). * * @see java.lang.Float#floatToRawIntBits( float ) */ public class FastLog { private final int q, qM1; private final float[] data; private float korr; /** * Create a new logarithm calculation instance. This will * hold the pre-calculated log values for a given base * and a table size depending on a given mantissa quantization. * * @param base the logarithm base (e.g. 2 for log duals, 10 for * decibels calculations, Math.E for natural log) * @param q the quantization, the number of bits to remove * from the mantissa. for q = 11, the table storage * requires 32 KB. */ public FastLog( double base, int q ) { final int tabSize = 1 << (24 - q); this.q = q; qM1 = q - 1; korr = (float) (MathUtil.LN2 / Math.log( base )); data = new float[ tabSize ]; for( int i = 0; i < tabSize; i++ ) { // note: the -150 is to avoid this addition in the calculation // of the exponent (see the floatToRawIntBits doc). data[ i ] = (float) (MathUtil.log2( i << q ) - 150); } } /** * Calculate the logarithm to the base given in the constructor. * * @param x the argument. must be positive! * @return log( x ) */ public float calc( float x ) { // final int raw = Float.floatToRawIntBits( x ); final int raw = Float.floatToIntBits( x ); final int exp = (raw >> 23) & 0xFF; final int mant = (raw & 0x7FFFFF); return (exp + data[ exp == 0 ? (mant >> qM1) : ((mant | 0x800000) >> q) ]) * korr; } }