c++: auto in trailing-return-type in parameter [PR117778]
[gcc.git] / libphobos / libdruntime / core / checkedint.d
blob4c40b9957a994096109537bf5d88b02072bb5814
2 /**********************************************
3 * This module implements integral arithmetic primitives that check
4 * for out-of-range results.
6 * Integral arithmetic operators operate on fixed width types.
7 * Results that are not representable in those fixed widths are silently
8 * truncated to fit.
9 * This module offers integral arithmetic primitives that produce the
10 * same results, but set an 'overflow' flag when such truncation occurs.
11 * The setting is sticky, meaning that numerous operations can be cascaded
12 * and then the flag need only be checked at the end.
13 * Whether the operation is signed or unsigned is indicated by an 's' or 'u'
14 * suffix, respectively. While this could be achieved without such suffixes by
15 * using overloading on the signedness of the types, the suffix makes it clear
16 * which is happening without needing to examine the types.
18 * While the generic versions of these functions are computationally expensive
19 * relative to the cost of the operation itself, compiler implementations are free
20 * to recognize them and generate equivalent and faster code.
22 * The functions here are templates so they can be used with -betterC,
23 * as betterC does not link with this library.
25 * References: $(LINK2 http://blog.regehr.org/archives/1139, Fast Integer Overflow Checks)
26 * Copyright: Copyright (c) Walter Bright 2014.
27 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
28 * Authors: Walter Bright
29 * Source: $(DRUNTIMESRC core/_checkedint.d)
32 module core.checkedint;
34 import core.internal.attributes : betterC;
36 nothrow:
37 @safe:
38 @nogc:
39 pure:
41 /*******************************
42 * Add two signed integers, checking for overflow.
44 * The overflow is sticky, meaning a sequence of operations can
45 * be done and overflow need only be checked at the end.
46 * Params:
47 * x = left operand
48 * y = right operand
49 * overflow = set if an overflow occurs, is not affected otherwise
50 * Returns:
51 * the sum
54 pragma(inline, true)
55 int adds()(int x, int y, ref bool overflow)
57 long r = cast(long)x + cast(long)y;
58 if (r < int.min || r > int.max)
59 overflow = true;
60 return cast(int)r;
63 ///
64 @betterC
65 unittest
67 bool overflow;
68 assert(adds(2, 3, overflow) == 5);
69 assert(!overflow);
71 assert(adds(1, int.max - 1, overflow) == int.max);
72 assert(!overflow);
74 assert(adds(int.min + 1, -1, overflow) == int.min);
75 assert(!overflow);
77 assert(adds(int.max, 1, overflow) == int.min);
78 assert(overflow);
80 overflow = false;
81 assert(adds(int.min, -1, overflow) == int.max);
82 assert(overflow);
84 assert(adds(0, 0, overflow) == 0);
85 assert(overflow); // sticky
88 /// ditto
89 pragma(inline, true)
90 long adds()(long x, long y, ref bool overflow)
92 long r = cast(ulong)x + cast(ulong)y;
93 if (x < 0 && y < 0 && r >= 0 ||
94 x >= 0 && y >= 0 && r < 0)
95 overflow = true;
96 return r;
99 ///
100 @betterC
101 unittest
103 bool overflow;
104 assert(adds(2L, 3L, overflow) == 5);
105 assert(!overflow);
107 assert(adds(1L, long.max - 1, overflow) == long.max);
108 assert(!overflow);
110 assert(adds(long.min + 1, -1, overflow) == long.min);
111 assert(!overflow);
113 assert(adds(long.max, 1, overflow) == long.min);
114 assert(overflow);
116 overflow = false;
117 assert(adds(long.min, -1, overflow) == long.max);
118 assert(overflow);
120 assert(adds(0L, 0L, overflow) == 0);
121 assert(overflow); // sticky
124 static if (is(cent))
126 /// ditto
127 pragma(inline, true)
128 cent adds()(cent x, cent y, ref bool overflow)
130 cent r = cast(ucent)x + cast(ucent)y;
131 if (x < 0 && y < 0 && r >= 0 ||
132 x >= 0 && y >= 0 && r < 0)
133 overflow = true;
134 return r;
137 unittest
139 bool overflow;
140 assert(adds(cast(cent)2L, 3L, overflow) == 5);
141 assert(!overflow);
142 assert(adds(1L, cent.max - 1, overflow) == cent.max);
143 assert(!overflow);
144 assert(adds(cent.min + 1, -1, overflow) == cent.min);
145 assert(!overflow);
146 assert(adds(cent.max, 1, overflow) == cent.min);
147 assert(overflow);
148 overflow = false;
149 assert(adds(cent.min, -1, overflow) == cent.max);
150 assert(overflow);
151 assert(adds(cast(cent)0L, 0L, overflow) == 0);
152 assert(overflow); // sticky
157 /*******************************
158 * Add two unsigned integers, checking for overflow (aka carry).
160 * The overflow is sticky, meaning a sequence of operations can
161 * be done and overflow need only be checked at the end.
162 * Params:
163 * x = left operand
164 * y = right operand
165 * overflow = set if an overflow occurs, is not affected otherwise
166 * Returns:
167 * the sum
170 pragma(inline, true)
171 uint addu()(uint x, uint y, ref bool overflow)
173 immutable uint r = x + y;
174 immutable bool o = r < x;
175 assert(o == (r < y));
176 if (o)
177 overflow = true;
178 return r;
182 @betterC
183 unittest
185 for (uint i = 0; i < 10; ++i)
187 bool overflow;
188 immutable uint r = addu (uint.max - i, uint.max - i, overflow);
189 assert(r == 2 * (uint.max - i));
190 assert(overflow);
193 bool overflow;
194 assert(addu(2, 3, overflow) == 5);
195 assert(!overflow);
197 assert(addu(1, uint.max - 1, overflow) == uint.max);
198 assert(!overflow);
200 assert(addu(uint.min, -1, overflow) == uint.max);
201 assert(!overflow);
203 assert(addu(uint.max, 1, overflow) == uint.min);
204 assert(overflow);
206 overflow = false;
207 assert(addu(uint.min + 1, -1, overflow) == uint.min);
208 assert(overflow);
210 assert(addu(0, 0, overflow) == 0);
211 assert(overflow); // sticky
214 /// ditto
215 pragma(inline, true)
216 ulong addu()(ulong x, ulong y, ref bool overflow)
218 immutable ulong r = x + y;
219 immutable bool o = r < x;
220 assert(o == (r < y));
221 if (o)
222 overflow = true;
223 return r;
227 @betterC
228 unittest
230 bool overflow;
231 assert(addu(2L, 3L, overflow) == 5);
232 assert(!overflow);
234 assert(addu(1, ulong.max - 1, overflow) == ulong.max);
235 assert(!overflow);
237 assert(addu(ulong.min, -1L, overflow) == ulong.max);
238 assert(!overflow);
240 assert(addu(ulong.max, 1, overflow) == ulong.min);
241 assert(overflow);
243 overflow = false;
244 assert(addu(ulong.min + 1, -1L, overflow) == ulong.min);
245 assert(overflow);
247 assert(addu(0L, 0L, overflow) == 0);
248 assert(overflow); // sticky
251 static if (is(ucent))
253 /// ditto
254 pragma(inline, true)
255 ucent addu()(ucent x, ucent y, ref bool overflow)
257 immutable ucent r = x + y;
258 immutable bool o = r < x;
259 assert(o == (r < y));
260 if (o)
261 overflow = true;
262 return r;
265 unittest
267 bool overflow;
268 assert(addu(cast(ucent)2L, 3L, overflow) == 5);
269 assert(!overflow);
270 assert(addu(1, ucent.max - 1, overflow) == ucent.max);
271 assert(!overflow);
272 assert(addu(ucent.min, -1L, overflow) == ucent.max);
273 assert(!overflow);
274 assert(addu(ucent.max, 1, overflow) == ucent.min);
275 assert(overflow);
276 overflow = false;
277 assert(addu(ucent.min + 1, -1L, overflow) == ucent.min);
278 assert(overflow);
279 assert(addu(cast(ucent)0L, 0L, overflow) == 0);
280 assert(overflow); // sticky
285 /*******************************
286 * Subtract two signed integers, checking for overflow.
288 * The overflow is sticky, meaning a sequence of operations can
289 * be done and overflow need only be checked at the end.
290 * Params:
291 * x = left operand
292 * y = right operand
293 * overflow = set if an overflow occurs, is not affected otherwise
294 * Returns:
295 * the difference
298 pragma(inline, true)
299 int subs()(int x, int y, ref bool overflow)
301 immutable long r = cast(long)x - cast(long)y;
302 if (r < int.min || r > int.max)
303 overflow = true;
304 return cast(int)r;
308 @betterC
309 unittest
311 bool overflow;
312 assert(subs(2, -3, overflow) == 5);
313 assert(!overflow);
315 assert(subs(1, -int.max + 1, overflow) == int.max);
316 assert(!overflow);
318 assert(subs(int.min + 1, 1, overflow) == int.min);
319 assert(!overflow);
321 assert(subs(int.max, -1, overflow) == int.min);
322 assert(overflow);
324 overflow = false;
325 assert(subs(int.min, 1, overflow) == int.max);
326 assert(overflow);
328 assert(subs(0, 0, overflow) == 0);
329 assert(overflow); // sticky
332 /// ditto
333 pragma(inline, true)
334 long subs()(long x, long y, ref bool overflow)
336 immutable long r = cast(ulong)x - cast(ulong)y;
337 if (x < 0 && y >= 0 && r >= 0 ||
338 x >= 0 && y < 0 && (r < 0 || y == long.min))
339 overflow = true;
340 return r;
344 @betterC
345 unittest
347 bool overflow;
348 assert(subs(2L, -3L, overflow) == 5);
349 assert(!overflow);
351 assert(subs(1L, -long.max + 1, overflow) == long.max);
352 assert(!overflow);
354 assert(subs(long.min + 1, 1, overflow) == long.min);
355 assert(!overflow);
357 assert(subs(-1L, long.min, overflow) == long.max);
358 assert(!overflow);
360 assert(subs(long.max, -1, overflow) == long.min);
361 assert(overflow);
363 overflow = false;
364 assert(subs(long.min, 1, overflow) == long.max);
365 assert(overflow);
367 assert(subs(0L, 0L, overflow) == 0);
368 assert(overflow); // sticky
371 static if (is(cent))
373 /// ditto
374 pragma(inline, true)
375 cent subs()(cent x, cent y, ref bool overflow)
377 immutable cent r = cast(ucent)x - cast(ucent)y;
378 if (x < 0 && y >= 0 && r >= 0 ||
379 x >= 0 && y < 0 && (r < 0 || y == long.min))
380 overflow = true;
381 return r;
384 unittest
386 bool overflow;
387 assert(subs(cast(cent)2L, -3L, overflow) == 5);
388 assert(!overflow);
389 assert(subs(1L, -cent.max + 1, overflow) == cent.max);
390 assert(!overflow);
391 assert(subs(cent.min + 1, 1, overflow) == cent.min);
392 assert(!overflow);
393 assert(subs(-1L, cent.min, overflow) == cent.max);
394 assert(!overflow);
395 assert(subs(cent.max, -1, overflow) == cent.min);
396 assert(overflow);
397 overflow = false;
398 assert(subs(cent.min, 1, overflow) == cent.max);
399 assert(overflow);
400 assert(subs(cast(cent)0L, 0L, overflow) == 0);
401 assert(overflow); // sticky
406 /*******************************
407 * Subtract two unsigned integers, checking for overflow (aka borrow).
409 * The overflow is sticky, meaning a sequence of operations can
410 * be done and overflow need only be checked at the end.
411 * Params:
412 * x = left operand
413 * y = right operand
414 * overflow = set if an overflow occurs, is not affected otherwise
415 * Returns:
416 * the difference
419 pragma(inline, true)
420 uint subu()(uint x, uint y, ref bool overflow)
422 if (x < y)
423 overflow = true;
424 return x - y;
428 @betterC
429 unittest
431 bool overflow;
432 assert(subu(3, 2, overflow) == 1);
433 assert(!overflow);
435 assert(subu(uint.max, 1, overflow) == uint.max - 1);
436 assert(!overflow);
438 assert(subu(1, 1, overflow) == uint.min);
439 assert(!overflow);
441 assert(subu(0, 1, overflow) == uint.max);
442 assert(overflow);
444 overflow = false;
445 assert(subu(uint.max - 1, uint.max, overflow) == uint.max);
446 assert(overflow);
448 assert(subu(0, 0, overflow) == 0);
449 assert(overflow); // sticky
453 /// ditto
454 pragma(inline, true)
455 ulong subu()(ulong x, ulong y, ref bool overflow)
457 if (x < y)
458 overflow = true;
459 return x - y;
463 @betterC
464 unittest
466 bool overflow;
467 assert(subu(3UL, 2UL, overflow) == 1);
468 assert(!overflow);
470 assert(subu(ulong.max, 1, overflow) == ulong.max - 1);
471 assert(!overflow);
473 assert(subu(1UL, 1UL, overflow) == ulong.min);
474 assert(!overflow);
476 assert(subu(0UL, 1UL, overflow) == ulong.max);
477 assert(overflow);
479 overflow = false;
480 assert(subu(ulong.max - 1, ulong.max, overflow) == ulong.max);
481 assert(overflow);
483 assert(subu(0UL, 0UL, overflow) == 0);
484 assert(overflow); // sticky
487 static if (is(ucent))
489 /// ditto
490 pragma(inline, true)
491 ucent subu()(ucent x, ucent y, ref bool overflow)
493 if (x < y)
494 overflow = true;
495 return x - y;
498 unittest
500 bool overflow;
501 assert(subu(cast(ucent)3UL, 2UL, overflow) == 1);
502 assert(!overflow);
503 assert(subu(ucent.max, 1, overflow) == ucent.max - 1);
504 assert(!overflow);
505 assert(subu(1UL, 1UL, overflow) == ucent.min);
506 assert(!overflow);
507 assert(subu(cast(ucent)0UL, 1UL, overflow) == ucent.max);
508 assert(overflow);
509 overflow = false;
510 assert(subu(ucent.max - 1, ucent.max, overflow) == ucent.max);
511 assert(overflow);
512 assert(subu(cast(ucent)0UL, 0UL, overflow) == 0);
513 assert(overflow); // sticky
518 /***********************************************
519 * Negate an integer.
521 * Params:
522 * x = operand
523 * overflow = set if x cannot be negated, is not affected otherwise
524 * Returns:
525 * the negation of x
528 pragma(inline, true)
529 int negs()(int x, ref bool overflow)
531 if (x == int.min)
532 overflow = true;
533 return -x;
537 @betterC
538 unittest
540 bool overflow;
541 assert(negs(0, overflow) == -0);
542 assert(!overflow);
544 assert(negs(1234, overflow) == -1234);
545 assert(!overflow);
547 assert(negs(-5678, overflow) == 5678);
548 assert(!overflow);
550 assert(negs(int.min, overflow) == -int.min);
551 assert(overflow);
553 assert(negs(0, overflow) == -0);
554 assert(overflow); // sticky
557 /// ditto
558 pragma(inline, true)
559 long negs()(long x, ref bool overflow)
561 if (x == long.min)
562 overflow = true;
563 return -x;
567 @betterC
568 unittest
570 bool overflow;
571 assert(negs(0L, overflow) == -0);
572 assert(!overflow);
574 assert(negs(1234L, overflow) == -1234);
575 assert(!overflow);
577 assert(negs(-5678L, overflow) == 5678);
578 assert(!overflow);
580 assert(negs(long.min, overflow) == -long.min);
581 assert(overflow);
583 assert(negs(0L, overflow) == -0);
584 assert(overflow); // sticky
587 static if (is(cent))
589 /// ditto
590 pragma(inline, true)
591 cent negs()(cent x, ref bool overflow)
593 if (x == cent.min)
594 overflow = true;
595 return -x;
598 unittest
600 bool overflow;
601 assert(negs(cast(cent)0L, overflow) == -0);
602 assert(!overflow);
603 assert(negs(cast(cent)1234L, overflow) == -1234);
604 assert(!overflow);
605 assert(negs(cast(cent)-5678L, overflow) == 5678);
606 assert(!overflow);
607 assert(negs(cent.min, overflow) == -cent.min);
608 assert(overflow);
609 assert(negs(cast(cent)0L, overflow) == -0);
610 assert(overflow); // sticky
615 /*******************************
616 * Multiply two signed integers, checking for overflow.
618 * The overflow is sticky, meaning a sequence of operations can
619 * be done and overflow need only be checked at the end.
620 * Params:
621 * x = left operand
622 * y = right operand
623 * overflow = set if an overflow occurs, is not affected otherwise
624 * Returns:
625 * the product
628 pragma(inline, true)
629 int muls()(int x, int y, ref bool overflow)
631 long r = cast(long)x * cast(long)y;
632 if (r < int.min || r > int.max)
633 overflow = true;
634 return cast(int)r;
638 @betterC
639 unittest
641 bool overflow;
642 assert(muls(2, 3, overflow) == 6);
643 assert(!overflow);
645 assert(muls(-200, 300, overflow) == -60_000);
646 assert(!overflow);
648 assert(muls(1, int.max, overflow) == int.max);
649 assert(!overflow);
651 assert(muls(int.min, 1, overflow) == int.min);
652 assert(!overflow);
654 assert(muls(int.max, 2, overflow) == (int.max * 2));
655 assert(overflow);
657 overflow = false;
658 assert(muls(int.min, -1, overflow) == int.min);
659 assert(overflow);
661 assert(muls(0, 0, overflow) == 0);
662 assert(overflow); // sticky
665 /// ditto
666 pragma(inline, true)
667 long muls()(long x, long y, ref bool overflow)
669 immutable long r = cast(ulong)x * cast(ulong)y;
670 enum not0or1 = ~1L;
671 if ((x & not0or1) &&
672 ((r == y) ? r != 0
673 : (r == 0x8000_0000_0000_0000 && x == -1L) || ((r / x) != y)))
674 overflow = true;
675 return r;
679 @betterC
680 unittest
682 bool overflow;
683 assert(muls(2L, 3L, overflow) == 6);
684 assert(!overflow);
686 assert(muls(-200L, 300L, overflow) == -60_000);
687 assert(!overflow);
689 assert(muls(1, long.max, overflow) == long.max);
690 assert(!overflow);
692 assert(muls(long.min, 1L, overflow) == long.min);
693 assert(!overflow);
695 assert(muls(long.max, 2L, overflow) == (long.max * 2));
696 assert(overflow);
697 overflow = false;
699 assert(muls(-1L, long.min, overflow) == long.min);
700 assert(overflow);
702 overflow = false;
703 assert(muls(long.min, -1L, overflow) == long.min);
704 assert(overflow);
706 assert(muls(0L, 0L, overflow) == 0);
707 assert(overflow); // sticky
710 static if (is(cent))
712 /// ditto
713 pragma(inline, true)
714 cent muls()(cent x, cent y, ref bool overflow)
716 immutable cent r = cast(ucent)x * cast(ucent)y;
717 enum not0or1 = ~1L;
718 if ((x & not0or1) && ((r == y)? r : (r / x) != y))
719 overflow = true;
720 return r;
723 unittest
725 bool overflow;
726 assert(muls(cast(cent)2L, 3L, overflow) == 6);
727 assert(!overflow);
728 assert(muls(cast(cent)-200L, 300L, overflow) == -60_000);
729 assert(!overflow);
730 assert(muls(1, cent.max, overflow) == cent.max);
731 assert(!overflow);
732 assert(muls(cent.min, 1L, overflow) == cent.min);
733 assert(!overflow);
734 assert(muls(cent.max, 2L, overflow) == (cent.max * 2));
735 assert(overflow);
736 overflow = false;
737 assert(muls(-1L, cent.min, overflow) == cent.min);
738 assert(overflow);
739 overflow = false;
740 assert(muls(cent.min, -1L, overflow) == cent.min);
741 assert(overflow);
742 assert(muls(cast(cent)0L, 0L, overflow) == 0);
743 assert(overflow); // sticky
748 /*******************************
749 * Multiply two unsigned integers, checking for overflow (aka carry).
751 * The overflow is sticky, meaning a sequence of operations can
752 * be done and overflow need only be checked at the end.
753 * Params:
754 * x = left operand
755 * y = right operand
756 * overflow = set if an overflow occurs, is not affected otherwise
757 * Returns:
758 * the product
760 pragma(inline, true)
761 uint mulu()(uint x, uint y, ref bool overflow)
763 immutable ulong r = ulong(x) * ulong(y);
764 if (r >> 32)
765 overflow = true;
766 return cast(uint) r;
769 @betterC
770 unittest
772 void test(uint x, uint y, uint r, bool overflow) @nogc nothrow
774 bool o;
775 assert(mulu(x, y, o) == r);
776 assert(o == overflow);
778 test(2, 3, 6, false);
779 test(1, uint.max, uint.max, false);
780 test(0, 1, 0, false);
781 test(0, uint.max, 0, false);
782 test(uint.max, 2, 2 * uint.max, true);
783 test(1 << 16, 1U << 16, 0, true);
785 bool overflow = true;
786 assert(mulu(0, 0, overflow) == 0);
787 assert(overflow); // sticky
790 /// ditto
791 pragma(inline, true)
792 ulong mulu()(ulong x, uint y, ref bool overflow)
794 ulong r = x * y;
795 if (x >> 32 &&
796 r / x != y)
797 overflow = true;
798 return r;
801 /// ditto
802 pragma(inline, true)
803 ulong mulu()(ulong x, ulong y, ref bool overflow)
805 immutable ulong r = x * y;
806 if ((x | y) >> 32 &&
807 x &&
808 r / x != y)
809 overflow = true;
810 return r;
813 @betterC
814 unittest
816 void test(T, U)(T x, U y, ulong r, bool overflow) @nogc nothrow
818 bool o;
819 assert(mulu(x, y, o) == r);
820 assert(o == overflow);
822 // One operand is zero
823 test(0, 3, 0, false);
824 test(0UL, 3, 0, false);
825 test(0UL, 3UL, 0, false);
826 test(3, 0, 0, false);
827 test(3UL, 0, 0, false);
828 test(3UL, 0UL, 0, false);
829 // Small numbers
830 test(2, 3, 6, false);
831 test(2UL, 3, 6, false);
832 test(2UL, 3UL, 6, false);
833 // At the 32/64 border
834 test(1, ulong(uint.max), uint.max, false);
835 test(1UL, ulong(uint.max), uint.max, false);
836 test(ulong(uint.max), 1, uint.max, false);
837 test(ulong(uint.max), 1UL, uint.max, false);
838 test(1, 1 + ulong(uint.max), 1 + ulong(uint.max), false);
839 test(1UL, 1 + ulong(uint.max), 1 + ulong(uint.max), false);
840 test(1 + ulong(uint.max), 1, 1 + ulong(uint.max), false);
841 test(1 + ulong(uint.max), 1UL, 1 + ulong(uint.max), false);
842 // At the limit
843 test(1, ulong.max, ulong.max, false);
844 test(1UL, ulong.max, ulong.max, false);
845 test(ulong.max, 1, ulong.max, false);
846 test(ulong.max, 1UL, ulong.max, false);
847 // Miscellaneous
848 test(0, 1, 0, false);
849 test(0, ulong.max, 0, false);
850 test(ulong.max, 2, 2 * ulong.max, true);
851 test(1UL << 32, 1UL << 32, 0, true);
852 // Must be sticky
853 bool overflow = true;
854 assert(mulu(0UL, 0UL, overflow) == 0);
855 assert(overflow); // sticky
858 static if (is(ucent))
860 /// ditto
861 pragma(inline, true)
862 ucent mulu()(ucent x, ucent y, ref bool overflow)
864 immutable ucent r = x * y;
865 if (x && (r / x) != y)
866 overflow = true;
867 return r;
870 unittest
872 void test(ucent x, ucent y, ucent r, bool overflow) @nogc nothrow
874 bool o;
875 assert(mulu(x, y, o) == r);
876 assert(o == overflow);
878 test(2, 3, 6, false);
879 test(1, ucent.max, ucent.max, false);
880 test(0, 1, 0, false);
881 test(0, ucent.max, 0, false);
882 test(ucent.max, 2, 2 * ucent.max, true);
883 test(cast(ucent)1UL << 64, cast(ucent)1UL << 64, 0, true);
885 bool overflow = true;
886 assert(mulu(0UL, 0UL, overflow) == 0);
887 assert(overflow); // sticky