From 26e878ab3a5b0844e09ce305fa07eb2d0ad93d41 Mon Sep 17 00:00:00 2001 From: Luc Maisonobe Date: Thu, 10 Sep 2015 09:49:05 +0200 Subject: [PATCH] Fixed infinite loop in FastMath.pow(double, long) with Long.MIN_VALUE. JIRA: MATH-1272 --- src/changes/changes.xml | 3 +++ src/main/java/org/apache/commons/math4/util/FastMath.java | 4 ++-- .../java/org/apache/commons/math4/util/FastMathTest.java | 5 +++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 91f3b2403..443c5ce79 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -54,6 +54,9 @@ If the output is not quite correct, check for invisible trailing spaces! + + Fixed infinite loop in FastMath.pow(double, long) with Long.MIN_VALUE. + Fixed split/side inconsistencies in BSP trees. diff --git a/src/main/java/org/apache/commons/math4/util/FastMath.java b/src/main/java/org/apache/commons/math4/util/FastMath.java index a4a9a1b10..46c8752a0 100644 --- a/src/main/java/org/apache/commons/math4/util/FastMath.java +++ b/src/main/java/org/apache/commons/math4/util/FastMath.java @@ -1711,7 +1711,7 @@ public class FastMath { } /** Computes this^e. - * @param e exponent (beware, here it MUST be > 0) + * @param e exponent (beware, here it MUST be > 0; the only exclusion is Long.MIN_VALUE) * @return d^e, split in high and low bits * @since 4.0 */ @@ -1723,7 +1723,7 @@ public class FastMath { // d^(2p) Split d2p = new Split(full, high, low); - for (long p = e; p != 0; p >>= 1) { + for (long p = e; p != 0; p >>>= 1) { if ((p & 0x1) != 0) { // accurate multiplication result = result * d^(2p) using Veltkamp TwoProduct algorithm diff --git a/src/test/java/org/apache/commons/math4/util/FastMathTest.java b/src/test/java/org/apache/commons/math4/util/FastMathTest.java index b95debac4..bccd0e8d4 100644 --- a/src/test/java/org/apache/commons/math4/util/FastMathTest.java +++ b/src/test/java/org/apache/commons/math4/util/FastMathTest.java @@ -1232,6 +1232,11 @@ public class FastMathTest { Assert.assertTrue(Double.isInfinite(FastMath.pow(FastMath.scalb(1.0, 500), 4))); } + @Test(timeout=5000L) // This test must finish in finite time. + public void testIntPowLongMinValue() { + Assert.assertEquals(1.0, FastMath.pow(1.0, Long.MIN_VALUE), -1.0); + } + @Test public void testIncrementExactInt() { int[] specialValues = new int[] {