1 /* 2 * Copyright (c) 2004, 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 27 * @summary Tests for {Math, StrictMath}.pow 28 * @author Joseph D. Darcy 29 */ 30 31 public 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 }