Skip to content

Commit 4484083

Browse files
committed
NUMBERS-168: Identify brackets with small objective values
1 parent 5579e8d commit 4484083

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

commons-numbers-rootfinder/src/main/java/org/apache/commons/numbers/rootfinder/BrentSolver.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ public double findRoot(DoubleUnaryOperator func,
115115
}
116116

117117
// Reduce interval if min and initial bracket the root.
118-
if (yInitial * yMin < 0) {
118+
if (Double.compare(yInitial * yMin, 0.0) < 0) {
119119
return brent(func, min, initial, yMin, yInitial);
120120
}
121121

@@ -126,7 +126,7 @@ public double findRoot(DoubleUnaryOperator func,
126126
}
127127

128128
// Reduce interval if initial and max bracket the root.
129-
if (yInitial * yMax < 0) {
129+
if (Double.compare(yInitial * yMax, 0.0) < 0) {
130130
return brent(func, initial, max, yInitial, yMax);
131131
}
132132

commons-numbers-rootfinder/src/test/java/org/apache/commons/numbers/rootfinder/BrentSolverTest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,4 +260,31 @@ void testInitialGuess() {
260260
Assertions.assertEquals(1.0, result, DEFAULT_ABSOLUTE_ACCURACY);
261261
Assertions.assertEquals(1, f.getCallsCount());
262262
}
263+
264+
/**
265+
* Test that a change in sign is detected with sub-normal numbers.
266+
* See NUMBERS-168.
267+
*/
268+
@Test
269+
void testSubNormalBracket() {
270+
final double lower = Double.MIN_VALUE;
271+
final double initial = lower * 5;
272+
final double upper = lower * 10;
273+
// Using zero for the accuracy will only terminate the solver if the root
274+
// equals 0.0 within 1 ULP.
275+
final BrentSolver solver = new BrentSolver(0.0,
276+
0.0,
277+
0.0);
278+
// Target below the initial estimate
279+
final double target1 = lower * 2;
280+
final DoubleUnaryOperator func1 = x -> x - target1;
281+
final double result1 = solver.findRoot(func1, lower, initial, upper);
282+
Assertions.assertEquals(target1, result1, Math.ulp(target1));
283+
284+
// Target above the initial estimate
285+
final double target2 = lower * 7;
286+
final DoubleUnaryOperator func2 = x -> x - target2;
287+
final double result2 = solver.findRoot(func2, lower, initial, upper);
288+
Assertions.assertEquals(target2, result2, Math.ulp(target2));
289+
}
263290
}

src/changes/changes.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ N.B. the Performance testing module requires Java 9+.
7272
(The unit tests require Java 8+)
7373
7474
">
75+
<action dev="aherbert" type="fix" issue="NUMBERS-168">
76+
"BrentSolver": Identify brackets with small objective values.
77+
</action>
7578
<action dev="aherbert" type="fix" due-to="Arturo Bernal">
7679
Fix wrong javadoc.
7780
</action>

0 commit comments

Comments
 (0)