/*
* 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è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=99 H=89 G=94
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-06-04)
¤
*© Formatika GbR, Deutschland