|  | // Copyright 2017 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_ | 
|  | #define BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_ | 
|  |  | 
|  | #include <stddef.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include <cassert> | 
|  | #include <climits> | 
|  | #include <cmath> | 
|  | #include <cstdlib> | 
|  | #include <limits> | 
|  | #include <type_traits> | 
|  |  | 
|  | #include "base/numerics/safe_conversions.h" | 
|  |  | 
|  | // Where available use builtin math overflow support on Clang and GCC. | 
|  | #if !defined(__native_client__) &&                         \ | 
|  | ((defined(__clang__) &&                                \ | 
|  | ((__clang_major__ > 3) ||                            \ | 
|  | (__clang_major__ == 3 && __clang_minor__ >= 4))) || \ | 
|  | (defined(__GNUC__) && __GNUC__ >= 5)) | 
|  | #include "base/numerics/safe_math_clang_gcc_impl.h" | 
|  | #define BASE_HAS_OPTIMIZED_SAFE_MATH (1) | 
|  | #else | 
|  | #define BASE_HAS_OPTIMIZED_SAFE_MATH (0) | 
|  | #endif | 
|  |  | 
|  | namespace base { | 
|  | namespace internal { | 
|  |  | 
|  | // These are the non-functioning boilerplate implementations of the optimized | 
|  | // safe math routines. | 
|  | #if !BASE_HAS_OPTIMIZED_SAFE_MATH | 
|  | template <typename T, typename U> | 
|  | struct CheckedAddFastOp { | 
|  | static const bool is_supported = false; | 
|  | template <typename V> | 
|  | static constexpr bool Do(T, U, V*) { | 
|  | // Force a compile failure if instantiated. | 
|  | return CheckOnFailure::template HandleFailure<bool>(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <typename T, typename U> | 
|  | struct CheckedSubFastOp { | 
|  | static const bool is_supported = false; | 
|  | template <typename V> | 
|  | static constexpr bool Do(T, U, V*) { | 
|  | // Force a compile failure if instantiated. | 
|  | return CheckOnFailure::template HandleFailure<bool>(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <typename T, typename U> | 
|  | struct CheckedMulFastOp { | 
|  | static const bool is_supported = false; | 
|  | template <typename V> | 
|  | static constexpr bool Do(T, U, V*) { | 
|  | // Force a compile failure if instantiated. | 
|  | return CheckOnFailure::template HandleFailure<bool>(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <typename T, typename U> | 
|  | struct ClampedAddFastOp { | 
|  | static const bool is_supported = false; | 
|  | template <typename V> | 
|  | static constexpr V Do(T, U) { | 
|  | // Force a compile failure if instantiated. | 
|  | return CheckOnFailure::template HandleFailure<V>(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <typename T, typename U> | 
|  | struct ClampedSubFastOp { | 
|  | static const bool is_supported = false; | 
|  | template <typename V> | 
|  | static constexpr V Do(T, U) { | 
|  | // Force a compile failure if instantiated. | 
|  | return CheckOnFailure::template HandleFailure<V>(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <typename T, typename U> | 
|  | struct ClampedMulFastOp { | 
|  | static const bool is_supported = false; | 
|  | template <typename V> | 
|  | static constexpr V Do(T, U) { | 
|  | // Force a compile failure if instantiated. | 
|  | return CheckOnFailure::template HandleFailure<V>(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <typename T> | 
|  | struct ClampedNegFastOp { | 
|  | static const bool is_supported = false; | 
|  | static constexpr T Do(T) { | 
|  | // Force a compile failure if instantiated. | 
|  | return CheckOnFailure::template HandleFailure<T>(); | 
|  | } | 
|  | }; | 
|  | #endif  // BASE_HAS_OPTIMIZED_SAFE_MATH | 
|  | #undef BASE_HAS_OPTIMIZED_SAFE_MATH | 
|  |  | 
|  | // This is used for UnsignedAbs, where we need to support floating-point | 
|  | // template instantiations even though we don't actually support the operations. | 
|  | // However, there is no corresponding implementation of e.g. SafeUnsignedAbs, | 
|  | // so the float versions will not compile. | 
|  | template <typename Numeric, | 
|  | bool IsInteger = std::is_integral<Numeric>::value, | 
|  | bool IsFloat = std::is_floating_point<Numeric>::value> | 
|  | struct UnsignedOrFloatForSize; | 
|  |  | 
|  | template <typename Numeric> | 
|  | struct UnsignedOrFloatForSize<Numeric, true, false> { | 
|  | using type = typename std::make_unsigned<Numeric>::type; | 
|  | }; | 
|  |  | 
|  | template <typename Numeric> | 
|  | struct UnsignedOrFloatForSize<Numeric, false, true> { | 
|  | using type = Numeric; | 
|  | }; | 
|  |  | 
|  | // Wrap the unary operations to allow SFINAE when instantiating integrals versus | 
|  | // floating points. These don't perform any overflow checking. Rather, they | 
|  | // exhibit well-defined overflow semantics and rely on the caller to detect | 
|  | // if an overflow occured. | 
|  |  | 
|  | template <typename T, | 
|  | typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> | 
|  | constexpr T NegateWrapper(T value) { | 
|  | using UnsignedT = typename std::make_unsigned<T>::type; | 
|  | // This will compile to a NEG on Intel, and is normal negation on ARM. | 
|  | return static_cast<T>(UnsignedT(0) - static_cast<UnsignedT>(value)); | 
|  | } | 
|  |  | 
|  | template < | 
|  | typename T, | 
|  | typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr> | 
|  | constexpr T NegateWrapper(T value) { | 
|  | return -value; | 
|  | } | 
|  |  | 
|  | template <typename T, | 
|  | typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> | 
|  | constexpr typename std::make_unsigned<T>::type InvertWrapper(T value) { | 
|  | return ~value; | 
|  | } | 
|  |  | 
|  | template <typename T, | 
|  | typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> | 
|  | constexpr T AbsWrapper(T value) { | 
|  | return static_cast<T>(SafeUnsignedAbs(value)); | 
|  | } | 
|  |  | 
|  | template < | 
|  | typename T, | 
|  | typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr> | 
|  | constexpr T AbsWrapper(T value) { | 
|  | return value < 0 ? -value : value; | 
|  | } | 
|  |  | 
|  | template <template <typename, typename, typename> class M, | 
|  | typename L, | 
|  | typename R> | 
|  | struct MathWrapper { | 
|  | using math = M<typename UnderlyingType<L>::type, | 
|  | typename UnderlyingType<R>::type, | 
|  | void>; | 
|  | using type = typename math::result_type; | 
|  | }; | 
|  |  | 
|  | // These variadic templates work out the return types. | 
|  | // TODO(jschuh): Rip all this out once we have C++14 non-trailing auto support. | 
|  | template <template <typename, typename, typename> class M, | 
|  | typename L, | 
|  | typename R, | 
|  | typename... Args> | 
|  | struct ResultType; | 
|  |  | 
|  | template <template <typename, typename, typename> class M, | 
|  | typename L, | 
|  | typename R> | 
|  | struct ResultType<M, L, R> { | 
|  | using type = typename MathWrapper<M, L, R>::type; | 
|  | }; | 
|  |  | 
|  | template <template <typename, typename, typename> class M, | 
|  | typename L, | 
|  | typename R, | 
|  | typename... Args> | 
|  | struct ResultType { | 
|  | using type = | 
|  | typename ResultType<M, typename ResultType<M, L, R>::type, Args...>::type; | 
|  | }; | 
|  |  | 
|  | // The following macros are just boilerplate for the standard arithmetic | 
|  | // operator overloads and variadic function templates. A macro isn't the nicest | 
|  | // solution, but it beats rewriting these over and over again. | 
|  | #define BASE_NUMERIC_ARITHMETIC_VARIADIC(CLASS, CL_ABBR, OP_NAME)       \ | 
|  | template <typename L, typename R, typename... Args>                   \ | 
|  | constexpr CLASS##Numeric<                                             \ | 
|  | typename ResultType<CLASS##OP_NAME##Op, L, R, Args...>::type>     \ | 
|  | CL_ABBR##OP_NAME(const L lhs, const R rhs, const Args... args) {  \ | 
|  | return CL_ABBR##MathOp<CLASS##OP_NAME##Op, L, R, Args...>(lhs, rhs, \ | 
|  | args...); \ | 
|  | } | 
|  |  | 
|  | #define BASE_NUMERIC_ARITHMETIC_OPERATORS(CLASS, CL_ABBR, OP_NAME, OP, CMP_OP) \ | 
|  | /* Binary arithmetic operator for all CLASS##Numeric operations. */          \ | 
|  | template <typename L, typename R,                                            \ | 
|  | typename std::enable_if<Is##CLASS##Op<L, R>::value>::type* =       \ | 
|  | nullptr>                                                       \ | 
|  | constexpr CLASS##Numeric<                                                    \ | 
|  | typename MathWrapper<CLASS##OP_NAME##Op, L, R>::type>                    \ | 
|  | operator OP(const L lhs, const R rhs) {                                      \ | 
|  | return decltype(lhs OP rhs)::template MathOp<CLASS##OP_NAME##Op>(lhs,      \ | 
|  | rhs);     \ | 
|  | }                                                                            \ | 
|  | /* Assignment arithmetic operator implementation from CLASS##Numeric. */     \ | 
|  | template <typename L>                                                        \ | 
|  | template <typename R>                                                        \ | 
|  | constexpr CLASS##Numeric<L>& CLASS##Numeric<L>::operator CMP_OP(             \ | 
|  | const R rhs) {                                                           \ | 
|  | return MathOp<CLASS##OP_NAME##Op>(rhs);                                    \ | 
|  | }                                                                            \ | 
|  | /* Variadic arithmetic functions that return CLASS##Numeric. */              \ | 
|  | BASE_NUMERIC_ARITHMETIC_VARIADIC(CLASS, CL_ABBR, OP_NAME) | 
|  |  | 
|  | }  // namespace internal | 
|  | }  // namespace base | 
|  |  | 
|  | #endif  // BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_ |