1919 * relative to the cost of the operation itself, compiler implementations are free
2020 * to recognize them and generate equivalent and faster code.
2121 *
22- * References: $(LINK2 http://blog.regehr.org/archives/1139, Fast Integer Overflow Checks)
2322 * Copyright: Copyright (c) Walter Bright 2014.
2423 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
25- * Authors: Walter Bright
24+ * Authors: Walter Bright, Denis Shelomovskij
2625 * Source: $(DRUNTIMESRC core/_checkedint.d)
2726 */
2827
@@ -49,10 +48,11 @@ pure:
4948pragma (inline, true )
5049int adds (int x, int y, ref bool overflow)
5150{
52- long r = cast (long )x + cast (long )y;
53- if (r < int .min || r > int .max)
51+ const r = x + y;
52+ if ( ~ x._differentSign(y) // x and y has the same sign
53+ & x._differentSign(r)) // result has different sign
5454 overflow = true ;
55- return cast ( int ) r;
55+ return r;
5656}
5757
5858unittest
@@ -77,9 +77,9 @@ unittest
7777pragma (inline, true )
7878long adds (long x, long y, ref bool overflow)
7979{
80- long r = cast ( ulong ) x + cast ( ulong ) y;
81- if (x < 0 && y < 0 && r >= 0 ||
82- x >= 0 && y >= 0 && r < 0 )
80+ const r = x + y;
81+ if ( ~ x._differentSign(y) // x and y has the same sign
82+ & x._differentSign(r)) // result has different sign
8383 overflow = true ;
8484 return r;
8585}
@@ -119,8 +119,8 @@ unittest
119119pragma (inline, true )
120120uint addu (uint x, uint y, ref bool overflow)
121121{
122- uint r = x + y;
123- if (r < x || r < y )
122+ const r = x + y;
123+ if (r < x)
124124 overflow = true ;
125125 return r;
126126}
@@ -147,8 +147,8 @@ unittest
147147pragma (inline, true )
148148ulong addu (ulong x, ulong y, ref bool overflow)
149149{
150- ulong r = x + y;
151- if (r < x || r < y )
150+ const r = x + y;
151+ if (r < x)
152152 overflow = true ;
153153 return r;
154154}
@@ -188,10 +188,11 @@ unittest
188188pragma (inline, true )
189189int subs (int x, int y, ref bool overflow)
190190{
191- long r = cast (long )x - cast (long )y;
192- if (r < int .min || r > int .max)
191+ const r = x - y;
192+ if ( x._differentSign(y) // x and y has different sign
193+ & x._differentSign(r)) // result and x has different sign
193194 overflow = true ;
194- return cast ( int ) r;
195+ return r;
195196}
196197
197198unittest
@@ -216,9 +217,9 @@ unittest
216217pragma (inline, true )
217218long subs (long x, long y, ref bool overflow)
218219{
219- long r = cast ( ulong ) x - cast ( ulong ) y;
220- if (x < 0 && y >= 0 && r >= 0 ||
221- x >= 0 && y < 0 && (r < 0 || y == long .min))
220+ const r = x - y;
221+ if ( x._differentSign(y) // x and y has different sign
222+ & x._differentSign(r)) // result and x has different sign
222223 overflow = true ;
223224 return r;
224225}
@@ -385,10 +386,10 @@ unittest
385386pragma (inline, true )
386387int muls (int x, int y, ref bool overflow)
387388{
388- long r = cast (long )x * cast ( long ) y;
389+ const r = cast (long ) x * y;
389390 if (r < int .min || r > int .max)
390391 overflow = true ;
391- return cast (int )r;
392+ return cast (int ) r;
392393}
393394
394395unittest
@@ -415,9 +416,10 @@ unittest
415416pragma (inline, true )
416417long muls (long x, long y, ref bool overflow)
417418{
418- long r = cast (ulong )x * cast (ulong )y;
419- enum not0or1 = ~ 1L ;
420- if ((x & not0or1) && ((r == y)? r : (r / x) != y))
419+ const r = x * y;
420+ if ( ~ x._differentSign(y) // x and y has the same sign
421+ & r._signBit // and result is negative (covers min * -1)
422+ || x && r / x != y) // or perform simple check for x != 0
421423 overflow = true ;
422424 return r;
423425}
@@ -462,10 +464,10 @@ unittest
462464pragma (inline, true )
463465uint mulu (uint x, uint y, ref bool overflow)
464466{
465- ulong r = ulong (x) * ulong (y) ;
467+ const r = cast ( ulong ) x * y ;
466468 if (r > uint .max)
467469 overflow = true ;
468- return cast (uint )r;
470+ return cast (uint ) r;
469471}
470472
471473unittest
@@ -492,8 +494,8 @@ unittest
492494pragma (inline, true )
493495ulong mulu (ulong x, ulong y, ref bool overflow)
494496{
495- ulong r = x * y;
496- if (x && ( r / x) != y)
497+ const r = x * y;
498+ if (x && r / x != y)
497499 overflow = true ;
498500 return r;
499501}
@@ -517,3 +519,20 @@ unittest
517519 assert (mulu(0UL , 0UL , overflow) == 0 );
518520 assert (overflow); // sticky
519521}
522+
523+
524+ private :
525+
526+ pragma (inline, true )
527+ @property size_t _signBit(T)(in T n)
528+ if (is (T == int ) || is (T == long ))
529+ {
530+ return cast (size_t ) (n >>> T.sizeof * 8 - 1 );
531+ }
532+
533+ pragma (inline, true )
534+ size_t _differentSign (T)(in T a, in T b)
535+ if (is (T == int ) || is (T == long ))
536+ {
537+ return a._signBit ^ b._signBit;
538+ }
0 commit comments