1 /* 2 * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any 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 private 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 private 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 public static int test(String testName, float input, 53 boolean result, boolean expected) { 54 if (expected != result) { 55 System.err.println("Failure for " + testName + ":\n" + 56 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 57 "\texpected " + expected + "\n" + 58 "\tgot " + result + ")."); 59 return 1; 60 } 61 else 62 return 0; 63 } 64 65 public static int test(String testName, double input, 66 boolean result, boolean expected) { 67 if (expected != result) { 68 System.err.println("Failure for " + testName + ":\n" + 69 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 70 "\texpected " + expected + "\n" + 71 "\tgot " + result + ")."); 72 return 1; 73 } 74 else 75 return 0; 76 } 77 78 public static int test(String testName, float input1, float input2, 79 boolean result, boolean expected) { 80 if (expected != result) { 81 System.err.println("Failure for " + testName + ":\n" + 82 "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " 83 + input2 + "\t(" + toHexString(input2) + ")\n" + 84 "\texpected " + expected + "\n" + 85 "\tgot " + result + ")."); 86 return 1; 87 } 88 return 0; 89 } 90 91 public static int test(String testName, double input1, double input2, 92 boolean result, boolean expected) { 93 if (expected != result) { 94 System.err.println("Failure for " + testName + ":\n" + 95 "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " 96 + input2 + "\t(" + toHexString(input2) + ")\n" + 97 "\texpected " + expected + "\n" + 98 "\tgot " + result + ")."); 99 return 1; 100 } 101 return 0; 102 } 103 104 public static int test(String testName, float input, 105 int result, int expected) { 106 if (expected != result) { 107 System.err.println("Failure for " + testName + ":\n" + 108 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 109 "\texpected " + expected + "\n" + 110 "\tgot " + result + ")."); 111 return 1; 112 } 113 return 0; 114 } 115 116 public static int test(String testName, double input, 117 int result, int expected) { 118 if (expected != result) { 119 System.err.println("Failure for " + testName + ":\n" + 120 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 121 "\texpected " + expected + "\n" + 122 "\tgot " + result + ")."); 123 return 1; 124 } 125 else 126 return 0; 127 } 128 129 public static int test(String testName, float input, 130 float result, float expected) { 131 if (Float.compare(expected, result) != 0 ) { 132 System.err.println("Failure for " + testName + ":\n" + 133 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 134 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 135 "\tgot " + result + "\t(" + toHexString(result) + ")."); 136 return 1; 137 } 138 else 139 return 0; 140 } 141 142 143 public static int test(String testName, double input, 144 double result, double expected) { 145 if (Double.compare(expected, result ) != 0) { 146 System.err.println("Failure for " + testName + ":\n" + 147 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 148 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 149 "\tgot " + result + "\t(" + toHexString(result) + ")."); 150 return 1; 151 } 152 else 153 return 0; 154 } 155 156 public static int test(String testName, 157 float input1, double input2, 158 float result, float expected) { 159 if (Float.compare(expected, result ) != 0) { 160 System.err.println("Failure for " + testName + ":\n" + 161 "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " 162 + input2 + "\t(" + toHexString(input2) + ")\n" + 163 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 164 "\tgot " + result + "\t(" + toHexString(result) + ")."); 165 return 1; 166 } 167 else 168 return 0; 169 } 170 171 public static int test(String testName, 172 double input1, double input2, 173 double result, double expected) { 174 if (Double.compare(expected, result ) != 0) { 175 System.err.println("Failure for " + testName + ":\n" + 176 "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " 177 + input2 + "\t(" + toHexString(input2) + ")\n" + 178 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 179 "\tgot " + result + "\t(" + toHexString(result) + ")."); 180 return 1; 181 } 182 else 183 return 0; 184 } 185 186 public static int test(String testName, 187 float input1, int input2, 188 float result, float expected) { 189 if (Float.compare(expected, result ) != 0) { 190 System.err.println("Failure for " + testName + ":\n" + 191 "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " 192 + input2 + "\n" + 193 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 194 "\tgot " + result + "\t(" + toHexString(result) + ")."); 195 return 1; 196 } 197 else 198 return 0; 199 } 200 201 public static int test(String testName, 202 double input1, int input2, 203 double result, double expected) { 204 if (Double.compare(expected, result ) != 0) { 205 System.err.println("Failure for " + testName + ":\n" + 206 "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " 207 + input2 + "\n" + 208 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 209 "\tgot " + result + "\t(" + toHexString(result) + ")."); 210 return 1; 211 } 212 else 213 return 0; 214 } 215 216 static int testUlpCore(double result, double expected, double ulps) { 217 // We assume we won't be unlucky and have an inexact expected 218 // be nextDown(2^i) when 2^i would be the correctly rounded 219 // answer. This would cause the ulp size to be half as large 220 // as it should be, doubling the measured error). 221 222 if (Double.compare(expected, result) == 0) { 223 return 0; // result and expected are equivalent 224 } else { 225 if( ulps == 0.0) { 226 // Equivalent results required but not found 227 return 1; 228 } else { 229 double difference = expected - result; 230 if (FpUtils.isUnordered(expected, result) || 231 Double.isNaN(difference) || 232 // fail if greater than or unordered 233 !(Math.abs( difference/Math.ulp(expected) ) <= Math.abs(ulps)) ) { 234 return 1; 235 } 236 else 237 return 0; 238 } 239 } 240 } 241 242 // One input argument. 243 public static int testUlpDiff(String testName, double input, 244 double result, double expected, double ulps) { 245 int code = testUlpCore(result, expected, ulps); 246 if (code == 1) { 247 System.err.println("Failure for " + testName + ":\n" + 248 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 249 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 250 "\tgot " + result + "\t(" + toHexString(result) + ");\n" + 251 "\tdifference greater than ulp tolerance " + ulps); 252 } 253 return code; 254 } 255 256 // Two input arguments. 257 public static int testUlpDiff(String testName, double input1, double input2, 258 double result, double expected, double ulps) { 259 int code = testUlpCore(result, expected, ulps); 260 if (code == 1) { 261 System.err.println("Failure for " + testName + ":\n" + 262 "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " 263 + input2 + "\t(" + toHexString(input2) + ")\n" + 264 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 265 "\tgot " + result + "\t(" + toHexString(result) + ");\n" + 266 "\tdifference greater than ulp tolerance " + ulps); 267 } 268 return code; 269 } 270 271 // For a successful test, the result must be within the ulp bound of 272 // expected AND the result must have absolute value less than or 273 // equal to absBound. 274 public static int testUlpDiffWithAbsBound(String testName, double input, 275 double result, double expected, 276 double ulps, double absBound) { 277 int code = 0; // return code value 278 279 if (!(StrictMath.abs(result) <= StrictMath.abs(absBound)) && 280 !Double.isNaN(expected)) { 281 code = 1; 282 } else 283 code = testUlpCore(result, expected, ulps); 284 285 if (code == 1) { 286 System.err.println("Failure for " + testName + ":\n" + 287 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 288 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 289 "\tgot " + result + "\t(" + toHexString(result) + ");\n" + 290 "\tdifference greater than ulp tolerance " + ulps + 291 " or the result has larger magnitude than " + absBound); 292 } 293 return code; 294 } 295 296 // For a successful test, the result must be within the ulp bound of 297 // expected AND the result must have absolute value greater than 298 // or equal to the lowerBound. 299 public static int testUlpDiffWithLowerBound(String testName, double input, 300 double result, double expected, 301 double ulps, double lowerBound) { 302 int code = 0; // return code value 303 304 if (!(result >= lowerBound) && !Double.isNaN(expected)) { 305 code = 1; 306 } else 307 code = testUlpCore(result, expected, ulps); 308 309 if (code == 1) { 310 System.err.println("Failure for " + testName + 311 ":\n" + 312 "\tFor input " + input + "\t(" + toHexString(input) + ")" + 313 "\n\texpected " + expected + "\t(" + toHexString(expected) + ")" + 314 "\n\tgot " + result + "\t(" + toHexString(result) + ");" + 315 "\ndifference greater than ulp tolerance " + ulps + 316 " or result not greater than or equal to the bound " + lowerBound); 317 } 318 return code; 319 } 320 321 public static int testTolerance(String testName, double input, 322 double result, double expected, double tolerance) { 323 if (Double.compare(expected, result ) != 0) { 324 double difference = expected - result; 325 if (FpUtils.isUnordered(expected, result) || 326 Double.isNaN(difference) || 327 // fail if greater than or unordered 328 !(Math.abs((difference)/expected) <= StrictMath.pow(10, -tolerance)) ) { 329 System.err.println("Failure for " + testName + ":\n" + 330 "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + 331 "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + 332 "\tgot " + result + "\t(" + toHexString(result) + ");\n" + 333 "\tdifference greater than tolerance 10^-" + tolerance); 334 return 1; 335 } 336 return 0; 337 } 338 else 339 return 0; 340 } 341 }