8136799: Port fdlibm cbrt to Java
authordarcy
Wed, 14 Oct 2015 16:17:08 -0700
changeset 32992 19ed8781c2ba
parent 32991 b27c76b82713
child 32993 fa6bbf6ed92b
8136799: Port fdlibm cbrt to Java Reviewed-by: bpb
jdk/make/mapfiles/libjava/mapfile-vers
jdk/src/java.base/share/classes/java/lang/FdLibm.java
jdk/src/java.base/share/classes/java/lang/StrictMath.java
jdk/src/java.base/share/native/libfdlibm/s_cbrt.c
jdk/src/java.base/share/native/libjava/StrictMath.c
jdk/test/java/lang/Math/CubeRootTests.java
jdk/test/java/lang/Math/HypotTests.java
jdk/test/java/lang/Math/IeeeRecommendedTests.java
jdk/test/java/lang/Math/Log1pTests.java
jdk/test/java/lang/StrictMath/CubeRootTests.java
jdk/test/java/lang/StrictMath/FdlibmTranslit.java
jdk/test/java/lang/StrictMath/HypotTests.java
--- a/jdk/make/mapfiles/libjava/mapfile-vers	Tue Oct 13 16:45:35 2015 -0700
+++ b/jdk/make/mapfiles/libjava/mapfile-vers	Wed Oct 14 16:17:08 2015 -0700
@@ -152,7 +152,6 @@
 		Java_java_lang_StrictMath_log10;
 		Java_java_lang_StrictMath_sin;
 		Java_java_lang_StrictMath_sqrt;
-		Java_java_lang_StrictMath_cbrt;
 		Java_java_lang_StrictMath_tan;
 		Java_java_lang_StrictMath_cosh;
 		Java_java_lang_StrictMath_sinh;
--- a/jdk/src/java.base/share/classes/java/lang/FdLibm.java	Tue Oct 13 16:45:35 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/FdLibm.java	Wed Oct 14 16:17:08 2015 -0700
@@ -100,6 +100,64 @@
     }
 
     /**
+     * cbrt(x)
+     * Return cube root of x
+     */
+    public static class Cbrt {
+        // unsigned
+        private static final int B1 = 715094163; /* B1 = (682-0.03306235651)*2**20 */
+        private static final int B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */
+
+        private static final double C =  0x1.15f15f15f15f1p-1; //   19/35   ~= 5.42857142857142815906e-01
+        private static final double D = -0x1.691de2532c834p-1; // -864/1225 ~= 7.05306122448979611050e-01
+        private static final double E =  0x1.6a0ea0ea0ea0fp0;  //   99/70   ~= 1.41428571428571436819e+00
+        private static final double F =  0x1.9b6db6db6db6ep0;  //   45/28   ~= 1.60714285714285720630e+00
+        private static final double G =  0x1.6db6db6db6db7p-2; //    5/14   ~= 3.57142857142857150787e-01
+
+        public static strictfp double compute(double x) {
+            double  t = 0.0;
+            double sign;
+
+            if (x == 0.0 || !Double.isFinite(x))
+                return x; // Handles signed zeros properly
+
+            sign = (x < 0.0) ? -1.0:  1.0;
+
+            x = Math.abs(x);   // x <- |x|
+
+            // Rough cbrt to 5 bits
+            if (x < 0x1.0p-1022) {     // subnormal number
+                t = 0x1.0p54;          // set t= 2**54
+                t *= x;
+                t = __HI(t, __HI(t)/3 + B2);
+            } else {
+                int hx = __HI(x);           // high word of x
+                t = __HI(t, hx/3 + B1);
+            }
+
+            // New cbrt to 23 bits, may be implemented in single precision
+            double  r, s, w;
+            r = t * t/x;
+            s = C + r*t;
+            t *= G + F/(s + E + D/s);
+
+            // Chopped to 20 bits and make it larger than cbrt(x)
+            t = __LO(t, 0);
+            t = __HI(t, __HI(t) + 0x00000001);
+
+            // One step newton iteration to 53 bits with error less than 0.667 ulps
+            s = t * t;          // t*t is exact
+            r = x / s;
+            w = t + t;
+            r = (r - t)/(w + r);  // r-s is exact
+            t = t + t*r;
+
+            // Restore the original sign bit
+            return sign * t;
+        }
+    }
+
+    /**
      * hypot(x,y)
      *
      * Method :
--- a/jdk/src/java.base/share/classes/java/lang/StrictMath.java	Tue Oct 13 16:45:35 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/StrictMath.java	Wed Oct 14 16:17:08 2015 -0700
@@ -307,7 +307,9 @@
      * @return  the cube root of {@code a}.
      * @since 1.5
      */
-    public static native double cbrt(double a);
+    public static double cbrt(double a) {
+        return FdLibm.Cbrt.compute(a);
+    }
 
     /**
      * Computes the remainder operation on two arguments as prescribed
--- a/jdk/src/java.base/share/native/libfdlibm/s_cbrt.c	Tue Oct 13 16:45:35 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-
-/*
- * Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "fdlibm.h"
-
-/* cbrt(x)
- * Return cube root of x
- */
-#ifdef __STDC__
-static const unsigned
-#else
-static unsigned
-#endif
-        B1 = 715094163, /* B1 = (682-0.03306235651)*2**20 */
-        B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */
-
-#ifdef __STDC__
-static const double
-#else
-static double
-#endif
-C =  5.42857142857142815906e-01, /* 19/35     = 0x3FE15F15, 0xF15F15F1 */
-D = -7.05306122448979611050e-01, /* -864/1225 = 0xBFE691DE, 0x2532C834 */
-E =  1.41428571428571436819e+00, /* 99/70     = 0x3FF6A0EA, 0x0EA0EA0F */
-F =  1.60714285714285720630e+00, /* 45/28     = 0x3FF9B6DB, 0x6DB6DB6E */
-G =  3.57142857142857150787e-01; /* 5/14      = 0x3FD6DB6D, 0xB6DB6DB7 */
-
-#ifdef __STDC__
-        double cbrt(double x)
-#else
-        double cbrt(x)
-        double x;
-#endif
-{
-        int     hx;
-        double r,s,t=0.0,w;
-        unsigned sign;
-
-
-        hx = __HI(x);           /* high word of x */
-        sign=hx&0x80000000;             /* sign= sign(x) */
-        hx  ^=sign;
-        if(hx>=0x7ff00000) return(x+x); /* cbrt(NaN,INF) is itself */
-        if((hx|__LO(x))==0)
-            return(x);          /* cbrt(0) is itself */
-
-        __HI(x) = hx;   /* x <- |x| */
-    /* rough cbrt to 5 bits */
-        if(hx<0x00100000)               /* subnormal number */
-          {__HI(t)=0x43500000;          /* set t= 2**54 */
-           t*=x; __HI(t)=__HI(t)/3+B2;
-          }
-        else
-          __HI(t)=hx/3+B1;
-
-
-    /* new cbrt to 23 bits, may be implemented in single precision */
-        r=t*t/x;
-        s=C+r*t;
-        t*=G+F/(s+E+D/s);
-
-    /* chopped to 20 bits and make it larger than cbrt(x) */
-        __LO(t)=0; __HI(t)+=0x00000001;
-
-
-    /* one step newton iteration to 53 bits with error less than 0.667 ulps */
-        s=t*t;          /* t*t is exact */
-        r=x/s;
-        w=t+t;
-        r=(r-t)/(w+r);  /* r-s is exact */
-        t=t+t*r;
-
-    /* retore the sign bit */
-        __HI(t) |= sign;
-        return(t);
-}
--- a/jdk/src/java.base/share/native/libjava/StrictMath.c	Tue Oct 13 16:45:35 2015 -0700
+++ b/jdk/src/java.base/share/native/libjava/StrictMath.c	Wed Oct 14 16:17:08 2015 -0700
@@ -89,12 +89,6 @@
 }
 
 JNIEXPORT jdouble JNICALL
-Java_java_lang_StrictMath_cbrt(JNIEnv *env, jclass unused, jdouble d)
-{
-    return (jdouble) jcbrt((double)d);
-}
-
-JNIEXPORT jdouble JNICALL
 Java_java_lang_StrictMath_atan2(JNIEnv *env, jclass unused, jdouble d1, jdouble d2)
 {
     return (jdouble) jatan2((double)d1, (double)d2);
--- a/jdk/test/java/lang/Math/CubeRootTests.java	Tue Oct 13 16:45:35 2015 -0700
+++ b/jdk/test/java/lang/Math/CubeRootTests.java	Wed Oct 14 16:17:08 2015 -0700
@@ -24,7 +24,7 @@
 /*
  * @test
  * @library /lib/testlibrary/
- * @build jdk.testlibrary.*
+ * @build jdk.testlibrary.RandomFactory
  * @run main CubeRootTests
  * @bug 4347132 4939441 8078672
  * @summary Tests for {Math, StrictMath}.cbrt (use -Dseed=X to set PRNG seed)
--- a/jdk/test/java/lang/Math/HypotTests.java	Tue Oct 13 16:45:35 2015 -0700
+++ b/jdk/test/java/lang/Math/HypotTests.java	Wed Oct 14 16:17:08 2015 -0700
@@ -24,7 +24,7 @@
 /*
  * @test
  * @library /lib/testlibrary/
- * @build jdk.testlibrary.*
+ * @build jdk.testlibrary.RandomFactory
  * @run main HypotTests
  * @bug 4851638 4939441 8078672
  * @summary Tests for {Math, StrictMath}.hypot (use -Dseed=X to set PRNG seed)
--- a/jdk/test/java/lang/Math/IeeeRecommendedTests.java	Tue Oct 13 16:45:35 2015 -0700
+++ b/jdk/test/java/lang/Math/IeeeRecommendedTests.java	Wed Oct 14 16:17:08 2015 -0700
@@ -24,7 +24,7 @@
 /*
  * @test
  * @library /lib/testlibrary/
- * @build jdk.testlibrary.*
+ * @build jdk.testlibrary.RandomFactory
  * @run main IeeeRecommendedTests
  * @bug 4860891 4826732 4780454 4939441 4826652 8078672
  * @summary Tests for IEEE 754[R] recommended functions and similar methods (use -Dseed=X to set PRNG seed)
--- a/jdk/test/java/lang/Math/Log1pTests.java	Tue Oct 13 16:45:35 2015 -0700
+++ b/jdk/test/java/lang/Math/Log1pTests.java	Wed Oct 14 16:17:08 2015 -0700
@@ -24,7 +24,7 @@
 /*
  * @test
  * @library /lib/testlibrary/
- * @build jdk.testlibrary.*
+ * @build jdk.testlibrary.RandomFactory
  * @run main Log1pTests
  * @bug 4851638 4939441 8078672
  * @summary Tests for {Math, StrictMath}.log1p (use -Dseed=X to set PRNG seed)
--- a/jdk/test/java/lang/StrictMath/CubeRootTests.java	Tue Oct 13 16:45:35 2015 -0700
+++ b/jdk/test/java/lang/StrictMath/CubeRootTests.java	Wed Oct 14 16:17:08 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,11 +23,20 @@
 
 /*
  * @test
- * @bug 4347132
+ * @bug 4347132 8136799
+ * @key randomness
+ * @library /lib/testlibrary/
+ * @build jdk.testlibrary.RandomFactory
+ * @build Tests
+ * @build FdlibmTranslit
+ * @build CubeRootTests
+ * @run main CubeRootTests
  * @summary Tests specifically for StrictMath.cbrt
  * @author Joseph D. Darcy
  */
 
+import jdk.testlibrary.RandomFactory;
+
 /**
  * The tests in ../Math/CubeRootTests.java test properties that should
  * hold for any cube root implementation, including the FDLIBM-based
@@ -42,6 +51,19 @@
 public class CubeRootTests {
     private CubeRootTests(){}
 
+    public static void main(String [] argv) {
+        int failures = 0;
+
+        failures += testCubeRoot();
+        failures += testAgainstTranslit();
+
+        if (failures > 0) {
+            System.err.println("Testing the cube root incurred "
+                               + failures + " failures.");
+            throw new RuntimeException();
+        }
+    }
+
     static int testCubeRootCase(double input, double expected) {
         int failures=0;
 
@@ -458,16 +480,44 @@
         return failures;
     }
 
+    // Initialize shared random number generator
+    private static java.util.Random random = RandomFactory.getRandom();
 
-    public static void main(String [] argv) {
+    /**
+     * Test StrictMath.cbrt against transliteration port of cbrt.
+     */
+    private static int testAgainstTranslit() {
         int failures = 0;
+        double x;
 
-        failures += testCubeRoot();
+        // Test just above subnormal threshold...
+        x = Double.MIN_NORMAL;
+        failures += testRange(x, Math.ulp(x), 1000);
+
+        // ... and just below subnormal threshold ...
+        x =  Math.nextDown(Double.MIN_NORMAL);
+        failures += testRange(x, -Math.ulp(x), 1000);
 
-        if (failures > 0) {
-            System.err.println("Testing the cube root incurred "
-                               + failures + " failures.");
-            throw new RuntimeException();
+        // ... and near zero.
+        failures += testRange(0.0, Double.MIN_VALUE, 1000);
+
+        x = Tests.createRandomDouble(random);
+
+        // Make the increment twice the ulp value in case the random
+        // value is near an exponent threshold. Don't worry about test
+        // elements overflowing to infinity if the starting value is
+        // near Double.MAX_VALUE.
+        failures += testRange(x, 2.0 * Math.ulp(x), 1000);
+
+        return failures;
+    }
+
+    private static int testRange(double start, double increment, int count) {
+        int failures = 0;
+        double x = start;
+        for (int i = 0; i < count; i++, x += increment) {
+            failures += testCubeRootCase(x, FdlibmTranslit.Cbrt.compute(x));
         }
+        return failures;
     }
 }
--- a/jdk/test/java/lang/StrictMath/FdlibmTranslit.java	Tue Oct 13 16:45:35 2015 -0700
+++ b/jdk/test/java/lang/StrictMath/FdlibmTranslit.java	Wed Oct 14 16:17:08 2015 -0700
@@ -73,6 +73,67 @@
     }
 
     /**
+     * cbrt(x)
+     * Return cube root of x
+     */
+    public static class Cbrt {
+        // unsigned
+        private static final int B1 = 715094163; /* B1 = (682-0.03306235651)*2**20 */
+        private static final int B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */
+
+        private static final double C =  5.42857142857142815906e-01; /* 19/35     = 0x3FE15F15, 0xF15F15F1 */
+        private static final double D = -7.05306122448979611050e-01; /* -864/1225 = 0xBFE691DE, 0x2532C834 */
+        private static final double E =  1.41428571428571436819e+00; /* 99/70     = 0x3FF6A0EA, 0x0EA0EA0F */
+        private static final double F =  1.60714285714285720630e+00; /* 45/28     = 0x3FF9B6DB, 0x6DB6DB6E */
+        private static final double G =  3.57142857142857150787e-01; /* 5/14      = 0x3FD6DB6D, 0xB6DB6DB7 */
+
+        public static strictfp double compute(double x) {
+            int     hx;
+            double  r, s, t=0.0, w;
+            int sign; // unsigned
+
+            hx = __HI(x);           // high word of x
+            sign = hx & 0x80000000;             // sign= sign(x)
+            hx  ^= sign;
+            if (hx >= 0x7ff00000)
+                return (x+x); // cbrt(NaN,INF) is itself
+            if ((hx | __LO(x)) == 0)
+                return(x);          // cbrt(0) is itself
+
+            x = __HI(x, hx);   // x <- |x|
+            // rough cbrt to 5 bits
+            if (hx < 0x00100000) {               // subnormal number
+                t = __HI(t, 0x43500000);          // set t= 2**54
+                t *= x;
+                t = __HI(t, __HI(t)/3+B2);
+            } else {
+                t = __HI(t, hx/3+B1);
+            }
+
+            // new cbrt to 23 bits, may be implemented in single precision
+            r = t * t/x;
+            s = C + r*t;
+            t *= G + F/(s + E + D/s);
+
+            // chopped to 20 bits and make it larger than cbrt(x)
+            t = __LO(t, 0);
+            t = __HI(t, __HI(t)+0x00000001);
+
+
+            // one step newton iteration to 53 bits with error less than 0.667 ulps
+            s = t * t;          // t*t is exact
+            r = x / s;
+            w = t + t;
+            r= (r - t)/(w + r);  // r-s is exact
+            t= t + t*r;
+
+            // retore the sign bit
+            t = __HI(t, __HI(t) | sign);
+            return(t);
+        }
+    }
+
+    /**
      * hypot(x,y)
      *
      * Method :
--- a/jdk/test/java/lang/StrictMath/HypotTests.java	Tue Oct 13 16:45:35 2015 -0700
+++ b/jdk/test/java/lang/StrictMath/HypotTests.java	Wed Oct 14 16:17:08 2015 -0700
@@ -27,7 +27,7 @@
  * @key randomness
  * @summary Tests for StrictMath.hypot
  * @library /lib/testlibrary/
- * @build jdk.testlibrary.*
+ * @build jdk.testlibrary.RandomFactory
  * @build Tests
  * @build FdlibmTranslit
  * @build HypotTests