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


The following commit(s) were added to refs/heads/master by this push:
     new 8bd0aba6 NUMBERS-200: Don't honour compensation if it's NaN in Sum#add 
(#136)
8bd0aba6 is described below

commit 8bd0aba6b031daed1d00de6805c1639fffe7f3d0
Author: Anirudh <129569933+ani5r...@users.noreply.github.com>
AuthorDate: Sun Jul 23 00:05:23 2023 +0530

    NUMBERS-200: Don't honour compensation if it's NaN in Sum#add (#136)
---
 .../java/org/apache/commons/numbers/core/Sum.java  |  8 ++++++-
 .../org/apache/commons/numbers/core/SumTest.java   | 28 ++++++++++++++++++++++
 2 files changed, 35 insertions(+), 1 deletion(-)

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 05ebecfe..6aaff723 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
@@ -202,7 +202,13 @@ public final class Sum
      * @return this instance.
      */
     private Sum add(double s, double c) {
-        return add(s).add(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);
+        }
+        return this;
     }
 
     /**
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 5e42a727..844d7096 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
@@ -19,9 +19,13 @@ package org.apache.commons.numbers.core;
 import java.math.BigDecimal;
 import java.math.MathContext;
 import java.util.Arrays;
+import java.util.stream.Stream;
 
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
 class SumTest {
 
@@ -49,6 +53,30 @@ class SumTest {
         assertSum(Double.NEGATIVE_INFINITY, 1, Double.NEGATIVE_INFINITY, 1);
     }
 
+    @ParameterizedTest
+    @MethodSource(value = "testAddInstance")
+    void testAddInstance(double[][] values, double expected) {
+        Sum sum1 = Sum.create().add(values[0]);
+        Sum sum2 = Sum.create().add(values[1]);
+        sum1.add(sum2);
+        Assertions.assertEquals(expected, sum1.getAsDouble());
+    }
+
+    static Stream<Arguments> testAddInstance() {
+        return Stream.of(
+            Arguments.of(new double[][] {{Double.POSITIVE_INFINITY}, 
{Double.POSITIVE_INFINITY}},
+                Double.POSITIVE_INFINITY),
+                Arguments.of(new double[][] {{1, 2, -3}, {3, -1, -2}}, 0),
+                Arguments.of(new double[][] {{1, 2, 3}, {4, 5, -6}}, 9),
+                Arguments.of(new double[][] {{3.1415, 2.718}, {1000, 0.001}},
+                    1005.8605),
+                Arguments.of(new double[][] {{1729, 2520}, {Double.MAX_VALUE, 
Double.MAX_VALUE}},
+                    Double.POSITIVE_INFINITY),
+                Arguments.of(new double[][] {{Double.NEGATIVE_INFINITY, 85}, 
{-1, -7, -2, -9}},
+                    Double.NEGATIVE_INFINITY)
+        );
+    }
+
     @Test
     void testSumAccuracy() {
         // arrange

Reply via email to