1/* 2 * Copyright (c) 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 * @test 26 * @bug 4900206 27 * @summary Test worst case behavior of exp, log, sin, cos, etc. 28 * @build Tests 29 * @build WorstCaseTests 30 * @run main WorstCaseTests 31 * @run main/othervm -Xcomp WorstCaseTests 32 * @author Joseph D. Darcy 33 */ 34 35/** 36 * Use "Table Maker's Dilemma" results from Jean-Michel Muller and 37 * Vincent Lefèvre, to test the math library. See 38 * http://perso.ens-lyon.fr/jean-michel.muller/TMD.html for original 39 * test vectors from 2000 and see 40 * http://perso.ens-lyon.fr/jean-michel.muller/TMDworstcases.pdf with 41 * additional test vectors from 2003. The latter link also contains 42 * some information about the methodology used to produce the test 43 * vectors. 44 * 45 * Most of the Java math library methods tested here have a 1-ulp 46 * error bound from their specifications. This implies the returned 47 * value must be one of the two representable floating-point numbers 48 * bracketing the exact result. The expected value in the test 49 * vectors below is the truncation of the exact value. Therefore, the 50 * computed result must either be that value or the value next larger 51 * in magnitude. The hyperbolic transcendental functions sinh and cosh 52 * have a larger 2.5 ulp error bound in their specification, but the 53 * JDK implementation complies with a 1 ulp bound on the worst-case 54 * values. Therefore, no addition leeway is afforded when testing 55 * sinh and cosh. 56 */ 57public class WorstCaseTests { 58 private WorstCaseTests() {throw new AssertionError("No instances for you.");} 59 60 public static void main(String... args) { 61 int failures = 0; 62 63 failures += testWorstExp(); 64 failures += testWorstLog(); 65 failures += testWorstSin(); 66 failures += testWorstAsin(); 67 failures += testWorstCos(); 68 failures += testWorstAcos(); 69 failures += testWorstTan(); 70 failures += testWorstAtan(); 71 failures += testWorstPow2(); 72 failures += testWorstSinh(); 73 failures += testWorstCosh(); 74 75 if (failures > 0) { 76 System.err.printf("Testing worst cases incurred %d failures.%n", failures); 77 throw new RuntimeException(); 78 } 79 } 80 81 private static int testWorstExp() { 82 int failures = 0; 83 double [][] testCases = { 84 {-0x1.E8BDBFCD9144Ep3, 0x1.F3E558CF4DE54p-23}, 85 {-0x1.71E0B869B5E79p2, 0x1.951C6DC5D24E2p-9}, 86 {-0x1.02393D5976769p1, 0x1.1064B2C103DDAp-3}, 87 {-0x1.2A9CAD9998262p0, 0x1.3EF1E9B3A81C7p-2}, 88 {-0x1.CC37EF7DE7501p0, 0x1.534D4DE870713p-3}, 89 {-0x1.22E24FA3D5CF9p-1, 0x1.2217147B85EA9p-1}, 90 {-0x1.DC2B5DF1F7D3Dp-1, 0x1.9403FD0EE51C8p-2}, 91 {-0x1.290EA09E36479p-3, 0x1.BADED30CBF1C3p-1}, 92 {-0x1.A2FEFEFD580DFp-13, 0x1.FFE5D0BB7EABFp-1}, 93 {-0x1.ED318EFB627EAp-27, 0x1.FFFFFF84B39C4p-1}, 94 {-0x1.4BD46601AE1EFp-31, 0x1.FFFFFFFAD0AE6p-1}, 95 {-0x1.1000000000242p-42, 0x1.FFFFFFFFFF780p-1}, 96 {-0x1.2000000000288p-42, 0x1.FFFFFFFFFF700p-1}, 97 {-0x1.8000000000012p-48, 0x1.FFFFFFFFFFFD0p-1}, 98 {-0x1.0000000000001p-51, 0x1.FFFFFFFFFFFFCp-1}, 99 100 {+0x1.FFFFFFFFFFFFFp-53, 0x1.0000000000000p0}, 101 {+0x1.FFFFFFFFFFFE0p-48, 0x1.000000000001Fp0}, 102 {+0x1.7FFE7FFEE0024p-32, 0x1.000000017FFE8p0}, 103 {+0x1.80017FFEDFFDCp-32, 0x1.0000000180017p0}, 104 {+0x1.9E9CBBFD6080Bp-31, 0x1.000000033D397p0}, 105 {+0x1.D7A7D893609E5p-26, 0x1.00000075E9F64p0}, 106 {+0x1.BA07D73250DE7p-14, 0x1.0006E83736F8Cp0}, 107 {+0x1.D77FD13D27FFFp-11, 0x1.003AF6C37C1D3p0}, 108 {+0x1.6A4D1AF9CC989p-8, 0x1.016B4DF3299D7p0}, 109 {+0x1.ACCFBE46B4EF0p-1, 0x2.4F85C9783DCE0p0}, 110 {+0x1.ACA7AE8DA5A7Bp0, 0x5.55F52B35F955Ap0}, 111 {+0x1.D6336A88077AAp0, 0x6.46A37FD503FDCp0}, 112 {+0x2.85DC78FB8928Cp0, 0xC.76F2496CB038Fp0}, 113 {+0x1.76E7E5D7B6EACp3, 0x1.DE7CD6751029Ap16}, 114 {+0x1.A8EAD058BC6B8p3, 0x1.1D71965F516ADp19}, 115 {+0x1.1D5C2DAEBE367p4, 0x1.A8C02E974C314p25}, 116 {+0x1.C44CE0D716A1Ap4, 0x1.B890CA8637AE1p40}, 117 }; 118 119 for(double[] testCase: testCases) { 120 failures += testExpCase(testCase[0], testCase[1]); 121 } 122 123 return failures; 124 } 125 126 private static int testExpCase(double input, double expected) { 127 int failures = 0; 128 double out = Tests.nextOut(expected); 129 failures += Tests.testBounds("Math.exp", input, Math.exp(input), expected, out); 130 failures += Tests.testBounds("StrictMath.exp", input, StrictMath.exp(input), expected, out); 131 return failures; 132 } 133 134 private static int testWorstLog() { 135 int failures = 0; 136 double [][] testCases = { 137 {+0x1.0000000000001p0, +0x1.FFFFFFFFFFFFFp-53}, 138 {+0x2.0012ECB039C9Cp0, +0x1.62F71C4656B60p-1}, 139 {+0x6.46A37FD503FDCp0, +0x1.D6336A88077A9p+0}, 140 {+0x7.78DFECC7F57Fp0, +0x2.02DD059DB46Bp+0}, 141 {+0x9.588CCF24BB9C8p0, +0x2.3C24DEBB2BE7p+0}, 142 {+0xA.AF87550D97E4p0, +0x2.5E706595A7ABEp+0}, 143 {+0xC.76F2496CB039p0, +0x2.85DC78FB8928Cp+0}, 144 {+0x11.1867637CBD03p0, +0x2.D6BBEFC79A842p+0}, 145 {+0x13.D9D7D597A9DDp0, +0x2.FCFE12AE07DDCp+0}, 146 {+0x17.F3825778AAAFp0, +0x3.2D0F907F5E00Cp+0}, 147 {+0x1AC.50B409C8AEEp0, +0x6.0F52F37AECFCCp+0}, 148 {+0x1.DE7CD6751029Ap16, +0x1.76E7E5D7B6EABp+3}, 149 }; 150 151 for(double[] testCase: testCases) { 152 failures += testLogCase(testCase[0], testCase[1]); 153 } 154 155 return failures; 156 } 157 158 private static int testLogCase(double input, double expected) { 159 int failures = 0; 160 double out = Tests.nextOut(expected); 161 failures += Tests.testBounds("Math.log", input, Math.log(input), expected, out); 162 failures += Tests.testBounds("StrictMath.log", input, StrictMath.log(input), expected, out); 163 return failures; 164 } 165 166 private static int testWorstSin() { 167 int failures = 0; 168 double [][] testCases = { 169 {+0x1.E0000000001C2p-20, +0x1.DFFFFFFFFF02Ep-20}, 170 {+0x1.598BAE9E632F6p-7, +0x1.598A0AEA48996p-7}, 171 172 {+0x1.9283586503FEp-5, +0x1.9259E3708BD39p-5}, 173 {+0x1.D7BDCD778049Fp-5, +0x1.D77B117F230D5p-5}, 174 {+0x1.A202B3FB84788p-4, +0x1.A1490C8C06BA6p-4}, 175 {+0x1.D037CB27EE6DFp-3, +0x1.CC40C3805229Ap-3}, 176 {+0x1.D5064E6FE82C5p-3, +0x1.D0EF799001BA9p-3}, 177 {+0x1.FE767739D0F6Dp-2, +0x1.E9950730C4695p-2}, 178 {+0x1.D98C4C612718Dp-1, +0x1.98DCD09337792p-1}, 179 {+0x1.921FB54442D18p-0, +0x1.FFFFFFFFFFFFFp-1}, 180 181 {+0x1.6756745770A51p+1, +0x1.4FF350E412821p-2}, 182 }; 183 184 for(double[] testCase: testCases) { 185 failures += testSinCase(testCase[0], testCase[1]); 186 } 187 188 return failures; 189 } 190 191 private static int testSinCase(double input, double expected) { 192 int failures = 0; 193 double out = Tests.nextOut(expected); 194 failures += Tests.testBounds("Math.sin", input, Math.sin(input), expected, out); 195 failures += Tests.testBounds("StrictMath.sin", input, StrictMath.sin(input), expected, out); 196 return failures; 197 } 198 199 private static int testWorstAsin() { 200 int failures = 0; 201 double [][] testCases = { 202 {+0x1.DFFFFFFFFF02Ep-20, +0x1.E0000000001C1p-20}, 203 {+0x1.DFFFFFFFFC0B8p-19, +0x1.E000000000707p-19}, 204 205 {+0x1.9259E3708BD3Ap-5, +0x1.9283586503FEp-5}, 206 {+0x1.D77B117F230D6p-5, +0x1.D7BDCD778049Fp-5}, 207 {+0x1.A1490C8C06BA7p-4, +0x1.A202B3FB84788p-4}, 208 {+0x1.9697CB602C582p-3, +0x1.994FFB5DAF0F9p-3}, 209 {+0x1.D0EF799001BA9p-3, +0x1.D5064E6FE82C4p-3}, 210 {+0x1.E9950730C4696p-2, +0x1.FE767739D0F6Dp-2}, 211 {+0x1.1ED06D50F7E88p-1, +0x1.30706F699466Dp-1}, 212 {+0x1.D5B05A89D3E77p-1, +0x1.29517AB4C132Ap+0}, 213 {+0x1.E264357EA0E29p-1, +0x1.3AA301F6EBB1Dp+0}, 214 }; 215 216 for(double[] testCase: testCases) { 217 failures += testAsinCase(testCase[0], testCase[1]); 218 } 219 220 return failures; 221 } 222 223 private static int testAsinCase(double input, double expected) { 224 int failures = 0; 225 double out = Tests.nextOut(expected); 226 failures += Tests.testBounds("Math.asin", input, Math.asin(input), expected, out); 227 failures += Tests.testBounds("StrictMath.asin", input, StrictMath.asin(input), expected, out); 228 return failures; 229 } 230 231 private static int testWorstCos() { 232 int failures = 0; 233 double [][] testCases = { 234 {+0x1.8000000000009p-23, +0x0.FFFFFFFFFFFB8p+0}, 235 {+0x1.8000000000024p-22, +0x0.FFFFFFFFFFEE0p+0}, 236 {+0x1.2000000000F30p-18, +0x0.FFFFFFFFF5E00p+0}, 237 {+0x1.06B505550E6B2p-9, +0x0.FFFFDE4D1FDFFp+0}, 238 {+0x1.97CCD3D2C438Fp-6, +0x0.FFEBB35D43854p+0}, 239 240 {+0x1.549EC0C0C5AFAp-5, +0x1.FF8EB6A91ECB0p-1}, 241 {+0x1.16E534EE36580p-4, +0x1.FED0476FC75C9p-1}, 242 {+0x1.EFEEF61D39AC2p-3, +0x1.F10FC61E2C78Ep-1}, 243 {+0x1.FEB1F7920E248p-2, +0x1.C1A27AE836F12p-1}, 244 {+0x1.7CB7648526F99p-1, +0x1.78DAF01036D0Cp-1}, 245 {+0x1.C65A170474549p-1, +0x1.434A3645BE208p-1}, 246 {+0x1.6B8A6273D7C21p+0, +0x1.337FC5B072C52p-3}, 247 }; 248 249 for(double[] testCase: testCases) { 250 failures += testCosCase(testCase[0], testCase[1]); 251 } 252 253 return failures; 254 } 255 256 private static int testCosCase(double input, double expected) { 257 int failures = 0; 258 double out = Tests.nextOut(expected); 259 failures += Tests.testBounds("Math.cos", input, Math.cos(input), expected, out); 260 failures += Tests.testBounds("StrictMath.cos", input, StrictMath.cos(input), expected, out); 261 return failures; 262 } 263 264 private static int testWorstAcos() { 265 int failures = 0; 266 double [][] testCases = { 267 {+0x1.FD737BE914578p-11, +0x1.91E006D41D8D8p+0}, 268 {+0x1.4182199998587p-1, +0x1.C8A538AE83D1Fp-1}, 269 {+0x1.E45A1C93651ECp-1, +0x1.520DC553F6B23p-2}, 270 {+0x1.F10FC61E2C78Fp-1, +0x1.EFEEF61D39AC1p-3}, 271 }; 272 273 for(double[] testCase: testCases) { 274 failures += testAcosCase(testCase[0], testCase[1]); 275 } 276 277 return failures; 278 } 279 280 private static int testAcosCase(double input, double expected) { 281 int failures = 0; 282 double out = Tests.nextOut(expected); 283 failures += Tests.testBounds("Math.acos", input, Math.acos(input), expected, out); 284 failures += Tests.testBounds("StrictMath.acos", input, StrictMath.acos(input), expected, out); 285 return failures; 286 } 287 288 private static int testWorstTan() { 289 int failures = 0; 290 double [][] testCases = { 291 {+0x1.DFFFFFFFFFF1Fp-22, +0x1.E000000000151p-22}, 292 {+0x1.67FFFFFFFA114p-18, +0x1.6800000008E61p-18}, 293 294 {+0x1.50486B2F87014p-5, +0x1.5078CEBFF9C72p-5}, 295 {+0x1.52C39EF070CADp-4, +0x1.5389E6DF41978p-4}, 296 {+0x1.A33F32AC5CEB5p-3, +0x1.A933FE176B375p-3}, 297 {+0x1.D696BFA988DB9p-2, +0x1.FAC71CD34EEA6p-2}, 298 {+0x1.46AC372243536p-1, +0x1.7BA49F739829Ep-1}, 299 {+0x0.A3561B9121A9Bp+0, +0x0.BDD24FB9CC14Fp+0}, 300 }; 301 302 for(double[] testCase: testCases) { 303 failures += testTanCase(testCase[0], testCase[1]); 304 } 305 306 return failures; 307 } 308 309 private static int testTanCase(double input, double expected) { 310 int failures = 0; 311 double out = Tests.nextOut(expected); 312 failures += Tests.testBounds("Math.tan", input, Math.tan(input), expected, out); 313 failures += Tests.testBounds("StrictMath.tan", input, StrictMath.tan(input), expected, out); 314 return failures; 315 } 316 317 private static int testWorstAtan() { 318 int failures = 0; 319 double [][] testCases = { 320 {+0x1.E000000000546p-21, +0x1.DFFFFFFFFFC7Cp-21}, 321 {+0x1.22E8D75E2BC7Fp-11, +0x1.22E8D5694AD2Bp-11}, 322 323 {+0x1.0FC9F1FABE658p-5, +0x1.0FB06EDE9973Ap-5}, 324 {+0x1.1BBE9C255698Dp-5, +0x1.1BA1951DB1D6Dp-5}, 325 {+0x1.8DDD25AB90CA1p-5, +0x1.8D8D2D4BD6FA2p-5}, 326 {+0x1.5389E6DF41979p-4, +0x1.52C39EF070CADp-4}, 327 {+0x1.A933FE176B375p-3, +0x1.A33F32AC5CEB4p-3}, 328 {+0x1.0F6E5D9960397p-2, +0x1.09544B71AD4A6p-2}, 329 {+0x1.7BA49F739829Fp-1, +0x1.46AC372243536p-1}, 330 331 {+0x0.BDD24FB9CC14F8p+0, +0x0.A3561B9121A9Bp+0}, 332 }; 333 334 for(double[] testCase: testCases) { 335 failures += testAtanCase(testCase[0], testCase[1]); 336 } 337 338 return failures; 339 } 340 341 private static int testAtanCase(double input, double expected) { 342 int failures = 0; 343 double out = Tests.nextOut(expected); 344 failures += Tests.testBounds("Math.atan", input, Math.atan(input), expected, out); 345 failures += Tests.testBounds("StrictMath.atan", input, StrictMath.atan(input), expected, out); 346 return failures; 347 } 348 349 private static int testWorstPow2() { 350 int failures = 0; 351 double [][] testCases = { 352 {+0x1.16A76EC41B516p-1, +0x1.7550685A42C63p+0}, 353 {+0x1.3E34FA6AB969Ep-1, +0x1.89D948A94FE16p+0}, 354 {+0x1.4A63FF1D53F53p-1, +0x1.90661DA12D528p+0}, 355 {+0x1.B32A6C92D1185p-1, +0x1.CD6B37EDECEAFp+0}, 356 357 {+0x1.25DD9EEDAC79Ap+0, +0x1.1BA39FF28E3E9p+1}, 358 }; 359 360 for(double[] testCase: testCases) { 361 failures += testPow2Case(testCase[0], testCase[1]); 362 } 363 364 return failures; 365 } 366 367 private static int testPow2Case(double input, double expected) { 368 int failures = 0; 369 double out = Tests.nextOut(expected); 370 failures += Tests.testBounds("Math.pow2", input, Math.pow(2, input), expected, out); 371 failures += Tests.testBounds("StrictMath.pow2", input, StrictMath.pow(2, input), expected, out); 372 return failures; 373 } 374 375 // 2.5 ulp error bound in the specification; the implementation 376 // does better on the tested values. 377 private static int testWorstSinh() { 378 int failures = 0; 379 double [][] testCases = { 380 {+0x1.DFFFFFFFFFE3Ep-20, +0x1.E000000000FD1p-20}, 381 {+0x1.DFFFFFFFFE3E0p-18, +0x1.E00000000FD1Fp-18}, 382 {+0x1.135E31FDD05D3p-5, +0x1.136B78B25CC57p-5}, 383 {+0x1.0DC68D5E8F959p-3, +0x1.0E8E73DC4FEE3p-3}, 384 {+0x1.616CC75D49226p-2, +0x1.687BD068C1C1Ep-2}, 385 {+0x1.3FFC12B81CBC2p+0, +0x1.9A0FF413A1AF2p+0}, 386 {+0x2.FE008C44BACA2p+0, +0x9.F08A43ED03AEp+0}, 387 {+0x1.C089FCF166171p+4, +0x1.5C452E0E37569p+39}, 388 {+0x1.E07E71BFCF06Fp+5, +0x1.91EC4412C344Fp+85}, 389 {+0x1.54CD1FEA7663Ap+7, +0x1.C90810D354618p+244}, 390 {+0x1.D6479EBA7C971p+8, +0x1.62A88613629B5p+677}, 391 }; 392 393 for(double[] testCase: testCases) { 394 failures += testSinhCase(testCase[0], testCase[1]); 395 } 396 397 return failures; 398 } 399 400 private static int testSinhCase(double input, double expected) { 401 int failures = 0; 402 double out = Tests.nextOut(expected); 403 failures += Tests.testBounds("Math.sinh", input, Math.sinh(input), expected, out); 404 failures += Tests.testBounds("StrictMath.sinh", input, StrictMath.sinh(input), expected, out); 405 return failures; 406 } 407 408 // 2.5 ulp error bound in the specification; the implementation 409 // does better on the tested values. 410 private static int testWorstCosh() { 411 int failures = 0; 412 double [][] testCases = { 413 {+0x1.17D8A9F206217p-6, +0x1.00098F5F09BE3p+0}, 414 {+0x1.BF0305E2C6C37p-3, +0x1.061F4C39E16F2p+0}, 415 {+0x1.03923F2B47C07p-1, +0x1.219C1989E3372p+0}, 416 {+0x1.A6031CD5F93BAp-1, +0x1.5BFF041B260FDp+0}, 417 {+0x1.104B648F113A1p+0, +0x1.9EFDCA62B7009p+0}, 418 {+0x1.EA5F2F2E4B0C5p+1, +0x17.10DB0CD0FED5p+0}, 419 }; 420 421 for(double[] testCase: testCases) { 422 failures += testCoshCase(testCase[0], testCase[1]); 423 } 424 425 return failures; 426 } 427 428 private static int testCoshCase(double input, double expected) { 429 int failures = 0; 430 double out = Tests.nextOut(expected); 431 failures += Tests.testBounds("Math.cosh", input, Math.cosh(input), expected, out); 432 failures += Tests.testBounds("StrictMath.cosh", input, StrictMath.cosh(input), expected, out); 433 return failures; 434 } 435} 436