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)
*/