Chromium Code Reviews| 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 |