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 }