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