Class TurboLog


  • public class TurboLog
    extends FastLog
    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).

    This class is based on the original algorithm description.

    The algorithm has been changed to detects when the unbiased exponent is zero and maintains the precision.

    Using look-up table the relative error ((fastLog(x)-Math.log(x))/Math.log(x)) is large (e>>1) when the input value x is close to 1. So the algorithm detects values close to 1 and uses Math.log(double) instead.

    See Also:
    http://www.icsi.berkeley.edu/pubs/techreports/TR- 07-002.pdf
    • Field Summary

      Fields 
      Modifier and Type Field Description
      protected static long LOWER_BOUND_MANTISSA
      The lower bound mantissa (for a double) below 1 where the function switches to use Math.log
      protected static int LOWER_BOUND_MANTISSA_F
      The lower bound mantissa (for a float) below 1 where the function switches to use Math.log
      static double LOWER_ONE_BOUND
      The bounds below 1 where the function switches to use Math.log.
      protected static long UPPER_BOUND_MANTISSA
      The upper bound mantissa (for a double) above 1 where the function switches to use Math.log
      protected static int UPPER_BOUND_MANTISSA_F
      The upper bound mantissa (for a float) above 1 where the function switches to use Math.log
      static double UPPER_ONE_BOUND
      The bounds above 1 where the function switches to use Math.log.
      • Fields inherited from class micycle.peasygradients.utilities.fastLog.FastLog

        LN2, LN2F, N
    • Constructor Summary

      Constructors 
      Constructor Description
      TurboLog()
      Create a new natural logarithm calculation instance.
      TurboLog​(int n)
      Create a new natural logarithm calculation instance.
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      protected float computeSubnormal​(int mantissa)
      Compute the log for a subnormal float-point number, i.e.
      protected double computeSubnormal​(long mantissa)
      Compute the log for a subnormal float-point number, i.e.
      protected float computeSubnormalF​(long mantissa)
      Compute the log for a subnormal float-point number, i.e.
      float fastLog​(double x)
      Calculate the natural logarithm.
      float fastLog​(float x)
      Calculate the natural logarithm.
      float fastLog2​(double x)
      Calculate the logarithm to base 2.
      float fastLog2​(float x)
      Calculate the logarithm to base 2.
      double fastLog2D​(double x)
      Calculate the logarithm to base 2.
      double fastLogD​(double x)
      Calculate the natural logarithm.
      double getBase()
      Gets the base.
      int getN()
      Gets the number of most significant bits to keep from the mantissa, i.e.
      double getScale()
      Gets the scale to convert from log2 to logB (the base given by FastLog.getBase()) by multiplication.
      float log​(double x)
      Calculate the logarithm to the configured base, handling special cases.
      float log​(float x)
      Calculate the logarithm to the configured base, handling special cases.
      float log2​(double x)
      Calculate the logarithm to base 2, handling special cases.
      float log2​(float x)
      Calculate the logarithm to base 2, handling special cases.
      double log2D​(double x)
      Calculate the logarithm to base 2, handling special cases.
      double logD​(double x)
      Calculate the logarithm to the configured base, handling special cases.
    • Field Detail

      • LOWER_ONE_BOUND

        public static final double LOWER_ONE_BOUND
        The bounds below 1 where the function switches to use Math.log. This results in a maximum relative error of 7.95e-4 for x below 1.
        See Also:
        Constant Field Values
      • UPPER_ONE_BOUND

        public static final double UPPER_ONE_BOUND
        The bounds above 1 where the function switches to use Math.log. This results in a maximum relative error of 7.09e-4 for x above 1.
        See Also:
        Constant Field Values
      • LOWER_BOUND_MANTISSA

        protected static final long LOWER_BOUND_MANTISSA
        The lower bound mantissa (for a double) below 1 where the function switches to use Math.log
      • UPPER_BOUND_MANTISSA

        protected static final long UPPER_BOUND_MANTISSA
        The upper bound mantissa (for a double) above 1 where the function switches to use Math.log
      • LOWER_BOUND_MANTISSA_F

        protected static final int LOWER_BOUND_MANTISSA_F
        The lower bound mantissa (for a float) below 1 where the function switches to use Math.log
      • UPPER_BOUND_MANTISSA_F

        protected static final int UPPER_BOUND_MANTISSA_F
        The upper bound mantissa (for a float) above 1 where the function switches to use Math.log
    • Constructor Detail

      • TurboLog

        public TurboLog()
        Create a new natural logarithm calculation instance. This will hold the pre-calculated log values for base E and the default table size.
      • TurboLog

        public TurboLog​(int n)
        Create a new natural logarithm calculation instance. This will hold the pre-calculated log values for base E and a table size depending on a given mantissa precision.
        Parameters:
        n - The number of bits to keep from the mantissa. Table storage = 2^n * 4 bytes, e.g. 32Kb for n=13.
    • Method Detail

      • getN

        public int getN()
        Description copied from class: FastLog
        Gets the number of most significant bits to keep from the mantissa, i.e. the binary precision of the floating point number before computing the log.
        Specified by:
        getN in class FastLog
        Returns:
        the number of most significant bits to keep
      • getScale

        public double getScale()
        Description copied from class: FastLog
        Gets the scale to convert from log2 to logB (the base given by FastLog.getBase()) by multiplication.
        Specified by:
        getScale in class FastLog
        Returns:
        the scale
      • getBase

        public double getBase()
        Description copied from class: FastLog
        Gets the base.
        Specified by:
        getBase in class FastLog
        Returns:
        the base
      • log

        public float log​(float x)
        Description copied from class: FastLog
        Calculate the logarithm to the configured base, handling special cases.

        Special cases:

        • If the argument is NaN or less than zero, then the result is NaN.
        • If the argument is positive infinity, then the result is positive infinity.
        • If the argument is positive zero or negative zero, then the result is negative infinity.
        Specified by:
        log in class FastLog
        Parameters:
        x - the argument
        Returns:
        log(x)
        See Also:
        FastLog.getBase()
      • log

        public float log​(double x)
        Description copied from class: FastLog
        Calculate the logarithm to the configured base, handling special cases.

        Special cases:

        • If the argument is NaN or less than zero, then the result is NaN.
        • If the argument is positive infinity, then the result is positive infinity.
        • If the argument is positive zero or negative zero, then the result is negative infinity.
        Specified by:
        log in class FastLog
        Parameters:
        x - the argument
        Returns:
        log(x)
        See Also:
        FastLog.getBase()
      • computeSubnormal

        protected float computeSubnormal​(int mantissa)
        Compute the log for a subnormal float-point number, i.e. where the exponent is 0 then there is no assumed leading 1.

        Note that if the mantissa is zero this will fail!

        No rounding to be done on sub-normal as the mantissa is shifted << 1 so the least significant digit is always 0.

        Parameters:
        mantissa - the mantissa (already bit shifted by 1)
        Returns:
        the log(x)
      • computeSubnormal

        protected double computeSubnormal​(long mantissa)
        Compute the log for a subnormal float-point number, i.e. where the exponent is 0 then there is no assumed leading 1.

        Note that if the mantissa is zero this will fail!

        No rounding to be done on sub-normal as the mantissa is shifted << 1 so the least significant digit is always 0.

        Parameters:
        mantissa - the mantissa (already bit shifted by 1)
        Returns:
        the log(x)
      • computeSubnormalF

        protected float computeSubnormalF​(long mantissa)
        Compute the log for a subnormal float-point number, i.e. where the exponent is 0 then there is no assumed leading 1.

        Note that if the mantissa is zero this will fail!

        No rounding to be done on sub-normal as the mantissa is shifted << 1 so the least significant digit is always 0.

        Parameters:
        mantissa - the mantissa (already bit shifted by 1)
        Returns:
        the log(x)
      • fastLog

        public float fastLog​(float x)
        Calculate the natural logarithm. Requires the argument be finite and positive.

        Special cases:

        • If the argument is NaN, then the result is incorrect (>fastLog(Float.MAX_VALUE)).
        • If the argument is negative, then the result is incorrect (fastLog(-x)).
        • If the argument is positive infinity, then the result is incorrect (>fastLog(Float.MAX_VALUE)).
        • If the argument is positive zero or negative zero, then the result is negative infinity.
        Specified by:
        fastLog in class FastLog
        Parameters:
        x - the argument (must be strictly positive)
        Returns:
        log(x)
        See Also:
        FastLog.getBase()
      • fastLog

        public float fastLog​(double x)
        Calculate the natural logarithm. Requires the argument be finite and positive.

        Special cases:

        • If the argument is NaN, then the result is incorrect (>fastLog(Double.MAX_VALUE)).
        • If the argument is negative, then the result is incorrect (fastLog(-x)).
        • If the argument is positive infinity, then the result is incorrect (>fastLog(Double.MAX_VALUE)).
        • If the argument is positive zero or negative zero, then the result is negative infinity.
        Specified by:
        fastLog in class FastLog
        Parameters:
        x - the argument (must be strictly positive)
        Returns:
        log(x)
        See Also:
        FastLog.getBase()
      • logD

        public double logD​(double x)
        Description copied from class: FastLog
        Calculate the logarithm to the configured base, handling special cases.

        Special cases:

        • If the argument is NaN or less than zero, then the result is NaN.
        • If the argument is positive infinity, then the result is positive infinity.
        • If the argument is positive zero or negative zero, then the result is negative infinity.

        This can be re-implemented if FastLog.log(double) can be returned in double precision.

        Overrides:
        logD in class FastLog
        Parameters:
        x - the argument
        Returns:
        log(x)
        See Also:
        FastLog.getBase()
      • fastLogD

        public double fastLogD​(double x)
        Calculate the natural logarithm. Requires the argument be finite and positive.

        Special cases:

        • If the argument is NaN, then the result is incorrect (>fastLog(Double.MAX_VALUE)).
        • If the argument is negative, then the result is incorrect (fastLog(-x)).
        • If the argument is positive infinity, then the result is incorrect (>fastLog(Double.MAX_VALUE)).
        • If the argument is positive zero or negative zero, then the result is negative infinity.
        Overrides:
        fastLogD in class FastLog
        Parameters:
        x - the argument (must be strictly positive)
        Returns:
        log(x)
        See Also:
        FastLog.getBase()
      • log2

        public float log2​(float x)
        Calculate the logarithm to base 2, handling special cases.

        Special cases:

        • If the argument is NaN or less than zero, then the result is NaN.
        • If the argument is positive infinity, then the result is positive infinity.
        • If the argument is positive zero or negative zero, then the result is negative infinity.

        Non-specialised version which calls the corresponding log function and divides by Math.log(2).

        Specified by:
        log2 in class FastLog
        Parameters:
        x - the argument
        Returns:
        log(x)
      • log2

        public float log2​(double x)
        Calculate the logarithm to base 2, handling special cases.

        Special cases:

        • If the argument is NaN or less than zero, then the result is NaN.
        • If the argument is positive infinity, then the result is positive infinity.
        • If the argument is positive zero or negative zero, then the result is negative infinity.

        Non-specialised version which calls the corresponding log function and divides by Math.log(2).

        Specified by:
        log2 in class FastLog
        Parameters:
        x - the argument
        Returns:
        log(x)
      • fastLog2

        public float fastLog2​(float x)
        Calculate the logarithm to base 2. Requires the argument be finite and strictly positive.

        Special cases:

        • If the argument is NaN, then the result is incorrect.
        • If the argument is negative, then the result is incorrect.
        • If the argument is positive infinity, then the result is incorrect.
        • If the argument is positive zero or negative zero, then the result is incorrect.

        Sub-classes may handle some of the special cases.

        Non-specialised version which calls the corresponding log function and divides by Math.log(2).

        Specified by:
        fastLog2 in class FastLog
        Parameters:
        x - the argument (must be strictly positive)
        Returns:
        log(x)
      • fastLog2

        public float fastLog2​(double x)
        Calculate the logarithm to base 2. Requires the argument be finite and strictly positive.

        Special cases:

        • If the argument is NaN, then the result is incorrect.
        • If the argument is negative, then the result is incorrect.
        • If the argument is positive infinity, then the result is incorrect.
        • If the argument is positive zero or negative zero, then the result is incorrect.

        Sub-classes may handle some of the special cases.

        Non-specialised version which calls the corresponding log function and divides by Math.log(2).

        Specified by:
        fastLog2 in class FastLog
        Parameters:
        x - the argument (must be strictly positive)
        Returns:
        log(x)
      • log2D

        public double log2D​(double x)
        Calculate the logarithm to base 2, handling special cases.

        Special cases:

        • If the argument is NaN or less than zero, then the result is NaN.
        • If the argument is positive infinity, then the result is positive infinity.
        • If the argument is positive zero or negative zero, then the result is negative infinity.

        This can be re-implemented if FastLog.fastLog(double) can be returned in double precision.

        Non-specialised version which calls the corresponding log function and divides by Math.log(2).

        Overrides:
        log2D in class FastLog
        Parameters:
        x - the argument
        Returns:
        log(x)
      • fastLog2D

        public double fastLog2D​(double x)
        Calculate the logarithm to base 2. Requires the argument be finite and strictly positive.

        Special cases:

        • If the argument is NaN, then the result is incorrect.
        • If the argument is negative, then the result is incorrect.
        • If the argument is positive infinity, then the result is incorrect.
        • If the argument is positive zero or negative zero, then the result is incorrect.

        Sub-classes may handle some of the special cases.

        This can be re-implemented if FastLog.fastLog(double) can be returned in double precision.

        Non-specialised version which calls the corresponding log function and divides by Math.log(2).

        Overrides:
        fastLog2D in class FastLog
        Parameters:
        x - the argument (must be strictly positive)
        Returns:
        log(x)