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