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 }