OLD | NEW |
---|---|
(Empty) | |
1 # `base/numerics` | |
2 | |
3 This directory contains templates providing well-defined semantics for safely | |
4 handling a variety of numeric operations, including most common arithmetic | |
5 operations and conversions. | |
6 | |
7 The public API is broken out into the following header files: | |
8 | |
9 * `checked_math.h` contains the `CheckedNumeric` template class and helper | |
10 functions for performing arithmetic and conversion operations that detect | |
11 errors and boundary conditions (e.g. overflow, truncation, etc.). | |
12 * `clamped_math.h` contains the `ClampedNumeric` template class and | |
13 helper functions for performing fast, clamped (i.e. non-sticky saturating) | |
14 arithmetic operations and conversions. | |
15 * `safe_conversions.h` contains the `StrictNumeric` template class and | |
16 a collection of custom casting templates and helper functions for safely | |
17 converting between a range of numeric types. | |
18 * `safe_math.h` includes all of the previously mentioned headers. | |
19 | |
20 *** aside | |
21 **Note:** The `Numeric` template types implicitly convert from C numeric types | |
22 and `Numeric` templates that are convertable to an underlying C numeric type. | |
23 The conversion priority for `Numeric` type coercions is: | |
24 | |
25 * `StrictNumeric` coerces to `ClampedNumeric` and `CheckedNumeric` | |
26 * `ClampedNumeric` coerces to `CheckedNumeric` | |
27 *** | |
28 | |
29 [TOC] | |
30 | |
31 ## Conversion functions and `StrictNumeric<>` in `safe_conversions.h` | |
32 | |
33 This header includes a collection of helper `constexpr` templates for safely | |
34 performing a range of conversions, assignments, and tests. | |
35 | |
36 ### Safe casting templates | |
37 | |
38 * `as_signed()` - Returns the supplied integral value as a signed type of | |
39 the same width. | |
40 * `as_unsigned()` - Returns the supplied integral value as an unsigned type | |
41 of the same width. | |
42 * `checked_cast<>()` - Analogous to `static_cast<>` for numeric types, except | |
43 that by default it will trigger a crash on an out-of-bounds conversion (e.g. | |
44 overflow, underflow, NaN to integral) or a compile error if the conversion | |
45 error can be detected at compile time. The crash handler can be overridden | |
46 to perform a behavior other than crashing. | |
47 * `saturated_cast<>()` - Analogous to `static_cast` for numeric types, except | |
48 that it returns a saturated result when the specified numeric conversion | |
49 would otherwise overflow or underflow. An NaN source returns 0 by | |
50 default, but can be overridden to return a different result. | |
51 * `strict_cast<>()` - Analogous to `static_cast` for numeric types, except | |
52 this causes a compile failure if the destination type is not large | |
53 enough to contain any value in the source type. It performs no runtime | |
54 checking and thus introduces no runtime overhead. | |
55 | |
56 ### Other helper and conversion functions | |
57 | |
58 * `IsValueInRangeForNumericType<>()` - A convenience function that returns | |
59 true if the type supplied to the template parameter can represent the value | |
60 passed as an argument to the function. | |
61 * `IsValueNegative()` - A convenience function that will accept any | |
62 arithmetic type as an argument and will return whether the value is less | |
63 than zero. Unsigned types always return false. | |
64 * `SafeUnsignedAbs()` - Returns the absolute value of the supplied integer | |
65 parameter as an unsigned result (thus avoiding an overflow if the value | |
66 is the signed, two's complement minimum). | |
67 | |
68 ### `StrictNumeric<>` | |
69 | |
70 `StrictNumeric<>` is a wrapper type that performs assignments and copies via | |
71 the `strict_cast` template, and can perform valid arithmetic comparisons | |
72 across any range of arithmetic types. `StrictNumeric` is the return type for | |
73 values extracted from a `CheckedNumeric` class instance. The raw numeric value | |
74 is extracted via `static_cast` to the underlying type or any type with | |
75 sufficient range to represent the underlying type. | |
76 | |
77 * `MakeStrictNum()` - Creates a new `StrictNumeric` from the underlying type | |
78 of the supplied arithmetic or StrictNumeric type. | |
79 * `SizeT` - Alias for `StrictNumeric<size_t>`. | |
80 | |
81 ## `CheckedNumeric<>` in `checked_math.h` | |
82 | |
83 `CheckedNumeric<>` implements all the logic and operators for detecting integer | |
84 boundary conditions such as overflow, underflow, and invalid conversions. | |
85 The `CheckedNumeric` type implicitly converts from floating point and integer | |
86 data types, and contains overloads for basic arithmetic operations (i.e.: `+`, | |
87 `-`, `*`, `/` for all types and `%`, `<<`, `>>`, `&`, `|`, `^` for integers). | |
88 Type promotions are a slightly modified version of the [standard C/C++ numeric | |
89 promotions | |
90 ](http://en.cppreference.com/w/cpp/language/implicit_conversion#Numeric_promotio ns) | |
91 with the two differences being that there is no default promotion to int | |
92 and bitwise logical operations always return an unsigned of the wider type. | |
93 | |
94 ### Members | |
95 | |
96 The unary negation, increment, and decrement operators are supported, along | |
97 with the following unary arithmetic methods, which return a new | |
98 `CheckedNumeric` as a result of the operation: | |
99 | |
100 * `Abs()` - Absolute value. | |
101 * `UnsignedAbs()` - Absolute value as an equal-width unsigned underlying type | |
102 (valid for only integral types). | |
103 * `Max()` - Returns whichever is greater of the current instance or argument. | |
104 The underlying return type is whichever has the greatest magnitude. | |
105 * `Min()` - Returns whichever is lowest of the current instance or argument. | |
106 The underlying return type is whichever has can represent the lowest | |
107 number in the smallest width (e.g. int8_t over unsigned, int over | |
108 int8_t, and float over int). | |
109 | |
110 The following are for converting `CheckedNumeric` instances: | |
111 | |
112 * `type` - The underlying numeric type. | |
113 * `AssignIfValid()` - Assigns the underlying value to the supplied | |
114 destination pointer if the value is currently valid and within the | |
115 range supported by the destination type. Returns true on success. | |
116 * `Cast<>()` - Instance method returning a `CheckedNumeric` derived from | |
117 casting the current instance to a `CheckedNumeric` of the supplied | |
118 destination type. | |
119 | |
120 *** aside | |
121 The following member functions return a `StrictNumeric`, which is valid for | |
122 comparison and assignment operations, but will trigger a compile failure on | |
123 attempts to assign to a type of insufficient range. The underlying value can | |
124 be extracted by an explicit `static_cast` to the underlying type or any type | |
125 with sufficient range to represent the underlying type. | |
126 *** | |
127 | |
128 * `IsValid()` - Returns true if the underlying numeric value is valid (i.e. | |
129 has not wrapped or saturated and is not the result of an invalid | |
130 conversion). | |
131 * `ValueOrDie()` - Returns the underlying value. If the state is not valid | |
132 this call will trigger a crash by default (but may be overridden by | |
133 supplying an alternate handler to the template). | |
134 * `ValueOrDefault()` - Returns the current value, or the supplied default if | |
135 the state is not valid (but will not crash). | |
136 | |
137 **Comparison operators are explicitly not provided** for `CheckedNumeric` | |
138 types because they could result in a crash if the type is not in a valid state. | |
139 Patterns like the following should be used instead: | |
140 | |
141 ```cpp | |
142 CheckedNumeric<size_t> checked_size = untrusted_input_value; | |
143 checked_size += HEADER LENGTH; | |
144 if (checked_size.IsValid() && checked_size.ValueOrDie() < buffer_size) { | |
145 \\ Do stuff on success... | |
146 } else { | |
147 \\ Handle an error... | |
148 } | |
149 ``` | |
150 | |
151 ### Non-member helper functions | |
152 | |
153 The following variadic convenience functions, which accept standard arithmetic | |
154 or `CheckedNumeric` types, perform arithmetic operations, and return a | |
155 `CheckedNumeric` result. The supported functions are: | |
156 | |
157 * `CheckAdd()` - Addition. | |
158 * `CheckSub()` - Subtraction. | |
159 * `CheckMul()` - Multiplication. | |
160 * `CheckDiv()` - Division. | |
161 * `CheckMod()` - Modulus (integer only). | |
162 * `CheckLsh()` - Left integer shift (integer only). | |
163 * `CheckRsh()` - Right integer shift (integer only). | |
164 * `CheckAnd()` - Bitwise AND (integer only with unsigned result). | |
165 * `CheckOr()` - Bitwise OR (integer only with unsigned result). | |
166 * `CheckXor()` - Bitwise XOR (integer only with unsigned result). | |
167 * `CheckMax()` - Maximum of supplied arguments. | |
168 * `CheckMin()` - Minimum of supplied arguments. | |
169 | |
170 The following wrapper functions can be used to avoid the template | |
171 disambiguator syntax when converting a destination type. | |
172 | |
173 * `IsValidForType<>()` in place of: `a.template IsValid<>()` | |
174 * `ValueOrDieForType<>()` in place of: `a.template ValueOrDie<>()` | |
175 * `ValueOrDefaultForType<>()` in place of: `a.template ValueOrDefault<>()` | |
176 | |
177 The following general utility methods is are useful for converting from | |
178 arithmetic types to `CheckedNumeric` types: | |
179 | |
180 * `MakeCheckedNum()` - Creates a new `CheckedNumeric` from the underlying type | |
181 of the supplied arithmetic or directly convertible type. | |
182 | |
183 ## `ClampedNumeric<>` in `clamped_math.h` | |
184 | |
185 `ClampedNumeric<>` implements all the logic and operators for clamped | |
186 (non-sticky saturating) arithmetic operations and conversions. The | |
187 `ClampedNumeric` type implicitly converts back and forth between floating point | |
188 and integer data types, saturating on assignment as appropriate. It contains | |
189 overloads for basic arithmetic operations (i.e.: `+`, `-`, `*`, `/` for | |
190 all types and `%`, `<<`, `>>`, `&`, `|`, `^` for integers) along with comparison | |
191 operators for arithmetic types of any size. Type promotions are a slightly | |
192 modified version of the [standard C/C++ numeric promotions | |
193 ](http://en.cppreference.com/w/cpp/language/implicit_conversion#Numeric_promotio ns) | |
194 with the two differences being that there is no default promotion to int and | |
195 bitwise logical operations always return an unsigned of the wider type. | |
196 | |
197 *** aside | |
198 Most arithmetic operations saturate normally, to the numeric limit in the | |
199 direction of the sign. The potentially unusual cases are: | |
200 | |
201 * **Division:** Division by zero returns the saturated limit in the direction | |
202 of sign of the dividend (first argument). | |
203 * **Modulus:** Division by zero returns the dividend (first argument). | |
204 * **Left shift:** Non-zero values saturate in the direction of the signed | |
205 limit (max/min). 0 shifted any amount results in 0. | |
dcheng
2017/07/03 10:01:44
Nit: maybe call out that a single shift > bit widt
jschuh
2017/07/03 13:03:46
Done.
| |
206 * **Right shift:** Negative values saturate to -1. Positive or 0 saturates | |
207 to 0. | |
208 * **Bitwise operations:** No saturation; bit pattern is identical to | |
209 non-saturated bitwise operations. | |
210 *** | |
211 | |
212 ### Members | |
213 | |
214 The unary negation, increment, and decrement operators are supported, along | |
215 with the following unary arithmetic methods, which return a new | |
216 `ClampedNumeric` as a result of the operation: | |
217 | |
218 * `Abs()` - Absolute value. | |
219 * `UnsignedAbs()` - Absolute value as an equal-width unsigned underlying type | |
220 (valid for only integral types). | |
221 * `Max()` - Returns whichever is greater of the current instance or argument. | |
222 The underlying return type is whichever has the greatest magnitude. | |
223 * `Min()` - Returns whichever is lowest of the current instance or argument. | |
224 The underlying return type is whichever has can represent the lowest | |
225 number in the smallest width (e.g. int8_t over unsigned, int over | |
226 int8_t, and float over int). | |
227 | |
228 The following are for converting `ClampedNumeric` instances: | |
229 | |
230 * `type` - The underlying numeric type. | |
231 * `Cast<>()` - Instance method returning a `ClampedNumeric` derived from | |
232 casting the current instance to a `ClampedNumeric` of the supplied | |
233 destination type. | |
234 | |
235 ### Non-member helper functions | |
236 | |
237 The following variadic convenience functions, which accept standard arithmetic | |
238 or `ClampedNumeric` types, perform arithmetic operations, and return a | |
239 `ClampedNumeric` result. The supported functions are: | |
240 | |
241 * `ClampAdd()` - Addition. | |
242 * `ClampSub()` - Subtraction. | |
243 * `ClampMul()` - Multiplication. | |
244 * `ClampDiv()` - Division. | |
245 * `ClampMod()` - Modulus (integer only). | |
246 * `ClampLsh()` - Left integer shift (integer only). | |
247 * `ClampRsh()` - Right integer shift (integer only). | |
248 * `ClampAnd()` - Bitwise AND (integer only with unsigned result). | |
249 * `ClampOr()` - Bitwise OR (integer only with unsigned result). | |
250 * `ClampXor()` - Bitwise XOR (integer only with unsigned result). | |
251 * `ClampMax()` - Maximum of supplied arguments. | |
252 * `ClampMin()` - Minimum of supplied arguments. | |
253 | |
254 The following is a general utility method that is useful for converting | |
255 to a `ClampedNumeric` type: | |
256 | |
257 * `MakeClampedNum()` - Creates a new `ClampedNumeric` from the underlying type | |
258 of the supplied arithmetic or directly convertible type. | |
OLD | NEW |