1 | #pragma once |
2 | |
3 | namespace common |
4 | { |
5 | template <typename T> |
6 | inline bool addOverflow(T x, T y, T & res) |
7 | { |
8 | return __builtin_add_overflow(x, y, &res); |
9 | } |
10 | |
11 | template <> |
12 | inline bool addOverflow(int x, int y, int & res) |
13 | { |
14 | return __builtin_sadd_overflow(x, y, &res); |
15 | } |
16 | |
17 | template <> |
18 | inline bool addOverflow(long x, long y, long & res) |
19 | { |
20 | return __builtin_saddl_overflow(x, y, &res); |
21 | } |
22 | |
23 | template <> |
24 | inline bool addOverflow(long long x, long long y, long long & res) |
25 | { |
26 | return __builtin_saddll_overflow(x, y, &res); |
27 | } |
28 | |
29 | template <> |
30 | inline bool addOverflow(__int128 x, __int128 y, __int128 & res) |
31 | { |
32 | static constexpr __int128 min_int128 = __int128(0x8000000000000000ll) << 64; |
33 | static constexpr __int128 max_int128 = (__int128(0x7fffffffffffffffll) << 64) + 0xffffffffffffffffll; |
34 | res = x + y; |
35 | return (y > 0 && x > max_int128 - y) || (y < 0 && x < min_int128 - y); |
36 | } |
37 | |
38 | template <typename T> |
39 | inline bool subOverflow(T x, T y, T & res) |
40 | { |
41 | return __builtin_sub_overflow(x, y, &res); |
42 | } |
43 | |
44 | template <> |
45 | inline bool subOverflow(int x, int y, int & res) |
46 | { |
47 | return __builtin_ssub_overflow(x, y, &res); |
48 | } |
49 | |
50 | template <> |
51 | inline bool subOverflow(long x, long y, long & res) |
52 | { |
53 | return __builtin_ssubl_overflow(x, y, &res); |
54 | } |
55 | |
56 | template <> |
57 | inline bool subOverflow(long long x, long long y, long long & res) |
58 | { |
59 | return __builtin_ssubll_overflow(x, y, &res); |
60 | } |
61 | |
62 | template <> |
63 | inline bool subOverflow(__int128 x, __int128 y, __int128 & res) |
64 | { |
65 | static constexpr __int128 min_int128 = __int128(0x8000000000000000ll) << 64; |
66 | static constexpr __int128 max_int128 = (__int128(0x7fffffffffffffffll) << 64) + 0xffffffffffffffffll; |
67 | res = x - y; |
68 | return (y < 0 && x > max_int128 + y) || (y > 0 && x < min_int128 + y); |
69 | } |
70 | |
71 | template <typename T> |
72 | inline bool mulOverflow(T x, T y, T & res) |
73 | { |
74 | return __builtin_mul_overflow(x, y, &res); |
75 | } |
76 | |
77 | template <> |
78 | inline bool mulOverflow(int x, int y, int & res) |
79 | { |
80 | return __builtin_smul_overflow(x, y, &res); |
81 | } |
82 | |
83 | template <> |
84 | inline bool mulOverflow(long x, long y, long & res) |
85 | { |
86 | return __builtin_smull_overflow(x, y, &res); |
87 | } |
88 | |
89 | template <> |
90 | inline bool mulOverflow(long long x, long long y, long long & res) |
91 | { |
92 | return __builtin_smulll_overflow(x, y, &res); |
93 | } |
94 | |
95 | template <> |
96 | inline bool mulOverflow(__int128 x, __int128 y, __int128 & res) |
97 | { |
98 | res = static_cast<unsigned __int128>(x) * static_cast<unsigned __int128>(y); /// Avoid signed integer overflow. |
99 | if (!x || !y) |
100 | return false; |
101 | |
102 | unsigned __int128 a = (x > 0) ? x : -x; |
103 | unsigned __int128 b = (y > 0) ? y : -y; |
104 | return (a * b) / b != a; |
105 | } |
106 | } |
107 | |