static int testUlpCore(double result, double expected, double ulps) { // We assume we won't be unlucky and have an inexact expected // be nextDown(2^i) when 2^i would be the correctly rounded // answer. This would cause the ulp size to be half as large // as it should be, doubling the measured error). if (Double.compare(expected, result) == 0) { return 0; // result and expected are equivalent } else { if( ulps == 0.0) { // Equivalent results required but not found return 1; } else { double difference = expected - result; if (FpUtils.isUnordered(expected, result) || Double.isNaN(difference) || // fail if greater than or unordered !(Math.abs( difference/Math.ulp(expected) ) <= Math.abs(ulps)) ) { return 1; } else return 0; } } }
public static int testTolerance(String testName, double input, double result, double expected, double tolerance) { if (Double.compare(expected, result ) != 0) { double difference = expected - result; if (FpUtils.isUnordered(expected, result) || Double.isNaN(difference) || // fail if greater than or unordered !(Math.abs((difference)/expected) <= StrictMath.pow(10, -tolerance)) ) { System.err.println("Failure for " + testName + ":\n" + "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + "\tgot " + result + "\t(" + toHexString(result) + ");\n" + "\tdifference greater than tolerance 10^-" + tolerance); return 1; } return 0; } else return 0; }
/** * Returns the <code>double</code> value that is closest in value * to the argument and is equal to a mathematical integer. If two * <code>double</code> values that are mathematical integers are * equally close to the value of the argument, the result is the * integer value that is even. Special cases: * <ul><li>If the argument value is already equal to a mathematical * integer, then the result is the same as the argument. * <li>If the argument is NaN or an infinity or positive zero or negative * zero, then the result is the same as the argument.</ul> * * @param a a value. * @return the closest floating-point value to <code>a</code> that is * equal to a mathematical integer. * @author Joseph D. Darcy */ public static double rint(double a) { /* * If the absolute value of a is not less than 2^52, it * is either a finite integer (the double format does not have * enough significand bits for a number that large to have any * fractional portion), an infinity, or a NaN. In any of * these cases, rint of the argument is the argument. * * Otherwise, the sum (twoToThe52 + a ) will properly round * away any fractional portion of a since ulp(twoToThe52) == * 1.0; subtracting out twoToThe52 from this sum will then be * exact and leave the rounded integer portion of a. * * This method does *not* need to be declared strictfp to get * fully reproducible results. Whether or not a method is * declared strictfp can only make a difference in the * returned result if some operation would overflow or * underflow with strictfp semantics. The operation * (twoToThe52 + a ) cannot overflow since large values of a * are screened out; the add cannot underflow since twoToThe52 * is too large. The subtraction ((twoToThe52 + a ) - * twoToThe52) will be exact as discussed above and thus * cannot overflow or meaningfully underflow. Finally, the * last multiply in the return statement is by plus or minus * 1.0, which is exact too. */ double twoToThe52 = (double)(1L << 52); // 2^52 double sign = FpUtils.rawCopySign(1.0, a); // preserve sign info a = Math.abs(a); if (a < twoToThe52) { // E_min <= ilogb(a) <= 51 a = ((twoToThe52 + a ) - twoToThe52); } return sign * a; // restore original sign }
/** * Returns the {@code double} value that is closest in value * to the argument and is equal to a mathematical integer. If two * {@code double} values that are mathematical integers are * equally close to the value of the argument, the result is the * integer value that is even. Special cases: * <ul><li>If the argument value is already equal to a mathematical * integer, then the result is the same as the argument. * <li>If the argument is NaN or an infinity or positive zero or negative * zero, then the result is the same as the argument.</ul> * * @param a a value. * @return the closest floating-point value to {@code a} that is * equal to a mathematical integer. * @author Joseph D. Darcy */ public static double rint(double a) { /* * If the absolute value of a is not less than 2^52, it * is either a finite integer (the double format does not have * enough significand bits for a number that large to have any * fractional portion), an infinity, or a NaN. In any of * these cases, rint of the argument is the argument. * * Otherwise, the sum (twoToThe52 + a ) will properly round * away any fractional portion of a since ulp(twoToThe52) == * 1.0; subtracting out twoToThe52 from this sum will then be * exact and leave the rounded integer portion of a. * * This method does *not* need to be declared strictfp to get * fully reproducible results. Whether or not a method is * declared strictfp can only make a difference in the * returned result if some operation would overflow or * underflow with strictfp semantics. The operation * (twoToThe52 + a ) cannot overflow since large values of a * are screened out; the add cannot underflow since twoToThe52 * is too large. The subtraction ((twoToThe52 + a ) - * twoToThe52) will be exact as discussed above and thus * cannot overflow or meaningfully underflow. Finally, the * last multiply in the return statement is by plus or minus * 1.0, which is exact too. */ double twoToThe52 = (double)(1L << 52); // 2^52 double sign = FpUtils.rawCopySign(1.0, a); // preserve sign info a = Math.abs(a); if (a < twoToThe52) { // E_min <= ilogb(a) <= 51 a = ((twoToThe52 + a ) - twoToThe52); } return sign * a; // restore original sign }
public static int 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, -FloatConsts.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}, {FloatConsts.MIN_NORMAL, Float_MAX_SUBNORMAL}, {FloatConsts.MIN_NORMAL+ Float.MIN_VALUE, FloatConsts.MIN_NORMAL}, {Float.MAX_VALUE, Float_MAX_VALUEmm}, {infinityF, Float.MAX_VALUE}, }; for(int i = 0; i < testCases.length; i++) { failures+=Tests.test("FpUtils.nextDown(float)", testCases[i][0], FpUtils.nextDown(testCases[i][0]), testCases[i][1]); } return failures; }
public static int 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, -DoubleConsts.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}, {DoubleConsts.MIN_NORMAL, Double_MAX_SUBNORMAL}, {DoubleConsts.MIN_NORMAL+ Double.MIN_VALUE, DoubleConsts.MIN_NORMAL}, {Double.MAX_VALUE, Double_MAX_VALUEmm}, {infinityD, Double.MAX_VALUE}, }; for(int i = 0; i < testCases.length; i++) { failures+=Tests.test("FpUtils.nextDown(double)", testCases[i][0], FpUtils.nextDown(testCases[i][0]), testCases[i][1]); } return failures; }
@AndroidIncompatible // no FpUtils public void testNextDown() { for (double d : FINITE_DOUBLE_CANDIDATES) { assertEquals(FpUtils.nextDown(d), DoubleUtils.nextDown(d)); } }
public static int testFloatBooleanMethods() { int failures = 0; float testCases [] = { NaNf, -infinityF, infinityF, -Float.MAX_VALUE, -3.0f, -1.0f, -FloatConsts.MIN_NORMAL, -Float_MAX_SUBNORMALmm, -Float_MAX_SUBNORMAL, -Float.MIN_VALUE, -0.0f, +0.0f, Float.MIN_VALUE, Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMAL, FloatConsts.MIN_NORMAL, 1.0f, 3.0f, Float_MAX_VALUEmm, Float.MAX_VALUE }; for(int i = 0; i < testCases.length; i++) { // isNaN failures+=Tests.test("FpUtils.isNaN(float)", testCases[i], FpUtils.isNaN(testCases[i]), (i ==0)); // isFinite failures+=Tests.test("Float.isFinite(float)", testCases[i], Float.isFinite(testCases[i]), (i >= 3)); // isInfinite failures+=Tests.test("FpUtils.isInfinite(float)", testCases[i], FpUtils.isInfinite(testCases[i]), (i==1 || i==2)); // isUnorderd for(int j = 0; j < testCases.length; j++) { failures+=Tests.test("FpUtils.isUnordered(float, float)", testCases[i],testCases[j], FpUtils.isUnordered(testCases[i],testCases[j]), (i==0 || j==0)); } } return failures; }