提交 4cbdf1b8 编写于 作者: D darcy

6908131: Pure Java implementations of StrictMath.floor(double) & StrictMath.ceil(double)

Reviewed-by: alanb
上级 acea5f52
......@@ -150,10 +150,8 @@ SUNWprivate_1.1 {
Java_java_lang_StrictMath_asin;
Java_java_lang_StrictMath_atan;
Java_java_lang_StrictMath_atan2;
Java_java_lang_StrictMath_ceil;
Java_java_lang_StrictMath_cos;
Java_java_lang_StrictMath_exp;
Java_java_lang_StrictMath_floor;
Java_java_lang_StrictMath_log;
Java_java_lang_StrictMath_log10;
Java_java_lang_StrictMath_pow;
......
......@@ -107,4 +107,3 @@ text: .text%Java_java_lang_Class_isInstance;
text: .text%Java_java_util_TimeZone_getSystemTimeZoneID;
text: .text%findJavaTZ_md;
text: .text%Java_java_lang_StrictMath_log;
text: .text%Java_java_lang_StrictMath_floor;
......@@ -105,4 +105,3 @@ text: .text%Java_java_util_TimeZone_getSystemTimeZoneID;
text: .text%findJavaTZ_md;
text: .text%Java_java_lang_StrictMath_log;
text: .text%Java_java_lang_StrictMath_sqrt;
text: .text%Java_java_lang_StrictMath_floor;
......@@ -101,4 +101,3 @@ text: .text%Java_java_util_TimeZone_getSystemTimeZoneID;
text: .text%findJavaTZ_md;
text: .text%Java_java_lang_StrictMath_log;
text: .text%Java_java_lang_StrictMath_sqrt;
text: .text%Java_java_lang_StrictMath_floor;
......@@ -26,6 +26,7 @@
package java.lang;
import java.util.Random;
import sun.misc.FpUtils;
import sun.misc.DoubleConsts;
/**
* The class {@code StrictMath} contains methods for performing basic
......@@ -316,7 +317,9 @@ public final class StrictMath {
* floating-point value that is greater than or equal to
* the argument and is equal to a mathematical integer.
*/
public static native double ceil(double a);
public static double ceil(double a) {
return floorOrCeil(a, -0.0, 1.0, 1.0);
}
/**
* Returns the largest (closest to positive infinity)
......@@ -333,7 +336,54 @@ public final class StrictMath {
* floating-point value that less than or equal to the argument
* and is equal to a mathematical integer.
*/
public static native double floor(double a);
public static double floor(double a) {
return floorOrCeil(a, -1.0, 0.0, -1.0);
}
/**
* Internal method to share logic between floor and ceil.
*
* @param a the value to be floored or ceiled
* @param negativeBoundary result for values in (-1, 0)
* @param positiveBoundary result for values in (0, 1)
* @param increment value to add when the argument is non-integral
*/
private static double floorOrCeil(double a,
double negativeBoundary,
double positiveBoundary,
double sign) {
int exponent = Math.getExponent(a);
if (exponent < 0) {
/*
* Absolute value of argument is less than 1.
* floorOrceil(-0.0) => -0.0
* floorOrceil(+0.0) => +0.0
*/
return ((a == 0.0) ? a :
( (a < 0.0) ? negativeBoundary : positiveBoundary) );
} else if (exponent >= 52) {
/*
* Infinity, NaN, or a value so large it must be integral.
*/
return a;
}
// Else the argument is either an integral value already XOR it
// has to be rounded to one.
assert exponent >= 0 && exponent <= 51;
long doppel = Double.doubleToRawLongBits(a);
long mask = DoubleConsts.SIGNIF_BIT_MASK >> exponent;
if ( (mask & doppel) == 0L )
return a; // integral value
else {
double result = Double.longBitsToDouble(doppel & (~mask));
if (sign*a > 0.0)
result = result + sign;
return result;
}
}
/**
* Returns the {@code double} value that is closest in value
......
......@@ -94,18 +94,6 @@ Java_java_lang_StrictMath_cbrt(JNIEnv *env, jclass unused, jdouble d)
return (jdouble) jcbrt((double)d);
}
JNIEXPORT jdouble JNICALL
Java_java_lang_StrictMath_ceil(JNIEnv *env, jclass unused, jdouble d)
{
return (jdouble) jceil((double)d);
}
JNIEXPORT jdouble JNICALL
Java_java_lang_StrictMath_floor(JNIEnv *env, jclass unused, jdouble d)
{
return (jdouble) jfloor((double)d);
}
JNIEXPORT jdouble JNICALL
Java_java_lang_StrictMath_atan2(JNIEnv *env, jclass unused, jdouble d1, jdouble d2)
{
......
/*
* Copyright 2009 Sun Microsystems, Inc. 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.
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6908131
* @summary Check for correct implementation of Math.ceil and Math.floor
*/
import sun.misc.FpUtils;
import sun.misc.DoubleConsts;
public class CeilAndFloorTests {
private static int testCeilCase(double input, double expected) {
int failures = 0;
failures += Tests.test("Math.ceil", input, Math.ceil(input), expected);
failures += Tests.test("StrictMath.ceil", input, StrictMath.ceil(input), expected);
return failures;
}
private static int testFloorCase(double input, double expected) {
int failures = 0;
failures += Tests.test("Math.floor", input, Math.floor(input), expected);
failures += Tests.test("StrictMath.floor", input, StrictMath.floor(input), expected);
return failures;
}
private static int nearIntegerTests() {
int failures = 0;
double [] fixedPoints = {
-0.0,
0.0,
-1.0,
1.0,
-0x1.0p52,
0x1.0p52,
-Double.MAX_VALUE,
Double.MAX_VALUE,
Double.NEGATIVE_INFINITY,
Double.POSITIVE_INFINITY,
Double.NaN,
};
for(double fixedPoint : fixedPoints) {
failures += testCeilCase(fixedPoint, fixedPoint);
failures += testFloorCase(fixedPoint, fixedPoint);
}
for(int i = Double.MIN_EXPONENT; i <= Double.MAX_EXPONENT; i++) {
double powerOfTwo = Math.scalb(1.0, i);
double neighborDown = FpUtils.nextDown(powerOfTwo);
double neighborUp = Math.nextUp(powerOfTwo);
if (i < 0) {
failures += testCeilCase( powerOfTwo, 1.0);
failures += testCeilCase(-powerOfTwo, -0.0);
failures += testFloorCase( powerOfTwo, 0.0);
failures += testFloorCase(-powerOfTwo, -1.0);
failures += testCeilCase( neighborDown, 1.0);
failures += testCeilCase(-neighborDown, -0.0);
failures += testFloorCase( neighborUp, 0.0);
failures += testFloorCase(-neighborUp, -1.0);
} else {
failures += testCeilCase(powerOfTwo, powerOfTwo);
failures += testFloorCase(powerOfTwo, powerOfTwo);
if (neighborDown==Math.rint(neighborDown)) {
failures += testCeilCase( neighborDown, neighborDown);
failures += testCeilCase(-neighborDown, -neighborDown);
failures += testFloorCase( neighborDown, neighborDown);
failures += testFloorCase(-neighborDown,-neighborDown);
} else {
failures += testCeilCase( neighborDown, powerOfTwo);
failures += testFloorCase(-neighborDown, -powerOfTwo);
}
if (neighborUp==Math.rint(neighborUp)) {
failures += testCeilCase(neighborUp, neighborUp);
failures += testCeilCase(-neighborUp, -neighborUp);
failures += testFloorCase(neighborUp, neighborUp);
failures += testFloorCase(-neighborUp, -neighborUp);
} else {
failures += testFloorCase(neighborUp, powerOfTwo);
failures += testCeilCase(-neighborUp, -powerOfTwo);
}
}
}
for(int i = -(0x10000); i <= 0x10000; i++) {
double d = (double) i;
double neighborDown = FpUtils.nextDown(d);
double neighborUp = Math.nextUp(d);
failures += testCeilCase( d, d);
failures += testCeilCase(-d, -d);
failures += testFloorCase( d, d);
failures += testFloorCase(-d, -d);
if (Math.abs(d) > 1.0) {
failures += testCeilCase( neighborDown, d);
failures += testCeilCase(-neighborDown, -d+1);
failures += testFloorCase( neighborUp, d);
failures += testFloorCase(-neighborUp, -d-1);
}
}
return failures;
}
public static int roundingTests() {
int failures = 0;
double [][] testCases = {
{ Double.MIN_VALUE, 1.0},
{-Double.MIN_VALUE, -0.0},
{ FpUtils.nextDown(DoubleConsts.MIN_NORMAL), 1.0},
{-FpUtils.nextDown(DoubleConsts.MIN_NORMAL), -0.0},
{ DoubleConsts.MIN_NORMAL, 1.0},
{-DoubleConsts.MIN_NORMAL, -0.0},
{ 0.1, 1.0},
{-0.1, -0.0},
{ 0.5, 1.0},
{-0.5, -0.0},
{ 1.5, 2.0},
{-1.5, -1.0},
{ 2.5, 3.0},
{-2.5, -2.0},
{ FpUtils.nextDown(1.0), 1.0},
{ FpUtils.nextDown(-1.0), -1.0},
{ Math.nextUp(1.0), 2.0},
{ Math.nextUp(-1.0), -0.0},
{ 0x1.0p51, 0x1.0p51},
{-0x1.0p51, -0x1.0p51},
{ FpUtils.nextDown(0x1.0p51), 0x1.0p51},
{-Math.nextUp(0x1.0p51), -0x1.0p51},
{ Math.nextUp(0x1.0p51), 0x1.0p51+1},
{-FpUtils.nextDown(0x1.0p51), -0x1.0p51+1},
{ FpUtils.nextDown(0x1.0p52), 0x1.0p52},
{-Math.nextUp(0x1.0p52), -0x1.0p52-1.0},
{ Math.nextUp(0x1.0p52), 0x1.0p52+1.0},
{-FpUtils.nextDown(0x1.0p52), -0x1.0p52+1.0},
};
for(double[] testCase : testCases) {
failures += testCeilCase(testCase[0], testCase[1]);
failures += testFloorCase(-testCase[0], -testCase[1]);
}
return failures;
}
public static void main(String... args) {
int failures = 0;
failures += nearIntegerTests();
failures += roundingTests();
if (failures > 0) {
System.err.println("Testing {Math, StrictMath}.ceil incurred "
+ failures + " failures.");
throw new RuntimeException();
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册