diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 4a7a8466c..5bdaf76c8 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -51,6 +51,9 @@ If the output is not quite correct, check for invisible trailing spaces! + + Fixed FastMath.exp that potentially returned NaN for non-NaN argument. + Added a nth order Brent solver for general real fields, replacing the former solver that was restricted to Dfp fields only. diff --git a/src/main/java/org/apache/commons/math3/util/FastMath.java b/src/main/java/org/apache/commons/math3/util/FastMath.java index 161ad6cf5..f30b50274 100644 --- a/src/main/java/org/apache/commons/math3/util/FastMath.java +++ b/src/main/java/org/apache/commons/math3/util/FastMath.java @@ -968,6 +968,13 @@ public class FastMath { much larger than the others. If there are extra bits specified from the pow() function, use them. */ final double tempC = tempB + tempA; + + // If tempC is positive infinite, the evaluation below could result in NaN, + // because z could be negative at the same time. + if (tempC == Double.POSITIVE_INFINITY) { + return Double.POSITIVE_INFINITY; + } + final double result; if (extra != 0.0) { result = tempC*extra*z + tempC*extra + tempC*z + tempB + tempA; diff --git a/src/test/java/org/apache/commons/math3/util/FastMathTest.java b/src/test/java/org/apache/commons/math3/util/FastMathTest.java index aadc4ecd5..2df5542f5 100644 --- a/src/test/java/org/apache/commons/math3/util/FastMathTest.java +++ b/src/test/java/org/apache/commons/math3/util/FastMathTest.java @@ -215,6 +215,15 @@ public class FastMathTest { } Assert.assertEquals(0, maxErr, 3); } + + @Test + public void testMath1269() { + final double arg = 709.8125; + final double vM = Math.exp(arg); + final double vFM = FastMath.exp(arg); + Assert.assertTrue("exp(" + arg + ") is " + vFM + " instead of " + vM, + Precision.equalsIncludingNaN(vM, vFM)); + } @Test public void testHyperbolicInverses() {