8136799: Port fdlibm cbrt to Java

Reviewed-by: bpb
This commit is contained in:
Joe Darcy 2015-10-14 16:17:08 -07:00
parent c38b0eaba5
commit 655a976e65
12 changed files with 185 additions and 120 deletions

View File

@ -152,7 +152,6 @@ SUNWprivate_1.1 {
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;

View File

@ -99,6 +99,64 @@ class FdLibm {
return Double.longBitsToDouble((transX & 0x0000_0000_FFFF_FFFFL)|( ((long)high)) << 32 );
}
/**
* 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)
*

View File

@ -307,7 +307,9 @@ public final class StrictMath {
* @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

View File

@ -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);
}

View File

@ -88,12 +88,6 @@ Java_java_lang_StrictMath_sqrt(JNIEnv *env, jclass unused, jdouble d)
return (jdouble) jsqrt((double)d);
}
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)
{

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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 @@ public class CubeRootTests {
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);
if (failures > 0) {
System.err.println("Testing the cube root incurred "
+ failures + " failures.");
throw new RuntimeException();
// ... and just below subnormal threshold ...
x = Math.nextDown(Double.MIN_NORMAL);
failures += testRange(x, -Math.ulp(x), 1000);
// ... 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;
}
}

View File

@ -72,6 +72,67 @@ public class FdlibmTranslit {
return Hypot.compute(x, y);
}
/**
* 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)
*

View File

@ -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