Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(189)

Side by Side Diff: base/numerics/README.md

Issue 2945433003: Add ClampedNumeric templates (Closed)
Patch Set: feedback round 2 Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698