1/*
2 * Copyright (c) 2004, 2015, 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 4984407 5033578 8134795
27 * @summary Tests for {Math, StrictMath}.pow
28 * @author Joseph D. Darcy
29 */
30
31public class PowTests {
32    private PowTests(){}
33
34    static final double infinityD = Double.POSITIVE_INFINITY;
35
36    static int testPowCase(double input1, double input2, double expected) {
37        int failures = 0;
38        failures += Tests.test("StrictMath.pow(double, double)", input1, input2,
39                               StrictMath.pow(input1, input2), expected);
40        failures += Tests.test("Math.pow(double, double)", input1, input2,
41                               Math.pow(input1, input2), expected);
42        return failures;
43    }
44
45
46    static int testStrictPowCase(double input1, double input2, double expected) {
47        int failures = 0;
48        failures += Tests.test("StrictMath.pow(double, double)", input1, input2,
49                               StrictMath.pow(input1, input2), expected);
50        return failures;
51    }
52
53    static int testNonstrictPowCase(double input1, double input2, double expected) {
54        int failures = 0;
55        failures += Tests.test("Math.pow(double, double)", input1, input2,
56                               Math.pow(input1, input2), expected);
57        return failures;
58    }
59
60    /*
61     * Test for bad negation implementation.
62     */
63    static int testPow() {
64        int failures = 0;
65
66        double [][] testCases = {
67            {-0.0,               3.0,   -0.0},
68            {-0.0,               4.0,    0.0},
69            {-infinityD,        -3.0,   -0.0},
70            {-infinityD,        -4.0,    0.0},
71        };
72
73        for (double[] testCase : testCases) {
74            failures+=testPowCase(testCase[0], testCase[1], testCase[2]);
75        }
76
77        return failures;
78    }
79
80    /*
81     * Test cross-product of different kinds of arguments.
82     */
83    static int testCrossProduct() {
84        int failures = 0;
85
86        double testData[] = {
87                                Double.NEGATIVE_INFINITY,
88/* > -oo */                     -Double.MAX_VALUE,
89/**/                            (double)Long.MIN_VALUE,
90/**/                            (double) -((1L<<53)+2L),
91                                -0x1.0p65,
92                                -0x1.0000000000001p64,
93                                -0x1.0p64,
94/**/                            (double) -((1L<<53)),
95/**/                            (double) -((1L<<53)-1L),
96/**/                            -((double)Integer.MAX_VALUE + 4.0),
97/**/                            (double)Integer.MIN_VALUE - 1.0,
98/**/                            (double)Integer.MIN_VALUE,
99/**/                            (double)Integer.MIN_VALUE + 1.0,
100                                -0x1.0p31 + 2.0,
101                                -0x1.0p31 + 1.0,
102                                -0x1.0000000000001p31,
103                                -0x1.0p31,
104/**/                            -Math.PI,
105/**/                            -3.0,
106/**/                            -Math.E,
107/**/                            -2.0,
108/**/                            -1.0000000000000004,
109/* < -1.0 */                    -1.0000000000000002, // nextAfter(-1.0, -oo)
110                                -1.0,
111/* > -1.0 */                    -0.9999999999999999, // nextAfter(-1.0, +oo)
112/* > -1.0 */                    -0.9999999999999998,
113                                -0x1.fffffp-1,
114                                -0x1.ffffeffffffffp-1,
115/**/                            -0.5,
116/**/                            -1.0/3.0,
117/* < 0.0 */                     -Double.MIN_VALUE,
118                                -0.0,
119                                +0.0,
120/* > 0.0 */                     +Double.MIN_VALUE,
121/**/                            +1.0/3.0,
122/**/                            +0.5,
123                                +0x1.ffffeffffffffp-1,
124                                +0x1.fffffp-1,
125/**/                            +0.9999999999999998,
126/* < +1.0 */                    +0.9999999999999999, // nextAfter(-1.0, +oo)
127                                +1.0,
128/* > 1.0 */                     +1.0000000000000002, // nextAfter(+1.0, +oo)
129/**/                            +1.0000000000000004,
130/**/                            +2.0,
131/**/                            +Math.E,
132/**/                            +3.0,
133/**/                            +Math.PI,
134                                0x1.0p31,
135                                0x1.0000000000001p31,
136                                0x1.0p31 + 1.0,
137                                0x1.0p31 + 2.0,
138/**/                            -(double)Integer.MIN_VALUE - 1.0,
139/**/                            -(double)Integer.MIN_VALUE,
140/**/                            -(double)Integer.MIN_VALUE + 1.0,
141/**/                            (double)Integer.MAX_VALUE + 4.0,
142/**/                            (double) ((1L<<53)-1L),
143/**/                            (double) ((1L<<53)),
144/**/                            (double) ((1L<<53)+2L),
145                                0x1.0p64,
146                                0x1.0000000000001p64,
147                                0x1.0p65,
148/**/                            -(double)Long.MIN_VALUE,
149/* < oo */                      Double.MAX_VALUE,
150                                Double.POSITIVE_INFINITY,
151                                Double.NaN
152    };
153
154        double NaN = Double.NaN;
155        for(double x: testData) {
156            for(double y: testData) {
157                boolean testPass = false;
158                double expected=NaN;
159                double actual;
160
161                // First, switch on y
162                if( Double.isNaN(y)) {
163                    expected = NaN;
164                } else if (y == 0.0) {
165                    expected = 1.0;
166                } else if (Double.isInfinite(y) ) {
167                    if(y > 0) { // x ^ (+oo)
168                        if (Math.abs(x) > 1.0) {
169                            expected = Double.POSITIVE_INFINITY;
170                        } else if (Math.abs(x) == 1.0) {
171                            expected = NaN;
172                        } else if (Math.abs(x) < 1.0) {
173                            expected = +0.0;
174                        } else { // x is NaN
175                            assert Double.isNaN(x);
176                            expected = NaN;
177                        }
178                    } else { // x ^ (-oo)
179                        if (Math.abs(x) > 1.0) {
180                            expected = +0.0;
181                        } else if (Math.abs(x) == 1.0) {
182                            expected = NaN;
183                        } else if (Math.abs(x) < 1.0) {
184                            expected = Double.POSITIVE_INFINITY;
185                        } else { // x is NaN
186                            assert Double.isNaN(x);
187                            expected = NaN;
188                        }
189                    } /* end Double.isInfinite(y) */
190                } else if (y == 1.0) {
191                    expected = x;
192                } else if (Double.isNaN(x)) { // Now start switching on x
193                    assert y != 0.0;
194                    expected = NaN;
195                } else if (x == Double.NEGATIVE_INFINITY) {
196                    expected = (y < 0.0) ? f2(y) :f1(y);
197                } else if (x == Double.POSITIVE_INFINITY) {
198                    expected = (y < 0.0) ? +0.0 : Double.POSITIVE_INFINITY;
199                } else if (equivalent(x, +0.0)) {
200                    assert y != 0.0;
201                    expected = (y < 0.0) ? Double.POSITIVE_INFINITY: +0.0;
202                } else if (equivalent(x, -0.0)) {
203                    assert y != 0.0;
204                    expected = (y < 0.0) ? f1(y): f2(y);
205                } else if( x < 0.0) {
206                    assert y != 0.0;
207                    failures += testStrictPowCase(x, y, f3(x, y));
208                    failures += testNonstrictPowCase(x, y, f3ns(x, y));
209                    continue;
210                } else {
211                    // go to next iteration
212                    expected = NaN;
213                    continue;
214                }
215
216                failures += testPowCase(x, y, expected);
217            } // y
218        } // x
219        return failures;
220    }
221
222    static boolean equivalent(double a, double b) {
223        return Double.compare(a, b) == 0;
224    }
225
226    static double f1(double y) {
227        return (intClassify(y) == 1)?
228            Double.NEGATIVE_INFINITY:
229            Double.POSITIVE_INFINITY;
230    }
231
232
233    static double f2(double y) {
234        return (intClassify(y) == 1)?-0.0:0.0;
235    }
236
237    static double f3(double x, double y) {
238        switch( intClassify(y) ) {
239        case 0:
240            return StrictMath.pow(Math.abs(x), y);
241            // break;
242
243        case 1:
244            return -StrictMath.pow(Math.abs(x), y);
245            // break;
246
247        case -1:
248            return Double.NaN;
249            // break;
250
251        default:
252            throw new AssertionError("Bad classification.");
253            // break;
254        }
255    }
256
257    static double f3ns(double x, double y) {
258        switch( intClassify(y) ) {
259        case 0:
260            return Math.pow(Math.abs(x), y);
261            // break;
262
263        case 1:
264            return -Math.pow(Math.abs(x), y);
265            // break;
266
267        case -1:
268            return Double.NaN;
269            // break;
270
271        default:
272            throw new AssertionError("Bad classification.");
273            // break;
274        }
275    }
276
277    static boolean isFinite(double a) {
278        return (0.0 * a  == 0);
279    }
280
281    /**
282     * Return classification of argument: -1 for non-integers, 0 for
283     * even integers, 1 for odd integers.
284     */
285    static int intClassify(double a) {
286        if(!isFinite(a) || // NaNs and infinities
287           (a != Math.floor(a) )) { // only integers are fixed-points of floor
288                return -1;
289        }
290        else {
291            // Determine if argument is an odd or even integer.
292
293            a = StrictMath.abs(a); // absolute value doesn't affect odd/even
294
295            if(a+1.0 == a) { // a > maximum odd floating-point integer
296                return 0; // Large integers are all even
297            }
298            else { // Convert double -> long and look at low-order bit
299                long ell = (long)  a;
300                return ((ell & 0x1L) == (long)1)?1:0;
301            }
302        }
303    }
304
305    public static void main(String [] argv) {
306        int failures = 0;
307
308        failures += testPow();
309        failures += testCrossProduct();
310
311        if (failures > 0) {
312            System.err.println("Testing pow incurred "
313                               + failures + " failures.");
314            throw new RuntimeException();
315        }
316    }
317}
318