This is an automated email from the ASF dual-hosted git repository. erans pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-numbers.git
commit 93c45e9dcde7f283c620508daacaf36383925596 Author: Gilles Sadowski <gillese...@gmail.com> AuthorDate: Sun Jun 20 04:10:59 2021 +0200 NUMBERS-163: Nits. Javadoc style to match style in (most) other files. Removed factory methods that were just one-liner replacements. Added "varargs" (any number of terms) methods. Explicit initialization of "comp" instance variable. Closes #97. --- .../java/org/apache/commons/numbers/core/Norm.java | 7 +- .../java/org/apache/commons/numbers/core/Sum.java | 239 ++++++++------------- .../org/apache/commons/numbers/core/SumTest.java | 16 +- 3 files changed, 99 insertions(+), 163 deletions(-) diff --git a/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/Norm.java b/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/Norm.java index 255215a..92587fc 100644 --- a/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/Norm.java +++ b/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/Norm.java @@ -219,9 +219,10 @@ public enum Norm { private static double manhattan(final double x, final double y, final double z) { - return Sum.of(Math.abs(x), - Math.abs(y), - Math.abs(z)).getAsDouble(); + return Sum.of(Math.abs(x)) + .add(Math.abs(y)) + .add(Math.abs(z)) + .getAsDouble(); } /** Computes the Manhattan norm. diff --git a/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/Sum.java b/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/Sum.java index 9939e62..390649a 100644 --- a/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/Sum.java +++ b/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/Sum.java @@ -19,40 +19,42 @@ package org.apache.commons.numbers.core; import java.util.function.DoubleConsumer; import java.util.function.DoubleSupplier; -/** Class providing accurate floating-point sums and linear combinations. The methods - * provided use compensated summation and multiplication techniques to reduce numerical errors. - * The approach is based on the <em>Sum2S</em> and <em>Dot2S</em> algorithms described in the - * 2005 paper <a href="https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547"> +/** + * Class providing accurate floating-point sums and linear combinations. + * + * In order to reduce errors, compensated summations and multiplications + * are performed according to the <em>Sum2S</em> and <em>Dot2S</em> + * algorithms described in + * <a href="https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547"> * Accurate Sum and Dot Product</a> by Takeshi Ogita, Siegfried M. Rump, - * and Shin'ichi Oishi published in <em>SIAM J. Sci. Comput</em>. + * and Shin'ichi Oishi (<em>SIAM J. Sci. Comput</em>, 2005). * - * <p>Method results follow the standard rules for IEEE 754 addition. For example, - * if any input value is NaN, the result is NaN. + * <p>Results follow the IEEE 754 rules for addition: For example, if any + * input value is {@link Double#NaN}, the result is {@link Double#NaN}. */ -public final class Sum implements DoubleSupplier, DoubleConsumer { - +public final class Sum + implements DoubleSupplier, + DoubleConsumer { /** Standard sum. */ private double sum; - /** Compensation value. */ private double comp; - /** Construct a new instance with an initial value of zero. - */ - private Sum() { - this(0d); - } - - /** Construct a new instance with the given initial value. - * @param initialValue initial value + /** + * Constructs a new instance with the given initial value. + * + * @param initialValue Initial value. */ private Sum(final double initialValue) { - this.sum = initialValue; + sum = initialValue; + comp = 0d; } - /** Add a single term to this sum. - * @param t value to add - * @return this instance + /** + * Adds a single term to this sum. + * + * @param t Value to add. + * @return this instance. */ public Sum add(final double t) { final double newSum = sum + t; @@ -62,11 +64,13 @@ public final class Sum implements DoubleSupplier, DoubleConsumer { return this; } - /** Add an array of value to the sum. - * @param terms terms to add - * @return this instance + /** + * Adds values from the given array to the sum. + * + * @param terms Terms to add. + * @return this instance. */ - public Sum add(final double[] terms) { + public Sum add(final double... terms) { for (double t : terms) { add(t); } @@ -74,12 +78,15 @@ public final class Sum implements DoubleSupplier, DoubleConsumer { return this; } - /** Add the high-accuracy product \(a b\) to this sum. - * @param a first factor - * @param b second factor + /** + * Adds the high-accuracy product \( a b \) to this sum. + * + * @param a Factor + * @param b Factor. * @return this instance */ - public Sum addProduct(final double a, final double b) { + public Sum addProduct(final double a, + final double b) { final double ab = a * b; final double pLow = ExtendedPrecision.productLow(a, b, ab); @@ -90,18 +97,20 @@ public final class Sum implements DoubleSupplier, DoubleConsumer { return this; } - /** Add \( \sum_i a_i b_i \). In other words, multiply each element - * in {@code a} with its corresponding element in {@code b} and add the product - * to the sum. - * @param a factors - * @param b factors - * @return this instance - * @throws IllegalArgumentException if the arrays do not have the same length + /** + * Adds \( \sum_i a_i b_i \) to this sum. + * + * @param a Factors. + * @param b Factors. + * @return this instance. + * @throws IllegalArgumentException if the arrays do not have the same length. */ - public Sum addProducts(final double[] a, final double[] b) { + public Sum addProducts(final double[] a, + final double[] b) { final int len = a.length; if (len != b.length) { - throw new IllegalArgumentException("Dimension mismatch: " + a.length + " != " + b.length); + throw new IllegalArgumentException("Dimension mismatch: " + + a.length + " != " + b.length); } for (int i = 0; i < len; ++i) { @@ -111,22 +120,27 @@ public final class Sum implements DoubleSupplier, DoubleConsumer { return this; } - /** Add another sum to this sum. - * @param other sum to add - * @return this instance + /** + * Adds another sum to this sum. + * + * @param other Sum to add. + * @return this instance. */ public Sum add(final Sum other) { - // pull both values first to ensure there are - // no issues when adding a sum to itself + // Pull both values first to ensure there are + // no issues when adding a sum to itself. final double s = other.sum; final double c = other.comp; - return add(s) - .add(c); + return add(s).add(c); } - /** Add a single term to this sum. This is equivalent to {@link #add(double)}. - * @param value value to add + /** + * Adds a single term to this sum. + * This is equivalent to {@link #add(double)}. + * + * @param value Value to add. + * * @see #add(double) */ @Override @@ -134,125 +148,58 @@ public final class Sum implements DoubleSupplier, DoubleConsumer { add(value); } - /** Get the sum value. - * @return sum value as a double + /** + * Gets the sum value. + * + * @return the sum value. */ @Override public double getAsDouble() { - // compute and return the high precision sum if it is finite; otherwise, - // return the standard IEEE754 result + // High-precision value if it is finite, standard IEEE754 result otherwise. final double hpsum = sum + comp; return Double.isFinite(hpsum) ? hpsum : sum; } - /** Create a new sum instance with an initial value of zero. - * @return new sum instance + /** + * Creates a new instance with an initial value of zero. + * + * @return a new instance. */ public static Sum create() { - return new Sum(); + return new Sum(0d); } - /** Return a new sum instance containing a single value. - * @param a value - * @return new sum instance - * @see #add(double) + /** + * Creates an instance initialized to the given value. + * + * @param a Initial value. + * @return a new instance. */ public static Sum of(final double a) { return new Sum(a); } - /** Return a new sum instance containing the value \(a + b\). - * @param a first term - * @param b second term - * @return new sum instance - * @see #add(double) - */ - public static Sum of(final double a, final double b) { - return new Sum(a).add(b); - } - - /** Return a new sum instance containing the value \(a + b + c\). - * @param a first term - * @param b second term - * @param c third term - * @return new sum instance - * @see #add(double) - */ - public static Sum of(final double a, final double b, final double c) { - return new Sum(a) - .add(b) - .add(c); - } - - /** Return a new sum instance containing the value \(a + b + c + d\). - * @param a first term - * @param b second term - * @param c third term - * @param d fourth term - * @return new sum instance - * @see #add(double) - */ - public static Sum of(final double a, final double b, final double c, final double d) { - return new Sum(a) - .add(b) - .add(c) - .add(d); - } - - /** Return a new sum instance containing the sum of the given values. - * @param values input values - * @return new sum instance - * @see #add(double[]) - */ - public static Sum of(final double[] values) { - return new Sum().add(values); - } - - /** Return a new sum instance containing the linear combination - * \(a_1 b_1 + a_2 b_2\). - * @param a1 first factor of first term - * @param b1 second factor of first term - * @param a2 first factor of second term - * @param b2 second factor of second term - * @return new sum instance - * @see #addProduct(double, double) - */ - public static Sum ofProducts(final double a1, final double b1, - final double a2, final double b2) { - return new Sum() - .addProduct(a1, b1) - .addProduct(a2, b2); - } - - /** Return a new sum instance containing the linear combination - * \(a_1 b_1 + a_2 b_2 + a_3 b_3\). - * @param a1 first factor of first term - * @param b1 second factor of first term - * @param a2 first factor of second term - * @param b2 second factor of second term - * @param a3 first factor of third term - * @param b3 second factor of third term - * @return new sum instance - * @see #addProduct(double, double) + /** + * Creates an instance containing the sum of the given values. + * + * @param values Values to add. + * @return a new instance. */ - public static Sum ofProducts(final double a1, final double b1, - final double a2, final double b2, - final double a3, final double b3) { - return new Sum() - .addProduct(a1, b1) - .addProduct(a2, b2) - .addProduct(a3, b3); + public static Sum of(final double... values) { + return create().add(values); } - /** Return a new sum instance containing \( \sum_i a_i b_i \). - * @param a first set of factors - * @param b second set of factors - * @return new sum instance - * @see #addProducts(double[], double[]) + /** + * Creates a new instance containing \( \sum_i a_i b_i \). + * + * @param a Factors. + * @param b Factors. + * @return a new instance. */ - public static Sum ofProducts(final double[] a, final double[] b) { - return new Sum().addProducts(a, b); + public static Sum ofProducts(final double[] a, + final double[] b) { + return create().addProducts(a, b); } } diff --git a/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/SumTest.java b/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/SumTest.java index 70afcd5..5d38260 100644 --- a/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/SumTest.java +++ b/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/SumTest.java @@ -193,9 +193,7 @@ class SumTest { } // act - final double sum = Sum.ofProducts(scaledA[0], scaledB[0], - scaledA[1], scaledB[1], - scaledA[2], scaledB[2]).getAsDouble(); + final double sum = Sum.ofProducts(scaledA, scaledB).getAsDouble(); // assert Assertions.assertEquals(-1.8551294182586248737720779899, sum, 1e-15); @@ -352,7 +350,7 @@ class SumTest { final double x = Math.nextDown(2.0); final double y = -Math.nextDown(x); final double xxMxy = x * x + x * y; - final double xxMxyHighPrecision = Sum.ofProducts(x, x, x, y).getAsDouble(); + final double xxMxyHighPrecision = Sum.create().addProduct(x, x).addProduct(x, y).getAsDouble(); Assertions.assertNotEquals(xxMxy, xxMxyHighPrecision, "High precision result should be different"); // Scale it close to max value. @@ -510,16 +508,6 @@ class SumTest { private static void assertSumOfProducts(final double expected, final double[] a, final double[] b) { final int len = a.length; - // check non-array method variants - if (len == 2) { - Assertions.assertEquals(expected, Sum.ofProducts(a[0], b[0], - a[1], b[1]).getAsDouble()); - } else if (len == 3) { - Assertions.assertEquals(expected, Sum.ofProducts(a[0], b[0], - a[1], b[1], - a[2], b[2]).getAsDouble()); - } - // check use of addProduct() final Sum accumulator = Sum.create(); for (int i = 0; i < len; ++i) {