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>