Iros
 
Loading...
Searching...
No Matches
checked.h
Go to the documentation of this file.
1#pragma once
2
4#include "di/meta/language.h"
7
8namespace di::math {
9template<concepts::Integer T>
10class Checked {
11public:
12 Checked() = default;
13
14 constexpr Checked(T value) : m_value(value) {}
15
16 constexpr auto value() const -> Optional<T> { return m_invalid ? nullopt : Optional(m_value); }
17
18 constexpr auto valid() const -> bool { return !m_invalid; }
19 constexpr auto invalid() const -> bool { return m_invalid; }
20
21 constexpr auto operator+=(Checked value) -> Checked& {
22 m_invalid |= value.m_invalid;
23 m_invalid |= __builtin_add_overflow(m_value, value.m_value, &m_value);
24 return *this;
25 }
26
27 constexpr auto operator-=(Checked value) -> Checked& {
28 m_invalid |= value.m_invalid;
29 m_invalid |= __builtin_sub_overflow(m_value, value.m_value, &m_value);
30 return *this;
31 }
32
33 constexpr auto operator*=(Checked value) -> Checked& {
34 m_invalid |= value.m_invalid;
35 m_invalid |= __builtin_mul_overflow(m_value, value.m_value, &m_value);
36 return *this;
37 }
38
39 constexpr auto operator/=(Checked value) -> Checked& {
40 m_invalid |= value.m_invalid;
41
42 // Division is undefined for signed integers if the divisor is -1 and the dividend is the minimum value. Also,
43 // division by zero is undefined.
44 if constexpr (concepts::Signed<T>) {
45 m_invalid |= value.m_value == -1 && m_value == NumericLimits<T>::min;
46 }
47 m_invalid |= value.m_value == 0;
48 if (!m_invalid) {
49 m_value /= value.m_value;
50 }
51
52 return *this;
53 }
54
55 constexpr auto operator%=(Checked value) -> Checked& {
56 m_invalid |= value.m_invalid;
57
58 // Division is undefined for signed integers if the divisor is -1 and the dividend is the minimum value. Also,
59 // division by zero is undefined.
60 if constexpr (concepts::Signed<T>) {
61 m_invalid |= value.m_value == -1 && m_value == NumericLimits<T>::min;
62 }
63 m_invalid |= value.m_value == 0;
64 if (!m_invalid) {
65 m_value %= value.m_value;
66 }
67
68 return *this;
69 }
70
71 constexpr auto operator&=(Checked value) -> Checked& {
72 m_invalid |= value.m_invalid;
73 m_value &= value.m_value;
74 return *this;
75 }
76
77 constexpr auto operator|=(Checked value) -> Checked& {
78 m_invalid |= value.m_invalid;
79 m_value |= value.m_value;
80 return *this;
81 }
82
83 constexpr auto operator^=(Checked value) -> Checked& {
84 m_invalid |= value.m_invalid;
85 m_value ^= value.m_value;
86 return *this;
87 }
88
89 constexpr auto operator<<=(Checked value) -> Checked& {
90 m_invalid |= value.m_invalid;
91
92 // Shifting by a negative amount is undefined, as it shifting by more than the number of bits in the "promoted"
93 // type. This implementation is more conservative, by ignoring promotions.
94 m_invalid |= value.m_value < 0 || value.m_value >= NumericLimits<meta::MakeUnsigned<T>>::digits;
95 if (!m_invalid) {
96 m_value <<= value.m_value;
97 }
98
99 return *this;
100 }
101
102 constexpr auto operator>>=(Checked value) -> Checked& {
103 m_invalid |= value.m_invalid;
104
105 // Shifting by a negative amount is undefined, as it shifting by more than the number of bits in the "promoted"
106 // type. This implementation is more conservative, by ignoring promotions.
107 m_invalid |= value.m_value < 0 || value.m_value >= NumericLimits<meta::MakeUnsigned<T>>::digits;
108 if (!m_invalid) {
109 m_value >>= value.m_value;
110 }
111
112 return *this;
113 }
114
115 constexpr auto operator++() -> Checked& {
116 *this += 1;
117 return *this;
118 }
119
120 constexpr auto operator--() -> Checked& {
121 *this -= 1;
122 return *this;
123 }
124
125 constexpr auto operator++(int) -> Checked {
126 auto result = *this;
127 ++*this;
128 return result;
129 }
130
131 constexpr auto operator--(int) -> Checked {
132 auto result = *this;
133 --*this;
134 return result;
135 }
136
137 constexpr auto operator+() const -> Checked { return *this; }
138 constexpr auto operator-() const -> Checked {
139 // Negating the minimum value is undefined for signed integers.
140 if constexpr (concepts::Signed<T>) {
141 if (m_value == NumericLimits<T>::min) {
142 auto result = *this;
143 result.m_invalid = true;
144 return result;
145 }
146 }
147 return Checked(-m_value);
148 }
149
150 constexpr auto operator~() const -> Checked { return Checked(~m_value); }
151
152 constexpr auto operator&(Checked value) const -> Checked {
153 auto result = *this;
154 result &= value;
155 return result;
156 }
157
158 constexpr auto operator|(Checked value) const -> Checked {
159 auto result = *this;
160 result |= value;
161 return result;
162 }
163
164 constexpr auto operator^(Checked value) const -> Checked {
165 auto result = *this;
166 result ^= value;
167 return result;
168 }
169
170 constexpr auto operator<<(Checked value) const -> Checked {
171 auto result = *this;
172 result <<= value;
173 return result;
174 }
175
176 constexpr auto operator>>(Checked value) const -> Checked {
177 auto result = *this;
178 result >>= value;
179 return result;
180 }
181
182 constexpr auto operator+(Checked value) const -> Checked {
183 auto result = *this;
184 result += value;
185 return result;
186 }
187
188 constexpr auto operator-(Checked value) const -> Checked {
189 auto result = *this;
190 result -= value;
191 return result;
192 }
193
194 constexpr auto operator*(Checked value) const -> Checked {
195 auto result = *this;
196 result *= value;
197 return result;
198 }
199
200 constexpr auto operator/(Checked value) const -> Checked {
201 auto result = *this;
202 result /= value;
203 return result;
204 }
205
206 constexpr auto operator%(Checked value) const -> Checked {
207 auto result = *this;
208 result %= value;
209 return result;
210 }
211
212private:
213 T m_value {};
214 bool m_invalid { false };
215};
216}
217
218namespace di {
219using math::Checked;
220}
Definition checked.h:10
constexpr auto operator++() -> Checked &
Definition checked.h:115
constexpr auto value() const -> Optional< T >
Definition checked.h:16
constexpr auto operator--(int) -> Checked
Definition checked.h:131
constexpr auto operator*=(Checked value) -> Checked &
Definition checked.h:33
constexpr auto operator+=(Checked value) -> Checked &
Definition checked.h:21
constexpr auto operator<<=(Checked value) -> Checked &
Definition checked.h:89
constexpr auto operator-=(Checked value) -> Checked &
Definition checked.h:27
constexpr auto operator^=(Checked value) -> Checked &
Definition checked.h:83
constexpr auto operator&(Checked value) const -> Checked
Definition checked.h:152
constexpr auto operator-() const -> Checked
Definition checked.h:138
constexpr auto operator--() -> Checked &
Definition checked.h:120
constexpr auto operator/(Checked value) const -> Checked
Definition checked.h:200
constexpr auto operator++(int) -> Checked
Definition checked.h:125
constexpr auto operator&=(Checked value) -> Checked &
Definition checked.h:71
constexpr auto operator<<(Checked value) const -> Checked
Definition checked.h:170
constexpr auto operator-(Checked value) const -> Checked
Definition checked.h:188
constexpr auto invalid() const -> bool
Definition checked.h:19
constexpr auto operator%=(Checked value) -> Checked &
Definition checked.h:55
constexpr auto operator|(Checked value) const -> Checked
Definition checked.h:158
constexpr Checked(T value)
Definition checked.h:14
constexpr auto operator^(Checked value) const -> Checked
Definition checked.h:164
constexpr auto operator+(Checked value) const -> Checked
Definition checked.h:182
constexpr auto operator*(Checked value) const -> Checked
Definition checked.h:194
constexpr auto operator~() const -> Checked
Definition checked.h:150
constexpr auto operator|=(Checked value) -> Checked &
Definition checked.h:77
constexpr auto operator>>(Checked value) const -> Checked
Definition checked.h:176
constexpr auto valid() const -> bool
Definition checked.h:18
constexpr auto operator>>=(Checked value) -> Checked &
Definition checked.h:102
constexpr auto operator%(Checked value) const -> Checked
Definition checked.h:206
constexpr auto operator+() const -> Checked
Definition checked.h:137
constexpr auto operator/=(Checked value) -> Checked &
Definition checked.h:39
Definition optional_forward_declaration.h:5
Definition language.h:238
Definition abs.h:10
Definition zstring_parser.h:9
constexpr auto nullopt
Definition nullopt.h:15
Definition numeric_limits.h:7