1 /* 2 * Copyright (c) 2003, 2011 Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * Shared static test methods for numerical tests. Sharing these 26 * helper test methods avoids repeated functions in the various test 27 * programs. The test methods return 1 for a test failure and 0 for 28 * success. The order of arguments to the test methods is generally 29 * the test name, followed by the test arguments, the computed result, 30 * and finally the expected result. 31 */ 32 33 import sun.misc.FpUtils; 34 35 public class Tests { 36 private Tests(){}; // do not instantiate 37 38 public static String toHexString(float f) { 39 if (!Float.isNaN(f)) 40 return Float.toHexString(f); 41 else 42 return "NaN(0x" + Integer.toHexString(Float.floatToRawIntBits(f)) + ")"; 43 } 44 45 public static String toHexString(double d) { 46 if (!Double.isNaN(d)) 47 return Double.toHexString(d); 48 else 49 return "NaN(0x" + Long.toHexString(Double.doubleToRawLongBits(d)) + ")"; 50 } 51 52 /** 53 * Return the floating-point value next larger in magnitude. 54 */ 55 public static double nextOut(double d) { 56 if (d > 0.0) 57 return Math.nextUp(d); 58 else 59 return -Math.nextUp(-d); 60 } 61 62 public static int test(String testName, float input, 63 boolean result, boolean expected) { 64 if (expected != result) { 65 System.err.println("Failure for " + testName + ":\n" + 66 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 67 "\texpected " + expected + "\n" + 68 "\tgot " + result + ")."); 69 return 1; 70 } 71 else 72 return 0; 73 } 74 75 public static int test(String testName, double input, 76 boolean result, boolean expected) { 77 if (expected != result) { 78 System.err.println("Failure for " + testName + ":\n" + 79 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 80 "\texpected " + expected + "\n" + 81 "\tgot " + result + ")."); 82 return 1; 83 } 84 else 85 return 0; 86 } 87 88 public static int test(String testName, float input1, float input2, 89 boolean result, boolean expected) { 90 if (expected != result) { 91 System.err.println("Failure for " + testName + ":\n" + 92 "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " 93 + input2 + "\t(" + toHexString(input2) + ")\n" + 94 "\texpected " + expected + "\n" + 95 "\tgot " + result + ")."); 96 return 1; 97 } 98 return 0; 99 } 100 101 public static int test(String testName, double input1, double input2, 102 boolean result, boolean expected) { 103 if (expected != result) { 104 System.err.println("Failure for " + testName + ":\n" + 105 "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " 106 + input2 + "\t(" + toHexString(input2) + ")\n" + 107 "\texpected " + expected + "\n" + 108 "\tgot " + result + ")."); 109 return 1; 110 } 111 return 0; 112 } 113 114 public static int test(String testName, float input, 115 int result, int expected) { 116 if (expected != result) { 117 System.err.println("Failure for " + testName + ":\n" + 118 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 119 "\texpected " + expected + "\n" + 120 "\tgot " + result + ")."); 121 return 1; 122 } 123 return 0; 124 } 125 126 public static int test(String testName, double input, 127 int result, int expected) { 128 if (expected != result) { 129 System.err.println("Failure for " + testName + ":\n" + 130 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 131 "\texpected " + expected + "\n" + 132 "\tgot " + result + ")."); 133 return 1; 134 } 135 else 136 return 0; 137 } 138 139 public static int test(String testName, float input, 140 float result, float expected) { 141 if (Float.compare(expected, result) != 0 ) { 142 System.err.println("Failure for " + testName + ":\n" + 143 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 144 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 145 "\tgot " + result + "\t(" + toHexString(result) + ")."); 146 return 1; 147 } 148 else 149 return 0; 150 } 151 152 153 public static int test(String testName, double input, 154 double result, double expected) { 155 if (Double.compare(expected, result ) != 0) { 156 System.err.println("Failure for " + testName + ":\n" + 157 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 158 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 159 "\tgot " + result + "\t(" + toHexString(result) + ")."); 160 return 1; 161 } 162 else 163 return 0; 164 } 165 166 public static int test(String testName, 167 float input1, double input2, 168 float result, float expected) { 169 if (Float.compare(expected, result ) != 0) { 170 System.err.println("Failure for " + testName + ":\n" + 171 "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " 172 + input2 + "\t(" + toHexString(input2) + ")\n" + 173 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 174 "\tgot " + result + "\t(" + toHexString(result) + ")."); 175 return 1; 176 } 177 else 178 return 0; 179 } 180 181 public static int test(String testName, 182 double input1, double input2, 183 double result, double expected) { 184 if (Double.compare(expected, result ) != 0) { 185 System.err.println("Failure for " + testName + ":\n" + 186 "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " 187 + input2 + "\t(" + toHexString(input2) + ")\n" + 188 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 189 "\tgot " + result + "\t(" + toHexString(result) + ")."); 190 return 1; 191 } 192 else 193 return 0; 194 } 195 196 public static int test(String testName, 197 float input1, int input2, 198 float result, float expected) { 199 if (Float.compare(expected, result ) != 0) { 200 System.err.println("Failure for " + testName + ":\n" + 201 "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " 202 + input2 + "\n" + 203 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 204 "\tgot " + result + "\t(" + toHexString(result) + ")."); 205 return 1; 206 } 207 else 208 return 0; 209 } 210 211 public static int test(String testName, 212 double input1, int input2, 213 double result, double expected) { 214 if (Double.compare(expected, result ) != 0) { 215 System.err.println("Failure for " + testName + ":\n" + 216 "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " 217 + input2 + "\n" + 218 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 219 "\tgot " + result + "\t(" + toHexString(result) + ")."); 220 return 1; 221 } 222 else 223 return 0; 224 } 225 226 static int testUlpCore(double result, double expected, double ulps) { 227 // We assume we won't be unlucky and have an inexact expected 228 // be nextDown(2^i) when 2^i would be the correctly rounded 229 // answer. This would cause the ulp size to be half as large 230 // as it should be, doubling the measured error). 231 232 if (Double.compare(expected, result) == 0) { 233 return 0; // result and expected are equivalent 234 } else { 235 if( ulps == 0.0) { 236 // Equivalent results required but not found 237 return 1; 238 } else { 239 double difference = expected - result; 240 if (FpUtils.isUnordered(expected, result) || 241 Double.isNaN(difference) || 242 // fail if greater than or unordered 243 !(Math.abs( difference/Math.ulp(expected) ) <= Math.abs(ulps)) ) { 244 return 1; 245 } 246 else 247 return 0; 248 } 249 } 250 } 251 252 // One input argument. 253 public static int testUlpDiff(String testName, double input, 254 double result, double expected, double ulps) { 255 int code = testUlpCore(result, expected, ulps); 256 if (code == 1) { 257 System.err.println("Failure for " + testName + ":\n" + 258 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 259 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 260 "\tgot " + result + "\t(" + toHexString(result) + ");\n" + 261 "\tdifference greater than ulp tolerance " + ulps); 262 } 263 return code; 264 } 265 266 // Two input arguments. 267 public static int testUlpDiff(String testName, double input1, double input2, 268 double result, double expected, double ulps) { 269 int code = testUlpCore(result, expected, ulps); 270 if (code == 1) { 271 System.err.println("Failure for " + testName + ":\n" + 272 "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " 273 + input2 + "\t(" + toHexString(input2) + ")\n" + 274 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 275 "\tgot " + result + "\t(" + toHexString(result) + ");\n" + 276 "\tdifference greater than ulp tolerance " + ulps); 277 } 278 return code; 279 } 280 281 // For a successful test, the result must be within the ulp bound of 282 // expected AND the result must have absolute value less than or 283 // equal to absBound. 284 public static int testUlpDiffWithAbsBound(String testName, double input, 285 double result, double expected, 286 double ulps, double absBound) { 287 int code = 0; // return code value 288 289 if (!(StrictMath.abs(result) <= StrictMath.abs(absBound)) && 290 !Double.isNaN(expected)) { 291 code = 1; 292 } else 293 code = testUlpCore(result, expected, ulps); 294 295 if (code == 1) { 296 System.err.println("Failure for " + testName + ":\n" + 297 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 298 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 299 "\tgot " + result + "\t(" + toHexString(result) + ");\n" + 300 "\tdifference greater than ulp tolerance " + ulps + 301 " or the result has larger magnitude than " + absBound); 302 } 303 return code; 304 } 305 306 // For a successful test, the result must be within the ulp bound of 307 // expected AND the result must have absolute value greater than 308 // or equal to the lowerBound. 309 public static int testUlpDiffWithLowerBound(String testName, double input, 310 double result, double expected, 311 double ulps, double lowerBound) { 312 int code = 0; // return code value 313 314 if (!(result >= lowerBound) && !Double.isNaN(expected)) { 315 code = 1; 316 } else 317 code = testUlpCore(result, expected, ulps); 318 319 if (code == 1) { 320 System.err.println("Failure for " + testName + 321 ":\n" + 322 "\tFor input " + input + "\t(" + toHexString(input) + ")" + 323 "\n\texpected " + expected + "\t(" + toHexString(expected) + ")" + 324 "\n\tgot " + result + "\t(" + toHexString(result) + ");" + 325 "\ndifference greater than ulp tolerance " + ulps + 326 " or result not greater than or equal to the bound " + lowerBound); 327 } 328 return code; 329 } 330 331 public static int testTolerance(String testName, double input, 332 double result, double expected, double tolerance) { 333 if (Double.compare(expected, result ) != 0) { 334 double difference = expected - result; 335 if (FpUtils.isUnordered(expected, result) || 336 Double.isNaN(difference) || 337 // fail if greater than or unordered 338 !(Math.abs((difference)/expected) <= StrictMath.pow(10, -tolerance)) ) { 339 System.err.println("Failure for " + testName + ":\n" + 340 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 341 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 342 "\tgot " + result + "\t(" + toHexString(result) + ");\n" + 343 "\tdifference greater than tolerance 10^-" + tolerance); 344 return 1; 345 } 346 return 0; 347 } 348 else 349 return 0; 350 } 351 352 // For a successful test, the result must be within the upper and 353 // lower bounds. 354 public static int testBounds(String testName, double input, double result, 355 double bound1, double bound2) { 356 if ((result >= bound1 && result <= bound2) || 357 (result <= bound1 && result >= bound2)) 358 return 0; 359 else { 360 double lowerBound = Math.min(bound1, bound2); 361 double upperBound = Math.max(bound1, bound2); 362 System.err.println("Failure for " + testName + ":\n" + 363 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 364 "\tgot " + result + "\t(" + toHexString(result) + ");\n" + 365 "\toutside of range\n" + 366 "\t[" + lowerBound + "\t(" + toHexString(lowerBound) + "), " + 367 upperBound + "\t(" + toHexString(upperBound) + ")]"); 368 return 1; 369 } 370 } 371 }