2 /**********************************************
3 * This module implements integral arithmetic primitives that check
4 * for out-of-range results.
5 * This is a translation to C++ of D's core.checkedint
7 * Integral arithmetic operators operate on fixed width types.
8 * Results that are not representable in those fixed widths are silently
10 * This module offers integral arithmetic primitives that produce the
11 * same results, but set an 'overflow' flag when such truncation occurs.
12 * The setting is sticky, meaning that numerous operations can be cascaded
13 * and then the flag need only be checked at the end.
14 * Whether the operation is signed or unsigned is indicated by an 's' or 'u'
15 * suffix, respectively. While this could be achieved without such suffixes by
16 * using overloading on the signedness of the types, the suffix makes it clear
17 * which is happening without needing to examine the types.
19 * While the generic versions of these functions are computationally expensive
20 * relative to the cost of the operation itself, compiler implementations are free
21 * to recognize them and generate equivalent and faster code.
23 * References: $(LINK2 http://blog.regehr.org/archives/1139, Fast Integer Overflow Checks)
24 * Copyright: Copyright (C) 2014-2018 by The D Language Foundation, All Rights Reserved
25 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
26 * Authors: Walter Bright
27 * Source: https://github.com/D-Programming-Language/dmd/blob/master/src/root/port.c
32 #include "checkedint.h"
34 /*******************************
35 * Add two signed integers, checking for overflow.
37 * The overflow is sticky, meaning a sequence of operations can
38 * be done and overflow need only be checked at the end.
42 * overflow = set if an overflow occurs, is not affected otherwise
47 int adds(int x
, int y
, bool& overflow
)
49 int64_t r
= (int64_t)x
+ (int64_t)y
;
50 if (r
< INT32_MIN
|| r
> INT32_MAX
)
56 int64_t adds(int64_t x
, int64_t y
, bool& overflow
)
58 int64_t r
= (uint64_t)x
+ (uint64_t)y
;
59 if ((x
< 0 && y
< 0 && r
>= 0) ||
60 (x
>= 0 && y
>= 0 && r
< 0))
65 /*******************************
66 * Add two unsigned integers, checking for overflow (aka carry).
68 * The overflow is sticky, meaning a sequence of operations can
69 * be done and overflow need only be checked at the end.
73 * overflow = set if an overflow occurs, is not affected otherwise
78 unsigned addu(unsigned x
, unsigned y
, bool& overflow
)
87 uint64_t addu(uint64_t x
, uint64_t y
, bool& overflow
)
95 /*******************************
96 * Subtract two signed integers, checking for overflow.
98 * The overflow is sticky, meaning a sequence of operations can
99 * be done and overflow need only be checked at the end.
103 * overflow = set if an overflow occurs, is not affected otherwise
108 int subs(int x
, int y
, bool& overflow
)
110 int64_t r
= (int64_t)x
- (int64_t)y
;
111 if (r
< INT32_MIN
|| r
> INT32_MAX
)
117 int64_t subs(int64_t x
, int64_t y
, bool& overflow
)
119 int64_t r
= (uint64_t)x
- (uint64_t)y
;
120 if ((x
< 0 && y
>= 0 && r
>= 0) ||
121 (x
>= 0 && y
< 0 && (r
< 0 || y
== INT64_MIN
)))
126 /*******************************
127 * Subtract two unsigned integers, checking for overflow (aka borrow).
129 * The overflow is sticky, meaning a sequence of operations can
130 * be done and overflow need only be checked at the end.
134 * overflow = set if an overflow occurs, is not affected otherwise
139 unsigned subu(unsigned x
, unsigned y
, bool& overflow
)
147 uint64_t subu(uint64_t x
, uint64_t y
, bool& overflow
)
154 /***********************************************
159 * overflow = set if x cannot be negated, is not affected otherwise
164 int negs(int x
, bool& overflow
)
166 if (x
== (int)INT32_MIN
)
172 int64_t negs(int64_t x
, bool& overflow
)
179 /*******************************
180 * Multiply two signed integers, checking for overflow.
182 * The overflow is sticky, meaning a sequence of operations can
183 * be done and overflow need only be checked at the end.
187 * overflow = set if an overflow occurs, is not affected otherwise
192 int muls(int x
, int y
, bool& overflow
)
194 int64_t r
= (int64_t)x
* (int64_t)y
;
195 if (r
< INT32_MIN
|| r
> INT32_MAX
)
201 int64_t muls(int64_t x
, int64_t y
, bool& overflow
)
203 int64_t r
= (uint64_t)x
* (uint64_t)y
;
204 int64_t not0or1
= ~(int64_t)1;
205 if ((x
& not0or1
) && ((r
== y
) ? r
: (r
/ x
) != y
))
210 /*******************************
211 * Multiply two unsigned integers, checking for overflow (aka carry).
213 * The overflow is sticky, meaning a sequence of operations can
214 * be done and overflow need only be checked at the end.
218 * overflow = set if an overflow occurs, is not affected otherwise
223 unsigned mulu(unsigned x
, unsigned y
, bool& overflow
)
225 uint64_t r
= (uint64_t)x
* (uint64_t)y
;
232 uint64_t mulu(uint64_t x
, uint64_t y
, bool& overflow
)
235 if (x
&& (r
/ x
) != y
)