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