/* * Copyright (c) 2003, 2022, 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. * * 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.
*/
/* * @test * @library /test/lib * @build jdk.test.lib.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) * @key randomness
*/
// Initialize shared random number generator static java.util.Random rand = RandomFactory.getRandom();
/** * Returns a floating-point power of two in the normal range.
*/ staticdouble powerOfTwoD(int n) { returnDouble.longBitsToDouble((((long)n + (long)Double.MAX_EXPONENT) <<
(DoubleConsts.SIGNIFICAND_WIDTH-1))
& DoubleConsts.EXP_BIT_MASK);
}
/** * Returns a floating-point power of two in the normal range.
*/ staticfloat powerOfTwoF(int n) { returnFloat.intBitsToFloat(((n + Float.MAX_EXPONENT) <<
(FloatConsts.SIGNIFICAND_WIDTH-1))
& FloatConsts.EXP_BIT_MASK);
}
/* * The tests for getExponent should test the special values (NaN, +/- * infinity, etc.), test the endpoints of each binade (set of * floating-point values with the same exponent), and for good * measure, test some random values within each binade. Testing * the endpoints of each binade includes testing both positive and * negative numbers. Subnormal values with different normalized * exponents should be tested too. Both Math and StrictMath * methods should return the same results.
*/
/* * Test Math.getExponent and StrictMath.getExponent with +d and -d.
*/ staticint testGetExponentCase(float f, int expected) { float minus_f = -f; int failures=0;
/* * Test Math.getExponent and StrictMath.getExponent with +d and -d.
*/ staticint testGetExponentCase(double d, int expected) { double minus_d = -d; int failures=0;
if (i > Float.MIN_EXPONENT) { float po2minus = Math.nextAfter(po2, Float.NEGATIVE_INFINITY);
failures += testGetExponentCase(po2minus, i-1);
}
}
// Subnormal exponent tests
/* * Start with MIN_VALUE, left shift, test high value, low * values, and random in between. * * Use nextAfter to calculate, high value of previous binade, * loop count i will indicate how many random bits, if any are * needed.
*/
float top=Float.MIN_VALUE; for( int i = 1;
i < FloatConsts.SIGNIFICAND_WIDTH;
i++, top *= 2.0f) {
// Test largest value in next smaller binade if (i >= 3) {// (i == 1) would test 0.0; // (i == 2) would just retest MIN_VALUE
testGetExponentCase(Math.nextAfter(top, 0.0f), Float.MIN_EXPONENT - 1);
if( i >= 10) { // create a bit mask with (i-1) 1's in the low order // bits int mask = ~((~0)<<(i-1)); float randFloat = Float.intBitsToFloat( // Exponent Float.floatToIntBits(top) | // Significand
(rand.nextInt() & mask ) ) ;
if (i > Double.MIN_EXPONENT) { double po2minus = Math.nextAfter(po2, Double.NEGATIVE_INFINITY);
failures += testGetExponentCase(po2minus, i-1);
}
}
// Subnormal exponent tests
/* * Start with MIN_VALUE, left shift, test high value, low * values, and random in between. * * Use nextAfter to calculate, high value of previous binade; * loop count i will indicate how many random bits, if any are * needed.
*/
double top=Double.MIN_VALUE; for( int i = 1;
i < DoubleConsts.SIGNIFICAND_WIDTH;
i++, top *= 2.0f) {
// Test largest value in next smaller binade if (i >= 3) {// (i == 1) would test 0.0; // (i == 2) would just retest MIN_VALUE
testGetExponentCase(Math.nextAfter(top, 0.0), Double.MIN_EXPONENT - 1);
if( i >= 10) { // create a bit mask with (i-1) 1's in the low order // bits long mask = ~((~0L)<<(i-1)); double randFloat = Double.longBitsToDouble( // Exponent Double.doubleToLongBits(top) | // Significand
(rand.nextLong() & mask ) ) ;
publicstaticint testFloatNextAfter() { int failures=0;
/* * Each row of the testCases matrix represents one test case * for nexAfter; given the input of the first two columns, the * result in the last column is expected.
*/ float [][] testCases = {
{NaNf, NaNf, NaNf},
{NaNf, 0.0f, NaNf},
{0.0f, NaNf, NaNf},
{NaNf, infinityF, NaNf},
{infinityF, NaNf, NaNf},
for(int i = 0; i < testCases.length; i++) {
failures += testNextAfterCase(testCases[i][0], testCases[i][1],
testCases[i][2]);
}
return failures;
}
publicstaticint testDoubleNextAfter() { int failures =0;
/* * Each row of the testCases matrix represents one test case * for nexAfter; given the input of the first two columns, the * result in the last column is expected.
*/ double [][] testCases = {
{NaNd, NaNd, NaNd},
{NaNd, 0.0d, NaNd},
{0.0d, NaNd, NaNd},
{NaNd, infinityD, NaNd},
{infinityD, NaNd, NaNd},
publicstaticint testFloatNextUp() { int failures=0;
/* * Each row of testCases represents one test case for nextUp; * the first column is the input and the second column is the * expected result.
*/ float testCases [][] = {
{NaNf, NaNf},
{-infinityF, -Float.MAX_VALUE},
{-Float.MAX_VALUE, -Float_MAX_VALUEmm},
{-Float.MIN_NORMAL, -Float_MAX_SUBNORMAL},
{-Float_MAX_SUBNORMAL, -Float_MAX_SUBNORMALmm},
{-Float.MIN_VALUE, -0.0f},
{-0.0f, Float.MIN_VALUE},
{+0.0f, Float.MIN_VALUE},
{Float.MIN_VALUE, Float.MIN_VALUE*2},
{Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMAL},
{Float_MAX_SUBNORMAL, Float.MIN_NORMAL},
{Float.MIN_NORMAL, Float.MIN_NORMAL+Float.MIN_VALUE},
{Float_MAX_VALUEmm, Float.MAX_VALUE},
{Float.MAX_VALUE, infinityF},
{infinityF, infinityF}
};
for(int i = 0; i < testCases.length; i++) {
failures+=Tests.test("Math.nextUp(float)",
testCases[i][0], Math.nextUp(testCases[i][0]), testCases[i][1]);
publicstaticint testDoubleNextUp() { int failures=0;
/* * Each row of testCases represents one test case for nextUp; * the first column is the input and the second column is the * expected result.
*/ double testCases [][] = {
{NaNd, NaNd},
{-infinityD, -Double.MAX_VALUE},
{-Double.MAX_VALUE, -Double_MAX_VALUEmm},
{-Double.MIN_NORMAL, -Double_MAX_SUBNORMAL},
{-Double_MAX_SUBNORMAL, -Double_MAX_SUBNORMALmm},
{-Double.MIN_VALUE, -0.0d},
{-0.0d, Double.MIN_VALUE},
{+0.0d, Double.MIN_VALUE},
{Double.MIN_VALUE, Double.MIN_VALUE*2},
{Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMAL},
{Double_MAX_SUBNORMAL, Double.MIN_NORMAL},
{Double.MIN_NORMAL, Double.MIN_NORMAL+Double.MIN_VALUE},
{Double_MAX_VALUEmm, Double.MAX_VALUE},
{Double.MAX_VALUE, infinityD},
{infinityD, infinityD}
};
for(int i = 0; i < testCases.length; i++) {
failures+=Tests.test("Math.nextUp(double)",
testCases[i][0], Math::nextUp, testCases[i][1]);
publicstaticint testFloatNextDown() { int failures=0;
/* * Each row of testCases represents one test case for nextDown; * the first column is the input and the second column is the * expected result.
*/ float testCases [][] = {
{NaNf, NaNf},
{-infinityF, -infinityF},
{-Float.MAX_VALUE, -infinityF},
{-Float_MAX_VALUEmm, -Float.MAX_VALUE},
{-Float_MAX_SUBNORMAL, -Float.MIN_NORMAL},
{-Float_MAX_SUBNORMALmm, -Float_MAX_SUBNORMAL},
{-0.0f, -Float.MIN_VALUE},
{+0.0f, -Float.MIN_VALUE},
{Float.MIN_VALUE, 0.0f},
{Float.MIN_VALUE*2, Float.MIN_VALUE},
{Float_MAX_SUBNORMAL, Float_MAX_SUBNORMALmm},
{Float.MIN_NORMAL, Float_MAX_SUBNORMAL},
{Float.MIN_NORMAL+ Float.MIN_VALUE, Float.MIN_NORMAL},
{Float.MAX_VALUE, Float_MAX_VALUEmm},
{infinityF, Float.MAX_VALUE},
};
for(int i = 0; i < testCases.length; i++) {
failures+=Tests.test("Math.nextDown(float)",
testCases[i][0], Math.nextDown(testCases[i][0]), testCases[i][1]);
publicstaticint testDoubleNextDown() { int failures=0;
/* * Each row of testCases represents one test case for nextDown; * the first column is the input and the second column is the * expected result.
*/ double testCases [][] = {
{NaNd, NaNd},
{-infinityD, -infinityD},
{-Double.MAX_VALUE, -infinityD},
{-Double_MAX_VALUEmm, -Double.MAX_VALUE},
{-Double_MAX_SUBNORMAL, -Double.MIN_NORMAL},
{-Double_MAX_SUBNORMALmm, -Double_MAX_SUBNORMAL},
{-0.0d, -Double.MIN_VALUE},
{+0.0d, -Double.MIN_VALUE},
{Double.MIN_VALUE, 0.0d},
{Double.MIN_VALUE*2, Double.MIN_VALUE},
{Double_MAX_SUBNORMAL, Double_MAX_SUBNORMALmm},
{Double.MIN_NORMAL, Double_MAX_SUBNORMAL},
{Double.MIN_NORMAL+ Double.MIN_VALUE, Double.MIN_NORMAL},
{Double.MAX_VALUE, Double_MAX_VALUEmm},
{infinityD, Double.MAX_VALUE},
};
for(int i = 0; i < testCases.length; i++) {
failures+=Tests.test("Math.nextDown(double)",
testCases[i][0], Math::nextDown, testCases[i][1]);
// For rawCopySign, NaN may effectively have either sign bit // while for copySign NaNs are treated as if they always have // a zero sign bit (i.e. as positive numbers) for(int i = 0; i < 2; i++) { for(int j = 0; j < NaNs.length; j++) { for(int m = 0; m < testCases[i].length; m++) { // copySign(magnitude, sign)
// For Math.copySign, NaN may effectively have either sign bit // while for StrictMath.copySign NaNs are treated as if they // always have a zero sign bit (i.e. as positive numbers) for(int i = 0; i < 2; i++) { for(int j = 0; j < NaNs.length; j++) { for(int m = 0; m < testCases[i].length; m++) { // copySign(magnitude, sign)
// Test cases where scaling is always a no-op for(int i=0; i < identityTestCases.length; i++) { for(int j=0; j < manyScalingFactors.length; j++) {
failures += testScalbCase(identityTestCases[i],
manyScalingFactors[j],
identityTestCases[i]);
}
}
// Test cases where result is 0.0 or infinity due to magnitude // of the scaling factor for(int i=0; i < someTestCases.length; i++) { for(int j=0; j < manyScalingFactors.length; j++) { int scaleFactor = manyScalingFactors[j]; if (Math.abs(scaleFactor) >= MAX_SCALE) { float value = someTestCases[i];
failures+=testScalbCase(value,
scaleFactor,
Math.copySign( (scaleFactor>0?infinityF:0.0f), value) );
}
}
}
// Test cases that could be done with one floating-point // multiply. for(int i=0; i < someTestCases.length; i++) { for(int j=0; j < oneMultiplyScalingFactors.length; j++) { int scaleFactor = oneMultiplyScalingFactors[j]; float value = someTestCases[i];
// Create 2^MAX_EXPONENT float twoToTheMaxExp = 1.0f; // 2^0 for(int i = 0; i < Float.MAX_EXPONENT; i++)
twoToTheMaxExp *=2.0f;
// Scale-up subnormal values until they all overflow for(int i=0; i < subnormalTestCases.length; i++) { float scale = 1.0f; // 2^j float value = subnormalTestCases[i];
for(int j=Float.MAX_EXPONENT*2; j < MAX_SCALE; j++) { // MAX_SCALE -1 should cause overflow int scaleFactor = j;
// Scale down a large number until it underflows. By scaling // down MAX_NORMALmm, the first subnormal result will be exact // but the next one will round -- all those results can be // checked by halving a separate value in the loop. Actually, // we can keep halving and checking until the product is zero // since: // // 1. If the scalb of MAX_VALUEmm is subnormal and *not* exact // it will round *up* // // 2. When rounding first occurs in the expected product, it // too rounds up, to 2^-MAX_EXPONENT. // // Halving expected after rounding happends to give the same // result as the scalb operation. float expected = Float_MAX_VALUEmm *0.5f; for(int i = -1; i > -MAX_SCALE; i--) {
failures+=testScalbCase(Float_MAX_VALUEmm, i, expected);
expected *= 0.5f;
}
// Tricky rounding tests: // Scale down a large number into subnormal range such that if // scalb is being implemented with multiple floating-point // multiplies, the value would round twice if the multiplies // were done in the wrong order.
float value = 0x8.0000bP-5f;
expected = 0x1.00001p-129f;
for(int i = 0; i < 129; i++) {
failures+=testScalbCase(value,
-127-i,
expected);
value *=2.0f;
}
return failures;
}
staticint testScalbCase(double value, int scale_factor, double expected) { int failures=0;
// Test cases where scaling is always a no-op for(int i=0; i < identityTestCases.length; i++) { for(int j=0; j < manyScalingFactors.length; j++) {
failures += testScalbCase(identityTestCases[i],
manyScalingFactors[j],
identityTestCases[i]);
}
}
// Test cases where result is 0.0 or infinity due to magnitude // of the scaling factor for(int i=0; i < someTestCases.length; i++) { for(int j=0; j < manyScalingFactors.length; j++) { int scaleFactor = manyScalingFactors[j]; if (Math.abs(scaleFactor) >= MAX_SCALE) { double value = someTestCases[i];
failures+=testScalbCase(value,
scaleFactor,
Math.copySign( (scaleFactor>0?infinityD:0.0), value) );
}
}
}
// Test cases that could be done with one floating-point // multiply. for(int i=0; i < someTestCases.length; i++) { for(int j=0; j < oneMultiplyScalingFactors.length; j++) { int scaleFactor = oneMultiplyScalingFactors[j]; double value = someTestCases[i];
// Create 2^MAX_EXPONENT double twoToTheMaxExp = 1.0; // 2^0 for(int i = 0; i < Double.MAX_EXPONENT; i++)
twoToTheMaxExp *=2.0;
// Scale-up subnormal values until they all overflow for(int i=0; i < subnormalTestCases.length; i++) { double scale = 1.0; // 2^j double value = subnormalTestCases[i];
for(int j=Double.MAX_EXPONENT*2; j < MAX_SCALE; j++) { // MAX_SCALE -1 should cause overflow int scaleFactor = j;
// Scale down a large number until it underflows. By scaling // down MAX_NORMALmm, the first subnormal result will be exact // but the next one will round -- all those results can be // checked by halving a separate value in the loop. Actually, // we can keep halving and checking until the product is zero // since: // // 1. If the scalb of MAX_VALUEmm is subnormal and *not* exact // it will round *up* // // 2. When rounding first occurs in the expected product, it // too rounds up, to 2^-MAX_EXPONENT. // // Halving expected after rounding happends to give the same // result as the scalb operation. double expected = Double_MAX_VALUEmm *0.5f; for(int i = -1; i > -MAX_SCALE; i--) {
failures+=testScalbCase(Double_MAX_VALUEmm, i, expected);
expected *= 0.5;
}
// Tricky rounding tests: // Scale down a large number into subnormal range such that if // scalb is being implemented with multiple floating-point // multiplies, the value would round twice if the multiplies // were done in the wrong order.
double value = 0x1.000000000000bP-1;
expected = 0x0.2000000000001P-1022; for(int i = 0; i < Double.MAX_EXPONENT+2; i++) {
failures+=testScalbCase(value,
-1024-i,
expected);
value *=2.0;
}
if (i > Float.MIN_EXPONENT) { float po2minus = Math.nextAfter(po2, Float.NEGATIVE_INFINITY);
failures += testUlpCase(po2minus, expected/2.0f);
}
}
// Subnormal tests
/* * Start with MIN_VALUE, left shift, test high value, low * values, and random in between. * * Use nextAfter to calculate, high value of previous binade, * loop count i will indicate how many random bits, if any are * needed.
*/
float top=Float.MIN_VALUE; for( int i = 1;
i < FloatConsts.SIGNIFICAND_WIDTH;
i++, top *= 2.0f) {
failures += testUlpCase(top, Float.MIN_VALUE);
// Test largest value in next smaller binade if (i >= 3) {// (i == 1) would test 0.0; // (i == 2) would just retest MIN_VALUE
testUlpCase(Math.nextAfter(top, 0.0f), Float.MIN_VALUE);
if( i >= 10) { // create a bit mask with (i-1) 1's in the low order // bits int mask = ~((~0)<<(i-1)); float randFloat = Float.intBitsToFloat( // Exponent Float.floatToIntBits(top) | // Significand
(rand.nextInt() & mask ) ) ;
if (i > Double.MIN_EXPONENT) { double po2minus = Math.nextAfter(po2, Double.NEGATIVE_INFINITY);
failures += testUlpCase(po2minus, expected/2.0f);
}
}
// Subnormal tests
/* * Start with MIN_VALUE, left shift, test high value, low * values, and random in between. * * Use nextAfter to calculate, high value of previous binade, * loop count i will indicate how many random bits, if any are * needed.
*/
double top=Double.MIN_VALUE; for( int i = 1;
i < DoubleConsts.SIGNIFICAND_WIDTH;
i++, top *= 2.0f) {
failures += testUlpCase(top, Double.MIN_VALUE);
// Test largest value in next smaller binade if (i >= 3) {// (i == 1) would test 0.0; // (i == 2) would just retest MIN_VALUE
testUlpCase(Math.nextAfter(top, 0.0f), Double.MIN_VALUE);
if( i >= 10) { // create a bit mask with (i-1) 1's in the low order // bits int mask = ~((~0)<<(i-1)); double randDouble = Double.longBitsToDouble( // Exponent Double.doubleToLongBits(top) | // Significand
(rand.nextLong() & mask ) ) ;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.