Class FastDoubleMath
- java.lang.Object
-
- ch.randelshofer.fastdoubleparser.FastDoubleMath
-
final class FastDoubleMath extends java.lang.ObjectThis class provides the mathematical functions needed byJavaDoubleParser.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 -
-
-
Field Summary
Fields Modifier and Type Field Description static intDOUBLE_EXPONENT_BIASBias used in the exponent of a double.(package private) static intDOUBLE_MAX_EXPONENT_POWER_OF_TENLargest power of 10 value of the exponent.private static intDOUBLE_MAX_EXPONENT_POWER_OF_TWO(package private) static intDOUBLE_MIN_EXPONENT_POWER_OF_TENSmallest power of 10 value of the exponent.private static intDOUBLE_MIN_EXPONENT_POWER_OF_TWOprivate static double[]DOUBLE_POWERS_OF_TENPrecomputed powers of ten from 10^0 to 10^22.static intDOUBLE_SIGNIFICAND_WIDTHThe number of bits in the significand, including the implicit bit.(package private) static long[]MANTISSA_128A complement to mantissa_64 complete to a 128-bit mantissa.(package private) static long[]MANTISSA_64When 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.static intMAX_REQUIRED_DIGITS
-
Constructor Summary
Constructors Modifier Constructor Description privateFastDoubleMath()Don't let anyone instantiate this class.
-
Method Summary
All Methods Static Methods Concrete Methods Modifier and Type Method Description (package private) static doublefastScalb(double number, long scaleFactor)This is a faster alternative toMath.scalb(double, int).(package private) static doubletryDecFloatToDoubleTruncated(boolean isNegative, long significand, int exponent, boolean isSignificandTruncated, int exponentOfTruncatedSignificand)Tries to computesignificand * 10^exponentexactly using a fast algorithm; and ifisNegativeis true, negate the result; the significand can be truncated.(package private) static doubletryDecToDoubleWithFastAlgorithm(boolean isNegative, long significand, int power)Tries to computesignificand * 10^powerexactly using a fast algorithm; and ifisNegativeis true, negate the result.(package private) static doubletryHexFloatToDoubleTruncated(boolean isNegative, long significand, long exponent, boolean isSignificandTruncated, long exponentOfTruncatedSignificand)Tries to computesignificand * 2^exponentexactly using a fast algorithm; and ifisNegativeis true, negate the result; the significand can be truncated.
-
-
-
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
-
MAX_REQUIRED_DIGITS
public static final int MAX_REQUIRED_DIGITS
- 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.
-
-
Method Detail
-
tryDecFloatToDoubleTruncated
static double tryDecFloatToDoubleTruncated(boolean isNegative, long significand, int exponent, boolean isSignificandTruncated, int exponentOfTruncatedSignificand)Tries to computesignificand * 10^exponentexactly using a fast algorithm; and ifisNegativeis true, negate the result; the significand can be truncated.- Parameters:
isNegative- true if the sign is negativesignificand- the significandexponent- the exponent number (the power)isSignificandTruncated- true if significand has been truncatedexponentOfTruncatedSignificand- the exponent number of the truncated significand- Returns:
- the double value,
or
Double.NaNif the fast path failed.
-
tryDecToDoubleWithFastAlgorithm
static double tryDecToDoubleWithFastAlgorithm(boolean isNegative, long significand, int power)Tries to computesignificand * 10^powerexactly using a fast algorithm; and ifisNegativeis 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 negativesignificand- uint64 the significandpower- the exponent number (the power)- Returns:
- the computed double on success,
Double.NaNon failure
-
tryHexFloatToDoubleTruncated
static double tryHexFloatToDoubleTruncated(boolean isNegative, long significand, long exponent, boolean isSignificandTruncated, long exponentOfTruncatedSignificand)Tries to computesignificand * 2^exponentexactly using a fast algorithm; and ifisNegativeis true, negate the result; the significand can be truncated.- Parameters:
isNegative- true if the sign is negativesignificand- the significand (unsigned long, uint64)exponent- the exponent number (the power)isSignificandTruncated- true if significand has been truncatedexponentOfTruncatedSignificand- the exponent number of the truncated significand- Returns:
- the double value,
or
Double.NaNif the fast path failed.
-
fastScalb
static double fastScalb(double number, long scaleFactor)This is a faster alternative toMath.scalb(double, int).This method only works if scaleFactor is within the range of
Double.MIN_EXPONENTthroughDouble.MAX_EXPONENT(inclusive), so that we do not underflow or overflow.- Parameters:
number- a double numberscaleFactor- the scale factor- Returns:
- number × 2scaleFactor
-
-