1 /* 2 * Copyright (c) 2013, 2014, 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 com.oracle.java.testlibrary.Utils; 25 import java.util.Random; 26 27 /** 28 * The class depends on Utils class from testlibrary package. 29 * It uses factory method that obtains random generator. 30 */ 31 public class Verify { 32 public static String throwWord(boolean threw) { 33 return (threw ? "threw" : "didn't throw"); 34 } 35 36 public static void verifyResult(UnaryMethod method, int result1, int result2, boolean exception1, boolean exception2, int value) { 37 if (exception1 != exception2) { 38 throw new RuntimeException("Intrinsic version [" + method.name() + "]" + throwWord(exception1) + " exception, NonIntrinsic version" + throwWord(exception2) + " for: " + value); 39 } 40 if (result1 != result2) { 41 throw new RuntimeException("Intrinsic version [" + method.name() + "] returned: " + result1 + " while NonIntrinsic version returned: " + result2); 42 } 43 } 44 45 public static void verifyResult(UnaryLongMethod method, long result1, long result2, boolean exception1, boolean exception2, long value) { 46 if (exception1 != exception2) { 47 throw new RuntimeException("Intrinsic version [" + method.name() + "]" + throwWord(exception1) + " exception, NonIntrinsic version" + throwWord(exception2) + " for: " + value); 48 } 49 if (result1 != result2) { 50 throw new RuntimeException("Intrinsic version [" + method.name() + "] returned: " + result1 + " while NonIntrinsic version returned: " + result2); 51 } 52 } 53 54 private static void verifyResult(BinaryMethod method, int result1, int result2, boolean exception1, boolean exception2, int a, int b) { 55 if (exception1 != exception2) { 56 throw new RuntimeException("Intrinsic version [" + method.name() + "]" + throwWord(exception1) + " exception, NonIntrinsic version " + throwWord(exception2) + " for: " + a + " + " + b); 57 } 58 if (result1 != result2) { 59 throw new RuntimeException("Intrinsic version [" + method.name() + "] returned: " + result1 + " while NonIntrinsic version returned: " + result2); 60 } 61 } 62 63 private static void verifyResult(BinaryLongMethod method, long result1, long result2, boolean exception1, boolean exception2, long a, long b) { 64 if (exception1 != exception2) { 65 throw new RuntimeException("Intrinsic version [" + method.name() + "]" + throwWord(exception1) + " exception, NonIntrinsic version " + throwWord(exception2) + " for: " + a + " + " + b); 66 } 67 if (result1 != result2) { 68 throw new RuntimeException("Intrinsic version [" + method.name() + "] returned: " + result1 + " while NonIntrinsic version returned: " + result2); 69 } 70 } 71 72 73 public static void verifyUnary(int a, UnaryMethod method) { 74 boolean exception1 = false, exception2 = false; 75 int result1 = 0, result2 = 0; 76 try { 77 result1 = method.checkMethod(a); 78 } catch (ArithmeticException e) { 79 exception1 = true; 80 } 81 try { 82 result2 = method.safeMethod(a); 83 } catch (ArithmeticException e) { 84 exception2 = true; 85 } 86 87 verifyResult(method, result1, result2, exception1, exception2, a); 88 } 89 90 public static void verifyUnary(long a, UnaryLongMethod method) { 91 boolean exception1 = false, exception2 = false; 92 long result1 = 0, result2 = 0; 93 try { 94 result1 = method.checkMethod(a); 95 } catch (ArithmeticException e) { 96 exception1 = true; 97 } 98 try { 99 result2 = method.safeMethod(a); 100 } catch (ArithmeticException e) { 101 exception2 = true; 102 } 103 104 verifyResult(method, result1, result2, exception1, exception2, a); 105 } 106 107 108 public static void verifyBinary(int a, int b, BinaryMethod method) { 109 boolean exception1 = false, exception2 = false; 110 int result1 = 0, result2 = 0; 111 try { 112 result1 = method.checkMethod(a, b); 113 } catch (ArithmeticException e) { 114 exception1 = true; 115 } 116 try { 117 result2 = method.safeMethod(a, b); 118 } catch (ArithmeticException e) { 119 exception2 = true; 120 } 121 122 verifyResult(method, result1, result2, exception1, exception2, a, b); 123 } 124 125 public static void verifyBinary(long a, long b, BinaryLongMethod method) { 126 boolean exception1 = false, exception2 = false; 127 long result1 = 0, result2 = 0; 128 try { 129 result1 = method.checkMethod(a, b); 130 } catch (ArithmeticException e) { 131 exception1 = true; 132 } 133 try { 134 result2 = method.safeMethod(a, b); 135 } catch (ArithmeticException e) { 136 exception2 = true; 137 } 138 139 verifyResult(method, result1, result2, exception1, exception2, a, b); 140 } 141 142 143 public static class LoadTest { 144 public static Random rnd = Utils.getRandomInstance(); 145 public static int[] values = new int[256]; 146 147 public static void init() { 148 for (int i = 0; i < values.length; ++i) { 149 values[i] = rnd.nextInt(); 150 } 151 } 152 153 public static void verify(BinaryMethod method) { 154 for (int i = 0; i < 50000; ++i) { 155 Verify.verifyBinary(values[i & 255], values[i & 255] - i, method); 156 Verify.verifyBinary(values[i & 255] + i, values[i & 255] - i, method); 157 Verify.verifyBinary(values[i & 255], values[i & 255], method); 158 if ((i & 1) == 1 && i > 5) { 159 Verify.verifyBinary(values[i & 255] + i, values[i & 255] - i, method); 160 } else { 161 Verify.verifyBinary(values[i & 255] - i, values[i & 255] + i, method); 162 } 163 Verify.verifyBinary(values[i & 255], values[(i + 1) & 255], method); 164 } 165 } 166 } 167 168 public static class NonConstantTest { 169 public static Random rnd = Utils.getRandomInstance(); 170 public static int[] values = new int[] { Integer.MAX_VALUE, Integer.MIN_VALUE }; 171 172 public static void verify(BinaryMethod method) { 173 for (int i = 0; i < 50000; ++i) { 174 int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt(); 175 Verify.verifyBinary(rnd1, rnd2, method); 176 Verify.verifyBinary(rnd1, rnd2 + 1, method); 177 Verify.verifyBinary(rnd1 + 1, rnd2, method); 178 Verify.verifyBinary(rnd1 - 1, rnd2, method); 179 Verify.verifyBinary(rnd1, rnd2 - 1, method); 180 Verify.verifyBinary(0, values[0], method); 181 Verify.verifyBinary(values[0], 0, method); 182 Verify.verifyBinary(0, values[1], method); 183 Verify.verifyBinary(values[1], 0, method); 184 } 185 } 186 } 187 188 public static class NonConstantLongTest { 189 public static long[] values = { Long.MIN_VALUE, Long.MAX_VALUE, 0, Long.MAX_VALUE - 1831 }; 190 public static Random rnd = Utils.getRandomInstance(); 191 192 public static void verify(BinaryLongMethod method) { 193 for (int i = 0; i < 50000; ++i) { 194 long rnd1 = rnd.nextLong(), rnd2 = rnd.nextLong(); 195 Verify.verifyBinary(rnd1, rnd2, method); 196 Verify.verifyBinary(rnd1, rnd2 + 1, method); 197 Verify.verifyBinary(rnd1 + 1, rnd2, method); 198 Verify.verifyBinary(rnd1 - 1, rnd2, method); 199 Verify.verifyBinary(rnd1, rnd2 - 1, method); 200 Verify.verifyBinary(rnd1 + Long.MAX_VALUE - rnd2, rnd2 + 1, method); 201 Verify.verifyBinary(values[0], values[2], method); 202 Verify.verifyBinary(values[1], values[2], method); 203 Verify.verifyBinary(values[3], 74L, method); 204 } 205 } 206 } 207 208 public static class LoopDependentTest { 209 public static Random rnd = Utils.getRandomInstance(); 210 211 public static void verify(BinaryMethod method) { 212 int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt(); 213 runTest(rnd1, rnd2, method); 214 } 215 216 private static void runTest(int rnd1, int rnd2, BinaryMethod method) { 217 for (int i = 0; i < 50000; ++i) { 218 Verify.verifyBinary(rnd1 + i, rnd2 + i, method); 219 Verify.verifyBinary(rnd1 + i, rnd2 + (i & 0xff), method); 220 Verify.verifyBinary(rnd1 - i, rnd2 - (i & 0xff), method); 221 Verify.verifyBinary(rnd1 + i + 1, rnd2 + i + 2, method); 222 Verify.verifyBinary(rnd1 + i * 2, rnd2 + i, method); 223 } 224 } 225 } 226 227 public static class ConstantTest { 228 public static void verify(BinaryMethod method) { 229 for (int i = 0; i < 50000; ++i) { 230 Verify.verifyBinary(5, 7, method); 231 Verify.verifyBinary(Integer.MAX_VALUE, 1, method); 232 Verify.verifyBinary(Integer.MIN_VALUE, -1, method); 233 Verify.verifyBinary(Integer.MAX_VALUE, -1, method); 234 Verify.verifyBinary(Integer.MIN_VALUE, 1, method); 235 Verify.verifyBinary(Integer.MAX_VALUE / 2, Integer.MAX_VALUE / 2, method); 236 Verify.verifyBinary(Integer.MAX_VALUE / 2, (Integer.MAX_VALUE / 2) + 3, method); 237 Verify.verifyBinary(Integer.MAX_VALUE, Integer.MIN_VALUE, method); 238 } 239 } 240 } 241 242 public static class ConstantLongTest { 243 public static void verify(BinaryLongMethod method) { 244 for (int i = 0; i < 50000; ++i) { 245 Verify.verifyBinary(5, 7, method); 246 Verify.verifyBinary(Long.MAX_VALUE, 1, method); 247 Verify.verifyBinary(Long.MIN_VALUE, -1, method); 248 Verify.verifyBinary(Long.MAX_VALUE, -1, method); 249 Verify.verifyBinary(Long.MIN_VALUE, 1, method); 250 Verify.verifyBinary(Long.MAX_VALUE / 2, Long.MAX_VALUE / 2, method); 251 Verify.verifyBinary(Long.MAX_VALUE / 2, (Long.MAX_VALUE / 2) + 3, method); 252 Verify.verifyBinary(Long.MAX_VALUE, Long.MIN_VALUE, method); 253 } 254 } 255 } 256 257 public static interface BinaryMethod { 258 int safeMethod(int a, int b); 259 int checkMethod(int a, int b); 260 int unchecked(int a, int b); 261 String name(); 262 } 263 264 public static interface UnaryMethod { 265 int safeMethod(int value); 266 int checkMethod(int value); 267 int unchecked(int value); 268 String name(); 269 } 270 271 public static interface BinaryLongMethod { 272 long safeMethod(long a, long b); 273 long checkMethod(long a, long b); 274 long unchecked(long a, long b); 275 String name(); 276 } 277 278 public static interface UnaryLongMethod { 279 long safeMethod(long value); 280 long checkMethod(long value); 281 long unchecked(long value); 282 String name(); 283 } 284 285 public static class UnaryToBinary implements BinaryMethod { 286 private final UnaryMethod method; 287 public UnaryToBinary(UnaryMethod method) { 288 this.method = method; 289 } 290 291 @Override 292 public int safeMethod(int a, int b) { 293 return method.safeMethod(a); 294 } 295 296 @Override 297 public int checkMethod(int a, int b) { 298 return method.checkMethod(a); 299 } 300 301 @Override 302 public int unchecked(int a, int b) { 303 return method.unchecked(a); 304 305 } 306 307 @Override 308 public String name() { 309 return method.name(); 310 } 311 } 312 313 public static class UnaryToBinaryLong implements BinaryLongMethod { 314 private final UnaryLongMethod method; 315 public UnaryToBinaryLong(UnaryLongMethod method) { 316 this.method = method; 317 } 318 319 @Override 320 public long safeMethod(long a, long b) { 321 return method.safeMethod(a); 322 } 323 324 @Override 325 public long checkMethod(long a, long b) { 326 return method.checkMethod(a); 327 } 328 329 @Override 330 public long unchecked(long a, long b) { 331 return method.unchecked(a); 332 333 } 334 335 @Override 336 public String name() { 337 return method.name(); 338 } 339 } 340 341 342 public static class AddExactI implements BinaryMethod { 343 @Override 344 public int safeMethod(int x, int y) { 345 int r = x + y; 346 // HD 2-12 Overflow iff both arguments have the opposite sign of the result 347 if (((x ^ r) & (y ^ r)) < 0) { 348 throw new ArithmeticException("integer overflow"); 349 } 350 return r; 351 352 } 353 354 @Override 355 public int checkMethod(int a, int b) { 356 return Math.addExact(a, b); 357 } 358 359 @Override 360 public String name() { 361 return "addExact"; 362 } 363 364 @Override 365 public int unchecked(int a, int b) { 366 return a + b; 367 } 368 } 369 370 public static class AddExactL implements BinaryLongMethod { 371 @Override 372 public long safeMethod(long x, long y) { 373 long r = x + y; 374 // HD 2-12 Overflow iff both arguments have the opposite sign of the result 375 if (((x ^ r) & (y ^ r)) < 0) { 376 throw new ArithmeticException("integer overflow"); 377 } 378 return r; 379 380 } 381 382 @Override 383 public long checkMethod(long a, long b) { 384 return Math.addExact(a, b); 385 } 386 387 @Override 388 public String name() { 389 return "addExactLong"; 390 } 391 392 @Override 393 public long unchecked(long a, long b) { 394 return a + b; 395 } 396 } 397 398 public static class MulExactI implements BinaryMethod { 399 @Override 400 public int safeMethod(int x, int y) { 401 long r = (long)x * (long)y; 402 if ((int)r != r) { 403 throw new ArithmeticException("integer overflow"); 404 } 405 return (int)r; 406 407 } 408 409 @Override 410 public int checkMethod(int a, int b) { 411 return Math.multiplyExact(a, b); 412 } 413 414 @Override 415 public int unchecked(int a, int b) { 416 return a * b; 417 } 418 419 @Override 420 public String name() { 421 return "multiplyExact"; 422 } 423 } 424 425 public static class MulExactL implements BinaryLongMethod { 426 @Override 427 public long safeMethod(long x, long y) { 428 long r = x * y; 429 long ax = Math.abs(x); 430 long ay = Math.abs(y); 431 if (((ax | ay) >>> 31 != 0)) { 432 // Some bits greater than 2^31 that might cause overflow 433 // Check the result using the divide operator 434 // and check for the special case of Long.MIN_VALUE * -1 435 if (((y != 0) && (r / y != x)) || 436 (x == Long.MIN_VALUE && y == -1)) { 437 throw new ArithmeticException("long overflow"); 438 } 439 } 440 return r; 441 } 442 443 @Override 444 public long checkMethod(long a, long b) { 445 return Math.multiplyExact(a, b); 446 } 447 448 @Override 449 public long unchecked(long a, long b) { 450 return a * b; 451 } 452 453 @Override 454 public String name() { 455 return "multiplyExact"; 456 } 457 } 458 459 public static class NegExactL implements UnaryLongMethod { 460 @Override 461 public long safeMethod(long a) { 462 if (a == Long.MIN_VALUE) { 463 throw new ArithmeticException("long overflow"); 464 } 465 466 return -a; 467 468 } 469 470 @Override 471 public long checkMethod(long value) { 472 return Math.negateExact(value); 473 } 474 475 @Override 476 public long unchecked(long value) { 477 return -value; 478 } 479 480 @Override 481 public String name() { 482 return "negateExactLong"; 483 } 484 } 485 486 public static class NegExactI implements UnaryMethod { 487 @Override 488 public int safeMethod(int a) { 489 if (a == Integer.MIN_VALUE) { 490 throw new ArithmeticException("integer overflow"); 491 } 492 493 return -a; 494 495 } 496 497 @Override 498 public int checkMethod(int value) { 499 return Math.negateExact(value); 500 } 501 502 @Override 503 public int unchecked(int value) { 504 return -value; 505 } 506 507 @Override 508 public String name() { 509 return "negateExact"; 510 } 511 } 512 513 public static class SubExactI implements BinaryMethod { 514 @Override 515 public int safeMethod(int x, int y) { 516 int r = x - y; 517 // HD 2-12 Overflow iff the arguments have different signs and 518 // the sign of the result is different than the sign of x 519 if (((x ^ y) & (x ^ r)) < 0) { 520 throw new ArithmeticException("integer overflow"); 521 } 522 return r; 523 } 524 525 @Override 526 public int checkMethod(int a, int b) { 527 return Math.subtractExact(a, b); 528 } 529 530 @Override 531 public int unchecked(int a, int b) { 532 return a - b; 533 } 534 535 @Override 536 public String name() { 537 return "subtractExact"; 538 } 539 } 540 541 public static class SubExactL implements BinaryLongMethod { 542 @Override 543 public long safeMethod(long x, long y) { 544 long r = x - y; 545 // HD 2-12 Overflow iff the arguments have different signs and 546 // the sign of the result is different than the sign of x 547 if (((x ^ y) & (x ^ r)) < 0) { 548 throw new ArithmeticException("integer overflow"); 549 } 550 return r; 551 } 552 553 @Override 554 public long checkMethod(long a, long b) { 555 return Math.subtractExact(a, b); 556 } 557 558 @Override 559 public long unchecked(long a, long b) { 560 return a - b; 561 } 562 563 @Override 564 public String name() { 565 return "subtractExactLong"; 566 } 567 } 568 569 static class IncExactL implements UnaryLongMethod { 570 @Override 571 public long safeMethod(long a) { 572 if (a == Long.MAX_VALUE) { 573 throw new ArithmeticException("long overflow"); 574 } 575 576 return a + 1L; 577 578 } 579 580 @Override 581 public long checkMethod(long value) { 582 return Math.incrementExact(value); 583 } 584 585 @Override 586 public long unchecked(long value) { 587 return value + 1; 588 } 589 590 @Override 591 public String name() { 592 return "incrementExactLong"; 593 } 594 } 595 596 static class IncExactI implements UnaryMethod { 597 @Override 598 public int safeMethod(int a) { 599 if (a == Integer.MAX_VALUE) { 600 throw new ArithmeticException("integer overflow"); 601 } 602 603 return a + 1; 604 } 605 606 @Override 607 public int checkMethod(int value) { 608 return Math.incrementExact(value); 609 } 610 611 @Override 612 public int unchecked(int value) { 613 return value + 1; 614 } 615 616 @Override 617 public String name() { 618 return "incrementExact"; 619 } 620 } 621 622 static class DecExactL implements UnaryLongMethod { 623 @Override 624 public long safeMethod(long a) { 625 if (a == Long.MIN_VALUE) { 626 throw new ArithmeticException("long overflow"); 627 } 628 629 return a - 1L; 630 } 631 632 @Override 633 public long checkMethod(long value) { 634 return Math.decrementExact(value); 635 } 636 637 @Override 638 public long unchecked(long value) { 639 return value - 1; 640 } 641 642 @Override 643 public String name() { 644 return "decExactLong"; 645 } 646 } 647 648 static class DecExactI implements UnaryMethod { 649 @Override 650 public int safeMethod(int a) { 651 if (a == Integer.MIN_VALUE) { 652 throw new ArithmeticException("integer overflow"); 653 } 654 655 return a - 1; 656 } 657 658 @Override 659 public int checkMethod(int value) { 660 return Math.decrementExact(value); 661 } 662 663 @Override 664 public int unchecked(int value) { 665 return value - 1; 666 } 667 668 @Override 669 public String name() { 670 return "decrementExact"; 671 } 672 } 673 674 }