# HG changeset patch # User darcy # Date 1444864628 25200 # Node ID 19ed8781c2badc54c58a408c593f2ade2b332090 # Parent b27c76b8271309c98e98d6fdd630b2a7a1ac9aee 8136799: Port fdlibm cbrt to Java Reviewed-by: bpb diff -r b27c76b82713 -r 19ed8781c2ba jdk/make/mapfiles/libjava/mapfile-vers --- 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; diff -r b27c76b82713 -r 19ed8781c2ba jdk/src/java.base/share/classes/java/lang/FdLibm.java --- 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 : diff -r b27c76b82713 -r 19ed8781c2ba jdk/src/java.base/share/classes/java/lang/StrictMath.java --- 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 diff -r b27c76b82713 -r 19ed8781c2ba jdk/src/java.base/share/native/libfdlibm/s_cbrt.c --- 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); -} diff -r b27c76b82713 -r 19ed8781c2ba jdk/src/java.base/share/native/libjava/StrictMath.c --- 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); diff -r b27c76b82713 -r 19ed8781c2ba jdk/test/java/lang/Math/CubeRootTests.java --- 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) diff -r b27c76b82713 -r 19ed8781c2ba jdk/test/java/lang/Math/HypotTests.java --- 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) diff -r b27c76b82713 -r 19ed8781c2ba jdk/test/java/lang/Math/IeeeRecommendedTests.java --- 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) diff -r b27c76b82713 -r 19ed8781c2ba jdk/test/java/lang/Math/Log1pTests.java --- 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) diff -r b27c76b82713 -r 19ed8781c2ba jdk/test/java/lang/StrictMath/CubeRootTests.java --- 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; } } diff -r b27c76b82713 -r 19ed8781c2ba jdk/test/java/lang/StrictMath/FdlibmTranslit.java --- 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 : diff -r b27c76b82713 -r 19ed8781c2ba jdk/test/java/lang/StrictMath/HypotTests.java --- 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