This is an automated email from the ASF dual-hosted git repository. aherbert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-numbers.git
commit 5e54406ae9895dd9c9f5831e6fcd1a9fb2a7b52f Author: aherbert <[email protected]> AuthorDate: Tue Oct 3 15:04:59 2023 +0100 Combine sums in double-double precision This enforces symmetry in the combine operation and maximises the precision from the available bits. --- .../java/org/apache/commons/numbers/core/Sum.java | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) 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 ee7b351f..eaee0d9b 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 @@ -196,16 +196,27 @@ public final class Sum * before addition to ensure there are no issues when adding a sum * to itself. * + * <p>This method sums the values in double-double precision. + * This enforces symmetry when combining sums and maximises the available precision. + * * @param s Sum. * @param c Compensation. * @return this instance. */ private Sum add(double s, double c) { - add(s); - // compensation can be NaN from accumulating one or more same-signed infinite values. - // Do not pollute the regular IEEE754 sum with a spurious NaN. - if (!Double.isNaN(c)) { - add(c); + // Re-normalise the sums and combine in double-double precision. + // Note: The conversion to a DD is lossless. + final DD result = DD.ofSum(sum, comp).add(DD.ofSum(s, c)); + if (result.isFinite()) { + sum = result.hi(); + comp = result.lo(); + } else { + // compensation can be NaN from accumulating one or more same-signed infinite values. + // Do not pollute the regular IEEE754 sum with a spurious NaN. + add(s); + if (!Double.isNaN(c)) { + add(c); + } } return this; }
