Class Sum

  • All Implemented Interfaces:
    DoubleConsumer, DoubleSupplier

    public final class Sum
    extends Object
    implements DoubleSupplier, DoubleConsumer
    Class providing accurate floating-point sums and linear combinations. This class uses techniques to mitigate round off errors resulting from standard floating-point operations, increasing the overall accuracy of results at the cost of a moderate increase in the number of computations. This functionality can be viewed as filling the gap between standard floating point operations (fast but prone to round off errors) and 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.

    • Method Detail

      • add

        public Sum add​(double t)
        Adds a single term to this sum.
        Parameters:
        t - Value to add.
        Returns:
        this instance.
      • add

        public Sum add​(double... terms)
        Adds values from the given array to the sum.
        Parameters:
        terms - Terms to add.
        Returns:
        this instance.
      • addProduct

        public Sum addProduct​(double a,
                              double b)
        Adds the high-accuracy product \( a b \) to this sum.
        Parameters:
        a - Factor
        b - Factor.
        Returns:
        this instance
      • addProducts

        public Sum addProducts​(double[] a,
                               double[] b)
        Adds \( \sum_i a_i b_i \) to this sum.
        Parameters:
        a - Factors.
        b - Factors.
        Returns:
        this instance.
        Throws:
        IllegalArgumentException - if the arrays do not have the same length.
      • add

        public Sum add​(Sum other)
        Adds another sum to this sum.
        Parameters:
        other - Sum to add.
        Returns:
        this instance.
      • create

        public static Sum create()
        Creates a new instance with an initial value of zero.
        Returns:
        a new instance.
      • of

        public static Sum of​(double a)
        Creates an instance initialized to the given value.
        Parameters:
        a - Initial value.
        Returns:
        a new instance.
      • of

        public static Sum of​(double... values)
        Creates an instance containing the sum of the given values.
        Parameters:
        values - Values to add.
        Returns:
        a new instance.
      • ofProducts

        public static Sum ofProducts​(double[] a,
                                     double[] b)
        Creates a new instance containing \( \sum_i a_i b_i \).
        Parameters:
        a - Factors.
        b - Factors.
        Returns:
        a new instance.