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 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 -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 }