You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2021/12/16 12:17:37 UTC

[commons-numbers] branch master updated: Avoid overflow computing the initial value

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 95fe6a8  Avoid overflow computing the initial value
95fe6a8 is described below

commit 95fe6a85a4672180f91160c435f39c2a49377a6e
Author: aherbert <ah...@apache.org>
AuthorDate: Thu Dec 16 11:38:24 2021 +0000

    Avoid overflow computing the initial value
---
 .../commons/numbers/rootfinder/BrentSolver.java    |  3 ++-
 .../numbers/rootfinder/BrentSolverTest.java        | 28 ++++++++++++++++++++++
 src/changes/changes.xml                            |  3 +++
 3 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/commons-numbers-rootfinder/src/main/java/org/apache/commons/numbers/rootfinder/BrentSolver.java b/commons-numbers-rootfinder/src/main/java/org/apache/commons/numbers/rootfinder/BrentSolver.java
index 87fe79d..1cf8a1f 100644
--- a/commons-numbers-rootfinder/src/main/java/org/apache/commons/numbers/rootfinder/BrentSolver.java
+++ b/commons-numbers-rootfinder/src/main/java/org/apache/commons/numbers/rootfinder/BrentSolver.java
@@ -73,7 +73,8 @@ public class BrentSolver {
     public double findRoot(DoubleUnaryOperator func,
                            double min,
                            double max) {
-        return findRoot(func, min, 0.5 * (min + max), max);
+        // Avoid overflow computing the initial value: 0.5 * (min + max)
+        return findRoot(func, min, 0.5 * min + 0.5 * max, max);
     }
 
     /**
diff --git a/commons-numbers-rootfinder/src/test/java/org/apache/commons/numbers/rootfinder/BrentSolverTest.java b/commons-numbers-rootfinder/src/test/java/org/apache/commons/numbers/rootfinder/BrentSolverTest.java
index 0bc295b..234fe48 100644
--- a/commons-numbers-rootfinder/src/test/java/org/apache/commons/numbers/rootfinder/BrentSolverTest.java
+++ b/commons-numbers-rootfinder/src/test/java/org/apache/commons/numbers/rootfinder/BrentSolverTest.java
@@ -287,4 +287,32 @@ class BrentSolverTest {
         final double result2 = solver.findRoot(func2, lower, initial, upper);
         Assertions.assertEquals(target2, result2, Math.ulp(target2));
     }
+
+    @Test
+    void testOverflowInInitialValue() {
+        final BrentSolver solver = new BrentSolver(DEFAULT_RELATIVE_ACCURACY,
+                                                   DEFAULT_ABSOLUTE_ACCURACY,
+                                                   DEFAULT_FUNCTION_ACCURACY);
+        // Linear function close to positive infinity
+        final double lower1 = Double.MAX_VALUE / 2;
+        final double upper1 = Double.MAX_VALUE;
+        final double target1 = lower1 + 0.5 * (upper1 - lower1);
+        final DoubleUnaryOperator func1 = x -> x - target1;
+        final double result1 = solver.findRoot(func1, lower1, upper1);
+        Assertions.assertEquals(target1, result1, Math.ulp(target1));
+
+        // Linear function close to negative infinity
+        final double lower2 = -Double.MAX_VALUE;
+        final double upper2 = -Double.MAX_VALUE / 2;
+        final double target2 = lower2 + 0.5 * (upper2 - lower2);
+        final DoubleUnaryOperator func2 = x -> x - target2;
+        final double result2 = solver.findRoot(func2, lower2, upper2);
+        Assertions.assertEquals(target2, result2, Math.ulp(target2));
+
+        // Linear function across the entire finite range of a double
+        final double target3 = Double.MAX_VALUE / 2;
+        final DoubleUnaryOperator func3 = x -> x - target3;
+        final double result3 = solver.findRoot(func3, -Double.MAX_VALUE, Double.MAX_VALUE);
+        Assertions.assertEquals(target3, result3, Math.ulp(target3));
+    }
 }
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 3f6fbb6..519ba8d 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -72,6 +72,9 @@ N.B. the Performance testing module requires Java 9+.
 (The unit tests require Java 8+)
 
 ">
+      <action dev="aherbert" type="fix">
+        "BrentSolver": Avoid overflow creating the initial value between the lower and upper.
+      </action>
       <action dev="aherbert" type="add" issue="NUMBERS-177">
         "Erfcx": Compute a scaled complementary error function: erfcx(z) = erfc(z) * exp(z*z).
       </action>