Class Real
- All Implemented Interfaces:
Serializable
Converting a sequence of a dozen strictfp arithmetic operations to use Real can take up to 20 times longer than the natural but imprecise approach of using built in double operators like + and *. Compared to other approaches like BigDecimal that consume more memory and typically slow operations down by a factor of 100, that's great, but use of this class should still be avoided when imprecise results will suffice.
This class exists as a package private element of the geometry library for the predicates in
S2Predicates
, that require arbitrary precision arithmetic. It could be made suitable for
general usage by adding robust implementations of multiplication and division between two Reals,
and a toString() implementation that prints the exact summation of all the components.
Many of the algorithms in this class were adapted from the multiple components technique for extended 64-bit IEEE 754 floating point precision, as described in:
Robust Adaptive Floating-Point Geometric Predicates Jonathan Richard Shewchuk School of Computer Science Carnegie Mellon University
Faster adaptive techniques are also presented in that paper, but are not implemented here.
-
Field Summary
FieldsModifier and TypeFieldDescriptionprivate static final long
private static final double
Used to split doubles into two half-length values, for exact multiplication.private final double[]
A sequence of ordinary double values, ordered by magnitude in ascending order, containing no zeroes and with no overlapping base 2 digits. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic Real
add
(double a, double b) Returns the result of a + b, without loss of precision.Returns the result of a + b, without loss of precision.private static Real
Returns the result of adding together the components of a and b, inverting each element of b if negateB is true.bigValue()
Returns a BigDecimal representation of this extended precision real value.private static double[]
copyOf
(double[] array, int newLength) double
private static double
fastTwoSumError
(double a, double b, double x) Returns the error in the sum x=a+b, when |a|>=|b|.float
int
intValue()
long
mul
(double scale) Returns the result of this * scale, without loss of precision.static Real
mul
(double a, double b) Returns the result of a * b, without loss of precision.negate()
Returns the negative of this number.int
signum()
Returns the signum of this number more quickly than via Math.signum(doubleValue()).private static boolean
smallerMagnitude
(double a, double b) Returns true if the magnitude of a is less than the magnitude of b.private static double
splitHigh
(double a) Returns the high split for the given value.private static double
splitLow
(double a, double ahi) Returns the low split for the given value and previously-computed high split as returned bysplitHigh(double)
.static Real
sub
(double a, double b) Returns the result of a - b, without loss of precision.Returns the result of a - b, without loss of precision.toString()
Returns the string representation of the double value nearest this Real.private static double
twoDiffError
(double a, double b, double x) Returns the error in the difference x=a-b.private static double
twoProductError
(double a, double bhi, double blo, double x) Returns the error in the product x=a*b, with precomputed splits for b.private static double
twoSumError
(double a, double b, double x) Returns the error in the sum x=a+b, when the relative magnitudes of a and b are not known in advance.Methods inherited from class java.lang.Number
byteValue, shortValue
-
Field Details
-
serialVersionUID
private static final long serialVersionUID- See Also:
-
SPLITTER
private static final double SPLITTERUsed to split doubles into two half-length values, for exact multiplication. The value should be Math.pow(2, Math.ceil(mantissaBits / 2)) + 1. -
values
private final double[] valuesA sequence of ordinary double values, ordered by magnitude in ascending order, containing no zeroes and with no overlapping base 2 digits.
-
-
Constructor Details
-
Real
public Real(double value) Creates a Real based on the given double value. -
Real
private Real(double... values)
-
-
Method Details
-
add
Returns the result of a + b, without loss of precision. -
sub
Returns the result of a - b, without loss of precision. -
mul
Returns the result of a * b, without loss of precision. -
add
Returns the result of a + b, without loss of precision. -
sub
Returns the result of a - b, without loss of precision. -
add
Returns the result of adding together the components of a and b, inverting each element of b if negateB is true. -
smallerMagnitude
private static boolean smallerMagnitude(double a, double b) Returns true if the magnitude of a is less than the magnitude of b. -
mul
Returns the result of this * scale, without loss of precision. -
negate
Returns the negative of this number. -
signum
public int signum()Returns the signum of this number more quickly than via Math.signum(doubleValue()). -
toString
Returns the string representation of the double value nearest this Real. -
intValue
public int intValue() -
longValue
public long longValue() -
floatValue
public float floatValue()- Specified by:
floatValue
in classNumber
-
doubleValue
public double doubleValue()- Specified by:
doubleValue
in classNumber
-
bigValue
Returns a BigDecimal representation of this extended precision real value. -
copyOf
private static double[] copyOf(double[] array, int newLength) -
fastTwoSumError
private static double fastTwoSumError(double a, double b, double x) Returns the error in the sum x=a+b, when |a|>=|b|. -
twoSumError
private static double twoSumError(double a, double b, double x) Returns the error in the sum x=a+b, when the relative magnitudes of a and b are not known in advance. -
twoDiffError
private static double twoDiffError(double a, double b, double x) Returns the error in the difference x=a-b. -
splitHigh
private static double splitHigh(double a) Returns the high split for the given value. -
splitLow
private static double splitLow(double a, double ahi) Returns the low split for the given value and previously-computed high split as returned bysplitHigh(double)
. -
twoProductError
private static double twoProductError(double a, double bhi, double blo, double x) Returns the error in the product x=a*b, with precomputed splits for b.
-