public final class Sum extends Object implements DoubleSupplier, DoubleConsumer
BigDecimal
(perfectly accurate but slow).
Usage
This class use a builder pattern in order to maximize the flexibility
of the API. Typical use involves constructing an instance from one
of the factory methods, adding any number of single value terms
and/or products
, and then extracting the
computed sum. Convenience methods exist for adding multiple values or products at once.
The examples below demonstrate some simple use cases.
// compute the sum a1 + a2 + a3 + a4 Sum sum = Sum.of(a1); .add(a2) .add(a3) .add(a4); double result = sum.getAsDouble(); // same as above but using the varargs factory method double result = Sum.of(a1, a2, a3, a4).getAsDouble(); // compute the dot product of two arrays of the same length, a and b Sum sum = Sum.create(); for (int i = 0; i < a.length; ++i) { sum.addProduct(a[i], b[i]); } double result = sum.getAsDouble(); // same as above but using a convenience factory method double result = Sum.ofProducts(a, b).getAsDouble();
It is worth noting that this class is designed to reduce floating point errors
across a sequence of operations and not just a single add or multiply. The
standard IEEE floating point operations already produce the most accurate results
possible given two arguments and this class does not improve on them. Rather, it tracks
the errors inherent with each operation and uses them to reduce the error of the overall
result. Therefore, this class is only beneficial in cases involving 3 or more floating point
operations. Code such as Sum.of(a, b).getAsDouble()
and
Sum.create().addProduct(a, b).getAsDouble()
only adds overhead with no benefit.
Implementation Notes
This class internally uses the Sum2S and Dot2S algorithms described in Accurate Sum and Dot Product by Takeshi Ogita, Siegfried M. Rump, and Shin'ichi Oishi (SIAM J. Sci. Comput, 2005). These are compensated summation and multiplication algorithms chosen here for their good balance of precision and performance. Future releases may choose to use different algorithms.
Results follow the IEEE 754 rules for addition: For example, if any
input value is Double.NaN
, the result is Double.NaN
.
Instances of this class are mutable and not safe for use by multiple threads.
Modifier and Type | Method and Description |
---|---|
void |
accept(double value)
Adds a single term to this sum.
|
Sum |
add(double... terms)
Adds values from the given array to the sum.
|
Sum |
add(double t)
Adds a single term to this sum.
|
Sum |
add(Sum other)
Adds another sum to this sum.
|
Sum |
addProduct(double a,
double b)
Adds the high-accuracy product \( a b \) to this sum.
|
Sum |
addProducts(double[] a,
double[] b)
Adds \( \sum_i a_i b_i \) to this sum.
|
static Sum |
create()
Creates a new instance with an initial value of zero.
|
double |
getAsDouble()
Gets the sum value.
|
static Sum |
of(double... values)
Creates an instance containing the sum of the given values.
|
static Sum |
of(double a)
Creates an instance initialized to the given value.
|
static Sum |
ofProducts(double[] a,
double[] b)
Creates a new instance containing \( \sum_i a_i b_i \).
|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
andThen
public Sum add(double t)
t
- Value to add.public Sum add(double... terms)
terms
- Terms to add.public Sum addProduct(double a, double b)
a
- Factorb
- Factor.public Sum addProducts(double[] a, double[] b)
a
- Factors.b
- Factors.IllegalArgumentException
- if the arrays do not have the same length.public Sum add(Sum other)
other
- Sum to add.public void accept(double value)
add(double)
.accept
in interface DoubleConsumer
value
- Value to add.add(double)
public double getAsDouble()
getAsDouble
in interface DoubleSupplier
public static Sum create()
public static Sum of(double a)
a
- Initial value.public static Sum of(double... values)
values
- Values to add.public static Sum ofProducts(double[] a, double[] b)
a
- Factors.b
- Factors.Copyright © 2017–2022 The Apache Software Foundation. All rights reserved.