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