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 }