1 /* 2 * Copyright (c) 2012, 2016, 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 Math.*Exact integer and long methods. 28 * @bug 6708398 29 * @summary Basic tests for Math 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 testLongIntExact(); 47 48 if (errors > 0) { 49 throw new RuntimeException(errors + " errors found in ExactArithTests."); 50 } 51 } 52 53 static void fail(String message) { 54 errors++; 55 System.err.println(message); 56 } 57 58 /** 59 * Test Math.addExact, multiplyExact, subtractExact, toIntValue methods 60 * with {@code int} arguments. 61 */ 62 static void testIntegerExact() { 63 testIntegerExact(0, 0); 64 testIntegerExact(1, 1); 65 testIntegerExact(1, -1); 66 testIntegerExact(-1, 1); 67 testIntegerExact(1000, 2000); 68 69 testIntegerExact(Integer.MIN_VALUE, Integer.MIN_VALUE); 70 testIntegerExact(Integer.MAX_VALUE, Integer.MAX_VALUE); 71 testIntegerExact(Integer.MIN_VALUE, 1); 72 testIntegerExact(Integer.MAX_VALUE, 1); 73 testIntegerExact(Integer.MIN_VALUE, 2); 74 testIntegerExact(Integer.MAX_VALUE, 2); 75 testIntegerExact(Integer.MIN_VALUE, -1); 76 testIntegerExact(Integer.MAX_VALUE, -1); 77 testIntegerExact(Integer.MIN_VALUE, -2); 78 testIntegerExact(Integer.MAX_VALUE, -2); 79 80 } 81 82 /** 83 * Test exact arithmetic by comparing with the same operations using long 84 * and checking that the result is the same as the integer truncation. 85 * Errors are reported with {@link fail}. 86 * 87 * @param x first parameter 88 * @param y second parameter 89 */ 90 static void testIntegerExact(int x, int y) { 91 try { 92 // Test addExact 93 int sum = Math.addExact(x, y); 94 long sum2 = (long) x + (long) y; 95 if ((int) sum2 != sum2) { 96 fail("FAIL: int Math.addExact(" + x + " + " + y + ") = " + sum + "; expected Arithmetic exception"); 97 } else if (sum != sum2) { 98 fail("FAIL: long Math.addExact(" + x + " + " + y + ") = " + sum + "; expected: " + sum2); 99 } 100 } catch (ArithmeticException ex) { 101 long sum2 = (long) x + (long) y; 102 if ((int) sum2 == sum2) { 103 fail("FAIL: int Math.addExact(" + x + " + " + y + ")" + "; Unexpected exception: " + ex); 104 105 } 106 } 107 108 try { 109 // Test subtractExact 110 int diff = Math.subtractExact(x, y); 111 long diff2 = (long) x - (long) y; 112 if ((int) diff2 != diff2) { 113 fail("FAIL: int Math.subtractExact(" + x + " - " + y + ") = " + diff + "; expected: " + diff2); 114 } 115 116 } catch (ArithmeticException ex) { 117 long diff2 = (long) x - (long) y; 118 if ((int) diff2 == diff2) { 119 fail("FAIL: int Math.subtractExact(" + x + " - " + y + ")" + "; Unexpected exception: " + ex); 120 } 121 } 122 123 try { 124 // Test multiplyExact 125 int product = Math.multiplyExact(x, y); 126 long m2 = (long) x * (long) y; 127 if ((int) m2 != m2) { 128 fail("FAIL: int Math.multiplyExact(" + x + " * " + y + ") = " + product + "; expected: " + m2); 129 } 130 } catch (ArithmeticException ex) { 131 long m2 = (long) x * (long) y; 132 if ((int) m2 == m2) { 133 fail("FAIL: int Math.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex); 134 } 135 } 136 137 try { 138 // Test incrementExact 139 int inc = Math.incrementExact(x); 140 long inc2 = (long) x + 1L; 141 if ((int) inc2 != inc2) { 142 fail("FAIL: int Math.incrementExact(" + x + ") = " + inc + "; expected Arithmetic exception"); 143 } else if (inc != inc2) { 144 fail("FAIL: long Math.incrementExact(" + x + ") = " + inc + "; expected: " + inc2); 145 } 146 } catch (ArithmeticException ex) { 147 long inc2 = (long) x + 1L; 148 if ((int) inc2 == inc2) { 149 fail("FAIL: int Math.incrementExact(" + x + ")" + "; Unexpected exception: " + ex); 150 151 } 152 } 153 154 try { 155 // Test decrementExact 156 int dec = Math.decrementExact(x); 157 long dec2 = (long) x - 1L; 158 if ((int) dec2 != dec2) { 159 fail("FAIL: int Math.decrementExact(" + x + ") = " + dec + "; expected Arithmetic exception"); 160 } else if (dec != dec2) { 161 fail("FAIL: long Math.decrementExact(" + x + ") = " + dec + "; expected: " + dec2); 162 } 163 } catch (ArithmeticException ex) { 164 long dec2 = (long) x - 1L; 165 if ((int) dec2 == dec2) { 166 fail("FAIL: int Math.decrementExact(" + x + ")" + "; Unexpected exception: " + ex); 167 168 } 169 } 170 171 try { 172 // Test negateExact 173 int neg = Math.negateExact(x); 174 long neg2 = -((long)x) ; 175 if ((int) neg2 != neg2) { 176 fail("FAIL: int Math.negateExact(" + x + ") = " + neg + "; expected Arithmetic exception"); 177 } else if (neg != neg2) { 178 fail("FAIL: long Math.negateExact(" + x + ") = " + neg + "; expected: " + neg2); 179 } 180 } catch (ArithmeticException ex) { 181 long neg2 = (long) x - 1L; 182 if ((int) neg2 == neg2) { 183 fail("FAIL: int Math.negateExact(" + x + ")" + "; Unexpected exception: " + ex); 184 185 } 186 } 187 } 188 189 /** 190 * Test Math.addExact, multiplyExact, subtractExact, toIntExact methods 191 * with {@code long} arguments. 192 */ 193 static void testLongExact() { 194 testLongExactTwice(0, 0); 195 testLongExactTwice(1, 1); 196 testLongExactTwice(1, -1); 197 testLongExactTwice(1000, 2000); 198 199 testLongExactTwice(Long.MIN_VALUE, Long.MIN_VALUE); 200 testLongExactTwice(Long.MAX_VALUE, Long.MAX_VALUE); 201 testLongExactTwice(Long.MIN_VALUE, 1); 202 testLongExactTwice(Long.MAX_VALUE, 1); 203 testLongExactTwice(Long.MIN_VALUE, 2); 204 testLongExactTwice(Long.MAX_VALUE, 2); 205 testLongExactTwice(Long.MIN_VALUE, -1); 206 testLongExactTwice(Long.MAX_VALUE, -1); 207 testLongExactTwice(Long.MIN_VALUE, -2); 208 testLongExactTwice(Long.MAX_VALUE, -2); 209 testLongExactTwice(Long.MIN_VALUE/2, 2); 210 testLongExactTwice(Long.MAX_VALUE, 2); 211 testLongExactTwice(Integer.MAX_VALUE, Integer.MAX_VALUE); 212 testLongExactTwice(Integer.MAX_VALUE, -Integer.MAX_VALUE); 213 testLongExactTwice(Integer.MAX_VALUE+1, Integer.MAX_VALUE+1); 214 testLongExactTwice(Integer.MAX_VALUE+1, -Integer.MAX_VALUE+1); 215 testLongExactTwice(Integer.MIN_VALUE-1, Integer.MIN_VALUE-1); 216 testLongExactTwice(Integer.MIN_VALUE-1, -Integer.MIN_VALUE-1); 217 testLongExactTwice(Integer.MIN_VALUE/2, 2); 218 219 } 220 221 /** 222 * Test each of the exact operations with the arguments and 223 * with the arguments reversed. 224 * @param x 225 * @param y 226 */ 227 static void testLongExactTwice(long x, long y) { 228 testLongExact(x, y); 229 testLongExact(y, x); 230 } 231 232 233 /** 234 * Test long exact arithmetic by comparing with the same operations using BigInteger 235 * and checking that the result is the same as the long truncation. 236 * Errors are reported with {@link fail}. 237 * 238 * @param x first parameter 239 * @param y second parameter 240 */ 241 static void testLongExact(long x, long y) { 242 BigInteger resultBig = null; 243 final BigInteger xBig = BigInteger.valueOf(x); 244 final BigInteger yBig = BigInteger.valueOf(y); 245 try { 246 // Test addExact 247 resultBig = xBig.add(yBig); 248 long sum = Math.addExact(x, y); 249 checkResult("long Math.addExact", x, y, sum, resultBig); 250 } catch (ArithmeticException ex) { 251 if (inLongRange(resultBig)) { 252 fail("FAIL: long Math.addExact(" + x + " + " + y + "); Unexpected exception: " + ex); 253 } 254 } 255 256 try { 257 // Test subtractExact 258 resultBig = xBig.subtract(yBig); 259 long diff = Math.subtractExact(x, y); 260 checkResult("long Math.subtractExact", x, y, diff, resultBig); 261 } catch (ArithmeticException ex) { 262 if (inLongRange(resultBig)) { 263 fail("FAIL: long Math.subtractExact(" + x + " - " + y + ")" + "; Unexpected exception: " + ex); 264 } 265 } 266 267 try { 268 // Test multiplyExact 269 resultBig = xBig.multiply(yBig); 270 long product = Math.multiplyExact(x, y); 271 checkResult("long Math.multiplyExact", x, y, product, resultBig); 272 } catch (ArithmeticException ex) { 273 if (inLongRange(resultBig)) { 274 fail("FAIL: long Math.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex); 275 } 276 } 277 278 try { 279 // Test incrementExact 280 resultBig = xBig.add(BigInteger.ONE); 281 long inc = Math.incrementExact(x); 282 checkResult("long Math.incrementExact", x, 1L, inc, resultBig); 283 } catch (ArithmeticException ex) { 284 if (inLongRange(resultBig)) { 285 fail("FAIL: long Math.incrementExact(" + x + "); Unexpected exception: " + ex); 286 } 287 } 288 289 try { 290 // Test decrementExact 291 resultBig = xBig.subtract(BigInteger.ONE); 292 long dec = Math.decrementExact(x); 293 checkResult("long Math.decrementExact", x, 1L, dec, resultBig); 294 } catch (ArithmeticException ex) { 295 if (inLongRange(resultBig)) { 296 fail("FAIL: long Math.decrementExact(" + x + "); Unexpected exception: " + ex); 297 } 298 } 299 300 try { 301 // Test negateExact 302 resultBig = xBig.negate(); 303 long dec = Math.negateExact(x); 304 checkResult("long Math.negateExact", x, 0L, dec, resultBig); 305 } catch (ArithmeticException ex) { 306 if (inLongRange(resultBig)) { 307 fail("FAIL: long Math.negateExact(" + x + "); Unexpected exception: " + ex); 308 } 309 } 310 311 try { 312 // Test toIntExact 313 int value = Math.toIntExact(x); 314 if ((long)value != x) { 315 fail("FAIL: " + "long Math.toIntExact" + "(" + x + ") = " + value + "; expected an arithmetic exception: "); 316 } 317 } catch (ArithmeticException ex) { 318 if (resultBig.bitLength() <= 32) { 319 fail("FAIL: long Math.toIntExact(" + x + ")" + "; Unexpected exception: " + ex); 320 } 321 } 322 323 } 324 325 /** 326 * Compare the expected and actual results. 327 * @param message message for the error 328 * @param x first argument 329 * @param y second argument 330 * @param result actual result value 331 * @param expected expected result value 332 */ 333 static void checkResult(String message, long x, long y, long result, BigInteger expected) { 334 BigInteger resultBig = BigInteger.valueOf(result); 335 if (!inLongRange(expected)) { 336 fail("FAIL: " + message + "(" + x + ", " + y + ") = " + result + "; expected an arithmetic exception: "); 337 } else if (!resultBig.equals(expected)) { 338 fail("FAIL: " + message + "(" + x + ", " + y + ") = " + result + "; expected " + expected); 339 } 340 } 341 342 /** 343 * Check if the value fits in 64 bits (a long). 344 * @param value 345 * @return true if the value fits in 64 bits (including the sign). 346 */ 347 static boolean inLongRange(BigInteger value) { 348 return value.bitLength() <= 63; 349 } 350 351 /** 352 * Test Math.multiplyExact method with {@code long} and {@code int} 353 * arguments. 354 */ 355 static void testLongIntExact() { 356 testLongIntExact(0, 0); 357 testLongIntExact(1, 1); 358 testLongIntExact(1, -1); 359 testLongIntExact(1000, 2000); 360 361 testLongIntExact(Long.MIN_VALUE, Integer.MIN_VALUE); 362 testLongIntExact(Long.MAX_VALUE, Integer.MAX_VALUE); 363 testLongIntExact(Long.MIN_VALUE, 1); 364 testLongIntExact(Long.MAX_VALUE, 1); 365 testLongIntExact(Long.MIN_VALUE, 2); 366 testLongIntExact(Long.MAX_VALUE, 2); 367 testLongIntExact(Long.MIN_VALUE, -1); 368 testLongIntExact(Long.MAX_VALUE, -1); 369 testLongIntExact(Long.MIN_VALUE, -2); 370 testLongIntExact(Long.MAX_VALUE, -2); 371 testLongIntExact(Long.MIN_VALUE/2, 2); 372 testLongIntExact(Long.MAX_VALUE, 2); 373 testLongIntExact(Integer.MAX_VALUE, Integer.MAX_VALUE); 374 testLongIntExact(Integer.MAX_VALUE, -Integer.MAX_VALUE); 375 testLongIntExact((long)Integer.MAX_VALUE+1L, Integer.MAX_VALUE); 376 testLongIntExact((long)Integer.MAX_VALUE+1L, -Integer.MAX_VALUE+1); 377 testLongIntExact((long)Integer.MIN_VALUE-1L, Integer.MIN_VALUE); 378 testLongIntExact((long)Integer.MIN_VALUE-1, Integer.MAX_VALUE); 379 testLongIntExact(Integer.MIN_VALUE/2, 2); 380 } 381 382 /** 383 * Test long-int exact arithmetic by comparing with the same operations using BigInteger 384 * and checking that the result is the same as the long truncation. 385 * Errors are reported with {@link fail}. 386 * 387 * @param x first parameter 388 * @param y second parameter 389 */ 390 static void testLongIntExact(long x, int y) { 391 BigInteger resultBig = null; 392 final BigInteger xBig = BigInteger.valueOf(x); 393 final BigInteger yBig = BigInteger.valueOf(y); 394 395 try { 396 // Test multiplyExact 397 resultBig = xBig.multiply(yBig); 398 long product = Math.multiplyExact(x, y); 399 checkResult("long Math.multiplyExact", x, y, product, resultBig); 400 } catch (ArithmeticException ex) { 401 if (inLongRange(resultBig)) { 402 fail("FAIL: long Math.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex); 403 } 404 } 405 } 406 }