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 }
157 }
158 }
159
160 public static class NonConstantTest {
161 public static java.util.Random rnd = new java.util.Random();
162
163 public static void verify(BinaryMethod method) {
164 for (int i = 0; i < 50000; ++i) {
165 int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt();
166 Verify.verifyBinary(rnd1, rnd2, method);
167 Verify.verifyBinary(rnd1, rnd2 + 1, method);
168 Verify.verifyBinary(rnd1 + 1, rnd2, method);
169 Verify.verifyBinary(rnd1 - 1, rnd2, method);
170 Verify.verifyBinary(rnd1, rnd2 - 1, method);
171 }
172 }
173 }
174
175 public static class NonConstantLongTest {
176 public static long[] values = { Long.MIN_VALUE, Long.MAX_VALUE, 0, Long.MAX_VALUE - 1831 };
177 public static java.util.Random rnd = new java.util.Random();
178
179 public static void verify(BinaryLongMethod method) {
180 for (int i = 0; i < 50000; ++i) {
181 long rnd1 = rnd.nextLong(), rnd2 = rnd.nextLong();
182 Verify.verifyBinary(rnd1, rnd2, method);
183 Verify.verifyBinary(rnd1, rnd2 + 1, method);
184 Verify.verifyBinary(rnd1 + 1, rnd2, method);
185 Verify.verifyBinary(rnd1 - 1, rnd2, method);
186 Verify.verifyBinary(rnd1, rnd2 - 1, method);
187 Verify.verifyBinary(rnd1 + Long.MAX_VALUE - rnd2, rnd2 + 1, method);
188 Verify.verifyBinary(values[0], values[2], method);
189 Verify.verifyBinary(values[1], values[2], method);
190 Verify.verifyBinary(values[3], 74L, method);
191 }
192 }
193 }
194
195 public static class LoopDependentTest {
196 public static java.util.Random rnd = new java.util.Random();
197
198 public static void verify(BinaryMethod method) {
199 int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt();
200 runTest(rnd1, rnd2, method);
201 }
202
203 private static void runTest(int rnd1, int rnd2, BinaryMethod method) {
204 for (int i = 0; i < 50000; ++i) {
205 Verify.verifyBinary(rnd1 + i, rnd2 + i, method);
206 Verify.verifyBinary(rnd1 + i, rnd2 + (i & 0xff), method);
207 Verify.verifyBinary(rnd1 - i, rnd2 - (i & 0xff), method);
208 Verify.verifyBinary(rnd1 + i + 1, rnd2 + i + 2, method);
209 Verify.verifyBinary(rnd1 + i * 2, rnd2 + i, method);
210 }
211 }
212 }
213
214 public static class ConstantTest {
215 public static void verify(BinaryMethod method) {
216 for (int i = 0; i < 50000; ++i) {
217 Verify.verifyBinary(5, 7, method);
218 Verify.verifyBinary(Integer.MAX_VALUE, 1, method);
219 Verify.verifyBinary(Integer.MIN_VALUE, -1, method);
220 Verify.verifyBinary(Integer.MAX_VALUE, -1, method);
221 Verify.verifyBinary(Integer.MIN_VALUE, 1, method);
222 Verify.verifyBinary(Integer.MAX_VALUE / 2, Integer.MAX_VALUE / 2, method);
223 Verify.verifyBinary(Integer.MAX_VALUE / 2, (Integer.MAX_VALUE / 2) + 3, method);
224 Verify.verifyBinary(Integer.MAX_VALUE, Integer.MIN_VALUE, method);
225 }
226 }
227 }
228
229 public static class ConstantLongTest {
230 public static void verify(BinaryLongMethod method) {
231 for (int i = 0; i < 50000; ++i) {
232 Verify.verifyBinary(5, 7, method);
233 Verify.verifyBinary(Long.MAX_VALUE, 1, method);
234 Verify.verifyBinary(Long.MIN_VALUE, -1, method);
235 Verify.verifyBinary(Long.MAX_VALUE, -1, method);
236 Verify.verifyBinary(Long.MIN_VALUE, 1, method);
237 Verify.verifyBinary(Long.MAX_VALUE / 2, Long.MAX_VALUE / 2, method);
238 Verify.verifyBinary(Long.MAX_VALUE / 2, (Long.MAX_VALUE / 2) + 3, method);
239 Verify.verifyBinary(Long.MAX_VALUE, Long.MIN_VALUE, method);
240 }
241 }
242 }
243
244 public static interface BinaryMethod {
245 int safeMethod(int a, int b);
246 int checkMethod(int a, int b);
247 int unchecked(int a, int b);
248 String name();
249 }
250
251 public static interface UnaryMethod {
252 int safeMethod(int value);
253 int checkMethod(int value);
254 int unchecked(int value);
255 String name();
256 }
257
258 public static interface BinaryLongMethod {
259 long safeMethod(long a, long b);
260 long checkMethod(long a, long b);
261 long unchecked(long a, long b);
262 String name();
263 }
264
265 public static interface UnaryLongMethod {
266 long safeMethod(long value);
267 long checkMethod(long value);
268 long unchecked(long value);
269 String name();
270 }
271
272 public static class UnaryToBinary implements BinaryMethod {
273 private final UnaryMethod method;
274 public UnaryToBinary(UnaryMethod method) {
275 this.method = method;
276 }
277
278 @Override
279 public int safeMethod(int a, int b) {
280 return method.safeMethod(a);
281 }
282
283 @Override
284 public int checkMethod(int a, int b) {
285 return method.checkMethod(a);
286 }
287
288 @Override
289 public int unchecked(int a, int b) {
290 return method.unchecked(a);
291
292 }
293
294 @Override
295 public String name() {
296 return method.name();
297 }
298 }
299
300 public static class UnaryToBinaryLong implements BinaryLongMethod {
301 private final UnaryLongMethod method;
302 public UnaryToBinaryLong(UnaryLongMethod method) {
303 this.method = method;
304 }
305
306 @Override
307 public long safeMethod(long a, long b) {
308 return method.safeMethod(a);
309 }
310
311 @Override
312 public long checkMethod(long a, long b) {
313 return method.checkMethod(a);
314 }
315
316 @Override
317 public long unchecked(long a, long b) {
318 return method.unchecked(a);
319
320 }
321
322 @Override
323 public String name() {
324 return method.name();
325 }
326 }
327
328
329 public static class AddExactI implements BinaryMethod {
330 @Override
331 public int safeMethod(int x, int y) {
332 int r = x + y;
333 // HD 2-12 Overflow iff both arguments have the opposite sign of the result
334 if (((x ^ r) & (y ^ r)) < 0) {
335 throw new ArithmeticException("integer overflow");
336 }
337 return r;
338
339 }
340
341 @Override
342 public int checkMethod(int a, int b) {
343 return Math.addExact(a, b);
344 }
345
346 @Override
347 public String name() {
348 return "addExact";
349 }
350
351 @Override
352 public int unchecked(int a, int b) {
353 return a + b;
354 }
355 }
356
357 public static class AddExactL implements BinaryLongMethod {
358 @Override
359 public long safeMethod(long x, long y) {
360 long r = x + y;
361 // HD 2-12 Overflow iff both arguments have the opposite sign of the result
362 if (((x ^ r) & (y ^ r)) < 0) {
363 throw new ArithmeticException("integer overflow");
364 }
365 return r;
366
367 }
368
369 @Override
370 public long checkMethod(long a, long b) {
371 return Math.addExact(a, b);
372 }
373
374 @Override
375 public String name() {
376 return "addExactLong";
377 }
378
379 @Override
380 public long unchecked(long a, long b) {
381 return a + b;
382 }
383 }
384
385 public static class MulExactI implements BinaryMethod {
386 @Override
387 public int safeMethod(int x, int y) {
388 long r = (long)x * (long)y;
389 if ((int)r != r) {
390 throw new ArithmeticException("integer overflow");
391 }
392 return (int)r;
393
394 }
395
396 @Override
397 public int checkMethod(int a, int b) {
398 return Math.multiplyExact(a, b);
399 }
400
401 @Override
402 public int unchecked(int a, int b) {
403 return a * b;
404 }
405
406 @Override
407 public String name() {
408 return "multiplyExact";
409 }
410 }
411
412 public static class MulExactL implements BinaryLongMethod {
413 @Override
414 public long safeMethod(long x, long y) {
415 long r = x * y;
416 long ax = Math.abs(x);
417 long ay = Math.abs(y);
418 if (((ax | ay) >>> 31 != 0)) {
419 // Some bits greater than 2^31 that might cause overflow
420 // Check the result using the divide operator
421 // and check for the special case of Long.MIN_VALUE * -1
422 if (((y != 0) && (r / y != x)) ||
423 (x == Long.MIN_VALUE && y == -1)) {
424 throw new ArithmeticException("long overflow");
425 }
426 }
427 return r;
428 }
429
430 @Override
431 public long checkMethod(long a, long b) {
432 return Math.multiplyExact(a, b);
433 }
434
435 @Override
436 public long unchecked(long a, long b) {
437 return a * b;
438 }
439
440 @Override
441 public String name() {
442 return "multiplyExact";
443 }
444 }
445
446 public static class NegExactL implements UnaryLongMethod {
447 @Override
448 public long safeMethod(long a) {
449 if (a == Long.MIN_VALUE) {
450 throw new ArithmeticException("long overflow");
451 }
452
453 return -a;
454
455 }
456
457 @Override
458 public long checkMethod(long value) {
459 return Math.negateExact(value);
460 }
461
462 @Override
463 public long unchecked(long value) {
464 return -value;
465 }
466
467 @Override
468 public String name() {
469 return "negateExactLong";
470 }
471 }
472
473 public static class NegExactI implements UnaryMethod {
474 @Override
475 public int safeMethod(int a) {
476 if (a == Integer.MIN_VALUE) {
477 throw new ArithmeticException("integer overflow");
478 }
479
480 return -a;
481
482 }
483
484 @Override
485 public int checkMethod(int value) {
486 return Math.negateExact(value);
487 }
488
489 @Override
490 public int unchecked(int value) {
491 return -value;
492 }
493
494 @Override
495 public String name() {
496 return "negateExact";
497 }
498 }
499
500 public static class SubExactI implements BinaryMethod {
501 @Override
502 public int safeMethod(int x, int y) {
503 int r = x - y;
504 // HD 2-12 Overflow iff the arguments have different signs and
505 // the sign of the result is different than the sign of x
506 if (((x ^ y) & (x ^ r)) < 0) {
507 throw new ArithmeticException("integer overflow");
508 }
509 return r;
510 }
511
512 @Override
513 public int checkMethod(int a, int b) {
514 return Math.subtractExact(a, b);
515 }
516
517 @Override
518 public int unchecked(int a, int b) {
519 return a - b;
520 }
521
522 @Override
523 public String name() {
524 return "subtractExact";
525 }
526 }
527
528 public static class SubExactL implements BinaryLongMethod {
529 @Override
530 public long safeMethod(long x, long y) {
531 long r = x - y;
532 // HD 2-12 Overflow iff the arguments have different signs and
533 // the sign of the result is different than the sign of x
534 if (((x ^ y) & (x ^ r)) < 0) {
535 throw new ArithmeticException("integer overflow");
536 }
537 return r;
538 }
539
540 @Override
541 public long checkMethod(long a, long b) {
542 return Math.subtractExact(a, b);
543 }
544
545 @Override
546 public long unchecked(long a, long b) {
547 return a - b;
548 }
549
550 @Override
551 public String name() {
552 return "subtractExactLong";
553 }
554 }
555
556 static class IncExactL implements UnaryLongMethod {
557 @Override
558 public long safeMethod(long a) {
559 if (a == Long.MAX_VALUE) {
560 throw new ArithmeticException("long overflow");
561 }
562
563 return a + 1L;
564
565 }
566
567 @Override
568 public long checkMethod(long value) {
569 return Math.incrementExact(value);
570 }
571
572 @Override
573 public long unchecked(long value) {
574 return value + 1;
575 }
576
577 @Override
578 public String name() {
579 return "incrementExactLong";
580 }
581 }
582
583 static class IncExactI implements UnaryMethod {
584 @Override
585 public int safeMethod(int a) {
586 if (a == Integer.MAX_VALUE) {
587 throw new ArithmeticException("integer overflow");
588 }
589
590 return a + 1;
591 }
592
593 @Override
594 public int checkMethod(int value) {
595 return Math.incrementExact(value);
596 }
597
598 @Override
599 public int unchecked(int value) {
600 return value + 1;
601 }
602
603 @Override
604 public String name() {
605 return "incrementExact";
606 }
607 }
608
609 static class DecExactL implements UnaryLongMethod {
610 @Override
611 public long safeMethod(long a) {
612 if (a == Long.MIN_VALUE) {
613 throw new ArithmeticException("long overflow");
614 }
615
616 return a - 1L;
617 }
618
619 @Override
620 public long checkMethod(long value) {
621 return Math.decrementExact(value);
622 }
623
624 @Override
625 public long unchecked(long value) {
626 return value - 1;
627 }
628
629 @Override
630 public String name() {
631 return "decExactLong";
632 }
633 }
634
635 static class DecExactI implements UnaryMethod {
636 @Override
637 public int safeMethod(int a) {
638 if (a == Integer.MIN_VALUE) {
639 throw new ArithmeticException("integer overflow");
640 }
641
642 return a - 1;
643 }
644
645 @Override
646 public int checkMethod(int value) {
647 return Math.decrementExact(value);
648 }
649
650 @Override
651 public int unchecked(int value) {
652 return value - 1;
653 }
654
655 @Override
656 public String name() {
657 return "decrementExact";
658 }
659 }
660
661 }
|