You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by re...@apache.org on 2010/02/12 06:55:40 UTC

svn commit: r909251 - in /harmony/enhanced/classlib/trunk/modules/luni/src: main/java/java/lang/Math.java main/native/luni/shared/math.c main/native/luni/unix/exports.txt test/api/common/org/apache/harmony/luni/tests/java/lang/MathTest.java

Author: regisxu
Date: Fri Feb 12 05:55:40 2010
New Revision: 909251

URL: http://svn.apache.org/viewvc?rev=909251&view=rev
Log:
Apply patch for HARMONY-6441: [classlib][luni]Math.pow(double, double) result differ from RI

Modified:
    harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/Math.java
    harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/math.c
    harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/unix/exports.txt
    harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/lang/MathTest.java

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/Math.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/Math.java?rev=909251&r1=909250&r2=909251&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/Math.java (original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/Math.java Fri Feb 12 05:55:40 2010
@@ -708,7 +708,23 @@
      *            the exponent of the operation.
      * @return {@code x} to the power of {@code y}.
      */
-    public static native double pow(double x, double y);
+    public static double pow(double x, double y) {
+        if (x < 0.0 && x != Double.NEGATIVE_INFINITY) {
+            if (y != Double.NEGATIVE_INFINITY && y != Double.POSITIVE_INFINITY) {  // is finit
+                if (y == Math.ceil(y)) {  // is integer
+                    double absx = Math.abs(x);
+                    if (y % 2 == 0.0) {
+                        return doPow(absx, y);
+                    }
+                    return -1.0 * doPow(absx, y);
+                }
+                return Double.NaN;
+            }
+        }
+        return doPow(x, y);
+    }
+
+    private static native double doPow(double x, double y);
 
     /**
      * Returns the double conversion of the result of rounding the argument to

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/math.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/math.c?rev=909251&r1=909250&r2=909251&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/math.c (original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/math.c Fri Feb 12 05:55:40 2010
@@ -542,7 +542,7 @@
 }
 
 JNIEXPORT jdouble JNICALL
-Java_java_lang_Math_pow (JNIEnv * env, jclass jclazz, jdouble arg1,
+Java_java_lang_Math_doPow (JNIEnv * env, jclass jclazz, jdouble arg1,
                          jdouble arg2)
 {
   return internal_pow (arg1, arg2);

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/unix/exports.txt
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/unix/exports.txt?rev=909251&r1=909250&r2=909251&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/unix/exports.txt (original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/unix/exports.txt Fri Feb 12 05:55:40 2010
@@ -73,7 +73,7 @@
 Java_java_lang_Math_log1p
 Java_java_lang_Math_nextafter
 Java_java_lang_Math_nextafterf
-Java_java_lang_Math_pow
+Java_java_lang_Math_doPow
 Java_java_lang_Math_rint
 Java_java_lang_Math_sin
 Java_java_lang_Math_sinh

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/lang/MathTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/lang/MathTest.java?rev=909251&r1=909250&r2=909251&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/lang/MathTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/lang/MathTest.java Fri Feb 12 05:55:40 2010
@@ -553,14 +553,266 @@
 	 */
 	public void test_powDD() {
 		// Test for method double java.lang.Math.pow(double, double)
+        double NZERO = longTodouble(doubleTolong(0.0) ^ 0x8000000000000000L);
+        double p1 = 1.0;
+        double p2 = 2.0;
+        double p3 = 3.0;
+        double p4 = 4.0;
+        double p5 = 5.0;
+        double p6 = 6.0;
+        double p7 = 7.0;
+        double p8 = 8.0;
+        double p9 = 9.0;
+        double p10 = 10.0;
+        double p11 = 11.0;
+        double p12 = 12.0;
+        double p13 = 13.0;
+        double p14 = 14.0;
+        double p15 = 15.0;
+        double p16 = 16.0;
+        double[] values = { p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12,
+                p13, p14, p15, p16 };
+
+        for (int x = 0; x < values.length; x++) {
+            double dval = values[x];
+            double nagateDval = negateDouble(dval);
+            if (nagateDval == Double.NaN) {
+                continue;
+            }
+
+            // If the second argument is positive or negative zero, then the
+            // result is 1.0.
+            assertEquals("Result should be Math.pow(" + dval
+                    + ",-0.0)=+1.0", 1.0, Math.pow(dval, NZERO));
+            assertEquals("Result should be Math.pow(" + nagateDval
+                    + ",-0.0)=+1.0", 1.0, Math.pow(nagateDval, NZERO));
+            assertEquals("Result should be Math.pow(" + dval
+                    + ",+0.0)=+1.0", 1.0, Math.pow(dval, +0.0));
+            assertEquals("Result should be Math.pow(" + nagateDval
+                    + ",+0.0)=+1.0", 1.0, Math.pow(nagateDval, +0.0));
+
+            // If the second argument is 1.0, then the result is the same as the
+            // first argument.
+            assertEquals("Result should be Math.pow(" + dval + "," + 1.0 + ")="
+                    + dval, dval, Math.pow(dval, 1.0));
+            assertEquals("Result should be Math.pow(" + nagateDval + "," + 1.0
+                    + ")=" + nagateDval, nagateDval, Math.pow(nagateDval, 1.0));
+
+            // If the second argument is NaN, then the result is NaN.
+            assertEquals("Result should be Math.pow(" + dval + "," + Double.NaN
+                    + ")=" + Double.NaN,  Double.NaN, Math.pow(dval, Double.NaN));
+            assertEquals("Result should be Math.pow(" + nagateDval + ","
+                    + Double.NaN + ")=" + Double.NaN,  Double.NaN, Math.pow(nagateDval,
+                    Double.NaN));
+
+            if (dval > 1) {
+                // If the first argument is NaN and the second argument is
+                // nonzero,
+                // then the result is NaN.
+                assertEquals("Result should be Math.pow(" + Double.NaN + ","
+                        + dval + ")=" + Double.NaN,  Double.NaN, Math.pow(Double.NaN, dval));
+                assertEquals("Result should be Math.pow(" + Double.NaN + ","
+                        + nagateDval + ")=" + Double.NaN,  Double.NaN, Math.pow(Double.NaN,
+                        nagateDval));
+
+                /*
+                 * 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.
+                 */
+                assertEquals("Result should be Math.pow(" + 0.0 + "," + dval
+                        + ")=" + 0.0, +0.0, Math.pow(0.0, dval));
+                assertEquals("Result should be Math.pow("
+                        + Double.POSITIVE_INFINITY + "," + nagateDval + ")="
+                        + 0.0, +0.0, Math.pow(Double.POSITIVE_INFINITY, nagateDval));
+
+                /*
+                 * 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.
+                 */
+                assertEquals("Result should be Math.pow(" + 0.0 + ","
+                        + nagateDval + ")=" + Double.POSITIVE_INFINITY,Double.POSITIVE_INFINITY,
+                        Math.pow(0.0, nagateDval));
+                assertEquals("Result should be Math.pow("
+                        + Double.POSITIVE_INFINITY + "," + dval + ")="
+                        + Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Math.pow(
+                        Double.POSITIVE_INFINITY, dval));
+
+                // Not a finite odd integer
+                if (dval % 2 == 0) {
+                    /*
+                     * 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.
+                     */
+                    assertEquals("Result should be Math.pow(" + NZERO + ","
+                            + dval + ")=" + 0.0, +0.0, Math.pow(NZERO, dval));
+                    assertEquals("Result should be Math.pow("
+                            + Double.NEGATIVE_INFINITY + "," + nagateDval
+                            + ")=" + 0.0, +0.0, Math.pow(Double.NEGATIVE_INFINITY,
+                            nagateDval));
+
+                    /*
+                     * 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.
+                     */
+                    assertEquals("Result should be Math.pow(" + NZERO + ","
+                            + nagateDval + ")=" + Double.POSITIVE_INFINITY,Double.POSITIVE_INFINITY,
+                            Math.pow(NZERO, nagateDval));
+                    assertEquals("Result should be Math.pow("
+                            + Double.NEGATIVE_INFINITY + "," + dval + ")="
+                            + Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Math.pow(
+                            Double.NEGATIVE_INFINITY, dval));
+                }
+
+                // finite odd integer
+                if (dval % 2 != 0) {
+                    /*
+                     * 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.
+                     */
+                    assertEquals("Result should be Math.pow(" + NZERO + ","
+                            + dval + ")=" + NZERO, NZERO, Math.pow(NZERO, dval));
+                    assertEquals("Result should be Math.pow("
+                            + Double.NEGATIVE_INFINITY + "," + nagateDval
+                            + ")=" + NZERO, NZERO, Math.pow(Double.NEGATIVE_INFINITY,
+                            nagateDval));
+                    /*
+                     * 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.
+                     */
+                    assertEquals("Result should be Math.pow(" + NZERO + ","
+                            + nagateDval + ")=" + Double.NEGATIVE_INFINITY,Double.NEGATIVE_INFINITY,
+                            Math.pow(NZERO, nagateDval));
+                    assertEquals("Result should be Math.pow("
+                            + Double.NEGATIVE_INFINITY + "," + dval + ")="
+                            + Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Math.pow(
+                            Double.NEGATIVE_INFINITY, dval));
+                }
+
+                /**
+                 * 1. If the first argument is finite and less than zero 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 
+                 * 
+                 * 2. 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 
+                 * 
+                 * 3. if the second argument is finite and not an integer, then the result
+                 * is NaN.
+                 */
+                for (int j = 1; j < values.length; j++) {
+                    double jval = values[j];
+                    if (jval % 2.0 == 0.0) {
+                        assertEquals("" + nagateDval + " " + jval, Math.pow(
+                                dval, jval), Math.pow(nagateDval, jval));
+                    } else {
+                        assertEquals("" + nagateDval + " " + jval, -1.0
+                                * Math.pow(dval, jval), Math.pow(nagateDval,
+                                jval));
+                    }
+                    assertEquals(Double.NaN, Math
+                            .pow(nagateDval, jval / 0.5467));
+                    assertEquals(Double.NaN, Math.pow(nagateDval, -1.0 * jval
+                            / 0.5467));
+                }
+            }
+
+            // If the absolute value of the first argument equals 1 and the
+            // second argument is infinite, then the result is NaN.
+            if (dval == 1) {
+                assertEquals("Result should be Math.pow(" + dval + ","
+                        + Double.POSITIVE_INFINITY + ")=" + Double.NaN, Double.NaN, Math
+                        .pow(dval, Double.POSITIVE_INFINITY));
+                assertEquals("Result should be Math.pow(" + dval + ","
+                        + Double.NEGATIVE_INFINITY + ")=" + Double.NaN, Double.NaN, Math
+                        .pow(dval, Double.NEGATIVE_INFINITY));
+
+                assertEquals("Result should be Math.pow(" + nagateDval + ","
+                        + Double.POSITIVE_INFINITY + ")=" + Double.NaN, Double.NaN, Math
+                        .pow(nagateDval, Double.POSITIVE_INFINITY));
+                assertEquals("Result should be Math.pow(" + nagateDval + ","
+                        + Double.NEGATIVE_INFINITY + ")=" + Double.NaN, Double.NaN, Math
+                        .pow(nagateDval, Double.NEGATIVE_INFINITY));
+            }
+
+            if (dval > 1) {
+                /*
+                 * 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.
+                 */
+                assertEquals("Result should be Math.pow(" + dval + ","
+                        + Double.POSITIVE_INFINITY + ")="
+                        + Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Math.pow(dval,
+                        Double.POSITIVE_INFINITY));
+
+                assertEquals("Result should be Math.pow(" + nagateDval + ","
+                        + Double.NEGATIVE_INFINITY + ")="
+                        + Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Math.pow(-0.13456,
+                        Double.NEGATIVE_INFINITY));
+
+                /*
+                 * 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.
+                 */
+                assertEquals("Result should be Math.pow(" + dval + ","
+                        + Double.NEGATIVE_INFINITY + ")= +0.0", +0.0, Math.pow(dval,
+                        Double.NEGATIVE_INFINITY));
+                assertEquals("Result should be Math.pow(" + nagateDval + ","
+                        + Double.POSITIVE_INFINITY + ")= +0.0", +0.0, Math.pow(
+                        -0.13456, Double.POSITIVE_INFINITY));
+            }
+
+            assertEquals("Result should be Math.pow(" + 0.0 + "," + dval + ")="
+                    + 0.0, 0.0, Math.pow(0.0, dval));
+            assertEquals("Result should be Math.pow(" + Double.NaN + "," + dval
+                    + ")=" + Double.NaN, Double.NaN, Math.pow(Double.NaN, dval));
+        }
 		assertTrue("pow returned incorrect value",
 				(long) Math.pow(2, 8) == 256l);
 		assertTrue("pow returned incorrect value",
 				Math.pow(2, -8) == 0.00390625d);
 		assertEquals("Incorrect root returned1",
                              2, Math.sqrt(Math.pow(Math.sqrt(2), 4)), 0);
+
+		assertEquals(Double.NEGATIVE_INFINITY, Math.pow(-10.0, 3.093403029238847E15));
+		assertEquals(Double.POSITIVE_INFINITY, Math.pow(10.0, 3.093403029238847E15));
 	}
 
+    private double longTodouble(long longvalue) {
+        return Double.longBitsToDouble(longvalue);
+    }
+
+    private long doubleTolong(double doublevalue) {
+        return Double.doubleToLongBits(doublevalue);
+    }
+
+    private double negateDouble(double doublevalue) {
+        return doublevalue * -1.0;
+    }
+
 	/**
 	 * @tests java.lang.Math#rint(double)
 	 */