| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 
|  | 2 // Use of this source code is governed by a BSD-style license that can be | 
|  | 3 // found in the LICENSE file. | 
|  | 4 | 
|  | 5 #ifndef BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_ | 
|  | 6 #define BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_ | 
|  | 7 | 
|  | 8 #include <stddef.h> | 
|  | 9 #include <stdint.h> | 
|  | 10 | 
|  | 11 #include <climits> | 
|  | 12 #include <cmath> | 
|  | 13 #include <cstdlib> | 
|  | 14 #include <limits> | 
|  | 15 #include <type_traits> | 
|  | 16 | 
|  | 17 #include "base/numerics/safe_conversions.h" | 
|  | 18 | 
|  | 19 namespace base { | 
|  | 20 namespace internal { | 
|  | 21 | 
|  | 22 // This is used for UnsignedAbs, where we need to support floating-point | 
|  | 23 // template instantiations even though we don't actually support the operations. | 
|  | 24 // However, there is no corresponding implementation of e.g. SafeUnsignedAbs, | 
|  | 25 // so the float versions will not compile. | 
|  | 26 template <typename Numeric, | 
|  | 27           bool IsInteger = std::is_integral<Numeric>::value, | 
|  | 28           bool IsFloat = std::is_floating_point<Numeric>::value> | 
|  | 29 struct UnsignedOrFloatForSize; | 
|  | 30 | 
|  | 31 template <typename Numeric> | 
|  | 32 struct UnsignedOrFloatForSize<Numeric, true, false> { | 
|  | 33   using type = typename std::make_unsigned<Numeric>::type; | 
|  | 34 }; | 
|  | 35 | 
|  | 36 template <typename Numeric> | 
|  | 37 struct UnsignedOrFloatForSize<Numeric, false, true> { | 
|  | 38   using type = Numeric; | 
|  | 39 }; | 
|  | 40 | 
|  | 41 // Wrap the unary operations to allow SFINAE when instantiating integrals versus | 
|  | 42 // floating points. These don't perform any overflow checking. Rather, they | 
|  | 43 // exhibit well-defined overflow semantics and rely on the caller to detect | 
|  | 44 // if an overflow occured. | 
|  | 45 | 
|  | 46 template <typename T, | 
|  | 47           typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> | 
|  | 48 constexpr T NegateWrapper(T value) { | 
|  | 49   using UnsignedT = typename std::make_unsigned<T>::type; | 
|  | 50   // This will compile to a NEG on Intel, and is normal negation on ARM. | 
|  | 51   return static_cast<T>(UnsignedT(0) - static_cast<UnsignedT>(value)); | 
|  | 52 } | 
|  | 53 | 
|  | 54 template < | 
|  | 55     typename T, | 
|  | 56     typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr> | 
|  | 57 constexpr T NegateWrapper(T value) { | 
|  | 58   return -value; | 
|  | 59 } | 
|  | 60 | 
|  | 61 template <typename T, | 
|  | 62           typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> | 
|  | 63 constexpr typename std::make_unsigned<T>::type InvertWrapper(T value) { | 
|  | 64   return ~value; | 
|  | 65 } | 
|  | 66 | 
|  | 67 template <typename T, | 
|  | 68           typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> | 
|  | 69 constexpr T AbsWrapper(T value) { | 
|  | 70   return static_cast<T>(SafeUnsignedAbs(value)); | 
|  | 71 } | 
|  | 72 | 
|  | 73 template < | 
|  | 74     typename T, | 
|  | 75     typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr> | 
|  | 76 constexpr T AbsWrapper(T value) { | 
|  | 77   return value < 0 ? -value : value; | 
|  | 78 } | 
|  | 79 | 
|  | 80 template <template <typename, typename, typename> class M, | 
|  | 81           typename L, | 
|  | 82           typename R> | 
|  | 83 struct MathWrapper { | 
|  | 84   using math = M<typename UnderlyingType<L>::type, | 
|  | 85                  typename UnderlyingType<R>::type, | 
|  | 86                  void>; | 
|  | 87   using type = typename math::result_type; | 
|  | 88 }; | 
|  | 89 | 
|  | 90 // These variadic templates work out the return types. | 
|  | 91 // TODO(jschuh): Rip all this out once we have C++14 non-trailing auto support. | 
|  | 92 template <template <typename, typename, typename> class M, | 
|  | 93           typename L, | 
|  | 94           typename R, | 
|  | 95           typename... Args> | 
|  | 96 struct ResultType; | 
|  | 97 | 
|  | 98 template <template <typename, typename, typename> class M, | 
|  | 99           typename L, | 
|  | 100           typename R> | 
|  | 101 struct ResultType<M, L, R> { | 
|  | 102   using type = typename MathWrapper<M, L, R>::type; | 
|  | 103 }; | 
|  | 104 | 
|  | 105 template <template <typename, typename, typename> class M, | 
|  | 106           typename L, | 
|  | 107           typename R, | 
|  | 108           typename... Args> | 
|  | 109 struct ResultType { | 
|  | 110   using type = | 
|  | 111       typename ResultType<M, typename ResultType<M, L, R>::type, Args...>::type; | 
|  | 112 }; | 
|  | 113 | 
|  | 114 // The following macros are just boilerplate for the standard arithmetic | 
|  | 115 // operator overloads and variadic function templates. A macro isn't the nicest | 
|  | 116 // solution, but it beats rewriting these over and over again. | 
|  | 117 #define BASE_NUMERIC_ARITHMETIC_VARIADIC(CLASS, CL_ABBR, OP_NAME)              \ | 
|  | 118   template <typename L, typename R, typename... Args>                          \ | 
|  | 119   CLASS##Numeric<typename ResultType<CLASS##OP_NAME##Op, L, R, Args...>::type> \ | 
|  | 120       CL_ABBR##OP_NAME(const L lhs, const R rhs, const Args... args) {         \ | 
|  | 121     return ChkMathOp<CLASS##OP_NAME##Op, L, R, Args...>(lhs, rhs, args...);    \ | 
|  | 122   } | 
|  | 123 | 
|  | 124 #define BASE_NUMERIC_ARITHMETIC_OPERATORS(CLASS, CL_ABBR, OP_NAME, OP, CMP_OP) \ | 
|  | 125   /* Binary arithmetic operator for all CheckedNumeric operations. */          \ | 
|  | 126   template <typename L, typename R,                                            \ | 
|  | 127             typename std::enable_if<IsCheckedOp<L, R>::value>::type* =         \ | 
|  | 128                 nullptr>                                                       \ | 
|  | 129   CheckedNumeric<typename MathWrapper<CLASS##OP_NAME##Op, L, R>::type>         \ | 
|  | 130   operator OP(const L lhs, const R rhs) {                                      \ | 
|  | 131     return decltype(lhs OP rhs)::template MathOp<CLASS##OP_NAME##Op>(lhs,      \ | 
|  | 132                                                                      rhs);     \ | 
|  | 133   }                                                                            \ | 
|  | 134   /* Assignment arithmetic operator implementation from CheckedNumeric. */     \ | 
|  | 135   template <typename L>                                                        \ | 
|  | 136   template <typename R>                                                        \ | 
|  | 137   CheckedNumeric<L>& CheckedNumeric<L>::operator CMP_OP(const R rhs) {         \ | 
|  | 138     return MathOp<CLASS##OP_NAME##Op>(rhs);                                    \ | 
|  | 139   }                                                                            \ | 
|  | 140   /* Variadic arithmetic functions that return CheckedNumeric. */              \ | 
|  | 141   BASE_NUMERIC_ARITHMETIC_VARIADIC(CLASS, CL_ABBR, OP_NAME) | 
|  | 142 | 
|  | 143 }  // namespace internal | 
|  | 144 }  // namespace base | 
|  | 145 | 
|  | 146 #endif  // BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_ | 
| OLD | NEW | 
|---|