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
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
;
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.
49 * overflow = set if an overflow occurs, is not affected otherwise
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
)
68 assert(adds(2, 3, overflow
) == 5);
71 assert(adds(1, int.max
- 1, overflow
) == int.max
);
74 assert(adds(int.min
+ 1, -1, overflow
) == int.min
);
77 assert(adds(int.max
, 1, overflow
) == int.min
);
81 assert(adds(int.min
, -1, overflow
) == int.max
);
84 assert(adds(0, 0, overflow
) == 0);
85 assert(overflow
); // sticky
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)
104 assert(adds(2L, 3L, overflow
) == 5);
107 assert(adds(1L, long.max
- 1, overflow
) == long.max
);
110 assert(adds(long.min
+ 1, -1, overflow
) == long.min
);
113 assert(adds(long.max
, 1, overflow
) == long.min
);
117 assert(adds(long.min
, -1, overflow
) == long.max
);
120 assert(adds(0L, 0L, overflow
) == 0);
121 assert(overflow
); // sticky
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)
140 assert(adds(cast(cent)2L, 3L, overflow
) == 5);
142 assert(adds(1L, cent.max
- 1, overflow
) == cent.max
);
144 assert(adds(cent.min
+ 1, -1, overflow
) == cent.min
);
146 assert(adds(cent.max
, 1, overflow
) == cent.min
);
149 assert(adds(cent.min
, -1, overflow
) == cent.max
);
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.
165 * overflow = set if an overflow occurs, is not affected otherwise
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
));
185 for (uint i
= 0; i
< 10; ++i
)
188 immutable uint r
= addu (uint.max
- i
, uint.max
- i
, overflow
);
189 assert(r
== 2 * (uint.max
- i
));
194 assert(addu(2, 3, overflow
) == 5);
197 assert(addu(1, uint.max
- 1, overflow
) == uint.max
);
200 assert(addu(uint.min
, -1, overflow
) == uint.max
);
203 assert(addu(uint.max
, 1, overflow
) == uint.min
);
207 assert(addu(uint.min
+ 1, -1, overflow
) == uint.min
);
210 assert(addu(0, 0, overflow
) == 0);
211 assert(overflow
); // sticky
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
));
231 assert(addu(2L, 3L, overflow
) == 5);
234 assert(addu(1, ulong.max
- 1, overflow
) == ulong.max
);
237 assert(addu(ulong.min
, -1L, overflow
) == ulong.max
);
240 assert(addu(ulong.max
, 1, overflow
) == ulong.min
);
244 assert(addu(ulong.min
+ 1, -1L, overflow
) == ulong.min
);
247 assert(addu(0L, 0L, overflow
) == 0);
248 assert(overflow
); // sticky
251 static if (is(ucent))
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
));
268 assert(addu(cast(ucent)2L, 3L, overflow
) == 5);
270 assert(addu(1, ucent.max
- 1, overflow
) == ucent.max
);
272 assert(addu(ucent.min
, -1L, overflow
) == ucent.max
);
274 assert(addu(ucent.max
, 1, overflow
) == ucent.min
);
277 assert(addu(ucent.min
+ 1, -1L, overflow
) == ucent.min
);
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.
293 * overflow = set if an overflow occurs, is not affected otherwise
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
)
312 assert(subs(2, -3, overflow
) == 5);
315 assert(subs(1, -int.max
+ 1, overflow
) == int.max
);
318 assert(subs(int.min
+ 1, 1, overflow
) == int.min
);
321 assert(subs(int.max
, -1, overflow
) == int.min
);
325 assert(subs(int.min
, 1, overflow
) == int.max
);
328 assert(subs(0, 0, overflow
) == 0);
329 assert(overflow
); // sticky
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
))
348 assert(subs(2L, -3L, overflow
) == 5);
351 assert(subs(1L, -long.max
+ 1, overflow
) == long.max
);
354 assert(subs(long.min
+ 1, 1, overflow
) == long.min
);
357 assert(subs(-1L, long.min
, overflow
) == long.max
);
360 assert(subs(long.max
, -1, overflow
) == long.min
);
364 assert(subs(long.min
, 1, overflow
) == long.max
);
367 assert(subs(0L, 0L, overflow
) == 0);
368 assert(overflow
); // sticky
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
))
387 assert(subs(cast(cent)2L, -3L, overflow
) == 5);
389 assert(subs(1L, -cent.max
+ 1, overflow
) == cent.max
);
391 assert(subs(cent.min
+ 1, 1, overflow
) == cent.min
);
393 assert(subs(-1L, cent.min
, overflow
) == cent.max
);
395 assert(subs(cent.max
, -1, overflow
) == cent.min
);
398 assert(subs(cent.min
, 1, overflow
) == cent.max
);
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.
414 * overflow = set if an overflow occurs, is not affected otherwise
420 uint subu()(uint x
, uint y
, ref bool overflow
)
432 assert(subu(3, 2, overflow
) == 1);
435 assert(subu(uint.max
, 1, overflow
) == uint.max
- 1);
438 assert(subu(1, 1, overflow
) == uint.min
);
441 assert(subu(0, 1, overflow
) == uint.max
);
445 assert(subu(uint.max
- 1, uint.max
, overflow
) == uint.max
);
448 assert(subu(0, 0, overflow
) == 0);
449 assert(overflow
); // sticky
455 ulong subu()(ulong x
, ulong y
, ref bool overflow
)
467 assert(subu(3UL, 2UL, overflow
) == 1);
470 assert(subu(ulong.max
, 1, overflow
) == ulong.max
- 1);
473 assert(subu(1UL, 1UL, overflow
) == ulong.min
);
476 assert(subu(0UL, 1UL, overflow
) == ulong.max
);
480 assert(subu(ulong.max
- 1, ulong.max
, overflow
) == ulong.max
);
483 assert(subu(0UL, 0UL, overflow
) == 0);
484 assert(overflow
); // sticky
487 static if (is(ucent))
491 ucent subu()(ucent x
, ucent y
, ref bool overflow
)
501 assert(subu(cast(ucent)3UL, 2UL, overflow
) == 1);
503 assert(subu(ucent.max
, 1, overflow
) == ucent.max
- 1);
505 assert(subu(1UL, 1UL, overflow
) == ucent.min
);
507 assert(subu(cast(ucent)0UL, 1UL, overflow
) == ucent.max
);
510 assert(subu(ucent.max
- 1, ucent.max
, overflow
) == ucent.max
);
512 assert(subu(cast(ucent)0UL, 0UL, overflow
) == 0);
513 assert(overflow
); // sticky
518 /***********************************************
523 * overflow = set if x cannot be negated, is not affected otherwise
529 int negs()(int x
, ref bool overflow
)
541 assert(negs(0, overflow
) == -0);
544 assert(negs(1234, overflow
) == -1234);
547 assert(negs(-5678, overflow
) == 5678);
550 assert(negs(int.min
, overflow
) == -int.min
);
553 assert(negs(0, overflow
) == -0);
554 assert(overflow
); // sticky
559 long negs()(long x
, ref bool overflow
)
571 assert(negs(0L, overflow
) == -0);
574 assert(negs(1234L, overflow
) == -1234);
577 assert(negs(-5678L, overflow
) == 5678);
580 assert(negs(long.min
, overflow
) == -long.min
);
583 assert(negs(0L, overflow
) == -0);
584 assert(overflow
); // sticky
591 cent negs()(cent x
, ref bool overflow
)
601 assert(negs(cast(cent)0L, overflow
) == -0);
603 assert(negs(cast(cent)1234L, overflow
) == -1234);
605 assert(negs(cast(cent)-5678L, overflow
) == 5678);
607 assert(negs(cent.min
, overflow
) == -cent.min
);
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.
623 * overflow = set if an overflow occurs, is not affected otherwise
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
)
642 assert(muls(2, 3, overflow
) == 6);
645 assert(muls(-200, 300, overflow
) == -60_000);
648 assert(muls(1, int.max
, overflow
) == int.max
);
651 assert(muls(int.min
, 1, overflow
) == int.min
);
654 assert(muls(int.max
, 2, overflow
) == (int.max
* 2));
658 assert(muls(int.min
, -1, overflow
) == int.min
);
661 assert(muls(0, 0, overflow
) == 0);
662 assert(overflow
); // sticky
667 long muls()(long x
, long y
, ref bool overflow
)
669 immutable long r
= cast(ulong)x
* cast(ulong)y
;
673 : (r
== 0x8000_0000_0000_0000 && x
== -1L) ||
((r
/ x
) != y
)))
683 assert(muls(2L, 3L, overflow
) == 6);
686 assert(muls(-200L, 300L, overflow
) == -60_000);
689 assert(muls(1, long.max
, overflow
) == long.max
);
692 assert(muls(long.min
, 1L, overflow
) == long.min
);
695 assert(muls(long.max
, 2L, overflow
) == (long.max
* 2));
699 assert(muls(-1L, long.min
, overflow
) == long.min
);
703 assert(muls(long.min
, -1L, overflow
) == long.min
);
706 assert(muls(0L, 0L, overflow
) == 0);
707 assert(overflow
); // sticky
714 cent muls()(cent x
, cent y
, ref bool overflow
)
716 immutable cent r
= cast(ucent)x
* cast(ucent)y
;
718 if ((x
& not0or1
) && ((r
== y
)? r
: (r
/ x
) != y
))
726 assert(muls(cast(cent)2L, 3L, overflow
) == 6);
728 assert(muls(cast(cent)-200L, 300L, overflow
) == -60_000);
730 assert(muls(1, cent.max
, overflow
) == cent.max
);
732 assert(muls(cent.min
, 1L, overflow
) == cent.min
);
734 assert(muls(cent.max
, 2L, overflow
) == (cent.max
* 2));
737 assert(muls(-1L, cent.min
, overflow
) == cent.min
);
740 assert(muls(cent.min
, -1L, overflow
) == cent.min
);
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.
756 * overflow = set if an overflow occurs, is not affected otherwise
761 uint mulu()(uint x
, uint y
, ref bool overflow
)
763 immutable ulong r
= ulong(x
) * ulong(y
);
772 void test(uint x
, uint y
, uint r
, bool overflow
) @nogc nothrow
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
792 ulong mulu()(ulong x
, uint y
, ref bool overflow
)
803 ulong mulu()(ulong x
, ulong y
, ref bool overflow
)
805 immutable ulong r
= x
* y
;
816 void test(T
, U
)(T x
, U y
, ulong r
, bool overflow
) @nogc nothrow
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);
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);
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);
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);
853 bool overflow
= true;
854 assert(mulu(0UL, 0UL, overflow
) == 0);
855 assert(overflow
); // sticky
858 static if (is(ucent))
862 ucent mulu()(ucent x
, ucent y
, ref bool overflow
)
864 immutable ucent r
= x
* y
;
865 if (x
&& (r
/ x
) != y
)
872 void test(ucent x
, ucent y
, ucent r
, bool overflow
) @nogc nothrow
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