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 }