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