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 24import 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 */ 33public 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} 267