1#pragma once
2
3namespace 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