Path: blob/master/test/jdk/java/lang/Math/Tests.java
41149 views
/*1* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* Shared static test methods for numerical tests. Sharing these25* helper test methods avoids repeated functions in the various test26* programs. The test methods return 1 for a test failure and 0 for27* success. The order of arguments to the test methods is generally28* the test name, followed by the test arguments, the computed result,29* and finally the expected result.30*/3132public class Tests {33private Tests(){}; // do not instantiate3435public static String toHexString(float f) {36if (!Float.isNaN(f))37return Float.toHexString(f);38else39return "NaN(0x" + Integer.toHexString(Float.floatToRawIntBits(f)) + ")";40}4142public static String toHexString(double d) {43if (!Double.isNaN(d))44return Double.toHexString(d);45else46return "NaN(0x" + Long.toHexString(Double.doubleToRawLongBits(d)) + ")";47}4849/**50* Return the floating-point value next larger in magnitude.51*/52public static double nextOut(double d) {53if (d > 0.0)54return Math.nextUp(d);55else56return -Math.nextUp(-d);57}5859/**60* Returns unbiased exponent of a {@code float}; for61* subnormal values, the number is treated as if it were62* normalized. That is for all finite, non-zero, positive numbers63* <i>x</i>, <code>scalb(<i>x</i>, -ilogb(<i>x</i>))</code> is64* always in the range [1, 2).65* <p>66* Special cases:67* <ul>68* <li> If the argument is NaN, then the result is 2<sup>30</sup>.69* <li> If the argument is infinite, then the result is 2<sup>28</sup>.70* <li> If the argument is zero, then the result is -(2<sup>28</sup>).71* </ul>72*73* @param f floating-point number whose exponent is to be extracted74* @return unbiased exponent of the argument.75*/76public static int ilogb(double d) {77int exponent = Math.getExponent(d);7879switch (exponent) {80case Double.MAX_EXPONENT+1: // NaN or infinity81if( Double.isNaN(d) )82return (1<<30); // 2^3083else // infinite value84return (1<<28); // 2^288586case Double.MIN_EXPONENT-1: // zero or subnormal87if(d == 0.0) {88return -(1<<28); // -(2^28)89}90else {91long transducer = Double.doubleToRawLongBits(d);9293/*94* To avoid causing slow arithmetic on subnormals,95* the scaling to determine when d's significand96* is normalized is done in integer arithmetic.97* (there must be at least one "1" bit in the98* significand since zero has been screened out.99*/100101// isolate significand bits102transducer &= DoubleConsts.SIGNIF_BIT_MASK;103assert(transducer != 0L);104105// This loop is simple and functional. We might be106// able to do something more clever that was faster;107// e.g. number of leading zero detection on108// (transducer << (# exponent and sign bits).109while (transducer <110(1L << (DoubleConsts.SIGNIFICAND_WIDTH - 1))) {111transducer *= 2;112exponent--;113}114exponent++;115assert( exponent >=116Double.MIN_EXPONENT - (DoubleConsts.SIGNIFICAND_WIDTH-1) &&117exponent < Double.MIN_EXPONENT);118return exponent;119}120121default:122assert( exponent >= Double.MIN_EXPONENT &&123exponent <= Double.MAX_EXPONENT);124return exponent;125}126}127128/**129* Returns unbiased exponent of a {@code float}; for130* subnormal values, the number is treated as if it were131* normalized. That is for all finite, non-zero, positive numbers132* <i>x</i>, <code>scalb(<i>x</i>, -ilogb(<i>x</i>))</code> is133* always in the range [1, 2).134* <p>135* Special cases:136* <ul>137* <li> If the argument is NaN, then the result is 2<sup>30</sup>.138* <li> If the argument is infinite, then the result is 2<sup>28</sup>.139* <li> If the argument is zero, then the result is -(2<sup>28</sup>).140* </ul>141*142* @param f floating-point number whose exponent is to be extracted143* @return unbiased exponent of the argument.144*/145public static int ilogb(float f) {146int exponent = Math.getExponent(f);147148switch (exponent) {149case Float.MAX_EXPONENT+1: // NaN or infinity150if( Float.isNaN(f) )151return (1<<30); // 2^30152else // infinite value153return (1<<28); // 2^28154155case Float.MIN_EXPONENT-1: // zero or subnormal156if(f == 0.0f) {157return -(1<<28); // -(2^28)158}159else {160int transducer = Float.floatToRawIntBits(f);161162/*163* To avoid causing slow arithmetic on subnormals,164* the scaling to determine when f's significand165* is normalized is done in integer arithmetic.166* (there must be at least one "1" bit in the167* significand since zero has been screened out.168*/169170// isolate significand bits171transducer &= FloatConsts.SIGNIF_BIT_MASK;172assert(transducer != 0);173174// This loop is simple and functional. We might be175// able to do something more clever that was faster;176// e.g. number of leading zero detection on177// (transducer << (# exponent and sign bits).178while (transducer <179(1 << (FloatConsts.SIGNIFICAND_WIDTH - 1))) {180transducer *= 2;181exponent--;182}183exponent++;184assert( exponent >=185Float.MIN_EXPONENT - (FloatConsts.SIGNIFICAND_WIDTH-1) &&186exponent < Float.MIN_EXPONENT);187return exponent;188}189190default:191assert( exponent >= Float.MIN_EXPONENT &&192exponent <= Float.MAX_EXPONENT);193return exponent;194}195}196197/**198* Returns {@code true} if the unordered relation holds199* between the two arguments. When two floating-point values are200* unordered, one value is neither less than, equal to, nor201* greater than the other. For the unordered relation to be true,202* at least one argument must be a {@code NaN}.203*204* @param arg1 the first argument205* @param arg2 the second argument206* @return {@code true} if at least one argument is a NaN,207* {@code false} otherwise.208*/209public static boolean isUnordered(float arg1, float arg2) {210return Float.isNaN(arg1) || Float.isNaN(arg2);211}212213/**214* Returns {@code true} if the unordered relation holds215* between the two arguments. When two floating-point values are216* unordered, one value is neither less than, equal to, nor217* greater than the other. For the unordered relation to be true,218* at least one argument must be a {@code NaN}.219*220* @param arg1 the first argument221* @param arg2 the second argument222* @return {@code true} if at least one argument is a NaN,223* {@code false} otherwise.224*/225public static boolean isUnordered(double arg1, double arg2) {226return Double.isNaN(arg1) || Double.isNaN(arg2);227}228229public static int test(String testName, float input,230boolean result, boolean expected) {231if (expected != result) {232System.err.println("Failure for " + testName + ":\n" +233"\tFor input " + input + "\t(" + toHexString(input) + ")\n" +234"\texpected " + expected + "\n" +235"\tgot " + result + ").");236return 1;237}238else239return 0;240}241242public static int test(String testName, double input,243boolean result, boolean expected) {244if (expected != result) {245System.err.println("Failure for " + testName + ":\n" +246"\tFor input " + input + "\t(" + toHexString(input) + ")\n" +247"\texpected " + expected + "\n" +248"\tgot " + result + ").");249return 1;250}251else252return 0;253}254255public static int test(String testName, float input1, float input2,256boolean result, boolean expected) {257if (expected != result) {258System.err.println("Failure for " + testName + ":\n" +259"\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and "260+ input2 + "\t(" + toHexString(input2) + ")\n" +261"\texpected " + expected + "\n" +262"\tgot " + result + ").");263return 1;264}265return 0;266}267268public static int test(String testName, double input1, double input2,269boolean result, boolean expected) {270if (expected != result) {271System.err.println("Failure for " + testName + ":\n" +272"\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and "273+ input2 + "\t(" + toHexString(input2) + ")\n" +274"\texpected " + expected + "\n" +275"\tgot " + result + ").");276return 1;277}278return 0;279}280281public static int test(String testName, float input,282int result, int expected) {283if (expected != result) {284System.err.println("Failure for " + testName + ":\n" +285"\tFor input " + input + "\t(" + toHexString(input) + ")\n" +286"\texpected " + expected + "\n" +287"\tgot " + result + ").");288return 1;289}290return 0;291}292293public static int test(String testName, double input,294int result, int expected) {295if (expected != result) {296System.err.println("Failure for " + testName + ":\n" +297"\tFor input " + input + "\t(" + toHexString(input) + ")\n" +298"\texpected " + expected + "\n" +299"\tgot " + result + ").");300return 1;301}302else303return 0;304}305306public static int test(String testName, float input,307float result, float expected) {308if (Float.compare(expected, result) != 0 ) {309System.err.println("Failure for " + testName + ":\n" +310"\tFor input " + input + "\t(" + toHexString(input) + ")\n" +311"\texpected " + expected + "\t(" + toHexString(expected) + ")\n" +312"\tgot " + result + "\t(" + toHexString(result) + ").");313return 1;314}315else316return 0;317}318319320public static int test(String testName, double input,321double result, double expected) {322if (Double.compare(expected, result ) != 0) {323System.err.println("Failure for " + testName + ":\n" +324"\tFor input " + input + "\t(" + toHexString(input) + ")\n" +325"\texpected " + expected + "\t(" + toHexString(expected) + ")\n" +326"\tgot " + result + "\t(" + toHexString(result) + ").");327return 1;328}329else330return 0;331}332333public static int test(String testName,334float input1, double input2,335float result, float expected) {336if (Float.compare(expected, result ) != 0) {337System.err.println("Failure for " + testName + ":\n" +338"\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and "339+ input2 + "\t(" + toHexString(input2) + ")\n" +340"\texpected " + expected + "\t(" + toHexString(expected) + ")\n" +341"\tgot " + result + "\t(" + toHexString(result) + ").");342return 1;343}344else345return 0;346}347348public static int test(String testName,349double input1, double input2,350double result, double expected) {351if (Double.compare(expected, result ) != 0) {352System.err.println("Failure for " + testName + ":\n" +353"\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and "354+ input2 + "\t(" + toHexString(input2) + ")\n" +355"\texpected " + expected + "\t(" + toHexString(expected) + ")\n" +356"\tgot " + result + "\t(" + toHexString(result) + ").");357return 1;358}359else360return 0;361}362363public static int test(String testName,364float input1, int input2,365float result, float expected) {366if (Float.compare(expected, result ) != 0) {367System.err.println("Failure for " + testName + ":\n" +368"\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and "369+ input2 + "\n" +370"\texpected " + expected + "\t(" + toHexString(expected) + ")\n" +371"\tgot " + result + "\t(" + toHexString(result) + ").");372return 1;373}374else375return 0;376}377378public static int test(String testName,379double input1, int input2,380double result, double expected) {381if (Double.compare(expected, result ) != 0) {382System.err.println("Failure for " + testName + ":\n" +383"\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and "384+ input2 + "\n" +385"\texpected " + expected + "\t(" + toHexString(expected) + ")\n" +386"\tgot " + result + "\t(" + toHexString(result) + ").");387return 1;388}389else390return 0;391}392393public static int test(String testName,394float input1, float input2, float input3,395float result, float expected) {396if (Float.compare(expected, result ) != 0) {397System.err.println("Failure for " + testName + ":\n" +398"\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and "399+ input2 + "\t(" + toHexString(input2) + ") and"400+ input3 + "\t(" + toHexString(input3) + ")\n" +401"\texpected " + expected + "\t(" + toHexString(expected) + ")\n" +402"\tgot " + result + "\t(" + toHexString(result) + ").");403return 1;404}405else406return 0;407}408409public static int test(String testName,410double input1, double input2, double input3,411double result, double expected) {412if (Double.compare(expected, result ) != 0) {413System.err.println("Failure for " + testName + ":\n" +414"\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and "415+ input2 + "\t(" + toHexString(input2) + ") and"416+ input3 + "\t(" + toHexString(input3) + ")\n" +417"\texpected " + expected + "\t(" + toHexString(expected) + ")\n" +418"\tgot " + result + "\t(" + toHexString(result) + ").");419return 1;420}421else422return 0;423}424425static int testUlpCore(double result, double expected, double ulps) {426// We assume we won't be unlucky and have an inexact expected427// be nextDown(2^i) when 2^i would be the correctly rounded428// answer. This would cause the ulp size to be half as large429// as it should be, doubling the measured error).430431if (Double.compare(expected, result) == 0) {432return 0; // result and expected are equivalent433} else {434if( ulps == 0.0) {435// Equivalent results required but not found436return 1;437} else {438double difference = expected - result;439if (isUnordered(expected, result) ||440Double.isNaN(difference) ||441// fail if greater than or unordered442!(Math.abs( difference/Math.ulp(expected) ) <= Math.abs(ulps)) ) {443return 1;444}445else446return 0;447}448}449}450451// One input argument.452public static int testUlpDiff(String testName, double input,453double result, double expected, double ulps) {454int code = testUlpCore(result, expected, ulps);455if (code == 1) {456System.err.println("Failure for " + testName + ":\n" +457"\tFor input " + input + "\t(" + toHexString(input) + ")\n" +458"\texpected " + expected + "\t(" + toHexString(expected) + ")\n" +459"\tgot " + result + "\t(" + toHexString(result) + ");\n" +460"\tdifference greater than ulp tolerance " + ulps);461}462return code;463}464465// Two input arguments.466public static int testUlpDiff(String testName, double input1, double input2,467double result, double expected, double ulps) {468int code = testUlpCore(result, expected, ulps);469if (code == 1) {470System.err.println("Failure for " + testName + ":\n" +471"\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and "472+ input2 + "\t(" + toHexString(input2) + ")\n" +473"\texpected " + expected + "\t(" + toHexString(expected) + ")\n" +474"\tgot " + result + "\t(" + toHexString(result) + ");\n" +475"\tdifference greater than ulp tolerance " + ulps);476}477return code;478}479480// For a successful test, the result must be within the ulp bound of481// expected AND the result must have absolute value less than or482// equal to absBound.483public static int testUlpDiffWithAbsBound(String testName, double input,484double result, double expected,485double ulps, double absBound) {486int code = 0; // return code value487488if (!(StrictMath.abs(result) <= StrictMath.abs(absBound)) &&489!Double.isNaN(expected)) {490code = 1;491} else492code = testUlpCore(result, expected, ulps);493494if (code == 1) {495System.err.println("Failure for " + testName + ":\n" +496"\tFor input " + input + "\t(" + toHexString(input) + ")\n" +497"\texpected " + expected + "\t(" + toHexString(expected) + ")\n" +498"\tgot " + result + "\t(" + toHexString(result) + ");\n" +499"\tdifference greater than ulp tolerance " + ulps +500" or the result has larger magnitude than " + absBound);501}502return code;503}504505// For a successful test, the result must be within the ulp bound of506// expected AND the result must have absolute value greater than507// or equal to the lowerBound.508public static int testUlpDiffWithLowerBound(String testName, double input,509double result, double expected,510double ulps, double lowerBound) {511int code = 0; // return code value512513if (!(result >= lowerBound) && !Double.isNaN(expected)) {514code = 1;515} else516code = testUlpCore(result, expected, ulps);517518if (code == 1) {519System.err.println("Failure for " + testName +520":\n" +521"\tFor input " + input + "\t(" + toHexString(input) + ")" +522"\n\texpected " + expected + "\t(" + toHexString(expected) + ")" +523"\n\tgot " + result + "\t(" + toHexString(result) + ");" +524"\ndifference greater than ulp tolerance " + ulps +525" or result not greater than or equal to the bound " + lowerBound);526}527return code;528}529530public static int testTolerance(String testName, double input,531double result, double expected, double tolerance) {532if (Double.compare(expected, result ) != 0) {533double difference = expected - result;534if (isUnordered(expected, result) ||535Double.isNaN(difference) ||536// fail if greater than or unordered537!(Math.abs((difference)/expected) <= StrictMath.pow(10, -tolerance)) ) {538System.err.println("Failure for " + testName + ":\n" +539"\tFor input " + input + "\t(" + toHexString(input) + ")\n" +540"\texpected " + expected + "\t(" + toHexString(expected) + ")\n" +541"\tgot " + result + "\t(" + toHexString(result) + ");\n" +542"\tdifference greater than tolerance 10^-" + tolerance);543return 1;544}545return 0;546}547else548return 0;549}550551// For a successful test, the result must be within the upper and552// lower bounds.553public static int testBounds(String testName, double input, double result,554double bound1, double bound2) {555if ((result >= bound1 && result <= bound2) ||556(result <= bound1 && result >= bound2))557return 0;558else {559double lowerBound = Math.min(bound1, bound2);560double upperBound = Math.max(bound1, bound2);561System.err.println("Failure for " + testName + ":\n" +562"\tFor input " + input + "\t(" + toHexString(input) + ")\n" +563"\tgot " + result + "\t(" + toHexString(result) + ");\n" +564"\toutside of range\n" +565"\t[" + lowerBound + "\t(" + toHexString(lowerBound) + "), " +566upperBound + "\t(" + toHexString(upperBound) + ")]");567return 1;568}569}570}571572573