1 /*
   2  * Copyright (c) 2012, 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 import java.math.BigInteger;
  25 
  26 /**
  27  * @test Test for StrictMath.*Exact integer and long methods.
  28  * @bug 6708398
  29  * @summary Basic tests for StrictMath exact arithmetic operations.
  30  *
  31  * @author Roger Riggs
  32  */
  33 public class ExactArithTests {
  34 
  35     /**
  36      * The count of test errors.
  37      */
  38     private static int errors = 0;
  39 
  40     /**
  41      * @param args the command line arguments
  42      */
  43     public static void main(String[] args) {
  44         testIntegerExact();
  45         testLongExact();
  46 
  47         if (errors > 0) {
  48             throw new RuntimeException(errors + " errors found in ExactArithTests.");
  49         }
  50     }
  51 
  52     static void fail(String message) {
  53         errors++;
  54         System.err.println(message);
  55     }
  56 
  57     /**
  58      * Test StrictMath.addExact, multiplyExact, subtractExact, toIntValue methods
  59      * with {@code int} arguments.
  60      */
  61     static void testIntegerExact() {
  62         testIntegerExact(0, 0);
  63         testIntegerExact(1, 1);
  64         testIntegerExact(1, -1);
  65         testIntegerExact(-1, 1);
  66         testIntegerExact(1000, 2000);
  67 
  68         testIntegerExact(Integer.MIN_VALUE, Integer.MIN_VALUE);
  69         testIntegerExact(Integer.MAX_VALUE, Integer.MAX_VALUE);
  70         testIntegerExact(Integer.MIN_VALUE, 1);
  71         testIntegerExact(Integer.MAX_VALUE, 1);
  72         testIntegerExact(Integer.MIN_VALUE, 2);
  73         testIntegerExact(Integer.MAX_VALUE, 2);
  74         testIntegerExact(Integer.MIN_VALUE, -1);
  75         testIntegerExact(Integer.MAX_VALUE, -1);
  76         testIntegerExact(Integer.MIN_VALUE, -2);
  77         testIntegerExact(Integer.MAX_VALUE, -2);
  78 
  79     }
  80 
  81     /**
  82      * Test exact arithmetic by comparing with the same operations using long
  83      * and checking that the result is the same as the integer truncation.
  84      * Errors are reported with {@link fail}.
  85      *
  86      * @param x first parameter
  87      * @param y second parameter
  88      */
  89     static void testIntegerExact(int x, int y) {
  90         try {
  91             // Test addExact
  92             int sum = StrictMath.addExact(x, y);
  93             long sum2 = (long) x + (long) y;
  94             if ((int) sum2 != sum2) {
  95                 fail("FAIL: int StrictMath.addExact(" + x + " + " + y + ") = " + sum + "; expected Arithmetic exception");
  96             } else if (sum != sum2) {
  97                 fail("FAIL: long StrictMath.addExact(" + x + " + " + y + ") = " + sum + "; expected: " + sum2);
  98             }
  99         } catch (ArithmeticException ex) {
 100             long sum2 = (long) x + (long) y;
 101             if ((int) sum2 == sum2) {
 102                 fail("FAIL: int StrictMath.addExact(" + x + " + " + y + ")" + "; Unexpected exception: " + ex);
 103 
 104             }
 105         }
 106 
 107         try {
 108             // Test subtractExact
 109             int diff = StrictMath.subtractExact(x, y);
 110             long diff2 = (long) x - (long) y;
 111             if ((int) diff2 != diff2) {
 112                 fail("FAIL: int StrictMath.subtractExact(" + x + " - " + y + ") = " + diff + "; expected: " + diff2);
 113             }
 114 
 115         } catch (ArithmeticException ex) {
 116             long diff2 = (long) x - (long) y;
 117             if ((int) diff2 == diff2) {
 118                 fail("FAIL: int StrictMath.subtractExact(" + x + " - " + y + ")" + "; Unexpected exception: " + ex);
 119             }
 120         }
 121 
 122         try {
 123             // Test multiplyExact
 124             int product = StrictMath.multiplyExact(x, y);
 125             long m2 = (long) x * (long) y;
 126             if ((int) m2 != m2) {
 127                 fail("FAIL: int StrictMath.multiplyExact(" + x + " * " + y + ") = " + product + "; expected: " + m2);
 128             }
 129         } catch (ArithmeticException ex) {
 130             long m2 = (long) x * (long) y;
 131             if ((int) m2 == m2) {
 132                 fail("FAIL: int StrictMath.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex);
 133             }
 134         }
 135 















































 136     }
 137 
 138     /**
 139      * Test StrictMath.addExact, multiplyExact, subtractExact, toIntExact methods
 140      * with {@code long} arguments.
 141      */
 142     static void testLongExact() {
 143         testLongExactTwice(0, 0);
 144         testLongExactTwice(1, 1);
 145         testLongExactTwice(1, -1);
 146         testLongExactTwice(1000, 2000);
 147 
 148         testLongExactTwice(Long.MIN_VALUE, Long.MIN_VALUE);
 149         testLongExactTwice(Long.MAX_VALUE, Long.MAX_VALUE);
 150         testLongExactTwice(Long.MIN_VALUE, 1);
 151         testLongExactTwice(Long.MAX_VALUE, 1);
 152         testLongExactTwice(Long.MIN_VALUE, 2);
 153         testLongExactTwice(Long.MAX_VALUE, 2);
 154         testLongExactTwice(Long.MIN_VALUE, -1);
 155         testLongExactTwice(Long.MAX_VALUE, -1);
 156         testLongExactTwice(Long.MIN_VALUE, -2);
 157         testLongExactTwice(Long.MAX_VALUE, -2);
 158         testLongExactTwice(Long.MIN_VALUE/2, 2);
 159         testLongExactTwice(Long.MAX_VALUE, 2);
 160         testLongExactTwice(Integer.MAX_VALUE, Integer.MAX_VALUE);
 161         testLongExactTwice(Integer.MAX_VALUE, -Integer.MAX_VALUE);
 162         testLongExactTwice(Integer.MAX_VALUE+1, Integer.MAX_VALUE+1);
 163         testLongExactTwice(Integer.MAX_VALUE+1, -Integer.MAX_VALUE+1);
 164         testLongExactTwice(Integer.MIN_VALUE-1, Integer.MIN_VALUE-1);
 165         testLongExactTwice(Integer.MIN_VALUE-1, -Integer.MIN_VALUE-1);
 166         testLongExactTwice(Integer.MIN_VALUE/2, 2);
 167 
 168     }
 169 
 170     /**
 171      * Test each of the exact operations with the arguments and
 172      * with the arguments reversed.
 173      * @param x
 174      * @param y
 175      */
 176     static void testLongExactTwice(long x, long y) {
 177         testLongExact(x, y);
 178         testLongExact(y, x);
 179     }
 180 
 181 
 182     /**
 183      * Test long exact arithmetic by comparing with the same operations using BigInteger
 184      * and checking that the result is the same as the long truncation.
 185      * Errors are reported with {@link fail}.
 186      *
 187      * @param x first parameter
 188      * @param y second parameter
 189      */
 190     static void testLongExact(long x, long y) {
 191         BigInteger resultBig = null;
 192         final BigInteger xBig = BigInteger.valueOf(x);
 193         final BigInteger yBig = BigInteger.valueOf(y);
 194         try {
 195             // Test addExact
 196             resultBig = xBig.add(yBig);
 197             long sum = StrictMath.addExact(x, y);
 198             checkResult("long StrictMath.addExact", x, y, sum, resultBig);
 199         } catch (ArithmeticException ex) {
 200             if (inLongRange(resultBig)) {
 201                 fail("FAIL: long StrictMath.addExact(" + x + " + " + y + "); Unexpected exception: " + ex);
 202             }
 203         }
 204 
 205         try {
 206             // Test subtractExact
 207             resultBig = xBig.subtract(yBig);
 208             long diff = StrictMath.subtractExact(x, y);
 209             checkResult("long StrictMath.subtractExact", x, y, diff, resultBig);
 210         } catch (ArithmeticException ex) {
 211             if (inLongRange(resultBig)) {
 212                 fail("FAIL: long StrictMath.subtractExact(" + x + " - " + y + ")" + "; Unexpected exception: " + ex);
 213             }
 214         }
 215 
 216         try {
 217             // Test multiplyExact
 218             resultBig = xBig.multiply(yBig);
 219             long product = StrictMath.multiplyExact(x, y);
 220             checkResult("long StrictMath.multiplyExact", x, y, product, resultBig);
 221         } catch (ArithmeticException ex) {
 222             if (inLongRange(resultBig)) {
 223                 fail("FAIL: long StrictMath.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex);
 224             }
 225         }
 226 
 227         try {

































 228             // Test toIntExact
 229             int value = StrictMath.toIntExact(x);
 230             if ((long)value != x) {
 231                 fail("FAIL: " + "long StrictMath.toIntExact" + "(" + x + ") = " + value + "; expected an arithmetic exception: ");
 232             }
 233         } catch (ArithmeticException ex) {
 234             if (resultBig.bitLength() <= 32) {
 235                 fail("FAIL: long StrictMath.toIntExact(" + x + ")" + "; Unexpected exception: " + ex);
 236             }
 237         }
 238 
 239     }
 240 
 241     /**
 242      * Compare the expected and actual results.
 243      * @param message message for the error
 244      * @param x first argument
 245      * @param y second argument
 246      * @param result actual result value
 247      * @param expected expected result value
 248      */
 249     static void checkResult(String message, long x, long y, long result, BigInteger expected) {
 250         BigInteger resultBig = BigInteger.valueOf(result);
 251         if (!inLongRange(expected)) {
 252             fail("FAIL: " + message + "(" + x + ", " + y + ") = " + result + "; expected an arithmetic exception: ");
 253         } else if (!resultBig.equals(expected)) {
 254             fail("FAIL: " + message + "(" + x + ", " + y + ") = " + result + "; expected " + expected);
 255         }
 256     }
 257 
 258     /**
 259      * Check if the value fits in 64 bits (a long).
 260      * @param value
 261      * @return true if the value fits in 64 bits (including the sign).
 262      */
 263     static boolean inLongRange(BigInteger value) {
 264         return value.bitLength() <= 63;
 265     }
 266 }
--- EOF ---