809N/A/*
2362N/A * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
809N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
809N/A *
809N/A * This code is free software; you can redistribute it and/or modify it
809N/A * under the terms of the GNU General Public License version 2 only, as
809N/A * published by the Free Software Foundation.
809N/A *
809N/A * This code is distributed in the hope that it will be useful, but WITHOUT
809N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
809N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
809N/A * version 2 for more details (a copy is included in the LICENSE file that
809N/A * accompanied this code).
809N/A *
809N/A * You should have received a copy of the GNU General Public License version
809N/A * 2 along with this work; if not, write to the Free Software Foundation,
809N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
809N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
809N/A */
809N/A
809N/A/*
809N/A * @test
809N/A * @bug 4860891 4826732 4780454 4939441 4826652
809N/A * @summary Tests for IEEE 754[R] recommended functions and similar methods
809N/A * @author Joseph D. Darcy
809N/A */
809N/A
809N/Aimport sun.misc.FpUtils;
809N/Aimport sun.misc.DoubleConsts;
809N/Aimport sun.misc.FloatConsts;
809N/A
809N/Apublic class IeeeRecommendedTests {
809N/A private IeeeRecommendedTests(){}
809N/A
809N/A static final float NaNf = Float.NaN;
809N/A static final double NaNd = Double.NaN;
809N/A static final float infinityF = Float.POSITIVE_INFINITY;
809N/A static final double infinityD = Double.POSITIVE_INFINITY;
809N/A
809N/A static final float Float_MAX_VALUEmm = 0x1.fffffcP+127f;
809N/A static final float Float_MAX_SUBNORMAL = 0x0.fffffeP-126f;
809N/A static final float Float_MAX_SUBNORMALmm = 0x0.fffffcP-126f;
809N/A
809N/A static final double Double_MAX_VALUEmm = 0x1.ffffffffffffeP+1023;
809N/A static final double Double_MAX_SUBNORMAL = 0x0.fffffffffffffP-1022;
809N/A static final double Double_MAX_SUBNORMALmm = 0x0.ffffffffffffeP-1022;
809N/A
809N/A // Initialize shared random number generator
809N/A static java.util.Random rand = new java.util.Random();
809N/A
809N/A /**
809N/A * Returns a floating-point power of two in the normal range.
809N/A */
809N/A static double powerOfTwoD(int n) {
809N/A return Double.longBitsToDouble((((long)n + (long)DoubleConsts.MAX_EXPONENT) <<
809N/A (DoubleConsts.SIGNIFICAND_WIDTH-1))
809N/A & DoubleConsts.EXP_BIT_MASK);
809N/A }
809N/A
809N/A /**
809N/A * Returns a floating-point power of two in the normal range.
809N/A */
809N/A static float powerOfTwoF(int n) {
809N/A return Float.intBitsToFloat(((n + FloatConsts.MAX_EXPONENT) <<
809N/A (FloatConsts.SIGNIFICAND_WIDTH-1))
809N/A & FloatConsts.EXP_BIT_MASK);
809N/A }
809N/A
809N/A /* ******************** getExponent tests ****************************** */
809N/A
809N/A /*
809N/A * The tests for getExponent should test the special values (NaN, +/-
809N/A * infinity, etc.), test the endpoints of each binade (set of
809N/A * floating-point values with the same exponent), and for good
809N/A * measure, test some random values within each binade. Testing
809N/A * the endpoints of each binade includes testing both positive and
809N/A * negative numbers. Subnormal values with different normalized
809N/A * exponents should be tested too. Both Math and StrictMath
809N/A * methods should return the same results.
809N/A */
809N/A
809N/A /*
809N/A * Test Math.getExponent and StrictMath.getExponent with +d and -d.
809N/A */
809N/A static int testGetExponentCase(float f, int expected) {
809N/A float minus_f = -f;
809N/A int failures=0;
809N/A
809N/A failures+=Tests.test("Math.getExponent(float)", f,
809N/A Math.getExponent(f), expected);
809N/A failures+=Tests.test("Math.getExponent(float)", minus_f,
809N/A Math.getExponent(minus_f), expected);
809N/A
809N/A failures+=Tests.test("StrictMath.getExponent(float)", f,
809N/A StrictMath.getExponent(f), expected);
809N/A failures+=Tests.test("StrictMath.getExponent(float)", minus_f,
809N/A StrictMath.getExponent(minus_f), expected);
809N/A return failures;
809N/A }
809N/A
809N/A /*
809N/A * Test Math.getExponent and StrictMath.getExponent with +d and -d.
809N/A */
809N/A static int testGetExponentCase(double d, int expected) {
809N/A double minus_d = -d;
809N/A int failures=0;
809N/A
809N/A failures+=Tests.test("Math.getExponent(double)", d,
809N/A Math.getExponent(d), expected);
809N/A failures+=Tests.test("Math.getExponent(double)", minus_d,
809N/A Math.getExponent(minus_d), expected);
809N/A
809N/A failures+=Tests.test("StrictMath.getExponent(double)", d,
809N/A StrictMath.getExponent(d), expected);
809N/A failures+=Tests.test("StrictMath.getExponent(double)", minus_d,
809N/A StrictMath.getExponent(minus_d), expected);
809N/A return failures;
809N/A }
809N/A
809N/A public static int testFloatGetExponent() {
809N/A int failures = 0;
809N/A float [] specialValues = {NaNf,
809N/A Float.POSITIVE_INFINITY,
809N/A +0.0f,
809N/A +1.0f,
809N/A +2.0f,
809N/A +16.0f,
809N/A +Float.MIN_VALUE,
809N/A +Float_MAX_SUBNORMAL,
809N/A +FloatConsts.MIN_NORMAL,
809N/A +Float.MAX_VALUE
809N/A };
809N/A
809N/A int [] specialResults = {Float.MAX_EXPONENT + 1, // NaN results
809N/A Float.MAX_EXPONENT + 1, // Infinite results
809N/A Float.MIN_EXPONENT - 1, // Zero results
809N/A 0,
809N/A 1,
809N/A 4,
809N/A FloatConsts.MIN_EXPONENT - 1,
809N/A -FloatConsts.MAX_EXPONENT,
809N/A FloatConsts.MIN_EXPONENT,
809N/A FloatConsts.MAX_EXPONENT
809N/A };
809N/A
809N/A // Special value tests
809N/A for(int i = 0; i < specialValues.length; i++) {
809N/A failures += testGetExponentCase(specialValues[i], specialResults[i]);
809N/A }
809N/A
809N/A
809N/A // Normal exponent tests
809N/A for(int i = FloatConsts.MIN_EXPONENT; i <= FloatConsts.MAX_EXPONENT; i++) {
809N/A int result;
809N/A
809N/A // Create power of two
809N/A float po2 = powerOfTwoF(i);
809N/A
809N/A failures += testGetExponentCase(po2, i);
809N/A
809N/A // Generate some random bit patterns for the significand
809N/A for(int j = 0; j < 10; j++) {
809N/A int randSignif = rand.nextInt();
809N/A float randFloat;
809N/A
809N/A randFloat = Float.intBitsToFloat( // Exponent
809N/A (Float.floatToIntBits(po2)&
809N/A (~FloatConsts.SIGNIF_BIT_MASK)) |
809N/A // Significand
809N/A (randSignif &
809N/A FloatConsts.SIGNIF_BIT_MASK) );
809N/A
809N/A failures += testGetExponentCase(randFloat, i);
809N/A }
809N/A
809N/A if (i > FloatConsts.MIN_EXPONENT) {
809N/A float po2minus = FpUtils.nextAfter(po2,
809N/A Float.NEGATIVE_INFINITY);
809N/A failures += testGetExponentCase(po2minus, i-1);
809N/A }
809N/A }
809N/A
809N/A // Subnormal exponent tests
809N/A
809N/A /*
809N/A * Start with MIN_VALUE, left shift, test high value, low
809N/A * values, and random in between.
809N/A *
809N/A * Use nextAfter to calculate, high value of previous binade,
809N/A * loop count i will indicate how many random bits, if any are
809N/A * needed.
809N/A */
809N/A
809N/A float top=Float.MIN_VALUE;
809N/A for( int i = 1;
809N/A i < FloatConsts.SIGNIFICAND_WIDTH;
809N/A i++, top *= 2.0f) {
809N/A
809N/A failures += testGetExponentCase(top,
809N/A FloatConsts.MIN_EXPONENT - 1);
809N/A
809N/A // Test largest value in next smaller binade
809N/A if (i >= 3) {// (i == 1) would test 0.0;
809N/A // (i == 2) would just retest MIN_VALUE
809N/A testGetExponentCase(FpUtils.nextAfter(top, 0.0f),
809N/A FloatConsts.MIN_EXPONENT - 1);
809N/A
809N/A if( i >= 10) {
809N/A // create a bit mask with (i-1) 1's in the low order
809N/A // bits
809N/A int mask = ~((~0)<<(i-1));
809N/A float randFloat = Float.intBitsToFloat( // Exponent
809N/A Float.floatToIntBits(top) |
809N/A // Significand
809N/A (rand.nextInt() & mask ) ) ;
809N/A
809N/A failures += testGetExponentCase(randFloat,
809N/A FloatConsts.MIN_EXPONENT - 1);
809N/A }
809N/A }
809N/A }
809N/A
809N/A return failures;
809N/A }
809N/A
809N/A
809N/A public static int testDoubleGetExponent() {
809N/A int failures = 0;
809N/A double [] specialValues = {NaNd,
809N/A infinityD,
809N/A +0.0,
809N/A +1.0,
809N/A +2.0,
809N/A +16.0,
809N/A +Double.MIN_VALUE,
809N/A +Double_MAX_SUBNORMAL,
809N/A +DoubleConsts.MIN_NORMAL,
809N/A +Double.MAX_VALUE
809N/A };
809N/A
809N/A int [] specialResults = {Double.MAX_EXPONENT + 1, // NaN results
809N/A Double.MAX_EXPONENT + 1, // Infinite results
809N/A Double.MIN_EXPONENT - 1, // Zero results
809N/A 0,
809N/A 1,
809N/A 4,
809N/A DoubleConsts.MIN_EXPONENT - 1,
809N/A -DoubleConsts.MAX_EXPONENT,
809N/A DoubleConsts.MIN_EXPONENT,
809N/A DoubleConsts.MAX_EXPONENT
809N/A };
809N/A
809N/A // Special value tests
809N/A for(int i = 0; i < specialValues.length; i++) {
809N/A failures += testGetExponentCase(specialValues[i], specialResults[i]);
809N/A }
809N/A
809N/A
809N/A // Normal exponent tests
809N/A for(int i = DoubleConsts.MIN_EXPONENT; i <= DoubleConsts.MAX_EXPONENT; i++) {
809N/A int result;
809N/A
809N/A // Create power of two
809N/A double po2 = powerOfTwoD(i);
809N/A
809N/A failures += testGetExponentCase(po2, i);
809N/A
809N/A // Generate some random bit patterns for the significand
809N/A for(int j = 0; j < 10; j++) {
809N/A long randSignif = rand.nextLong();
809N/A double randFloat;
809N/A
809N/A randFloat = Double.longBitsToDouble( // Exponent
809N/A (Double.doubleToLongBits(po2)&
809N/A (~DoubleConsts.SIGNIF_BIT_MASK)) |
809N/A // Significand
809N/A (randSignif &
809N/A DoubleConsts.SIGNIF_BIT_MASK) );
809N/A
809N/A failures += testGetExponentCase(randFloat, i);
809N/A }
809N/A
809N/A if (i > DoubleConsts.MIN_EXPONENT) {
809N/A double po2minus = FpUtils.nextAfter(po2,
809N/A Double.NEGATIVE_INFINITY);
809N/A failures += testGetExponentCase(po2minus, i-1);
809N/A }
809N/A }
809N/A
809N/A // Subnormal exponent tests
809N/A
809N/A /*
809N/A * Start with MIN_VALUE, left shift, test high value, low
809N/A * values, and random in between.
809N/A *
809N/A * Use nextAfter to calculate, high value of previous binade;
809N/A * loop count i will indicate how many random bits, if any are
809N/A * needed.
809N/A */
809N/A
809N/A double top=Double.MIN_VALUE;
809N/A for( int i = 1;
809N/A i < DoubleConsts.SIGNIFICAND_WIDTH;
809N/A i++, top *= 2.0f) {
809N/A
809N/A failures += testGetExponentCase(top,
809N/A DoubleConsts.MIN_EXPONENT - 1);
809N/A
809N/A // Test largest value in next smaller binade
809N/A if (i >= 3) {// (i == 1) would test 0.0;
809N/A // (i == 2) would just retest MIN_VALUE
809N/A testGetExponentCase(FpUtils.nextAfter(top, 0.0),
809N/A DoubleConsts.MIN_EXPONENT - 1);
809N/A
809N/A if( i >= 10) {
809N/A // create a bit mask with (i-1) 1's in the low order
809N/A // bits
809N/A long mask = ~((~0L)<<(i-1));
809N/A double randFloat = Double.longBitsToDouble( // Exponent
809N/A Double.doubleToLongBits(top) |
809N/A // Significand
809N/A (rand.nextLong() & mask ) ) ;
809N/A
809N/A failures += testGetExponentCase(randFloat,
809N/A DoubleConsts.MIN_EXPONENT - 1);
809N/A }
809N/A }
809N/A }
809N/A
809N/A return failures;
809N/A }
809N/A
809N/A
809N/A /* ******************** nextAfter tests ****************************** */
809N/A
809N/A static int testNextAfterCase(float start, double direction, float expected) {
809N/A int failures=0;
809N/A float minus_start = -start;
809N/A double minus_direction = -direction;
809N/A float minus_expected = -expected;
809N/A
809N/A failures+=Tests.test("Math.nextAfter(float,double)", start, direction,
809N/A Math.nextAfter(start, direction), expected);
809N/A failures+=Tests.test("Math.nextAfter(float,double)", minus_start, minus_direction,
809N/A Math.nextAfter(minus_start, minus_direction), minus_expected);
809N/A
809N/A failures+=Tests.test("StrictMath.nextAfter(float,double)", start, direction,
809N/A StrictMath.nextAfter(start, direction), expected);
809N/A failures+=Tests.test("StrictMath.nextAfter(float,double)", minus_start, minus_direction,
809N/A StrictMath.nextAfter(minus_start, minus_direction), minus_expected);
809N/A return failures;
809N/A }
809N/A
809N/A static int testNextAfterCase(double start, double direction, double expected) {
809N/A int failures=0;
809N/A
809N/A double minus_start = -start;
809N/A double minus_direction = -direction;
809N/A double minus_expected = -expected;
809N/A
809N/A failures+=Tests.test("Math.nextAfter(double,double)", start, direction,
809N/A Math.nextAfter(start, direction), expected);
809N/A failures+=Tests.test("Math.nextAfter(double,double)", minus_start, minus_direction,
809N/A Math.nextAfter(minus_start, minus_direction), minus_expected);
809N/A
809N/A failures+=Tests.test("StrictMath.nextAfter(double,double)", start, direction,
809N/A StrictMath.nextAfter(start, direction), expected);
809N/A failures+=Tests.test("StrictMath.nextAfter(double,double)", minus_start, minus_direction,
809N/A StrictMath.nextAfter(minus_start, minus_direction), minus_expected);
809N/A return failures;
809N/A }
809N/A
809N/A public static int testFloatNextAfter() {
809N/A int failures=0;
809N/A
809N/A /*
809N/A * Each row of the testCases matrix represents one test case
809N/A * for nexAfter; given the input of the first two columns, the
809N/A * result in the last column is expected.
809N/A */
809N/A float [][] testCases = {
809N/A {NaNf, NaNf, NaNf},
809N/A {NaNf, 0.0f, NaNf},
809N/A {0.0f, NaNf, NaNf},
809N/A {NaNf, infinityF, NaNf},
809N/A {infinityF, NaNf, NaNf},
809N/A
809N/A {infinityF, infinityF, infinityF},
809N/A {infinityF, -infinityF, Float.MAX_VALUE},
809N/A {infinityF, 0.0f, Float.MAX_VALUE},
809N/A
809N/A {Float.MAX_VALUE, infinityF, infinityF},
809N/A {Float.MAX_VALUE, -infinityF, Float_MAX_VALUEmm},
809N/A {Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE},
809N/A {Float.MAX_VALUE, 0.0f, Float_MAX_VALUEmm},
809N/A
809N/A {Float_MAX_VALUEmm, Float.MAX_VALUE, Float.MAX_VALUE},
809N/A {Float_MAX_VALUEmm, infinityF, Float.MAX_VALUE},
809N/A {Float_MAX_VALUEmm, Float_MAX_VALUEmm, Float_MAX_VALUEmm},
809N/A
809N/A {FloatConsts.MIN_NORMAL, infinityF, FloatConsts.MIN_NORMAL+
809N/A Float.MIN_VALUE},
809N/A {FloatConsts.MIN_NORMAL, -infinityF, Float_MAX_SUBNORMAL},
809N/A {FloatConsts.MIN_NORMAL, 1.0f, FloatConsts.MIN_NORMAL+
809N/A Float.MIN_VALUE},
809N/A {FloatConsts.MIN_NORMAL, -1.0f, Float_MAX_SUBNORMAL},
809N/A {FloatConsts.MIN_NORMAL, FloatConsts.MIN_NORMAL, FloatConsts.MIN_NORMAL},
809N/A
809N/A {Float_MAX_SUBNORMAL, FloatConsts.MIN_NORMAL, FloatConsts.MIN_NORMAL},
809N/A {Float_MAX_SUBNORMAL, Float_MAX_SUBNORMAL, Float_MAX_SUBNORMAL},
809N/A {Float_MAX_SUBNORMAL, 0.0f, Float_MAX_SUBNORMALmm},
809N/A
809N/A {Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMAL, Float_MAX_SUBNORMAL},
809N/A {Float_MAX_SUBNORMALmm, 0.0f, Float_MAX_SUBNORMALmm-Float.MIN_VALUE},
809N/A {Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMALmm},
809N/A
809N/A {Float.MIN_VALUE, 0.0f, 0.0f},
809N/A {-Float.MIN_VALUE, 0.0f, -0.0f},
809N/A {Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE},
809N/A {Float.MIN_VALUE, 1.0f, 2*Float.MIN_VALUE},
809N/A
809N/A // Make sure zero behavior is tested
809N/A {0.0f, 0.0f, 0.0f},
809N/A {0.0f, -0.0f, -0.0f},
809N/A {-0.0f, 0.0f, 0.0f},
809N/A {-0.0f, -0.0f, -0.0f},
809N/A {0.0f, infinityF, Float.MIN_VALUE},
809N/A {0.0f, -infinityF, -Float.MIN_VALUE},
809N/A {-0.0f, infinityF, Float.MIN_VALUE},
809N/A {-0.0f, -infinityF, -Float.MIN_VALUE},
809N/A {0.0f, Float.MIN_VALUE, Float.MIN_VALUE},
809N/A {0.0f, -Float.MIN_VALUE, -Float.MIN_VALUE},
809N/A {-0.0f, Float.MIN_VALUE, Float.MIN_VALUE},
809N/A {-0.0f, -Float.MIN_VALUE, -Float.MIN_VALUE}
809N/A };
809N/A
809N/A for(int i = 0; i < testCases.length; i++) {
809N/A failures += testNextAfterCase(testCases[i][0], testCases[i][1],
809N/A testCases[i][2]);
809N/A }
809N/A
809N/A return failures;
809N/A }
809N/A
809N/A public static int testDoubleNextAfter() {
809N/A int failures =0;
809N/A
809N/A /*
809N/A * Each row of the testCases matrix represents one test case
809N/A * for nexAfter; given the input of the first two columns, the
809N/A * result in the last column is expected.
809N/A */
809N/A double [][] testCases = {
809N/A {NaNd, NaNd, NaNd},
809N/A {NaNd, 0.0d, NaNd},
809N/A {0.0d, NaNd, NaNd},
809N/A {NaNd, infinityD, NaNd},
809N/A {infinityD, NaNd, NaNd},
809N/A
809N/A {infinityD, infinityD, infinityD},
809N/A {infinityD, -infinityD, Double.MAX_VALUE},
809N/A {infinityD, 0.0d, Double.MAX_VALUE},
809N/A
809N/A {Double.MAX_VALUE, infinityD, infinityD},
809N/A {Double.MAX_VALUE, -infinityD, Double_MAX_VALUEmm},
809N/A {Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE},
809N/A {Double.MAX_VALUE, 0.0d, Double_MAX_VALUEmm},
809N/A
809N/A {Double_MAX_VALUEmm, Double.MAX_VALUE, Double.MAX_VALUE},
809N/A {Double_MAX_VALUEmm, infinityD, Double.MAX_VALUE},
809N/A {Double_MAX_VALUEmm, Double_MAX_VALUEmm, Double_MAX_VALUEmm},
809N/A
809N/A {DoubleConsts.MIN_NORMAL, infinityD, DoubleConsts.MIN_NORMAL+
809N/A Double.MIN_VALUE},
809N/A {DoubleConsts.MIN_NORMAL, -infinityD, Double_MAX_SUBNORMAL},
809N/A {DoubleConsts.MIN_NORMAL, 1.0f, DoubleConsts.MIN_NORMAL+
809N/A Double.MIN_VALUE},
809N/A {DoubleConsts.MIN_NORMAL, -1.0f, Double_MAX_SUBNORMAL},
809N/A {DoubleConsts.MIN_NORMAL, DoubleConsts.MIN_NORMAL,DoubleConsts.MIN_NORMAL},
809N/A
809N/A {Double_MAX_SUBNORMAL, DoubleConsts.MIN_NORMAL,DoubleConsts.MIN_NORMAL},
809N/A {Double_MAX_SUBNORMAL, Double_MAX_SUBNORMAL, Double_MAX_SUBNORMAL},
809N/A {Double_MAX_SUBNORMAL, 0.0d, Double_MAX_SUBNORMALmm},
809N/A
809N/A {Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMAL, Double_MAX_SUBNORMAL},
809N/A {Double_MAX_SUBNORMALmm, 0.0d, Double_MAX_SUBNORMALmm-Double.MIN_VALUE},
809N/A {Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMALmm},
809N/A
809N/A {Double.MIN_VALUE, 0.0d, 0.0d},
809N/A {-Double.MIN_VALUE, 0.0d, -0.0d},
809N/A {Double.MIN_VALUE, Double.MIN_VALUE, Double.MIN_VALUE},
809N/A {Double.MIN_VALUE, 1.0f, 2*Double.MIN_VALUE},
809N/A
809N/A // Make sure zero behavior is tested
809N/A {0.0d, 0.0d, 0.0d},
809N/A {0.0d, -0.0d, -0.0d},
809N/A {-0.0d, 0.0d, 0.0d},
809N/A {-0.0d, -0.0d, -0.0d},
809N/A {0.0d, infinityD, Double.MIN_VALUE},
809N/A {0.0d, -infinityD, -Double.MIN_VALUE},
809N/A {-0.0d, infinityD, Double.MIN_VALUE},
809N/A {-0.0d, -infinityD, -Double.MIN_VALUE},
809N/A {0.0d, Double.MIN_VALUE, Double.MIN_VALUE},
809N/A {0.0d, -Double.MIN_VALUE, -Double.MIN_VALUE},
809N/A {-0.0d, Double.MIN_VALUE, Double.MIN_VALUE},
809N/A {-0.0d, -Double.MIN_VALUE, -Double.MIN_VALUE}
809N/A };
809N/A
809N/A for(int i = 0; i < testCases.length; i++) {
809N/A failures += testNextAfterCase(testCases[i][0], testCases[i][1],
809N/A testCases[i][2]);
809N/A }
809N/A return failures;
809N/A }
809N/A
809N/A /* ******************** nextUp tests ********************************* */
809N/A
809N/A public static int testFloatNextUp() {
809N/A int failures=0;
809N/A
809N/A /*
809N/A * Each row of testCases represents one test case for nextUp;
809N/A * the first column is the input and the second column is the
809N/A * expected result.
809N/A */
809N/A float testCases [][] = {
809N/A {NaNf, NaNf},
809N/A {-infinityF, -Float.MAX_VALUE},
809N/A {-Float.MAX_VALUE, -Float_MAX_VALUEmm},
809N/A {-FloatConsts.MIN_NORMAL, -Float_MAX_SUBNORMAL},
809N/A {-Float_MAX_SUBNORMAL, -Float_MAX_SUBNORMALmm},
809N/A {-Float.MIN_VALUE, -0.0f},
809N/A {-0.0f, Float.MIN_VALUE},
809N/A {+0.0f, Float.MIN_VALUE},
809N/A {Float.MIN_VALUE, Float.MIN_VALUE*2},
809N/A {Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMAL},
809N/A {Float_MAX_SUBNORMAL, FloatConsts.MIN_NORMAL},
809N/A {FloatConsts.MIN_NORMAL, FloatConsts.MIN_NORMAL+Float.MIN_VALUE},
809N/A {Float_MAX_VALUEmm, Float.MAX_VALUE},
809N/A {Float.MAX_VALUE, infinityF},
809N/A {infinityF, infinityF}
809N/A };
809N/A
809N/A for(int i = 0; i < testCases.length; i++) {
809N/A failures+=Tests.test("Math.nextUp(float)",
809N/A testCases[i][0], Math.nextUp(testCases[i][0]), testCases[i][1]);
809N/A
809N/A failures+=Tests.test("StrictMath.nextUp(float)",
809N/A testCases[i][0], StrictMath.nextUp(testCases[i][0]), testCases[i][1]);
809N/A }
809N/A
809N/A return failures;
809N/A }
809N/A
809N/A
809N/A public static int testDoubleNextUp() {
809N/A int failures=0;
809N/A
809N/A /*
809N/A * Each row of testCases represents one test case for nextUp;
809N/A * the first column is the input and the second column is the
809N/A * expected result.
809N/A */
809N/A double testCases [][] = {
809N/A {NaNd, NaNd},
809N/A {-infinityD, -Double.MAX_VALUE},
809N/A {-Double.MAX_VALUE, -Double_MAX_VALUEmm},
809N/A {-DoubleConsts.MIN_NORMAL, -Double_MAX_SUBNORMAL},
809N/A {-Double_MAX_SUBNORMAL, -Double_MAX_SUBNORMALmm},
809N/A {-Double.MIN_VALUE, -0.0d},
809N/A {-0.0d, Double.MIN_VALUE},
809N/A {+0.0d, Double.MIN_VALUE},
809N/A {Double.MIN_VALUE, Double.MIN_VALUE*2},
809N/A {Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMAL},
809N/A {Double_MAX_SUBNORMAL, DoubleConsts.MIN_NORMAL},
809N/A {DoubleConsts.MIN_NORMAL, DoubleConsts.MIN_NORMAL+Double.MIN_VALUE},
809N/A {Double_MAX_VALUEmm, Double.MAX_VALUE},
809N/A {Double.MAX_VALUE, infinityD},
809N/A {infinityD, infinityD}
809N/A };
809N/A
809N/A for(int i = 0; i < testCases.length; i++) {
809N/A failures+=Tests.test("Math.nextUp(double)",
809N/A testCases[i][0], Math.nextUp(testCases[i][0]), testCases[i][1]);
809N/A
809N/A failures+=Tests.test("StrictMath.nextUp(double)",
809N/A testCases[i][0], StrictMath.nextUp(testCases[i][0]), testCases[i][1]);
809N/A }
809N/A
809N/A return failures;
809N/A }
809N/A
809N/A /* ******************** nextDown tests ********************************* */
809N/A
809N/A public static int testFloatNextDown() {
809N/A int failures=0;
809N/A
809N/A /*
809N/A * Each row of testCases represents one test case for nextDown;
809N/A * the first column is the input and the second column is the
809N/A * expected result.
809N/A */
809N/A float testCases [][] = {
809N/A {NaNf, NaNf},
809N/A {-infinityF, -infinityF},
809N/A {-Float.MAX_VALUE, -infinityF},
809N/A {-Float_MAX_VALUEmm, -Float.MAX_VALUE},
809N/A {-Float_MAX_SUBNORMAL, -FloatConsts.MIN_NORMAL},
809N/A {-Float_MAX_SUBNORMALmm, -Float_MAX_SUBNORMAL},
809N/A {-0.0f, -Float.MIN_VALUE},
809N/A {+0.0f, -Float.MIN_VALUE},
809N/A {Float.MIN_VALUE, 0.0f},
809N/A {Float.MIN_VALUE*2, Float.MIN_VALUE},
809N/A {Float_MAX_SUBNORMAL, Float_MAX_SUBNORMALmm},
809N/A {FloatConsts.MIN_NORMAL, Float_MAX_SUBNORMAL},
809N/A {FloatConsts.MIN_NORMAL+
809N/A Float.MIN_VALUE, FloatConsts.MIN_NORMAL},
809N/A {Float.MAX_VALUE, Float_MAX_VALUEmm},
809N/A {infinityF, Float.MAX_VALUE},
809N/A };
809N/A
809N/A for(int i = 0; i < testCases.length; i++) {
809N/A failures+=Tests.test("FpUtils.nextDown(float)",
809N/A testCases[i][0], FpUtils.nextDown(testCases[i][0]), testCases[i][1]);
809N/A }
809N/A
809N/A return failures;
809N/A }
809N/A
809N/A
809N/A public static int testDoubleNextDown() {
809N/A int failures=0;
809N/A
809N/A /*
809N/A * Each row of testCases represents one test case for nextDown;
809N/A * the first column is the input and the second column is the
809N/A * expected result.
809N/A */
809N/A double testCases [][] = {
809N/A {NaNd, NaNd},
809N/A {-infinityD, -infinityD},
809N/A {-Double.MAX_VALUE, -infinityD},
809N/A {-Double_MAX_VALUEmm, -Double.MAX_VALUE},
809N/A {-Double_MAX_SUBNORMAL, -DoubleConsts.MIN_NORMAL},
809N/A {-Double_MAX_SUBNORMALmm, -Double_MAX_SUBNORMAL},
809N/A {-0.0d, -Double.MIN_VALUE},
809N/A {+0.0d, -Double.MIN_VALUE},
809N/A {Double.MIN_VALUE, 0.0d},
809N/A {Double.MIN_VALUE*2, Double.MIN_VALUE},
809N/A {Double_MAX_SUBNORMAL, Double_MAX_SUBNORMALmm},
809N/A {DoubleConsts.MIN_NORMAL, Double_MAX_SUBNORMAL},
809N/A {DoubleConsts.MIN_NORMAL+
809N/A Double.MIN_VALUE, DoubleConsts.MIN_NORMAL},
809N/A {Double.MAX_VALUE, Double_MAX_VALUEmm},
809N/A {infinityD, Double.MAX_VALUE},
809N/A };
809N/A
809N/A for(int i = 0; i < testCases.length; i++) {
809N/A failures+=Tests.test("FpUtils.nextDown(double)",
809N/A testCases[i][0], FpUtils.nextDown(testCases[i][0]), testCases[i][1]);
809N/A }
809N/A
809N/A return failures;
809N/A }
809N/A
809N/A
809N/A /* ********************** boolean tests ****************************** */
809N/A
809N/A /*
809N/A * Combined tests for boolean functions, isFinite, isInfinite,
809N/A * isNaN, isUnordered.
809N/A */
809N/A
809N/A public static int testFloatBooleanMethods() {
809N/A int failures = 0;
809N/A
809N/A float testCases [] = {
809N/A NaNf,
809N/A -infinityF,
809N/A infinityF,
809N/A -Float.MAX_VALUE,
809N/A -3.0f,
809N/A -1.0f,
809N/A -FloatConsts.MIN_NORMAL,
809N/A -Float_MAX_SUBNORMALmm,
809N/A -Float_MAX_SUBNORMAL,
809N/A -Float.MIN_VALUE,
809N/A -0.0f,
809N/A +0.0f,
809N/A Float.MIN_VALUE,
809N/A Float_MAX_SUBNORMALmm,
809N/A Float_MAX_SUBNORMAL,
809N/A FloatConsts.MIN_NORMAL,
809N/A 1.0f,
809N/A 3.0f,
809N/A Float_MAX_VALUEmm,
809N/A Float.MAX_VALUE
809N/A };
809N/A
809N/A for(int i = 0; i < testCases.length; i++) {
809N/A // isNaN
809N/A failures+=Tests.test("FpUtils.isNaN(float)", testCases[i],
809N/A FpUtils.isNaN(testCases[i]), (i ==0));
809N/A
809N/A // isFinite
809N/A failures+=Tests.test("FpUtils.isFinite(float)", testCases[i],
809N/A FpUtils.isFinite(testCases[i]), (i >= 3));
809N/A
809N/A // isInfinite
809N/A failures+=Tests.test("FpUtils.isInfinite(float)", testCases[i],
809N/A FpUtils.isInfinite(testCases[i]), (i==1 || i==2));
809N/A
809N/A // isUnorderd
809N/A for(int j = 0; j < testCases.length; j++) {
809N/A failures+=Tests.test("FpUtils.isUnordered(float, float)", testCases[i],testCases[j],
809N/A FpUtils.isUnordered(testCases[i],testCases[j]), (i==0 || j==0));
809N/A }
809N/A }
809N/A
809N/A return failures;
809N/A }
809N/A
809N/A public static int testDoubleBooleanMethods() {
809N/A int failures = 0;
809N/A boolean result = false;
809N/A
809N/A double testCases [] = {
809N/A NaNd,
809N/A -infinityD,
809N/A infinityD,
809N/A -Double.MAX_VALUE,
809N/A -3.0d,
809N/A -1.0d,
809N/A -DoubleConsts.MIN_NORMAL,
809N/A -Double_MAX_SUBNORMALmm,
809N/A -Double_MAX_SUBNORMAL,
809N/A -Double.MIN_VALUE,
809N/A -0.0d,
809N/A +0.0d,
809N/A Double.MIN_VALUE,
809N/A Double_MAX_SUBNORMALmm,
809N/A Double_MAX_SUBNORMAL,
809N/A DoubleConsts.MIN_NORMAL,
809N/A 1.0d,
809N/A 3.0d,
809N/A Double_MAX_VALUEmm,
809N/A Double.MAX_VALUE
809N/A };
809N/A
809N/A for(int i = 0; i < testCases.length; i++) {
809N/A // isNaN
809N/A failures+=Tests.test("FpUtils.isNaN(double)", testCases[i],
809N/A FpUtils.isNaN(testCases[i]), (i ==0));
809N/A
809N/A // isFinite
809N/A failures+=Tests.test("FpUtils.isFinite(double)", testCases[i],
809N/A FpUtils.isFinite(testCases[i]), (i >= 3));
809N/A
809N/A // isInfinite
809N/A failures+=Tests.test("FpUtils.isInfinite(double)", testCases[i],
809N/A FpUtils.isInfinite(testCases[i]), (i==1 || i==2));
809N/A
809N/A // isUnorderd
809N/A for(int j = 0; j < testCases.length; j++) {
809N/A failures+=Tests.test("FpUtils.isUnordered(double, double)", testCases[i],testCases[j],
809N/A FpUtils.isUnordered(testCases[i],testCases[j]), (i==0 || j==0));
809N/A }
809N/A }
809N/A
809N/A return failures;
809N/A }
809N/A
809N/A /* ******************** copySign tests******************************** */
809N/A
809N/A public static int testFloatCopySign() {
809N/A int failures = 0;
809N/A
809N/A // testCases[0] are logically positive numbers;
809N/A // testCases[1] are negative numbers.
809N/A float testCases [][] = {
809N/A {+0.0f,
809N/A Float.MIN_VALUE,
809N/A Float_MAX_SUBNORMALmm,
809N/A Float_MAX_SUBNORMAL,
809N/A FloatConsts.MIN_NORMAL,
809N/A 1.0f,
809N/A 3.0f,
809N/A Float_MAX_VALUEmm,
809N/A Float.MAX_VALUE,
809N/A infinityF,
809N/A },
809N/A {-infinityF,
809N/A -Float.MAX_VALUE,
809N/A -3.0f,
809N/A -1.0f,
809N/A -FloatConsts.MIN_NORMAL,
809N/A -Float_MAX_SUBNORMALmm,
809N/A -Float_MAX_SUBNORMAL,
809N/A -Float.MIN_VALUE,
809N/A -0.0f}
809N/A };
809N/A
809N/A float NaNs[] = {Float.intBitsToFloat(0x7fc00000), // "positive" NaN
809N/A Float.intBitsToFloat(0xFfc00000)}; // "negative" NaN
809N/A
809N/A // Tests shared between raw and non-raw versions
809N/A for(int i = 0; i < 2; i++) {
809N/A for(int j = 0; j < 2; j++) {
809N/A for(int m = 0; m < testCases[i].length; m++) {
809N/A for(int n = 0; n < testCases[j].length; n++) {
809N/A // copySign(magnitude, sign)
809N/A failures+=Tests.test("Math.copySign(float,float)",
809N/A testCases[i][m],testCases[j][n],
809N/A Math.copySign(testCases[i][m], testCases[j][n]),
809N/A (j==0?1.0f:-1.0f)*Math.abs(testCases[i][m]) );
809N/A
809N/A failures+=Tests.test("StrictMath.copySign(float,float)",
809N/A testCases[i][m],testCases[j][n],
809N/A StrictMath.copySign(testCases[i][m], testCases[j][n]),
809N/A (j==0?1.0f:-1.0f)*Math.abs(testCases[i][m]) );
809N/A }
809N/A }
809N/A }
809N/A }
809N/A
809N/A // For rawCopySign, NaN may effectively have either sign bit
809N/A // while for copySign NaNs are treated as if they always have
809N/A // a zero sign bit (i.e. as positive numbers)
809N/A for(int i = 0; i < 2; i++) {
809N/A for(int j = 0; j < NaNs.length; j++) {
809N/A for(int m = 0; m < testCases[i].length; m++) {
809N/A // copySign(magnitude, sign)
809N/A
809N/A failures += (Math.abs(Math.copySign(testCases[i][m], NaNs[j])) ==
809N/A Math.abs(testCases[i][m])) ? 0:1;
809N/A
809N/A
809N/A failures+=Tests.test("StrictMath.copySign(float,float)",
809N/A testCases[i][m], NaNs[j],
809N/A StrictMath.copySign(testCases[i][m], NaNs[j]),
809N/A Math.abs(testCases[i][m]) );
809N/A }
809N/A }
809N/A }
809N/A
809N/A return failures;
809N/A }
809N/A
809N/A public static int testDoubleCopySign() {
809N/A int failures = 0;
809N/A
809N/A // testCases[0] are logically positive numbers;
809N/A // testCases[1] are negative numbers.
809N/A double testCases [][] = {
809N/A {+0.0d,
809N/A Double.MIN_VALUE,
809N/A Double_MAX_SUBNORMALmm,
809N/A Double_MAX_SUBNORMAL,
809N/A DoubleConsts.MIN_NORMAL,
809N/A 1.0d,
809N/A 3.0d,
809N/A Double_MAX_VALUEmm,
809N/A Double.MAX_VALUE,
809N/A infinityD,
809N/A },
809N/A {-infinityD,
809N/A -Double.MAX_VALUE,
809N/A -3.0d,
809N/A -1.0d,
809N/A -DoubleConsts.MIN_NORMAL,
809N/A -Double_MAX_SUBNORMALmm,
809N/A -Double_MAX_SUBNORMAL,
809N/A -Double.MIN_VALUE,
809N/A -0.0d}
809N/A };
809N/A
809N/A double NaNs[] = {Double.longBitsToDouble(0x7ff8000000000000L), // "positive" NaN
809N/A Double.longBitsToDouble(0xfff8000000000000L), // "negative" NaN
809N/A Double.longBitsToDouble(0x7FF0000000000001L),
809N/A Double.longBitsToDouble(0xFFF0000000000001L),
809N/A Double.longBitsToDouble(0x7FF8555555555555L),
809N/A Double.longBitsToDouble(0xFFF8555555555555L),
809N/A Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL),
809N/A Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL),
809N/A Double.longBitsToDouble(0x7FFDeadBeef00000L),
809N/A Double.longBitsToDouble(0xFFFDeadBeef00000L),
809N/A Double.longBitsToDouble(0x7FFCafeBabe00000L),
809N/A Double.longBitsToDouble(0xFFFCafeBabe00000L)};
809N/A
809N/A // Tests shared between Math and StrictMath versions
809N/A for(int i = 0; i < 2; i++) {
809N/A for(int j = 0; j < 2; j++) {
809N/A for(int m = 0; m < testCases[i].length; m++) {
809N/A for(int n = 0; n < testCases[j].length; n++) {
809N/A // copySign(magnitude, sign)
809N/A failures+=Tests.test("MathcopySign(double,double)",
809N/A testCases[i][m],testCases[j][n],
809N/A Math.copySign(testCases[i][m], testCases[j][n]),
809N/A (j==0?1.0f:-1.0f)*Math.abs(testCases[i][m]) );
809N/A
809N/A failures+=Tests.test("StrictMath.copySign(double,double)",
809N/A testCases[i][m],testCases[j][n],
809N/A StrictMath.copySign(testCases[i][m], testCases[j][n]),
809N/A (j==0?1.0f:-1.0f)*Math.abs(testCases[i][m]) );
809N/A }
809N/A }
809N/A }
809N/A }
809N/A
809N/A // For Math.copySign, NaN may effectively have either sign bit
809N/A // while for StrictMath.copySign NaNs are treated as if they
809N/A // always have a zero sign bit (i.e. as positive numbers)
809N/A for(int i = 0; i < 2; i++) {
809N/A for(int j = 0; j < NaNs.length; j++) {
809N/A for(int m = 0; m < testCases[i].length; m++) {
809N/A // copySign(magnitude, sign)
809N/A
809N/A failures += (Math.abs(Math.copySign(testCases[i][m], NaNs[j])) ==
809N/A Math.abs(testCases[i][m])) ? 0:1;
809N/A
809N/A
809N/A failures+=Tests.test("StrictMath.copySign(double,double)",
809N/A testCases[i][m], NaNs[j],
809N/A StrictMath.copySign(testCases[i][m], NaNs[j]),
809N/A Math.abs(testCases[i][m]) );
809N/A }
809N/A }
809N/A }
809N/A
809N/A
809N/A return failures;
809N/A }
809N/A
809N/A /* ************************ scalb tests ******************************* */
809N/A
809N/A static int testScalbCase(float value, int scale_factor, float expected) {
809N/A int failures=0;
809N/A
809N/A failures+=Tests.test("Math.scalb(float,int)",
809N/A value, scale_factor,
809N/A Math.scalb(value, scale_factor), expected);
809N/A
809N/A failures+=Tests.test("Math.scalb(float,int)",
809N/A -value, scale_factor,
809N/A Math.scalb(-value, scale_factor), -expected);
809N/A
809N/A failures+=Tests.test("StrictMath.scalb(float,int)",
809N/A value, scale_factor,
809N/A StrictMath.scalb(value, scale_factor), expected);
809N/A
809N/A failures+=Tests.test("StrictMath.scalb(float,int)",
809N/A -value, scale_factor,
809N/A StrictMath.scalb(-value, scale_factor), -expected);
809N/A return failures;
809N/A }
809N/A
809N/A public static int testFloatScalb() {
809N/A int failures=0;
809N/A int MAX_SCALE = FloatConsts.MAX_EXPONENT + -FloatConsts.MIN_EXPONENT +
809N/A FloatConsts.SIGNIFICAND_WIDTH + 1;
809N/A
809N/A
809N/A // Arguments x, where scalb(x,n) is x for any n.
809N/A float [] identityTestCases = {NaNf,
809N/A -0.0f,
809N/A +0.0f,
809N/A infinityF,
809N/A -infinityF
809N/A };
809N/A
809N/A float [] subnormalTestCases = {
809N/A Float.MIN_VALUE,
809N/A 3.0f*Float.MIN_VALUE,
809N/A Float_MAX_SUBNORMALmm,
809N/A Float_MAX_SUBNORMAL
809N/A };
809N/A
809N/A float [] someTestCases = {
809N/A Float.MIN_VALUE,
809N/A 3.0f*Float.MIN_VALUE,
809N/A Float_MAX_SUBNORMALmm,
809N/A Float_MAX_SUBNORMAL,
809N/A FloatConsts.MIN_NORMAL,
809N/A 1.0f,
809N/A 2.0f,
809N/A 3.0f,
809N/A (float)Math.PI,
809N/A Float_MAX_VALUEmm,
809N/A Float.MAX_VALUE
809N/A };
809N/A
809N/A int [] oneMultiplyScalingFactors = {
809N/A FloatConsts.MIN_EXPONENT,
809N/A FloatConsts.MIN_EXPONENT+1,
809N/A -3,
809N/A -2,
809N/A -1,
809N/A 0,
809N/A 1,
809N/A 2,
809N/A 3,
809N/A FloatConsts.MAX_EXPONENT-1,
809N/A FloatConsts.MAX_EXPONENT
809N/A };
809N/A
809N/A int [] manyScalingFactors = {
809N/A Integer.MIN_VALUE,
809N/A Integer.MIN_VALUE+1,
809N/A -MAX_SCALE -1,
809N/A -MAX_SCALE,
809N/A -MAX_SCALE+1,
809N/A
809N/A 2*FloatConsts.MIN_EXPONENT-1, // -253
809N/A 2*FloatConsts.MIN_EXPONENT, // -252
809N/A 2*FloatConsts.MIN_EXPONENT+1, // -251
809N/A
809N/A FpUtils.ilogb(Float.MIN_VALUE)-1, // -150
809N/A FpUtils.ilogb(Float.MIN_VALUE), // -149
809N/A -FloatConsts.MAX_EXPONENT, // -127
809N/A FloatConsts.MIN_EXPONENT, // -126
809N/A
809N/A -2,
809N/A -1,
809N/A 0,
809N/A 1,
809N/A 2,
809N/A
809N/A FloatConsts.MAX_EXPONENT-1, // 126
809N/A FloatConsts.MAX_EXPONENT, // 127
809N/A FloatConsts.MAX_EXPONENT+1, // 128
809N/A
809N/A 2*FloatConsts.MAX_EXPONENT-1, // 253
809N/A 2*FloatConsts.MAX_EXPONENT, // 254
809N/A 2*FloatConsts.MAX_EXPONENT+1, // 255
809N/A
809N/A MAX_SCALE-1,
809N/A MAX_SCALE,
809N/A MAX_SCALE+1,
809N/A Integer.MAX_VALUE-1,
809N/A Integer.MAX_VALUE
809N/A };
809N/A
809N/A // Test cases where scaling is always a no-op
809N/A for(int i=0; i < identityTestCases.length; i++) {
809N/A for(int j=0; j < manyScalingFactors.length; j++) {
809N/A failures += testScalbCase(identityTestCases[i],
809N/A manyScalingFactors[j],
809N/A identityTestCases[i]);
809N/A }
809N/A }
809N/A
809N/A // Test cases where result is 0.0 or infinity due to magnitude
809N/A // of the scaling factor
809N/A for(int i=0; i < someTestCases.length; i++) {
809N/A for(int j=0; j < manyScalingFactors.length; j++) {
809N/A int scaleFactor = manyScalingFactors[j];
809N/A if (Math.abs(scaleFactor) >= MAX_SCALE) {
809N/A float value = someTestCases[i];
809N/A failures+=testScalbCase(value,
809N/A scaleFactor,
809N/A FpUtils.copySign( (scaleFactor>0?infinityF:0.0f), value) );
809N/A }
809N/A }
809N/A }
809N/A
809N/A // Test cases that could be done with one floating-point
809N/A // multiply.
809N/A for(int i=0; i < someTestCases.length; i++) {
809N/A for(int j=0; j < oneMultiplyScalingFactors.length; j++) {
809N/A int scaleFactor = oneMultiplyScalingFactors[j];
809N/A float value = someTestCases[i];
809N/A
809N/A failures+=testScalbCase(value,
809N/A scaleFactor,
809N/A value*powerOfTwoF(scaleFactor));
809N/A }
809N/A }
809N/A
809N/A // Create 2^MAX_EXPONENT
809N/A float twoToTheMaxExp = 1.0f; // 2^0
809N/A for(int i = 0; i < FloatConsts.MAX_EXPONENT; i++)
809N/A twoToTheMaxExp *=2.0f;
809N/A
809N/A // Scale-up subnormal values until they all overflow
809N/A for(int i=0; i < subnormalTestCases.length; i++) {
809N/A float scale = 1.0f; // 2^j
809N/A float value = subnormalTestCases[i];
809N/A
809N/A for(int j=FloatConsts.MAX_EXPONENT*2; j < MAX_SCALE; j++) { // MAX_SCALE -1 should cause overflow
809N/A int scaleFactor = j;
809N/A
809N/A failures+=testScalbCase(value,
809N/A scaleFactor,
809N/A (FpUtils.ilogb(value) +j > FloatConsts.MAX_EXPONENT ) ?
809N/A FpUtils.copySign(infinityF, value) : // overflow
809N/A // calculate right answer
809N/A twoToTheMaxExp*(twoToTheMaxExp*(scale*value)) );
809N/A scale*=2.0f;
809N/A }
809N/A }
809N/A
809N/A // Scale down a large number until it underflows. By scaling
809N/A // down MAX_NORMALmm, the first subnormal result will be exact
809N/A // but the next one will round -- all those results can be
809N/A // checked by halving a separate value in the loop. Actually,
809N/A // we can keep halving and checking until the product is zero
809N/A // since:
809N/A //
809N/A // 1. If the scalb of MAX_VALUEmm is subnormal and *not* exact
809N/A // it will round *up*
809N/A //
809N/A // 2. When rounding first occurs in the expected product, it
809N/A // too rounds up, to 2^-MAX_EXPONENT.
809N/A //
809N/A // Halving expected after rounding happends to give the same
809N/A // result as the scalb operation.
809N/A float expected = Float_MAX_VALUEmm *0.5f;
809N/A for(int i = -1; i > -MAX_SCALE; i--) {
809N/A failures+=testScalbCase(Float_MAX_VALUEmm, i, expected);
809N/A
809N/A expected *= 0.5f;
809N/A }
809N/A
809N/A // Tricky rounding tests:
809N/A // Scale down a large number into subnormal range such that if
809N/A // scalb is being implemented with multiple floating-point
809N/A // multiplies, the value would round twice if the multiplies
809N/A // were done in the wrong order.
809N/A
809N/A float value = 0x8.0000bP-5f;
809N/A expected = 0x1.00001p-129f;
809N/A
809N/A for(int i = 0; i < 129; i++) {
809N/A failures+=testScalbCase(value,
809N/A -127-i,
809N/A expected);
809N/A value *=2.0f;
809N/A }
809N/A
809N/A return failures;
809N/A }
809N/A
809N/A static int testScalbCase(double value, int scale_factor, double expected) {
809N/A int failures=0;
809N/A
809N/A failures+=Tests.test("Math.scalb(double,int)",
809N/A value, scale_factor,
809N/A Math.scalb(value, scale_factor), expected);
809N/A
809N/A failures+=Tests.test("Math.scalb(double,int)",
809N/A -value, scale_factor,
809N/A Math.scalb(-value, scale_factor), -expected);
809N/A
809N/A failures+=Tests.test("StrictMath.scalb(double,int)",
809N/A value, scale_factor,
809N/A StrictMath.scalb(value, scale_factor), expected);
809N/A
809N/A failures+=Tests.test("StrictMath.scalb(double,int)",
809N/A -value, scale_factor,
809N/A StrictMath.scalb(-value, scale_factor), -expected);
809N/A
809N/A return failures;
809N/A }
809N/A
809N/A public static int testDoubleScalb() {
809N/A int failures=0;
809N/A int MAX_SCALE = DoubleConsts.MAX_EXPONENT + -DoubleConsts.MIN_EXPONENT +
809N/A DoubleConsts.SIGNIFICAND_WIDTH + 1;
809N/A
809N/A
809N/A // Arguments x, where scalb(x,n) is x for any n.
809N/A double [] identityTestCases = {NaNd,
809N/A -0.0,
809N/A +0.0,
809N/A infinityD,
809N/A };
809N/A
809N/A double [] subnormalTestCases = {
809N/A Double.MIN_VALUE,
809N/A 3.0d*Double.MIN_VALUE,
809N/A Double_MAX_SUBNORMALmm,
809N/A Double_MAX_SUBNORMAL
809N/A };
809N/A
809N/A double [] someTestCases = {
809N/A Double.MIN_VALUE,
809N/A 3.0d*Double.MIN_VALUE,
809N/A Double_MAX_SUBNORMALmm,
809N/A Double_MAX_SUBNORMAL,
809N/A DoubleConsts.MIN_NORMAL,
809N/A 1.0d,
809N/A 2.0d,
809N/A 3.0d,
809N/A Math.PI,
809N/A Double_MAX_VALUEmm,
809N/A Double.MAX_VALUE
809N/A };
809N/A
809N/A int [] oneMultiplyScalingFactors = {
809N/A DoubleConsts.MIN_EXPONENT,
809N/A DoubleConsts.MIN_EXPONENT+1,
809N/A -3,
809N/A -2,
809N/A -1,
809N/A 0,
809N/A 1,
809N/A 2,
809N/A 3,
809N/A DoubleConsts.MAX_EXPONENT-1,
809N/A DoubleConsts.MAX_EXPONENT
809N/A };
809N/A
809N/A int [] manyScalingFactors = {
809N/A Integer.MIN_VALUE,
809N/A Integer.MIN_VALUE+1,
809N/A -MAX_SCALE -1,
809N/A -MAX_SCALE,
809N/A -MAX_SCALE+1,
809N/A
809N/A 2*DoubleConsts.MIN_EXPONENT-1, // -2045
809N/A 2*DoubleConsts.MIN_EXPONENT, // -2044
809N/A 2*DoubleConsts.MIN_EXPONENT+1, // -2043
809N/A
809N/A FpUtils.ilogb(Double.MIN_VALUE)-1, // -1076
809N/A FpUtils.ilogb(Double.MIN_VALUE), // -1075
809N/A -DoubleConsts.MAX_EXPONENT, // -1023
809N/A DoubleConsts.MIN_EXPONENT, // -1022
809N/A
809N/A -2,
809N/A -1,
809N/A 0,
809N/A 1,
809N/A 2,
809N/A
809N/A DoubleConsts.MAX_EXPONENT-1, // 1022
809N/A DoubleConsts.MAX_EXPONENT, // 1023
809N/A DoubleConsts.MAX_EXPONENT+1, // 1024
809N/A
809N/A 2*DoubleConsts.MAX_EXPONENT-1, // 2045
809N/A 2*DoubleConsts.MAX_EXPONENT, // 2046
809N/A 2*DoubleConsts.MAX_EXPONENT+1, // 2047
809N/A
809N/A MAX_SCALE-1,
809N/A MAX_SCALE,
809N/A MAX_SCALE+1,
809N/A Integer.MAX_VALUE-1,
809N/A Integer.MAX_VALUE
809N/A };
809N/A
809N/A // Test cases where scaling is always a no-op
809N/A for(int i=0; i < identityTestCases.length; i++) {
809N/A for(int j=0; j < manyScalingFactors.length; j++) {
809N/A failures += testScalbCase(identityTestCases[i],
809N/A manyScalingFactors[j],
809N/A identityTestCases[i]);
809N/A }
809N/A }
809N/A
809N/A // Test cases where result is 0.0 or infinity due to magnitude
809N/A // of the scaling factor
809N/A for(int i=0; i < someTestCases.length; i++) {
809N/A for(int j=0; j < manyScalingFactors.length; j++) {
809N/A int scaleFactor = manyScalingFactors[j];
809N/A if (Math.abs(scaleFactor) >= MAX_SCALE) {
809N/A double value = someTestCases[i];
809N/A failures+=testScalbCase(value,
809N/A scaleFactor,
809N/A FpUtils.copySign( (scaleFactor>0?infinityD:0.0), value) );
809N/A }
809N/A }
809N/A }
809N/A
809N/A // Test cases that could be done with one floating-point
809N/A // multiply.
809N/A for(int i=0; i < someTestCases.length; i++) {
809N/A for(int j=0; j < oneMultiplyScalingFactors.length; j++) {
809N/A int scaleFactor = oneMultiplyScalingFactors[j];
809N/A double value = someTestCases[i];
809N/A
809N/A failures+=testScalbCase(value,
809N/A scaleFactor,
809N/A value*powerOfTwoD(scaleFactor));
809N/A }
809N/A }
809N/A
809N/A // Create 2^MAX_EXPONENT
809N/A double twoToTheMaxExp = 1.0; // 2^0
809N/A for(int i = 0; i < DoubleConsts.MAX_EXPONENT; i++)
809N/A twoToTheMaxExp *=2.0;
809N/A
809N/A // Scale-up subnormal values until they all overflow
809N/A for(int i=0; i < subnormalTestCases.length; i++) {
809N/A double scale = 1.0; // 2^j
809N/A double value = subnormalTestCases[i];
809N/A
809N/A for(int j=DoubleConsts.MAX_EXPONENT*2; j < MAX_SCALE; j++) { // MAX_SCALE -1 should cause overflow
809N/A int scaleFactor = j;
809N/A
809N/A failures+=testScalbCase(value,
809N/A scaleFactor,
809N/A (FpUtils.ilogb(value) +j > DoubleConsts.MAX_EXPONENT ) ?
809N/A FpUtils.copySign(infinityD, value) : // overflow
809N/A // calculate right answer
809N/A twoToTheMaxExp*(twoToTheMaxExp*(scale*value)) );
809N/A scale*=2.0;
809N/A }
809N/A }
809N/A
809N/A // Scale down a large number until it underflows. By scaling
809N/A // down MAX_NORMALmm, the first subnormal result will be exact
809N/A // but the next one will round -- all those results can be
809N/A // checked by halving a separate value in the loop. Actually,
809N/A // we can keep halving and checking until the product is zero
809N/A // since:
809N/A //
809N/A // 1. If the scalb of MAX_VALUEmm is subnormal and *not* exact
809N/A // it will round *up*
809N/A //
809N/A // 2. When rounding first occurs in the expected product, it
809N/A // too rounds up, to 2^-MAX_EXPONENT.
809N/A //
809N/A // Halving expected after rounding happends to give the same
809N/A // result as the scalb operation.
809N/A double expected = Double_MAX_VALUEmm *0.5f;
809N/A for(int i = -1; i > -MAX_SCALE; i--) {
809N/A failures+=testScalbCase(Double_MAX_VALUEmm, i, expected);
809N/A
809N/A expected *= 0.5;
809N/A }
809N/A
809N/A // Tricky rounding tests:
809N/A // Scale down a large number into subnormal range such that if
809N/A // scalb is being implemented with multiple floating-point
809N/A // multiplies, the value would round twice if the multiplies
809N/A // were done in the wrong order.
809N/A
809N/A double value = 0x1.000000000000bP-1;
809N/A expected = 0x0.2000000000001P-1022;
809N/A for(int i = 0; i < DoubleConsts.MAX_EXPONENT+2; i++) {
809N/A failures+=testScalbCase(value,
809N/A -1024-i,
809N/A expected);
809N/A value *=2.0;
809N/A }
809N/A
809N/A return failures;
809N/A }
809N/A
809N/A /* ************************* ulp tests ******************************* */
809N/A
809N/A
809N/A /*
809N/A * Test Math.ulp and StrictMath.ulp with +d and -d.
809N/A */
809N/A static int testUlpCase(float f, float expected) {
809N/A float minus_f = -f;
809N/A int failures=0;
809N/A
809N/A failures+=Tests.test("Math.ulp(float)", f,
809N/A Math.ulp(f), expected);
809N/A failures+=Tests.test("Math.ulp(float)", minus_f,
809N/A Math.ulp(minus_f), expected);
809N/A failures+=Tests.test("StrictMath.ulp(float)", f,
809N/A StrictMath.ulp(f), expected);
809N/A failures+=Tests.test("StrictMath.ulp(float)", minus_f,
809N/A StrictMath.ulp(minus_f), expected);
809N/A return failures;
809N/A }
809N/A
809N/A static int testUlpCase(double d, double expected) {
809N/A double minus_d = -d;
809N/A int failures=0;
809N/A
809N/A failures+=Tests.test("Math.ulp(double)", d,
809N/A Math.ulp(d), expected);
809N/A failures+=Tests.test("Math.ulp(double)", minus_d,
809N/A Math.ulp(minus_d), expected);
809N/A failures+=Tests.test("StrictMath.ulp(double)", d,
809N/A StrictMath.ulp(d), expected);
809N/A failures+=Tests.test("StrictMath.ulp(double)", minus_d,
809N/A StrictMath.ulp(minus_d), expected);
809N/A return failures;
809N/A }
809N/A
809N/A public static int testFloatUlp() {
809N/A int failures = 0;
809N/A float [] specialValues = {NaNf,
809N/A Float.POSITIVE_INFINITY,
809N/A +0.0f,
809N/A +1.0f,
809N/A +2.0f,
809N/A +16.0f,
809N/A +Float.MIN_VALUE,
809N/A +Float_MAX_SUBNORMAL,
809N/A +FloatConsts.MIN_NORMAL,
809N/A +Float.MAX_VALUE
809N/A };
809N/A
809N/A float [] specialResults = {NaNf,
809N/A Float.POSITIVE_INFINITY,
809N/A Float.MIN_VALUE,
809N/A powerOfTwoF(-23),
809N/A powerOfTwoF(-22),
809N/A powerOfTwoF(-19),
809N/A Float.MIN_VALUE,
809N/A Float.MIN_VALUE,
809N/A Float.MIN_VALUE,
809N/A powerOfTwoF(104)
809N/A };
809N/A
809N/A // Special value tests
809N/A for(int i = 0; i < specialValues.length; i++) {
809N/A failures += testUlpCase(specialValues[i], specialResults[i]);
809N/A }
809N/A
809N/A
809N/A // Normal exponent tests
809N/A for(int i = FloatConsts.MIN_EXPONENT; i <= FloatConsts.MAX_EXPONENT; i++) {
809N/A float expected;
809N/A
809N/A // Create power of two
809N/A float po2 = powerOfTwoF(i);
809N/A expected = FpUtils.scalb(1.0f, i - (FloatConsts.SIGNIFICAND_WIDTH-1));
809N/A
809N/A failures += testUlpCase(po2, expected);
809N/A
809N/A // Generate some random bit patterns for the significand
809N/A for(int j = 0; j < 10; j++) {
809N/A int randSignif = rand.nextInt();
809N/A float randFloat;
809N/A
809N/A randFloat = Float.intBitsToFloat( // Exponent
809N/A (Float.floatToIntBits(po2)&
809N/A (~FloatConsts.SIGNIF_BIT_MASK)) |
809N/A // Significand
809N/A (randSignif &
809N/A FloatConsts.SIGNIF_BIT_MASK) );
809N/A
809N/A failures += testUlpCase(randFloat, expected);
809N/A }
809N/A
809N/A if (i > FloatConsts.MIN_EXPONENT) {
809N/A float po2minus = FpUtils.nextAfter(po2,
809N/A Float.NEGATIVE_INFINITY);
809N/A failures += testUlpCase(po2minus, expected/2.0f);
809N/A }
809N/A }
809N/A
809N/A // Subnormal tests
809N/A
809N/A /*
809N/A * Start with MIN_VALUE, left shift, test high value, low
809N/A * values, and random in between.
809N/A *
809N/A * Use nextAfter to calculate, high value of previous binade,
809N/A * loop count i will indicate how many random bits, if any are
809N/A * needed.
809N/A */
809N/A
809N/A float top=Float.MIN_VALUE;
809N/A for( int i = 1;
809N/A i < FloatConsts.SIGNIFICAND_WIDTH;
809N/A i++, top *= 2.0f) {
809N/A
809N/A failures += testUlpCase(top, Float.MIN_VALUE);
809N/A
809N/A // Test largest value in next smaller binade
809N/A if (i >= 3) {// (i == 1) would test 0.0;
809N/A // (i == 2) would just retest MIN_VALUE
809N/A testUlpCase(FpUtils.nextAfter(top, 0.0f),
809N/A Float.MIN_VALUE);
809N/A
809N/A if( i >= 10) {
809N/A // create a bit mask with (i-1) 1's in the low order
809N/A // bits
809N/A int mask = ~((~0)<<(i-1));
809N/A float randFloat = Float.intBitsToFloat( // Exponent
809N/A Float.floatToIntBits(top) |
809N/A // Significand
809N/A (rand.nextInt() & mask ) ) ;
809N/A
809N/A failures += testUlpCase(randFloat, Float.MIN_VALUE);
809N/A }
809N/A }
809N/A }
809N/A
809N/A return failures;
809N/A }
809N/A
809N/A public static int testDoubleUlp() {
809N/A int failures = 0;
809N/A double [] specialValues = {NaNd,
809N/A Double.POSITIVE_INFINITY,
809N/A +0.0d,
809N/A +1.0d,
809N/A +2.0d,
809N/A +16.0d,
809N/A +Double.MIN_VALUE,
809N/A +Double_MAX_SUBNORMAL,
809N/A +DoubleConsts.MIN_NORMAL,
809N/A +Double.MAX_VALUE
809N/A };
809N/A
809N/A double [] specialResults = {NaNf,
809N/A Double.POSITIVE_INFINITY,
809N/A Double.MIN_VALUE,
809N/A powerOfTwoD(-52),
809N/A powerOfTwoD(-51),
809N/A powerOfTwoD(-48),
809N/A Double.MIN_VALUE,
809N/A Double.MIN_VALUE,
809N/A Double.MIN_VALUE,
809N/A powerOfTwoD(971)
809N/A };
809N/A
809N/A // Special value tests
809N/A for(int i = 0; i < specialValues.length; i++) {
809N/A failures += testUlpCase(specialValues[i], specialResults[i]);
809N/A }
809N/A
809N/A
809N/A // Normal exponent tests
809N/A for(int i = DoubleConsts.MIN_EXPONENT; i <= DoubleConsts.MAX_EXPONENT; i++) {
809N/A double expected;
809N/A
809N/A // Create power of two
809N/A double po2 = powerOfTwoD(i);
809N/A expected = FpUtils.scalb(1.0, i - (DoubleConsts.SIGNIFICAND_WIDTH-1));
809N/A
809N/A failures += testUlpCase(po2, expected);
809N/A
809N/A // Generate some random bit patterns for the significand
809N/A for(int j = 0; j < 10; j++) {
809N/A long randSignif = rand.nextLong();
809N/A double randDouble;
809N/A
809N/A randDouble = Double.longBitsToDouble( // Exponent
809N/A (Double.doubleToLongBits(po2)&
809N/A (~DoubleConsts.SIGNIF_BIT_MASK)) |
809N/A // Significand
809N/A (randSignif &
809N/A DoubleConsts.SIGNIF_BIT_MASK) );
809N/A
809N/A failures += testUlpCase(randDouble, expected);
809N/A }
809N/A
809N/A if (i > DoubleConsts.MIN_EXPONENT) {
809N/A double po2minus = FpUtils.nextAfter(po2,
809N/A Double.NEGATIVE_INFINITY);
809N/A failures += testUlpCase(po2minus, expected/2.0f);
809N/A }
809N/A }
809N/A
809N/A // Subnormal tests
809N/A
809N/A /*
809N/A * Start with MIN_VALUE, left shift, test high value, low
809N/A * values, and random in between.
809N/A *
809N/A * Use nextAfter to calculate, high value of previous binade,
809N/A * loop count i will indicate how many random bits, if any are
809N/A * needed.
809N/A */
809N/A
809N/A double top=Double.MIN_VALUE;
809N/A for( int i = 1;
809N/A i < DoubleConsts.SIGNIFICAND_WIDTH;
809N/A i++, top *= 2.0f) {
809N/A
809N/A failures += testUlpCase(top, Double.MIN_VALUE);
809N/A
809N/A // Test largest value in next smaller binade
809N/A if (i >= 3) {// (i == 1) would test 0.0;
809N/A // (i == 2) would just retest MIN_VALUE
809N/A testUlpCase(FpUtils.nextAfter(top, 0.0f),
809N/A Double.MIN_VALUE);
809N/A
809N/A if( i >= 10) {
809N/A // create a bit mask with (i-1) 1's in the low order
809N/A // bits
809N/A int mask = ~((~0)<<(i-1));
809N/A double randDouble = Double.longBitsToDouble( // Exponent
809N/A Double.doubleToLongBits(top) |
809N/A // Significand
809N/A (rand.nextLong() & mask ) ) ;
809N/A
809N/A failures += testUlpCase(randDouble, Double.MIN_VALUE);
809N/A }
809N/A }
809N/A }
809N/A
809N/A return failures;
809N/A }
809N/A
809N/A public static int testFloatSignum() {
809N/A int failures = 0;
809N/A float testCases [][] = {
809N/A {NaNf, NaNf},
809N/A {-infinityF, -1.0f},
809N/A {-Float.MAX_VALUE, -1.0f},
809N/A {-FloatConsts.MIN_NORMAL, -1.0f},
809N/A {-1.0f, -1.0f},
809N/A {-2.0f, -1.0f},
809N/A {-Float_MAX_SUBNORMAL, -1.0f},
809N/A {-Float.MIN_VALUE, -1.0f},
809N/A {-0.0f, -0.0f},
809N/A {+0.0f, +0.0f},
809N/A {Float.MIN_VALUE, 1.0f},
809N/A {Float_MAX_SUBNORMALmm, 1.0f},
809N/A {Float_MAX_SUBNORMAL, 1.0f},
809N/A {FloatConsts.MIN_NORMAL, 1.0f},
809N/A {1.0f, 1.0f},
809N/A {2.0f, 1.0f},
809N/A {Float_MAX_VALUEmm, 1.0f},
809N/A {Float.MAX_VALUE, 1.0f},
809N/A {infinityF, 1.0f}
809N/A };
809N/A
809N/A for(int i = 0; i < testCases.length; i++) {
809N/A failures+=Tests.test("Math.signum(float)",
809N/A testCases[i][0], Math.signum(testCases[i][0]), testCases[i][1]);
809N/A failures+=Tests.test("StrictMath.signum(float)",
809N/A testCases[i][0], StrictMath.signum(testCases[i][0]), testCases[i][1]);
809N/A }
809N/A
809N/A return failures;
809N/A }
809N/A
809N/A public static int testDoubleSignum() {
809N/A int failures = 0;
809N/A double testCases [][] = {
809N/A {NaNd, NaNd},
809N/A {-infinityD, -1.0},
809N/A {-Double.MAX_VALUE, -1.0},
809N/A {-DoubleConsts.MIN_NORMAL, -1.0},
809N/A {-1.0, -1.0},
809N/A {-2.0, -1.0},
809N/A {-Double_MAX_SUBNORMAL, -1.0},
809N/A {-Double.MIN_VALUE, -1.0d},
809N/A {-0.0d, -0.0d},
809N/A {+0.0d, +0.0d},
809N/A {Double.MIN_VALUE, 1.0},
809N/A {Double_MAX_SUBNORMALmm, 1.0},
809N/A {Double_MAX_SUBNORMAL, 1.0},
809N/A {DoubleConsts.MIN_NORMAL, 1.0},
809N/A {1.0, 1.0},
809N/A {2.0, 1.0},
809N/A {Double_MAX_VALUEmm, 1.0},
809N/A {Double.MAX_VALUE, 1.0},
809N/A {infinityD, 1.0}
809N/A };
809N/A
809N/A for(int i = 0; i < testCases.length; i++) {
809N/A failures+=Tests.test("Math.signum(double)",
809N/A testCases[i][0], Math.signum(testCases[i][0]), testCases[i][1]);
809N/A failures+=Tests.test("StrictMath.signum(double)",
809N/A testCases[i][0], StrictMath.signum(testCases[i][0]), testCases[i][1]);
809N/A }
809N/A
809N/A return failures;
809N/A }
809N/A
809N/A
809N/A public static void main(String argv[]) {
809N/A int failures = 0;
809N/A
809N/A failures += testFloatGetExponent();
809N/A failures += testDoubleGetExponent();
809N/A
809N/A failures += testFloatNextAfter();
809N/A failures += testDoubleNextAfter();
809N/A
809N/A failures += testFloatNextUp();
809N/A failures += testDoubleNextUp();
809N/A
809N/A failures += testFloatNextDown();
809N/A failures += testDoubleNextDown();
809N/A
809N/A failures += testFloatBooleanMethods();
809N/A failures += testDoubleBooleanMethods();
809N/A
809N/A failures += testFloatCopySign();
809N/A failures += testDoubleCopySign();
809N/A
809N/A failures += testFloatScalb();
809N/A failures += testDoubleScalb();
809N/A
809N/A failures += testFloatUlp();
809N/A failures += testDoubleUlp();
809N/A
809N/A failures += testFloatSignum();
809N/A failures += testDoubleSignum();
809N/A
809N/A if (failures > 0) {
809N/A System.err.println("Testing the recommended functions incurred "
809N/A + failures + " failures.");
809N/A throw new RuntimeException();
809N/A }
809N/A }
809N/A}