PowTests.java revision 1952:1755493c5774
1/*
2 * Copyright 2004 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/*
25 * @test
26 * @bug 4984407 5033578
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/**/                            (double) -((1L<<53)),
92/**/                            (double) -((1L<<53)-1L),
93/**/                            -((double)Integer.MAX_VALUE + 4.0),
94/**/                            (double)Integer.MIN_VALUE - 1.0,
95/**/                            (double)Integer.MIN_VALUE,
96/**/                            (double)Integer.MIN_VALUE + 1.0,
97/**/                            -Math.PI,
98/**/                            -3.0,
99/**/                            -Math.E,
100/**/                            -2.0,
101/**/                            -1.0000000000000004,
102/* < -1.0 */                    -1.0000000000000002, // nextAfter(-1.0, -oo)
103                                -1.0,
104/* > -1.0 */                    -0.9999999999999999, // nextAfter(-1.0, +oo)
105/* > -1.0 */                    -0.9999999999999998,
106/**/                            -0.5,
107/**/                            -1.0/3.0,
108/* < 0.0 */                     -Double.MIN_VALUE,
109                                -0.0,
110                                +0.0,
111/* > 0.0 */                     +Double.MIN_VALUE,
112/**/                            +1.0/3.0,
113/**/                            +0.5,
114/**/                            +0.9999999999999998,
115/* < +1.0 */                    +0.9999999999999999, // nextAfter(-1.0, +oo)
116                                +1.0,
117/* > 1.0 */                     +1.0000000000000002, // nextAfter(+1.0, +oo)
118/**/                            +1.0000000000000004,
119/**/                            +2.0,
120/**/                            +Math.E,
121/**/                            +3.0,
122/**/                            +Math.PI,
123/**/                            -(double)Integer.MIN_VALUE - 1.0,
124/**/                            -(double)Integer.MIN_VALUE,
125/**/                            -(double)Integer.MIN_VALUE + 1.0,
126/**/                            (double)Integer.MAX_VALUE + 4.0,
127/**/                            (double) ((1L<<53)-1L),
128/**/                            (double) ((1L<<53)),
129/**/                            (double) ((1L<<53)+2L),
130/**/                            -(double)Long.MIN_VALUE,
131/* < oo */                      Double.MAX_VALUE,
132                                Double.POSITIVE_INFINITY,
133                                Double.NaN
134    };
135
136        double NaN = Double.NaN;
137        for(double x: testData) {
138            for(double y: testData) {
139                boolean testPass = false;
140                double expected=NaN;
141                double actual;
142
143                // First, switch on y
144                if( Double.isNaN(y)) {
145                    expected = NaN;
146                } else if (y == 0.0) {
147                    expected = 1.0;
148                } else if (Double.isInfinite(y) ) {
149                    if(y > 0) { // x ^ (+oo)
150                        if (Math.abs(x) > 1.0) {
151                            expected = Double.POSITIVE_INFINITY;
152                        } else if (Math.abs(x) == 1.0) {
153                            expected = NaN;
154                        } else if (Math.abs(x) < 1.0) {
155                            expected = +0.0;
156                        } else { // x is NaN
157                            assert Double.isNaN(x);
158                            expected = NaN;
159                        }
160                    } else { // x ^ (-oo)
161                        if (Math.abs(x) > 1.0) {
162                            expected = +0.0;
163                        } else if (Math.abs(x) == 1.0) {
164                            expected = NaN;
165                        } else if (Math.abs(x) < 1.0) {
166                            expected = Double.POSITIVE_INFINITY;
167                        } else { // x is NaN
168                            assert Double.isNaN(x);
169                            expected = NaN;
170                        }
171                    } /* end Double.isInfinite(y) */
172                } else if (y == 1.0) {
173                    expected = x;
174                } else if (Double.isNaN(x)) { // Now start switching on x
175                    assert y != 0.0;
176                    expected = NaN;
177                } else if (x == Double.NEGATIVE_INFINITY) {
178                    expected = (y < 0.0) ? f2(y) :f1(y);
179                } else if (x == Double.POSITIVE_INFINITY) {
180                    expected = (y < 0.0) ? +0.0 : Double.POSITIVE_INFINITY;
181                } else if (equivalent(x, +0.0)) {
182                    assert y != 0.0;
183                    expected = (y < 0.0) ? Double.POSITIVE_INFINITY: +0.0;
184                } else if (equivalent(x, -0.0)) {
185                    assert y != 0.0;
186                    expected = (y < 0.0) ? f1(y): f2(y);
187                } else if( x < 0.0) {
188                    assert y != 0.0;
189                    failures += testStrictPowCase(x, y, f3(x, y));
190                    failures += testNonstrictPowCase(x, y, f3ns(x, y));
191                    continue;
192                } else {
193                    // go to next iteration
194                    expected = NaN;
195                    continue;
196                }
197
198                failures += testPowCase(x, y, expected);
199            } // y
200        } // x
201        return failures;
202    }
203
204    static boolean equivalent(double a, double b) {
205        return Double.compare(a, b) == 0;
206    }
207
208    static double f1(double y) {
209        return (intClassify(y) == 1)?
210            Double.NEGATIVE_INFINITY:
211            Double.POSITIVE_INFINITY;
212    }
213
214
215    static double f2(double y) {
216        return (intClassify(y) == 1)?-0.0:0.0;
217    }
218
219    static double f3(double x, double y) {
220        switch( intClassify(y) ) {
221        case 0:
222            return StrictMath.pow(Math.abs(x), y);
223            // break;
224
225        case 1:
226            return -StrictMath.pow(Math.abs(x), y);
227            // break;
228
229        case -1:
230            return Double.NaN;
231            // break;
232
233        default:
234            throw new AssertionError("Bad classification.");
235            // break;
236        }
237    }
238
239    static double f3ns(double x, double y) {
240        switch( intClassify(y) ) {
241        case 0:
242            return Math.pow(Math.abs(x), y);
243            // break;
244
245        case 1:
246            return -Math.pow(Math.abs(x), y);
247            // break;
248
249        case -1:
250            return Double.NaN;
251            // break;
252
253        default:
254            throw new AssertionError("Bad classification.");
255            // break;
256        }
257    }
258
259    static boolean isFinite(double a) {
260        return (0.0*a  == 0);
261    }
262
263    /**
264     * Return classification of argument: -1 for non-integers, 0 for
265     * even integers, 1 for odd integers.
266     */
267    static int intClassify(double a) {
268        if(!isFinite(a) || // NaNs and infinities
269           (a != Math.floor(a) )) { // only integers are fixed-points of floor
270                return -1;
271        }
272        else {
273            // Determine if argument is an odd or even integer.
274
275            a = StrictMath.abs(a); // absolute value doesn't affect odd/even
276
277            if(a+1.0 == a) { // a > maximum odd floating-point integer
278                return 0; // Large integers are all even
279            }
280            else { // Convert double -> long and look at low-order bit
281                long ell = (long)  a;
282                return ((ell & 0x1L) == (long)1)?1:0;
283            }
284        }
285    }
286
287    public static void main(String [] argv) {
288        int failures = 0;
289
290        failures += testPow();
291        failures += testCrossProduct();
292
293        if (failures > 0) {
294            System.err.println("Testing pow incurred "
295                               + failures + " failures.");
296            throw new RuntimeException();
297        }
298    }
299}
300