OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef BASE_NUMERICS_SAFE_MATH_H_ | 5 #ifndef BASE_NUMERICS_SAFE_MATH_H_ |
6 #define BASE_NUMERICS_SAFE_MATH_H_ | 6 #define BASE_NUMERICS_SAFE_MATH_H_ |
7 | 7 |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 | 9 |
10 #include <limits> | 10 #include <limits> |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
188 CheckedNumericState<T> state_; | 188 CheckedNumericState<T> state_; |
189 }; | 189 }; |
190 | 190 |
191 // This is the boilerplate for the standard arithmetic operator overloads. A | 191 // This is the boilerplate for the standard arithmetic operator overloads. A |
192 // macro isn't the prettiest solution, but it beats rewriting these five times. | 192 // macro isn't the prettiest solution, but it beats rewriting these five times. |
193 // Some details worth noting are: | 193 // Some details worth noting are: |
194 // * We apply the standard arithmetic promotions. | 194 // * We apply the standard arithmetic promotions. |
195 // * We skip range checks for floating points. | 195 // * We skip range checks for floating points. |
196 // * We skip range checks for destination integers with sufficient range. | 196 // * We skip range checks for destination integers with sufficient range. |
197 // TODO(jschuh): extract these out into templates. | 197 // TODO(jschuh): extract these out into templates. |
198 #define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \ | 198 #define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP, PROMOTION) \ |
199 /* Binary arithmetic operator for CheckedNumerics of the same type. */ \ | 199 /* Binary arithmetic operator for CheckedNumerics of the same type. */ \ |
200 template <typename L, typename R> \ | 200 template <typename L, typename R> \ |
201 CheckedNumeric<typename ArithmeticPromotion<L, R>::type> operator OP( \ | 201 CheckedNumeric<typename ArithmeticPromotion<PROMOTION, L, R>::type> \ |
202 const CheckedNumeric<L>& lhs, const CheckedNumeric<R>& rhs) { \ | 202 operator OP(const CheckedNumeric<L>& lhs, const CheckedNumeric<R>& rhs) { \ |
203 using P = typename ArithmeticPromotion<L, R>::type; \ | 203 using P = typename ArithmeticPromotion<PROMOTION, L, R>::type; \ |
204 if (!rhs.IsValid() || !lhs.IsValid()) \ | 204 if (!rhs.IsValid() || !lhs.IsValid()) \ |
205 return CheckedNumeric<P>(0, false); \ | 205 return CheckedNumeric<P>(0, false); \ |
206 /* Floating point always takes the fast path */ \ | 206 /* Floating point always takes the fast path */ \ |
207 if (std::is_floating_point<L>::value || std::is_floating_point<R>::value) \ | 207 if (std::is_floating_point<L>::value || std::is_floating_point<R>::value) \ |
208 return CheckedNumeric<P>(lhs.ValueUnsafe() OP rhs.ValueUnsafe()); \ | 208 return CheckedNumeric<P>(lhs.ValueUnsafe() OP rhs.ValueUnsafe()); \ |
209 P result = 0; \ | 209 P result = 0; \ |
210 bool is_valid = \ | 210 bool is_valid = \ |
211 Checked##NAME(lhs.ValueUnsafe(), rhs.ValueUnsafe(), &result); \ | 211 Checked##NAME(lhs.ValueUnsafe(), rhs.ValueUnsafe(), &result); \ |
212 return CheckedNumeric<P>(result, is_valid); \ | 212 return CheckedNumeric<P>(result, is_valid); \ |
213 } \ | 213 } \ |
214 /* Assignment arithmetic operator implementation from CheckedNumeric. */ \ | 214 /* Assignment arithmetic operator implementation from CheckedNumeric. */ \ |
215 template <typename L> \ | 215 template <typename L> \ |
216 template <typename R> \ | 216 template <typename R> \ |
217 CheckedNumeric<L>& CheckedNumeric<L>::operator COMPOUND_OP(R rhs) { \ | 217 CheckedNumeric<L>& CheckedNumeric<L>::operator COMPOUND_OP(R rhs) { \ |
218 *this = *this OP rhs; \ | 218 *this = *this OP rhs; \ |
219 return *this; \ | 219 return *this; \ |
220 } \ | 220 } \ |
221 /* Binary arithmetic operator for left CheckedNumeric and right numeric. */ \ | 221 /* Binary arithmetic operator for left CheckedNumeric and right numeric. */ \ |
222 template <typename L, typename R, \ | 222 template <typename L, typename R, \ |
223 typename std::enable_if<std::is_arithmetic<R>::value>::type* = \ | 223 typename std::enable_if<std::is_arithmetic<R>::value>::type* = \ |
224 nullptr> \ | 224 nullptr> \ |
225 CheckedNumeric<typename ArithmeticPromotion<L, R>::type> operator OP( \ | 225 CheckedNumeric<typename ArithmeticPromotion<PROMOTION, L, R>::type> \ |
226 const CheckedNumeric<L>& lhs, R rhs) { \ | 226 operator OP(const CheckedNumeric<L>& lhs, R rhs) { \ |
227 return lhs OP CheckedNumeric<R>(rhs); \ | 227 return lhs OP CheckedNumeric<R>(rhs); \ |
228 } \ | 228 } \ |
229 /* Binary arithmetic operator for left numeric and right CheckedNumeric. */ \ | 229 /* Binary arithmetic operator for left numeric and right CheckedNumeric. */ \ |
230 template <typename L, typename R, \ | 230 template <typename L, typename R, \ |
231 typename std::enable_if<std::is_arithmetic<L>::value>::type* = \ | 231 typename std::enable_if<std::is_arithmetic<L>::value>::type* = \ |
232 nullptr> \ | 232 nullptr> \ |
233 CheckedNumeric<typename ArithmeticPromotion<L, R>::type> operator OP( \ | 233 CheckedNumeric<typename ArithmeticPromotion<PROMOTION, L, R>::type> \ |
234 L lhs, const CheckedNumeric<R>& rhs) { \ | 234 operator OP(L lhs, const CheckedNumeric<R>& rhs) { \ |
235 return CheckedNumeric<L>(lhs) OP rhs; \ | 235 return CheckedNumeric<L>(lhs) OP rhs; \ |
236 } | 236 } |
237 | 237 |
238 BASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, += ) | 238 BASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, +=, MAX_EXPONENT_PROMOTION) |
239 BASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -= ) | 239 BASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -=, MAX_EXPONENT_PROMOTION) |
240 BASE_NUMERIC_ARITHMETIC_OPERATORS(Mul, *, *= ) | 240 BASE_NUMERIC_ARITHMETIC_OPERATORS(Mul, *, *=, MAX_EXPONENT_PROMOTION) |
Tom Sepez
2016/11/15 22:31:17
Shouldn't multiplicaton be BIG_ENOUGH_PROMOTION?
jschuh
2016/11/15 22:38:49
It is, but in the intermediate representation for
| |
241 BASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /= ) | 241 BASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /=, MAX_EXPONENT_PROMOTION) |
242 BASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %= ) | 242 BASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %=, MAX_EXPONENT_PROMOTION) |
243 | 243 |
244 #undef BASE_NUMERIC_ARITHMETIC_OPERATORS | 244 #undef BASE_NUMERIC_ARITHMETIC_OPERATORS |
245 | 245 |
246 } // namespace internal | 246 } // namespace internal |
247 | 247 |
248 using internal::CheckedNumeric; | 248 using internal::CheckedNumeric; |
249 | 249 |
250 } // namespace base | 250 } // namespace base |
251 | 251 |
252 #endif // BASE_NUMERICS_SAFE_MATH_H_ | 252 #endif // BASE_NUMERICS_SAFE_MATH_H_ |
OLD | NEW |