/*
* Copyright ( c ) 2011 , 2022 , Oracle and / or its affiliates . All rights reserved .
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER .
*
* This code is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 only , as
* published by the Free Software Foundation .
*
* This code is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* version 2 for more details ( a copy is included in the LICENSE file that
* accompanied this code ) .
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work ; if not , write to the Free Software Foundation ,
* Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA .
*
* Please contact Oracle , 500 Oracle Parkway , Redwood Shores , CA 94065 USA
* or visit www . oracle . com if you need additional information or have any
* questions .
*/
/*
* @ test
* @ bug 4900206
* @ summary Test worst case behavior of exp , log , sin , cos , etc .
* @ build Tests
* @ build WorstCaseTests
* @ run main WorstCaseTests
* @ run main / othervm - Xcomp WorstCaseTests
*/
/**
* Use " Table Maker ' s Dilemma " results from Jean - Michel Muller and
* Vincent Lef & egrave ; vre , to test the math library . See
* http : //perso.ens-lyon.fr/jean-michel.muller/TMD.html for original
* test vectors from 2000 and see
* http : //perso.ens-lyon.fr/jean-michel.muller/TMDworstcases.pdf with
* additional test vectors from 2003 . The latter link also contains
* some information about the methodology used to produce the test
* vectors .
*
* Most of the Java math library methods tested here have a 1 - ulp
* error bound from their specifications . This implies the returned
* value must be one of the two representable floating - point numbers
* bracketing the exact result . The expected value in the test
* vectors below is the truncation of the exact value . Therefore , the
* computed result must either be that value or the value next larger
* in magnitude . The hyperbolic transcendental functions sinh and cosh
* have a larger 2 . 5 ulp error bound in their specification , but the
* JDK implementation complies with a 1 ulp bound on the worst - case
* values . Therefore , no addition leeway is afforded when testing
* sinh and cosh .
*/
public class WorstCaseTests {
private WorstCaseTests() {throw new AssertionError("No instances for you." );}
public static void main(String... args) {
int failures = 0 ;
failures += testWorstExp();
failures += testWorstLog();
failures += testWorstSin();
failures += testWorstAsin();
failures += testWorstCos();
failures += testWorstAcos();
failures += testWorstTan();
failures += testWorstAtan();
failures += testWorstPow2();
failures += testWorstSinh();
failures += testWorstCosh();
if (failures > 0 ) {
System.err.printf("Testing worst cases incurred %d failures.%n" , failures);
throw new RuntimeException();
}
}
private static int testWorstExp() {
int failures = 0 ;
double [][] testCases = {
{-0 x1.E8BDBFCD9144Ep3, 0 x1.F3E558CF4DE54p-23 },
{-0 x1.71 E0B869B5E79p2, 0 x1.951 C6DC5D24E2p-9 },
{-0 x1.02393 D5976769p1, 0 x1.1064 B2C103DDAp-3 },
{-0 x1.2 A9CAD9998262p0, 0 x1.3 EF1E9B3A81C7p-2 },
{-0 x1.CC37EF7DE7501p0, 0 x1.534 D4DE870713p-3 },
{-0 x1.22 E24FA3D5CF9p-1 , 0 x1.2217147 B85EA9p-1 },
{-0 x1.DC2B5DF1F7D3Dp-1 , 0 x1.9403 FD0EE51C8p-2 },
{-0 x1.290 EA09E36479p-3 , 0 x1.BADED30CBF1C3p-1 },
{-0 x1.A2FEFEFD580DFp-13 , 0 x1.FFE5D0BB7EABFp-1 },
{-0 x1.ED318EFB627EAp-27 , 0 x1.FFFFFF84B39C4p-1 },
{-0 x1.4 BD46601AE1EFp-31 , 0 x1.FFFFFFFAD0AE6p-1 },
{-0 x1.1000000000242 p-42 , 0 x1.FFFFFFFFFF780p-1 },
{-0 x1.2000000000288 p-42 , 0 x1.FFFFFFFFFF700p-1 },
{-0 x1.8000000000012 p-48 , 0 x1.FFFFFFFFFFFD0p-1 },
{-0 x1.0000000000001 p-51 , 0 x1.FFFFFFFFFFFFCp-1 },
{+0 x1.FFFFFFFFFFFFFp-53 , 0 x1.0000000000000 p0},
{+0 x1.FFFFFFFFFFFE0p-48 , 0 x1.000000000001 Fp0},
{+0 x1.7 FFE7FFEE0024p-32 , 0 x1.000000017 FFE8p0},
{+0 x1.80017 FFEDFFDCp-32 , 0 x1.0000000180017 p0},
{+0 x1.9 E9CBBFD6080Bp-31 , 0 x1.000000033 D397p0},
{+0 x1.D7A7D893609E5p-26 , 0 x1.00000075 E9F64p0},
{+0 x1.BA07D73250DE7p-14 , 0 x1.0006 E83736F8Cp0},
{+0 x1.D77FD13D27FFFp-11 , 0 x1.003 AF6C37C1D3p0},
{+0 x1.6 A4D1AF9CC989p-8 , 0 x1.016 B4DF3299D7p0},
{+0 x1.ACCFBE46B4EF0p-1 , 0 x2.4 F85C9783DCE0p0},
{+0 x1.ACA7AE8DA5A7Bp0, 0 x5.55 F52B35F955Ap0},
{+0 x1.D6336A88077AAp0, 0 x6.46 A37FD503FDCp0},
{+0 x2.85 DC78FB8928Cp0, 0 xC.76 F2496CB038Fp0},
{+0 x1.76 E7E5D7B6EACp3, 0 x1.DE7CD6751029Ap16},
{+0 x1.A8EAD058BC6B8p3, 0 x1.1 D71965F516ADp19},
{+0 x1.1 D5C2DAEBE367p4, 0 x1.A8C02E974C314p25},
{+0 x1.C44CE0D716A1Ap4, 0 x1.B890CA8637AE1p40},
};
for (double [] testCase: testCases) {
failures += testExpCase(testCase[0 ], testCase[1 ]);
}
return failures;
}
private static int testExpCase(double input, double expected) {
int failures = 0 ;
double out = Tests.nextOut(expected);
failures += Tests.testBounds("Math.exp" , input, Math::exp, expected, out);
failures += Tests.testBounds("StrictMath.exp" , input, StrictMath::exp, expected, out);
return failures;
}
private static int testWorstLog() {
int failures = 0 ;
double [][] testCases = {
{+0 x1.0000000000001 p0, +0 x1.FFFFFFFFFFFFFp-53 },
{+0 x2.0012 ECB039C9Cp0, +0 x1.62 F71C4656B60p-1 },
{+0 x6.46 A37FD503FDCp0, +0 x1.D6336A88077A9p+0 },
{+0 x7.78 DFECC7F57Fp0, +0 x2.02 DD059DB46Bp+0 },
{+0 x9.588 CCF24BB9C8p0, +0 x2.3 C24DEBB2BE7p+0 },
{+0 xA.AF87550D97E4p0, +0 x2.5 E706595A7ABEp+0 },
{+0 xC.76 F2496CB039p0, +0 x2.85 DC78FB8928Cp+0 },
{+0 x11.1867637 CBD03p0, +0 x2.D6BBEFC79A842p+0 },
{+0 x13.D9D7D597A9DDp0, +0 x2.FCFE12AE07DDCp+0 },
{+0 x17.F3825778AAAFp0, +0 x3.2 D0F907F5E00Cp+0 },
{+0 x1AC.50 B409C8AEEp0, +0 x6.0 F52F37AECFCCp+0 },
{+0 x1.DE7CD6751029Ap16, +0 x1.76 E7E5D7B6EABp+3 },
};
for (double [] testCase: testCases) {
failures += testLogCase(testCase[0 ], testCase[1 ]);
}
return failures;
}
private static int testLogCase(double input, double expected) {
int failures = 0 ;
double out = Tests.nextOut(expected);
failures += Tests.testBounds("Math.log" , input, Math::log, expected, out);
failures += Tests.testBounds("StrictMath.log" , input, StrictMath::log, expected, out);
return failures;
}
private static int testWorstSin() {
int failures = 0 ;
double [][] testCases = {
{+0 x1.E0000000001C2p-20 , +0 x1.DFFFFFFFFF02Ep-20 },
{+0 x1.598 BAE9E632F6p-7 , +0 x1.598 A0AEA48996p-7 },
{+0 x1.9283586503 FEp-5 , +0 x1.9259 E3708BD39p-5 },
{+0 x1.D7BDCD778049Fp-5 , +0 x1.D77B117F230D5p-5 },
{+0 x1.A202B3FB84788p-4 , +0 x1.A1490C8C06BA6p-4 },
{+0 x1.D037CB27EE6DFp-3 , +0 x1.CC40C3805229Ap-3 },
{+0 x1.D5064E6FE82C5p-3 , +0 x1.D0EF799001BA9p-3 },
{+0 x1.FE767739D0F6Dp-2 , +0 x1.E9950730C4695p-2 },
{+0 x1.D98C4C612718Dp-1 , +0 x1.98 DCD09337792p-1 },
{+0 x1.921 FB54442D18p-0 , +0 x1.FFFFFFFFFFFFFp-1 },
{+0 x1.6756745770 A51p+1 , +0 x1.4 FF350E412821p-2 },
};
for (double [] testCase: testCases) {
failures += testSinCase(testCase[0 ], testCase[1 ]);
}
return failures;
}
private static int testSinCase(double input, double expected) {
int failures = 0 ;
double out = Tests.nextOut(expected);
failures += Tests.testBounds("Math.sin" , input, Math::sin, expected, out);
failures += Tests.testBounds("StrictMath.sin" , input, StrictMath::sin, expected, out);
return failures;
}
private static int testWorstAsin() {
int failures = 0 ;
double [][] testCases = {
{+0 x1.DFFFFFFFFF02Ep-20 , +0 x1.E0000000001C1p-20 },
{+0 x1.DFFFFFFFFC0B8p-19 , +0 x1.E000000000707p-19 },
{+0 x1.9259 E3708BD3Ap-5 , +0 x1.9283586503 FEp-5 },
{+0 x1.D77B117F230D6p-5 , +0 x1.D7BDCD778049Fp-5 },
{+0 x1.A1490C8C06BA7p-4 , +0 x1.A202B3FB84788p-4 },
{+0 x1.9697 CB602C582p-3 , +0 x1.994 FFB5DAF0F9p-3 },
{+0 x1.D0EF799001BA9p-3 , +0 x1.D5064E6FE82C4p-3 },
{+0 x1.E9950730C4696p-2 , +0 x1.FE767739D0F6Dp-2 },
{+0 x1.1 ED06D50F7E88p-1 , +0 x1.30706 F699466Dp-1 },
{+0 x1.D5B05A89D3E77p-1 , +0 x1.29517 AB4C132Ap+0 },
{+0 x1.E264357EA0E29p-1 , +0 x1.3 AA301F6EBB1Dp+0 },
};
for (double [] testCase: testCases) {
failures += testAsinCase(testCase[0 ], testCase[1 ]);
}
return failures;
}
private static int testAsinCase(double input, double expected) {
int failures = 0 ;
double out = Tests.nextOut(expected);
failures += Tests.testBounds("Math.asin" , input, Math::asin, expected, out);
failures += Tests.testBounds("StrictMath.asin" , input, StrictMath::asin, expected, out);
return failures;
}
private static int testWorstCos() {
int failures = 0 ;
double [][] testCases = {
{+0 x1.8000000000009 p-23 , +0 x0.FFFFFFFFFFFB8p+0 },
{+0 x1.8000000000024 p-22 , +0 x0.FFFFFFFFFFEE0p+0 },
{+0 x1.2000000000 F30p-18 , +0 x0.FFFFFFFFF5E00p+0 },
{+0 x1.06 B505550E6B2p-9 , +0 x0.FFFFDE4D1FDFFp+0 },
{+0 x1.97 CCD3D2C438Fp-6 , +0 x0.FFEBB35D43854p+0 },
{+0 x1.549 EC0C0C5AFAp-5 , +0 x1.FF8EB6A91ECB0p-1 },
{+0 x1.16 E534EE36580p-4 , +0 x1.FED0476FC75C9p-1 },
{+0 x1.EFEEF61D39AC2p-3 , +0 x1.F10FC61E2C78Ep-1 },
{+0 x1.FEB1F7920E248p-2 , +0 x1.C1A27AE836F12p-1 },
{+0 x1.7 CB7648526F99p-1 , +0 x1.78 DAF01036D0Cp-1 },
{+0 x1.C65A170474549p-1 , +0 x1.434 A3645BE208p-1 },
{+0 x1.6 B8A6273D7C21p+0 , +0 x1.337 FC5B072C52p-3 },
};
for (double [] testCase: testCases) {
failures += testCosCase(testCase[0 ], testCase[1 ]);
}
return failures;
}
private static int testCosCase(double input, double expected) {
int failures = 0 ;
double out = Tests.nextOut(expected);
failures += Tests.testBounds("Math.cos" , input, Math::cos, expected, out);
failures += Tests.testBounds("StrictMath.cos" , input, StrictMath::cos, expected, out);
return failures;
}
private static int testWorstAcos() {
int failures = 0 ;
double [][] testCases = {
{+0 x1.FD737BE914578p-11 , +0 x1.91 E006D41D8D8p+0 },
{+0 x1.4182199998587 p-1 , +0 x1.C8A538AE83D1Fp-1 },
{+0 x1.E45A1C93651ECp-1 , +0 x1.520 DC553F6B23p-2 },
{+0 x1.F10FC61E2C78Fp-1 , +0 x1.EFEEF61D39AC1p-3 },
};
for (double [] testCase: testCases) {
failures += testAcosCase(testCase[0 ], testCase[1 ]);
}
return failures;
}
private static int testAcosCase(double input, double expected) {
int failures = 0 ;
double out = Tests.nextOut(expected);
failures += Tests.testBounds("Math.acos" , input, Math::acos, expected, out);
failures += Tests.testBounds("StrictMath.acos" , input, StrictMath::acos, expected, out);
return failures;
}
private static int testWorstTan() {
int failures = 0 ;
double [][] testCases = {
{+0 x1.DFFFFFFFFFF1Fp-22 , +0 x1.E000000000151p-22 },
{+0 x1.67 FFFFFFFA114p-18 , +0 x1.6800000008 E61p-18 },
{+0 x1.50486 B2F87014p-5 , +0 x1.5078 CEBFF9C72p-5 },
{+0 x1.52 C39EF070CADp-4 , +0 x1.5389 E6DF41978p-4 },
{+0 x1.A33F32AC5CEB5p-3 , +0 x1.A933FE176B375p-3 },
{+0 x1.D696BFA988DB9p-2 , +0 x1.FAC71CD34EEA6p-2 },
{+0 x1.46 AC372243536p-1 , +0 x1.7 BA49F739829Ep-1 },
{+0 x0.A3561B9121A9Bp+0 , +0 x0.BDD24FB9CC14Fp+0 },
};
for (double [] testCase: testCases) {
failures += testTanCase(testCase[0 ], testCase[1 ]);
}
return failures;
}
private static int testTanCase(double input, double expected) {
int failures = 0 ;
double out = Tests.nextOut(expected);
failures += Tests.testBounds("Math.tan" , input, Math::tan, expected, out);
failures += Tests.testBounds("StrictMath.tan" , input, StrictMath::tan, expected, out);
return failures;
}
private static int testWorstAtan() {
int failures = 0 ;
double [][] testCases = {
{+0 x1.E000000000546p-21 , +0 x1.DFFFFFFFFFC7Cp-21 },
{+0 x1.22 E8D75E2BC7Fp-11 , +0 x1.22 E8D5694AD2Bp-11 },
{+0 x1.0 FC9F1FABE658p-5 , +0 x1.0 FB06EDE9973Ap-5 },
{+0 x1.1 BBE9C255698Dp-5 , +0 x1.1 BA1951DB1D6Dp-5 },
{+0 x1.8 DDD25AB90CA1p-5 , +0 x1.8 D8D2D4BD6FA2p-5 },
{+0 x1.5389 E6DF41979p-4 , +0 x1.52 C39EF070CADp-4 },
{+0 x1.A933FE176B375p-3 , +0 x1.A33F32AC5CEB4p-3 },
{+0 x1.0 F6E5D9960397p-2 , +0 x1.09544 B71AD4A6p-2 },
{+0 x1.7 BA49F739829Fp-1 , +0 x1.46 AC372243536p-1 },
{+0 x0.BDD24FB9CC14F8p+0 , +0 x0.A3561B9121A9Bp+0 },
};
for (double [] testCase: testCases) {
failures += testAtanCase(testCase[0 ], testCase[1 ]);
}
return failures;
}
private static int testAtanCase(double input, double expected) {
int failures = 0 ;
double out = Tests.nextOut(expected);
failures += Tests.testBounds("Math.atan" , input, Math::atan, expected, out);
failures += Tests.testBounds("StrictMath.atan" , input, StrictMath::atan, expected, out);
return failures;
}
private static int testWorstPow2() {
int failures = 0 ;
double [][] testCases = {
{+0 x1.16 A76EC41B516p-1 , +0 x1.7550685 A42C63p+0 },
{+0 x1.3 E34FA6AB969Ep-1 , +0 x1.89 D948A94FE16p+0 },
{+0 x1.4 A63FF1D53F53p-1 , +0 x1.90661 DA12D528p+0 },
{+0 x1.B32A6C92D1185p-1 , +0 x1.CD6B37EDECEAFp+0 },
{+0 x1.25 DD9EEDAC79Ap+0 , +0 x1.1 BA39FF28E3E9p+1 },
};
for (double [] testCase: testCases) {
failures += testPow2Case(testCase[0 ], testCase[1 ]);
}
return failures;
}
private static int testPow2Case(double input, double expected) {
int failures = 0 ;
double out = Tests.nextOut(expected);
failures += Tests.testBounds("Math.pow2" , input, d -> Math.pow(2 , d), expected, out);
failures += Tests.testBounds("StrictMath.pow2" , input, d -> StrictMath.pow(2 , d), expected, out);
return failures;
}
// 2.5 ulp error bound in the specification; the implementation
// does better on the tested values.
private static int testWorstSinh() {
int failures = 0 ;
double [][] testCases = {
{+0 x1.DFFFFFFFFFE3Ep-20 , +0 x1.E000000000FD1p-20 },
{+0 x1.DFFFFFFFFE3E0p-18 , +0 x1.E00000000FD1Fp-18 },
{+0 x1.135 E31FDD05D3p-5 , +0 x1.136 B78B25CC57p-5 },
{+0 x1.0 DC68D5E8F959p-3 , +0 x1.0 E8E73DC4FEE3p-3 },
{+0 x1.616 CC75D49226p-2 , +0 x1.687 BD068C1C1Ep-2 },
{+0 x1.3 FFC12B81CBC2p+0 , +0 x1.9 A0FF413A1AF2p+0 },
{+0 x2.FE008C44BACA2p+0 , +0 x9.F08A43ED03AEp+0 },
{+0 x1.C089FCF166171p+4 , +0 x1.5 C452E0E37569p+39 },
{+0 x1.E07E71BFCF06Fp+5 , +0 x1.91 EC4412C344Fp+85 },
{+0 x1.54 CD1FEA7663Ap+7 , +0 x1.C90810D354618p+244 },
{+0 x1.D6479EBA7C971p+8 , +0 x1.62 A88613629B5p+677 },
};
for (double [] testCase: testCases) {
failures += testSinhCase(testCase[0 ], testCase[1 ]);
}
return failures;
}
private static int testSinhCase(double input, double expected) {
int failures = 0 ;
double out = Tests.nextOut(expected);
failures += Tests.testBounds("Math.sinh" , input, Math::sinh, expected, out);
failures += Tests.testBounds("StrictMath.sinh" , input, StrictMath::sinh, expected, out);
return failures;
}
// 2.5 ulp error bound in the specification; the implementation
// does better on the tested values.
private static int testWorstCosh() {
int failures = 0 ;
double [][] testCases = {
{+0 x1.17 D8A9F206217p-6 , +0 x1.00098 F5F09BE3p+0 },
{+0 x1.BF0305E2C6C37p-3 , +0 x1.061 F4C39E16F2p+0 },
{+0 x1.03923 F2B47C07p-1 , +0 x1.219 C1989E3372p+0 },
{+0 x1.A6031CD5F93BAp-1 , +0 x1.5 BFF041B260FDp+0 },
{+0 x1.104 B648F113A1p+0 , +0 x1.9 EFDCA62B7009p+0 },
{+0 x1.EA5F2F2E4B0C5p+1 , +0 x17.10 DB0CD0FED5p+0 },
};
for (double [] testCase: testCases) {
failures += testCoshCase(testCase[0 ], testCase[1 ]);
}
return failures;
}
private static int testCoshCase(double input, double expected) {
int failures = 0 ;
double out = Tests.nextOut(expected);
failures += Tests.testBounds("Math.cosh" , input, Math::cosh, expected, out);
failures += Tests.testBounds("StrictMath.cosh" , input, StrictMath::cosh, expected, out);
return failures;
}
}
Messung V0.5 in Prozent C=98 H=89 G=93
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-10-11)
¤
*© Formatika GbR, Deutschland