Class FastDoubleMath


  • final class FastDoubleMath
    extends java.lang.Object
    This class provides the mathematical functions needed by JavaDoubleParser.

    References:

    Daniel Lemire, fast_float number parsing library: 4x faster than strtod. MIT License.
    github.com
    Daniel Lemire, Number Parsing at a Gigabyte per Second, Software: Practice and Experience 51 (8), 2021. arXiv.2101.11408v3 [cs.DS] 24 Feb 2021
    arxiv.org
    Clinger WD (1990). How to read floating point numbers accurately. ACM SIGPLAN Notices.
    - no link -

    • Constructor Summary

      Constructors 
      Modifier Constructor Description
      private FastDoubleMath()
      Don't let anyone instantiate this class.
    • Method Summary

      All Methods Static Methods Concrete Methods 
      Modifier and Type Method Description
      (package private) static double fastScalb​(double number, long scaleFactor)
      This is a faster alternative to Math.scalb(double, int).
      (package private) static double tryDecFloatToDoubleTruncated​(boolean isNegative, long significand, int exponent, boolean isSignificandTruncated, int exponentOfTruncatedSignificand)
      Tries to compute significand * 10^exponent exactly using a fast algorithm; and if isNegative is true, negate the result; the significand can be truncated.
      (package private) static double tryDecToDoubleWithFastAlgorithm​(boolean isNegative, long significand, int power)
      Tries to compute significand * 10^power exactly using a fast algorithm; and if isNegative is true, negate the result.
      (package private) static double tryHexFloatToDoubleTruncated​(boolean isNegative, long significand, long exponent, boolean isSignificandTruncated, long exponentOfTruncatedSignificand)
      Tries to compute significand * 2^exponent exactly using a fast algorithm; and if isNegative is true, negate the result; the significand can be truncated.
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Field Detail

      • DOUBLE_EXPONENT_BIAS

        public static final int DOUBLE_EXPONENT_BIAS
        Bias used in the exponent of a double.
        See Also:
        Constant Field Values
      • DOUBLE_SIGNIFICAND_WIDTH

        public static final int DOUBLE_SIGNIFICAND_WIDTH
        The number of bits in the significand, including the implicit bit.
        See Also:
        Constant Field Values
      • DOUBLE_MIN_EXPONENT_POWER_OF_TEN

        static final int DOUBLE_MIN_EXPONENT_POWER_OF_TEN
        Smallest power of 10 value of the exponent.

        The smallest non-zero double is 2^−1074.

        We take as input numbers of the form w x 10^q where w < 2^64.

        We have that w * 10^-343 < 2^(63-343) * 5^-343 < 2^-1076.

        However, we have that (2^64-1) * 10^-342 = (2^64 - 1) * 2^-342 * 5^-342 > 2^−1074. Thus, it is possible for a number of the form w * 10^-342 where w is a 64-bit value to be a non-zero double.

        ********

        If we are solely interested in the *normal* numbers then the smallest value is 2^-1022. We can generate a value larger than 2^-1022 with expressions of the form w * 10^-326. Thus, we need to pick SMALLEST_POWER_OF_TEN >= -326.

        See Also:
        Constant Field Values
      • DOUBLE_MAX_EXPONENT_POWER_OF_TEN

        static final int DOUBLE_MAX_EXPONENT_POWER_OF_TEN
        Largest power of 10 value of the exponent.

        Any number of form w * 10^309 where w >= 1 is going to be infinite in a double, so we never need to worry about powers of 10 greater than 308.

        See Also:
        Constant Field Values
      • MANTISSA_64

        static final long[] MANTISSA_64
        When mapping numbers from decimal to binary, we go from w * 10^q to m * 2^p, but we have 10^q = 5^q * 2^q, so effectively we are trying to match w * 2^q * 5^q to m * 2^p.

        Thus, the powers of two are not a concern since they can be represented exactly using the binary notation, only the powers of five affect the binary significand.

        The mantissas of powers of ten from -308 to 308, extended out to sixty-four bits. The array contains the powers of ten approximated as a 64-bit mantissa. It goes from 10^-325 to 10^308 (inclusively). The mantissa is truncated, and never rounded up. Uses about 5 KB.

         long getMantissaHigh(int q) {
          MANTISSA_64[q - SMALLEST_POWER_OF_TEN];
         }
         
      • MANTISSA_128

        static final long[] MANTISSA_128
        A complement to mantissa_64 complete to a 128-bit mantissa.

        Uses about 5KB but is rarely accessed.

         UInt128 getMantissa128(int q) {
             return new UInt128(
                MANTISSA_64[q - SMALLEST_POWER_OF_TEN],
                MANTISSA_128[q - SMALLEST_POWER_OF_TEN];
             );
         }
         
      • DOUBLE_MIN_EXPONENT_POWER_OF_TWO

        private static final int DOUBLE_MIN_EXPONENT_POWER_OF_TWO
        See Also:
        Constant Field Values
      • DOUBLE_MAX_EXPONENT_POWER_OF_TWO

        private static final int DOUBLE_MAX_EXPONENT_POWER_OF_TWO
        See Also:
        Constant Field Values
      • DOUBLE_POWERS_OF_TEN

        private static final double[] DOUBLE_POWERS_OF_TEN
        Precomputed powers of ten from 10^0 to 10^22. These can be represented exactly using the double type.
    • Constructor Detail

      • FastDoubleMath

        private FastDoubleMath()
        Don't let anyone instantiate this class.
    • Method Detail

      • tryDecFloatToDoubleTruncated

        static double tryDecFloatToDoubleTruncated​(boolean isNegative,
                                                   long significand,
                                                   int exponent,
                                                   boolean isSignificandTruncated,
                                                   int exponentOfTruncatedSignificand)
        Tries to compute significand * 10^exponent exactly using a fast algorithm; and if isNegative is true, negate the result; the significand can be truncated.
        Parameters:
        isNegative - true if the sign is negative
        significand - the significand
        exponent - the exponent number (the power)
        isSignificandTruncated - true if significand has been truncated
        exponentOfTruncatedSignificand - the exponent number of the truncated significand
        Returns:
        the double value, or Double.NaN if the fast path failed.
      • tryDecToDoubleWithFastAlgorithm

        static double tryDecToDoubleWithFastAlgorithm​(boolean isNegative,
                                                      long significand,
                                                      int power)
        Tries to compute significand * 10^power exactly using a fast algorithm; and if isNegative is true, negate the result.

        This function will only work in some cases, when it does not work it returns NaN. This should work *most of the time* (like 99% of the time). We assume that power is in the [-325, 308] interval: the caller is responsible for this check.

        References:

        Noble Mushtak, Daniel Lemire. (2023) Fast Number Parsing Without Fallback.
        arxiv.org
        Parameters:
        isNegative - whether the number is negative
        significand - uint64 the significand
        power - the exponent number (the power)
        Returns:
        the computed double on success, Double.NaN on failure
      • tryHexFloatToDoubleTruncated

        static double tryHexFloatToDoubleTruncated​(boolean isNegative,
                                                   long significand,
                                                   long exponent,
                                                   boolean isSignificandTruncated,
                                                   long exponentOfTruncatedSignificand)
        Tries to compute significand * 2^exponent exactly using a fast algorithm; and if isNegative is true, negate the result; the significand can be truncated.
        Parameters:
        isNegative - true if the sign is negative
        significand - the significand (unsigned long, uint64)
        exponent - the exponent number (the power)
        isSignificandTruncated - true if significand has been truncated
        exponentOfTruncatedSignificand - the exponent number of the truncated significand
        Returns:
        the double value, or Double.NaN if the fast path failed.
      • fastScalb

        static double fastScalb​(double number,
                                long scaleFactor)
        This is a faster alternative to Math.scalb(double, int).

        This method only works if scaleFactor is within the range of Double.MIN_EXPONENT through Double.MAX_EXPONENT (inclusive), so that we do not underflow or overflow.

        Parameters:
        number - a double number
        scaleFactor - the scale factor
        Returns:
        number × 2scaleFactor