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