1/*
2 * Copyright (c) 2015, 2016, 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 8139688
27 * @key randomness
28 * @library /lib/testlibrary/
29 * @build jdk.testlibrary.RandomFactory
30 * @build Tests
31 * @build FdlibmTranslit
32 * @build ExpTests
33 * @run main ExpTests
34 * @summary Tests specifically for StrictMath.exp
35 */
36
37import jdk.testlibrary.RandomFactory;
38
39/**
40 * The role of this test is to verify that the FDLIBM exp algorithm is
41 * being used by running golden file style tests on values that may
42 * vary from one conforming exponential implementation to another.
43 */
44
45public class ExpTests {
46    private ExpTests(){}
47
48    public static void main(String [] argv) {
49        int failures = 0;
50
51        failures += testExp();
52        failures += testAgainstTranslit();
53
54        if (failures > 0) {
55            System.err.println("Testing the exponential incurred "
56                               + failures + " failures.");
57            throw new RuntimeException();
58        }
59    }
60
61    // From the fdlibm source, the overflow threshold in hex is:
62    // 0x4086_2E42_FEFA_39EF.
63    static final double EXP_OVERFLOW_THRESH  = Double.longBitsToDouble(0x4086_2E42_FEFA_39EFL);
64
65    // From the fdlibm source, the underflow threshold in hex is:
66    // 0xc087_4910_D52D_3051L.
67    static final double EXP_UNDERFLOW_THRESH = Double.longBitsToDouble(0xc087_4910_D52D_3051L);
68
69    static int testExp() {
70        int failures = 0;
71
72        double [][] testCases = {
73            // Some of these could be moved to common Math/StrictMath exp testing.
74            {Double.NaN,                      Double.NaN},
75            {Double.MAX_VALUE,                Double.POSITIVE_INFINITY},
76            {Double.POSITIVE_INFINITY,        Double.POSITIVE_INFINITY},
77            {Double.NEGATIVE_INFINITY,        +0.0},
78            {EXP_OVERFLOW_THRESH,                 0x1.ffff_ffff_fff2ap1023},
79            {Math.nextUp(EXP_OVERFLOW_THRESH),    Double.POSITIVE_INFINITY},
80            {Math.nextDown(EXP_UNDERFLOW_THRESH), +0.0},
81            {EXP_UNDERFLOW_THRESH,                +Double.MIN_VALUE},
82        };
83
84        for(double[] testCase: testCases)
85            failures+=testExpCase(testCase[0], testCase[1]);
86
87        return failures;
88    }
89
90    static int testExpCase(double input, double expected) {
91        int failures = 0;
92
93        failures+=Tests.test("StrictMath.exp(double)", input,
94                             StrictMath.exp(input), expected);
95        return failures;
96    }
97
98    // Initialize shared random number generator
99    private static java.util.Random random = RandomFactory.getRandom();
100
101    /**
102     * Test StrictMath.exp against transliteration port of exp.
103     */
104    private static int testAgainstTranslit() {
105        int failures = 0;
106
107        double[] decisionPoints = {
108            // Near overflow threshold
109            EXP_OVERFLOW_THRESH - 512*Math.ulp(EXP_OVERFLOW_THRESH),
110
111            // Near underflow threshold
112            EXP_UNDERFLOW_THRESH - 512*Math.ulp(EXP_UNDERFLOW_THRESH),
113
114            // Straddle algorithm conditional checks
115            Double.longBitsToDouble(0x4086_2E42_0000_0000L - 512L),
116            Double.longBitsToDouble(0x3fd6_2e42_0000_0000L - 512L),
117            Double.longBitsToDouble(0x3FF0_A2B2_0000_0000L - 512L),
118            Double.longBitsToDouble(0x3e30_0000_0000_0000L - 512L),
119
120            // Other notable points
121            Double.MIN_NORMAL - Math.ulp(Double.MIN_NORMAL)*512,
122            -Double.MIN_VALUE*512,
123        };
124
125        for (double decisionPoint : decisionPoints) {
126            double ulp = Math.ulp(decisionPoint);
127            failures += testRange(decisionPoint - 1024*ulp, ulp, 1_024);
128        }
129
130        // Try out some random values
131        for (int i = 0; i < 100; i++) {
132            double x = Tests.createRandomDouble(random);
133            failures += testRange(x, Math.ulp(x), 100);
134        }
135
136        return failures;
137    }
138
139    private static int testRange(double start, double increment, int count) {
140        int failures = 0;
141        double x = start;
142        for (int i = 0; i < count; i++, x += increment) {
143            failures += testExpCase(x, FdlibmTranslit.Exp.compute(x));
144        }
145        return failures;
146    }
147}
148