commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From l..@apache.org
Subject [math] Added negative zero support in FastMath.pow.
Date Fri, 11 Sep 2015 18:01:44 GMT
Repository: commons-math
Updated Branches:
  refs/heads/master 8c141a170 -> 40f969bc9


Added negative zero support in FastMath.pow.

JIRA: MATH-1273
Github: closes #16


Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/40f969bc
Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/40f969bc
Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/40f969bc

Branch: refs/heads/master
Commit: 40f969bc9e162deead55967da3c128e2da933dfc
Parents: 8c141a1
Author: Qualtagh <a@a.a>
Authored: Fri Sep 11 19:42:20 2015 +0200
Committer: Luc Maisonobe <luc@apache.org>
Committed: Fri Sep 11 19:47:56 2015 +0200

----------------------------------------------------------------------
 src/changes/changes.xml                         |   3 +
 .../org/apache/commons/math4/util/FastMath.java |   2 +-
 .../apache/commons/math4/util/FastMathTest.java | 387 ++++++++++++++++++-
 3 files changed, 387 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/40f969bc/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index a8a09fa..561bccc 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!
     </release>
 
     <release version="4.0" date="XXXX-XX-XX" description="">
+      <action dev="luc" type="add" issue="MATH-1273" due-to="Qualtagh"> <!-- backported
to 3.6 -->
+        Added negative zero support in FastMath.pow.
+      </action>
       <action dev="luc" type="add" issue="MATH-1271" due-to="Qualtagh">
         Added divideUnsigned and remainderUnsigned to ArithmeticUtils.
       </action>

http://git-wip-us.apache.org/repos/asf/commons-math/blob/40f969bc/src/main/java/org/apache/commons/math4/util/FastMath.java
----------------------------------------------------------------------
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 3e2ee1f..1a294af 100644
--- a/src/main/java/org/apache/commons/math4/util/FastMath.java
+++ b/src/main/java/org/apache/commons/math4/util/FastMath.java
@@ -1666,7 +1666,7 @@ public class FastMath {
          * @param low low order bits
          */
         public Split(final double high, final double low) {
-            this(high + low, high, low);
+            this(high == 0.0 ? (low == 0.0 && Double.doubleToRawLongBits(high) ==
Long.MIN_VALUE /* negative zero */ ? -0.0 : low) : high + low, high, low);
         }
 
         /** Simple constructor.

http://git-wip-us.apache.org/repos/asf/commons-math/blob/40f969bc/src/test/java/org/apache/commons/math4/util/FastMathTest.java
----------------------------------------------------------------------
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 bccd0e8..ec0d91c 100644
--- a/src/test/java/org/apache/commons/math4/util/FastMathTest.java
+++ b/src/test/java/org/apache/commons/math4/util/FastMathTest.java
@@ -19,7 +19,9 @@ package org.apache.commons.math4.util;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Type;
+import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.math.RoundingMode;
 
 import org.apache.commons.math4.TestUtils;
 import org.apache.commons.math4.dfp.Dfp;
@@ -353,6 +355,7 @@ public class FastMathTest {
 
     @Test
     public void testPowSpecialCases() {
+        final double EXACT = -1.0;
 
         Assert.assertEquals("pow(-1, 0) should be 1.0", 1.0, FastMath.pow(-1.0, 0.0), Precision.EPSILON);
 
@@ -392,7 +395,9 @@ public class FastMathTest {
 
         Assert.assertEquals("pow(-0.0, -huge) should be Infinity", Double.POSITIVE_INFINITY,
FastMath.pow(-0.0, -Double.MAX_VALUE), 1.0);
 
-        Assert.assertEquals("pow(-Inf, -3.0) should be -Inf", Double.NEGATIVE_INFINITY, FastMath.pow(Double.NEGATIVE_INFINITY,
3.0), 1.0);
+        Assert.assertEquals("pow(-Inf, 3.0) should be -Inf", Double.NEGATIVE_INFINITY, FastMath.pow(Double.NEGATIVE_INFINITY,
3.0), 1.0);
+
+        Assert.assertEquals("pow(-Inf, -3.0) should be -0.0", -0.0, FastMath.pow(Double.NEGATIVE_INFINITY,
-3.0), EXACT);
 
         Assert.assertEquals("pow(-0.0, -3.5) should be Inf", Double.POSITIVE_INFINITY, FastMath.pow(-0.0,
-3.5), 1.0);
 
@@ -414,7 +419,7 @@ public class FastMathTest {
 
         Assert.assertTrue("pow(NaN, -Infinity) should be NaN", Double.isNaN(FastMath.pow(Double.NaN,
Double.NEGATIVE_INFINITY)));
 
-        Assert.assertEquals("pow(NaN, 0.0) should be 1.0", 1.0, FastMath.pow(Double.NaN,
0.0), Precision.EPSILON);
+        Assert.assertEquals("pow(NaN, -0.0) should be 1.0", 1.0, FastMath.pow(Double.NaN,
-0.0), Precision.EPSILON);
 
         Assert.assertEquals("pow(-Infinity, -Infinity) should be 0.0", 0.0, FastMath.pow(Double.NEGATIVE_INFINITY,
Double.NEGATIVE_INFINITY), Precision.EPSILON);
 
@@ -430,9 +435,9 @@ public class FastMathTest {
 
         Assert.assertTrue("pow(-Inf, NaN) should be NaN", Double.isNaN(FastMath.pow(Double.NEGATIVE_INFINITY,
Double.NaN)));
 
-        Assert.assertEquals("pow(-Inf, -1.0) should be 0.0", 0.0, FastMath.pow(Double.NEGATIVE_INFINITY,
-1.0), Precision.EPSILON);
+        Assert.assertEquals("pow(-Inf, -1.0) should be -0.0", -0.0, FastMath.pow(Double.NEGATIVE_INFINITY,
-1.0), EXACT);
 
-        Assert.assertEquals("pow(-Inf, -2.0) should be 0.0", 0.0, FastMath.pow(Double.NEGATIVE_INFINITY,
-2.0), Precision.EPSILON);
+        Assert.assertEquals("pow(-Inf, -2.0) should be 0.0", 0.0, FastMath.pow(Double.NEGATIVE_INFINITY,
-2.0), EXACT);
 
         Assert.assertEquals("pow(-Inf, 1.0) should be -Inf", Double.NEGATIVE_INFINITY, FastMath.pow(Double.NEGATIVE_INFINITY,
1.0), 1.0);
 
@@ -440,6 +445,216 @@ public class FastMathTest {
 
         Assert.assertTrue("pow(1.0, -Inf) should be NaN", Double.isNaN(FastMath.pow(1.0,
Double.NEGATIVE_INFINITY)));
 
+        Assert.assertEquals("pow(-0.0, 1.0) should be -0.0", -0.0, FastMath.pow(-0.0, 1.0),
EXACT);
+
+        Assert.assertEquals("pow(0.0, 1.0) should be 0.0", 0.0, FastMath.pow(0.0, 1.0), EXACT);
+
+        Assert.assertEquals("pow(0.0, +Inf) should be 0.0", 0.0, FastMath.pow(0.0, Double.POSITIVE_INFINITY),
EXACT);
+
+        Assert.assertEquals("pow(-0.0, even) should be 0.0", 0.0, FastMath.pow(-0.0, 6.0),
EXACT);
+
+        Assert.assertEquals("pow(-0.0, odd) should be -0.0", -0.0, FastMath.pow(-0.0, 13.0),
EXACT);
+
+        Assert.assertEquals("pow(-0.0, -even) should be +Inf", Double.POSITIVE_INFINITY,
FastMath.pow(-0.0, -6.0), EXACT);
+
+        Assert.assertEquals("pow(-0.0, -odd) should be -Inf", Double.NEGATIVE_INFINITY, FastMath.pow(-0.0,
-13.0), EXACT);
+
+        Assert.assertEquals("pow(-2.0, 4.0) should be 16.0", 16.0, FastMath.pow(-2.0, 4.0),
EXACT);
+
+        Assert.assertEquals("pow(-2.0, 4.5) should be NaN", Double.NaN, FastMath.pow(-2.0,
4.5), EXACT);
+
+        Assert.assertEquals("pow(-0.0, -0.0) should be 1.0", 1.0, FastMath.pow(-0.0, -0.0),
EXACT);
+
+        Assert.assertEquals("pow(-0.0, 0.0) should be 1.0", 1.0, FastMath.pow(-0.0, 0.0),
EXACT);
+
+        Assert.assertEquals("pow(0.0, -0.0) should be 1.0", 1.0, FastMath.pow(0.0, -0.0),
EXACT);
+
+        Assert.assertEquals("pow(0.0, 0.0) should be 1.0", 1.0, FastMath.pow(0.0, 0.0), EXACT);
+
+    }
+
+    @Test(timeout=20000L)
+    public void testPowAllSpecialCases() {
+        final double EXACT = -1.0;
+        final double DOUBLES[] = new double[]{Double.NEGATIVE_INFINITY, -0.0, Double.NaN,
0.0, Double.POSITIVE_INFINITY,
+                                              Long.MIN_VALUE, Integer.MIN_VALUE, Short.MIN_VALUE,
Byte.MIN_VALUE,
+                                              -(double)Long.MIN_VALUE, -(double)Integer.MIN_VALUE,
-(double)Short.MIN_VALUE, -(double)Byte.MIN_VALUE,
+                                              Byte.MAX_VALUE, Short.MAX_VALUE, Integer.MAX_VALUE,
Long.MAX_VALUE,
+                                              -Byte.MAX_VALUE, -Short.MAX_VALUE, -Integer.MAX_VALUE,
-Long.MAX_VALUE,
+                                              Float.MAX_VALUE, Double.MAX_VALUE, Double.MIN_VALUE,
Float.MIN_VALUE,
+                                              -Float.MAX_VALUE, -Double.MAX_VALUE, -Double.MIN_VALUE,
-Float.MIN_VALUE,
+                                              0.5, 0.1, 0.2, 0.8, 1.1, 1.2, 1.5, 1.8, 1.0,
2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 1.3, 2.2, 2.5, 2.8, 33.0, 33.1, 33.5, 33.8, 10.0,
300.0, 400.0, 500.0,
+                                              -0.5, -0.1, -0.2, -0.8, -1.1, -1.2, -1.5, -1.8,
-1.0, -2.0, -3.0, -4.0, -5.0, -6.0, -7.0, -8.0, -9.0, -1.3, -2.2, -2.5, -2.8, -33.0, -33.1,
-33.5, -33.8, -10.0, -300.0, -400.0, -500.0};
+        // Special cases from Math.pow javadoc:
+        // If the second argument is positive or negative zero, then the result is 1.0.
+        for (double d : DOUBLES) {
+            Assert.assertEquals(1.0, FastMath.pow(d, 0.0), EXACT);
+        }
+        for (double d : DOUBLES) {
+            Assert.assertEquals(1.0, FastMath.pow(d, -0.0), EXACT);
+        }
+        // If the second argument is 1.0, then the result is the same as the first argument.
+        for (double d : DOUBLES) {
+            Assert.assertEquals(d, FastMath.pow(d, 1.0), EXACT);
+        }
+        // If the second argument is NaN, then the result is NaN.
+        for (double d : DOUBLES) {
+            Assert.assertEquals(Double.NaN, FastMath.pow(d, Double.NaN), EXACT);
+        }
+        // If the first argument is NaN and the second argument is nonzero, then the result
is NaN.
+        for (double i : DOUBLES) {
+            if (i != 0.0) {
+                Assert.assertEquals(Double.NaN, FastMath.pow(Double.NaN, i), EXACT);
+            }
+        }
+        // If the absolute value of the first argument is greater than 1 and the second argument
is positive infinity, or
+        // the absolute value of the first argument is less than 1 and the second argument
is negative infinity, then the result is positive infinity.
+        for (double d : DOUBLES) {
+            if (Math.abs(d) > 1.0) {
+                Assert.assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(d, Double.POSITIVE_INFINITY),
EXACT);
+            }
+        }
+        for (double d : DOUBLES) {
+            if (Math.abs(d) < 1.0) {
+                Assert.assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(d, Double.NEGATIVE_INFINITY),
EXACT);
+            }
+        }
+        // If the absolute value of the first argument is greater than 1 and the second argument
is negative infinity, or
+        // the absolute value of the first argument is less than 1 and the second argument
is positive infinity, then the result is positive zero.
+        for (double d : DOUBLES) {
+            if (Math.abs(d) > 1.0) {
+                Assert.assertEquals(0.0, FastMath.pow(d, Double.NEGATIVE_INFINITY), EXACT);
+            }
+        }
+        for (double d : DOUBLES) {
+            if (Math.abs(d) < 1.0) {
+                Assert.assertEquals(0.0, FastMath.pow(d, Double.POSITIVE_INFINITY), EXACT);
+            }
+        }
+        // If the absolute value of the first argument equals 1 and the second argument is
infinite, then the result is NaN.
+        Assert.assertEquals(Double.NaN, FastMath.pow(1.0, Double.POSITIVE_INFINITY), EXACT);
+        Assert.assertEquals(Double.NaN, FastMath.pow(1.0, Double.NEGATIVE_INFINITY), EXACT);
+        Assert.assertEquals(Double.NaN, FastMath.pow(-1.0, Double.POSITIVE_INFINITY), EXACT);
+        Assert.assertEquals(Double.NaN, FastMath.pow(-1.0, Double.NEGATIVE_INFINITY), EXACT);
+        // If the first argument is positive zero and the second argument is greater than
zero, or
+        // the first argument is positive infinity and the second argument is less than zero,
then the result is positive zero.
+        for (double i : DOUBLES) {
+            if (i > 0.0) {
+                Assert.assertEquals(0.0, FastMath.pow(0.0, i), EXACT);
+            }
+        }
+        for (double i : DOUBLES) {
+            if (i < 0.0) {
+                Assert.assertEquals(0.0, FastMath.pow(Double.POSITIVE_INFINITY, i), EXACT);
+            }
+        }
+        // If the first argument is positive zero and the second argument is less than zero,
or
+        // the first argument is positive infinity and the second argument is greater than
zero, then the result is positive infinity.
+        for (double i : DOUBLES) {
+            if (i < 0.0) {
+                Assert.assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(0.0, i), EXACT);
+            }
+        }
+        for (double i : DOUBLES) {
+            if (i > 0.0) {
+                Assert.assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(Double.POSITIVE_INFINITY,
i), EXACT);
+            }
+        }
+        // If the first argument is negative zero and the second argument is greater than
zero but not a finite odd integer, or
+        // the first argument is negative infinity and the second argument is less than zero
but not a finite odd integer, then the result is positive zero.
+        for (double i : DOUBLES) {
+            if (i > 0.0 && (Double.isInfinite(i) || i % 2.0 == 0.0)) {
+                Assert.assertEquals(0.0, FastMath.pow(-0.0, i), EXACT);
+            }
+        }
+        for (double i : DOUBLES) {
+            if (i < 0.0 && (Double.isInfinite(i) || i % 2.0 == 0.0)) {
+                Assert.assertEquals(0.0, FastMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
+            }
+        }
+        // If the first argument is negative zero and the second argument is a positive finite
odd integer, or
+        // the first argument is negative infinity and the second argument is a negative
finite odd integer, then the result is negative zero.
+        for (double i : DOUBLES) {
+            if (i > 0.0 && i % 2.0 == 1.0) {
+                Assert.assertEquals(-0.0, FastMath.pow(-0.0, i), EXACT);
+            }
+        }
+        for (double i : DOUBLES) {
+            if (i < 0.0 && i % 2.0 == -1.0) {
+                Assert.assertEquals(-0.0, FastMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
+            }
+        }
+        // If the first argument is negative zero and the second argument is less than zero
but not a finite odd integer, or
+        // the first argument is negative infinity and the second argument is greater than
zero but not a finite odd integer, then the result is positive infinity.
+        for (double i : DOUBLES) {
+            if (i > 0.0 && (Double.isInfinite(i) || i % 2.0 == 0.0)) {
+                Assert.assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(Double.NEGATIVE_INFINITY,
i), EXACT);
+            }
+        }
+        for (double i : DOUBLES) {
+            if (i < 0.0 && (Double.isInfinite(i) || i % 2.0 == 0.0)) {
+                Assert.assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(-0.0, i), EXACT);
+            }
+        }
+        // If the first argument is negative zero and the second argument is a negative finite
odd integer, or
+        // the first argument is negative infinity and the second argument is a positive
finite odd integer, then the result is negative infinity.
+        for (double i : DOUBLES) {
+            if (i > 0.0 && i % 2.0 == 1.0) {
+                Assert.assertEquals(Double.NEGATIVE_INFINITY, FastMath.pow(Double.NEGATIVE_INFINITY,
i), EXACT);
+            }
+        }
+        for (double i : DOUBLES) {
+            if (i < 0.0 && i % 2.0 == -1.0) {
+                Assert.assertEquals(Double.NEGATIVE_INFINITY, FastMath.pow(-0.0, i), EXACT);
+            }
+        }
+        for (double d : DOUBLES) {
+            // If the first argument is finite and less than zero
+            if (d < 0.0 && Math.abs(d) <= Double.MAX_VALUE) {
+                for (double i : DOUBLES) {
+                    if (Math.abs(i) <= Double.MAX_VALUE) {
+                        // if the second argument is a finite even integer, the result is
equal to the result of raising the absolute value of the first argument to the power of the
second argument
+                        if (i % 2.0 == 0.0) Assert.assertEquals(FastMath.pow(-d, i), FastMath.pow(d,
i), EXACT);
+                        // if the second argument is a finite odd integer, the result is
equal to the negative of the result of raising the absolute value of the first argument to
the power of the second argument
+                        else if (Math.abs(i) % 2.0 == 1.0) Assert.assertEquals(-FastMath.pow(-d,
i), FastMath.pow(d, i), EXACT);
+                        // if the second argument is finite and not an integer, then the
result is NaN.
+                        else Assert.assertEquals(Double.NaN, FastMath.pow(d, i), EXACT);
+                    }
+                }
+            }
+        }
+        // If both arguments are integers, then the result is exactly equal to the mathematical
result of raising the first argument to the power
+        // of the second argument if that result can in fact be represented exactly as a
double value.
+        final int TOO_BIG_TO_CALCULATE = 18; // This value is empirical: 2^18 > 200.000
resulting bits after raising d to power i.
+        for (double d : DOUBLES) {
+            if (d % 1.0 == 0.0) {
+                boolean dNegative = Double.doubleToRawLongBits( d ) < 0L;
+                for (double i : DOUBLES) {
+                    if (i % 1.0 == 0.0) {
+                        BigInteger bd = BigDecimal.valueOf(d).toBigInteger().abs();
+                        BigInteger bi = BigDecimal.valueOf(i).toBigInteger().abs();
+                        double expected;
+                        if (bd.bitLength() > 1 && bi.bitLength() > 1 &&
32 - Integer.numberOfLeadingZeros(bd.bitLength()) + bi.bitLength() > TOO_BIG_TO_CALCULATE)
{
+                            // Result would be too big.
+                            expected = i < 0.0 ? 0.0 : Double.POSITIVE_INFINITY;
+                        } else {
+                            BigInteger res = ArithmeticUtils.pow(bd, bi);
+                            if (i >= 0.0) {
+                                expected = res.doubleValue();
+                            } else if (res.signum() == 0) {
+                                expected = Double.POSITIVE_INFINITY;
+                            } else {
+                                expected = BigDecimal.ONE.divide( new BigDecimal( res ),
1024, RoundingMode.HALF_UP ).doubleValue();
+                            }
+                        }
+                        if (dNegative && bi.testBit( 0 )) {
+                            expected = -expected;
+                        }
+                        Assert.assertEquals(d + "^" + i + "=" + expected + ", Math.pow="
+ Math.pow(d, i), expected, FastMath.pow(d, i), expected == 0.0 || Double.isInfinite(expected)
|| Double.isNaN(expected) ? EXACT : 2.0 * Math.ulp(expected));
+                    }
+                }
+            }
+        }
     }
 
     @Test
@@ -1236,6 +1451,170 @@ public class FastMathTest {
     public void testIntPowLongMinValue() {
         Assert.assertEquals(1.0, FastMath.pow(1.0, Long.MIN_VALUE), -1.0);
     }
+    
+    @Test(timeout=5000L)
+    public void testIntPowSpecialCases() {
+        final double EXACT = -1.0;
+        final double DOUBLES[] = new double[]{Double.NEGATIVE_INFINITY, -0.0, Double.NaN,
0.0, Double.POSITIVE_INFINITY,
+                                              Long.MIN_VALUE, Integer.MIN_VALUE, Short.MIN_VALUE,
Byte.MIN_VALUE,
+                                              -(double)Long.MIN_VALUE, -(double)Integer.MIN_VALUE,
-(double)Short.MIN_VALUE, -(double)Byte.MIN_VALUE,
+                                              Byte.MAX_VALUE, Short.MAX_VALUE, Integer.MAX_VALUE,
Long.MAX_VALUE,
+                                              -Byte.MAX_VALUE, -Short.MAX_VALUE, -Integer.MAX_VALUE,
-Long.MAX_VALUE,
+                                              Float.MAX_VALUE, Double.MAX_VALUE, Double.MIN_VALUE,
Float.MIN_VALUE,
+                                              -Float.MAX_VALUE, -Double.MAX_VALUE, -Double.MIN_VALUE,
-Float.MIN_VALUE,
+                                              0.5, 0.1, 0.2, 0.8, 1.1, 1.2, 1.5, 1.8, 1.0,
2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 1.3, 2.2, 2.5, 2.8, 33.0, 33.1, 33.5, 33.8, 10.0,
300.0, 400.0, 500.0,
+                                              -0.5, -0.1, -0.2, -0.8, -1.1, -1.2, -1.5, -1.8,
-1.0, -2.0, -3.0, -4.0, -5.0, -6.0, -7.0, -8.0, -9.0, -1.3, -2.2, -2.5, -2.8, -33.0, -33.1,
-33.5, -33.8, -10.0, -300.0, -400.0, -500.0};
+        final long INTS[] = new long[]{Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MIN_VALUE,
Long.MIN_VALUE + 1, Long.MIN_VALUE + 2, Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MIN_VALUE,
Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2, 0, 1, 2, 3, 5, 8, 10, 20, 100, 300, 500, -1,
-2, -3, -5, -8, -10, -20, -100, -300, -500};
+        // Special cases from Math.pow javadoc:
+        // If the second argument is positive or negative zero, then the result is 1.0.
+        for (double d : DOUBLES) {
+            Assert.assertEquals(1.0, FastMath.pow(d, 0L), EXACT);
+        }
+        // If the second argument is 1.0, then the result is the same as the first argument.
+        for (double d : DOUBLES) {
+            Assert.assertEquals(d, FastMath.pow(d, 1L), EXACT);
+        }
+        // If the second argument is NaN, then the result is NaN. <- Impossible with int.
+        // If the first argument is NaN and the second argument is nonzero, then the result
is NaN.
+        for (long i : INTS) {
+            if (i != 0L) {
+                Assert.assertEquals(Double.NaN, FastMath.pow(Double.NaN, i), EXACT);
+            }
+        }
+        // If the absolute value of the first argument is greater than 1 and the second argument
is positive infinity, or
+        // the absolute value of the first argument is less than 1 and the second argument
is negative infinity, then the result is positive infinity.
+        for (double d : DOUBLES) {
+            if (Math.abs(d) > 1.0) {
+                Assert.assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(d, Long.MAX_VALUE
- 1L), EXACT);
+            }
+        }
+        for (double d : DOUBLES) {
+            if (Math.abs(d) < 1.0) {
+                Assert.assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(d, Long.MIN_VALUE),
EXACT);
+            }
+        }
+        // Note: Long.MAX_VALUE isn't actually an infinity, so its parity affects the sign
of resulting infinity.
+        for (double d : DOUBLES) {
+            if (Math.abs(d) > 1.0) {
+                Assert.assertTrue(Double.isInfinite(FastMath.pow(d, Long.MAX_VALUE)));
+            }
+        }
+        for (double d : DOUBLES) {
+            if (Math.abs(d) < 1.0) {
+                Assert.assertTrue(Double.isInfinite(FastMath.pow(d, Long.MIN_VALUE + 1L)));
+            }
+        }
+        // If the absolute value of the first argument is greater than 1 and the second argument
is negative infinity, or
+        // the absolute value of the first argument is less than 1 and the second argument
is positive infinity, then the result is positive zero.
+        for (double d : DOUBLES) {
+            if (Math.abs(d) > 1.0) {
+                Assert.assertEquals(0.0, FastMath.pow(d, Long.MIN_VALUE), EXACT);
+            }
+        }
+        for (double d : DOUBLES) {
+            if (Math.abs(d) < 1.0) {
+                Assert.assertEquals(0.0, FastMath.pow(d, Long.MAX_VALUE - 1L), EXACT);
+            }
+        }
+        // Note: Long.MAX_VALUE isn't actually an infinity, so its parity affects the sign
of resulting zero.
+        for (double d : DOUBLES) {
+            if (Math.abs(d) > 1.0) {
+                Assert.assertTrue(FastMath.pow(d, Long.MIN_VALUE + 1L) == 0.0);
+            }
+        }
+        for (double d : DOUBLES) {
+            if (Math.abs(d) < 1.0) {
+                Assert.assertTrue(FastMath.pow(d, Long.MAX_VALUE) == 0.0);
+            }
+        }
+        // If the absolute value of the first argument equals 1 and the second argument is
infinite, then the result is NaN. <- Impossible with int.
+        // If the first argument is positive zero and the second argument is greater than
zero, or
+        // the first argument is positive infinity and the second argument is less than zero,
then the result is positive zero.
+        for (long i : INTS) {
+            if (i > 0L) {
+                Assert.assertEquals(0.0, FastMath.pow(0.0, i), EXACT);
+            }
+        }
+        for (long i : INTS) {
+            if (i < 0L) {
+                Assert.assertEquals(0.0, FastMath.pow(Double.POSITIVE_INFINITY, i), EXACT);
+            }
+        }
+        // If the first argument is positive zero and the second argument is less than zero,
or
+        // the first argument is positive infinity and the second argument is greater than
zero, then the result is positive infinity.
+        for (long i : INTS) {
+            if (i < 0L) {
+                Assert.assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(0.0, i), EXACT);
+            }
+        }
+        for (long i : INTS) {
+            if (i > 0L) {
+                Assert.assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(Double.POSITIVE_INFINITY,
i), EXACT);
+            }
+        }
+        // If the first argument is negative zero and the second argument is greater than
zero but not a finite odd integer, or
+        // the first argument is negative infinity and the second argument is less than zero
but not a finite odd integer, then the result is positive zero.
+        for (long i : INTS) {
+            if (i > 0L && (i & 1L) == 0L) {
+                Assert.assertEquals(0.0, FastMath.pow(-0.0, i), EXACT);
+            }
+        }
+        for (long i : INTS) {
+            if (i < 0L && (i & 1L) == 0L) {
+                Assert.assertEquals(0.0, FastMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
+            }
+        }
+        // If the first argument is negative zero and the second argument is a positive finite
odd integer, or
+        // the first argument is negative infinity and the second argument is a negative
finite odd integer, then the result is negative zero.
+        for (long i : INTS) {
+            if (i > 0L && (i & 1L) == 1L) {
+                Assert.assertEquals(-0.0, FastMath.pow(-0.0, i), EXACT);
+            }
+        }
+        for (long i : INTS) {
+            if (i < 0L && (i & 1L) == 1L) {
+                Assert.assertEquals(-0.0, FastMath.pow(Double.NEGATIVE_INFINITY, i), EXACT);
+            }
+        }
+        // If the first argument is negative zero and the second argument is less than zero
but not a finite odd integer, or
+        // the first argument is negative infinity and the second argument is greater than
zero but not a finite odd integer, then the result is positive infinity.
+        for (long i : INTS) {
+            if (i > 0L && (i & 1L) == 0L) {
+                Assert.assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(Double.NEGATIVE_INFINITY,
i), EXACT);
+            }
+        }
+        for (long i : INTS) {
+            if (i < 0L && (i & 1L) == 0L) {
+                Assert.assertEquals(Double.POSITIVE_INFINITY, FastMath.pow(-0.0, i), EXACT);
+            }
+        }
+        // If the first argument is negative zero and the second argument is a negative finite
odd integer, or
+        // the first argument is negative infinity and the second argument is a positive
finite odd integer, then the result is negative infinity.
+        for (long i : INTS) {
+            if (i > 0L && (i & 1L) == 1L) {
+                Assert.assertEquals(Double.NEGATIVE_INFINITY, FastMath.pow(Double.NEGATIVE_INFINITY,
i), EXACT);
+            }
+        }
+        for (long i : INTS) {
+            if (i < 0L && (i & 1L) == 1L) {
+                Assert.assertEquals(Double.NEGATIVE_INFINITY, FastMath.pow(-0.0, i), EXACT);
+            }
+        }
+        for (double d : DOUBLES) {
+            // If the first argument is finite and less than zero
+            if (d < 0.0 && Math.abs(d) <= Double.MAX_VALUE) {
+                for (long i : INTS) {
+                    // if the second argument is a finite even integer, the result is equal
to the result of raising the absolute value of the first argument to the power of the second
argument
+                    if ((i & 1L) == 0L) Assert.assertEquals(FastMath.pow(-d, i), FastMath.pow(d,
i), EXACT);
+                    // if the second argument is a finite odd integer, the result is equal
to the negative of the result of raising the absolute value of the first argument to the power
of the second argument
+                    else Assert.assertEquals(-FastMath.pow(-d, i), FastMath.pow(d, i), EXACT);
+                    // if the second argument is finite and not an integer, then the result
is NaN. <- Impossible with int.
+                }
+            }
+        }
+        // If both arguments are integers, then the result is exactly equal to the mathematical
result of raising the first argument to the power
+        // of the second argument if that result can in fact be represented exactly as a
double value. <- Other tests.
+    }
 
     @Test
     public void testIncrementExactInt() {


Mime
View raw message