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