| Index: base/numerics/safe_math_shared_impl.h | 
| diff --git a/base/numerics/safe_math_shared_impl.h b/base/numerics/safe_math_shared_impl.h | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..3e75bfecdea38aa0177fbf99ef34098a83f2ffd1 | 
| --- /dev/null | 
| +++ b/base/numerics/safe_math_shared_impl.h | 
| @@ -0,0 +1,146 @@ | 
| +// 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 <climits> | 
| +#include <cmath> | 
| +#include <cstdlib> | 
| +#include <limits> | 
| +#include <type_traits> | 
| + | 
| +#include "base/numerics/safe_conversions.h" | 
| + | 
| +namespace base { | 
| +namespace internal { | 
| + | 
| +// 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>                          \ | 
| +  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 ChkMathOp<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 CheckedNumeric operations. */          \ | 
| +  template <typename L, typename R,                                            \ | 
| +            typename std::enable_if<IsCheckedOp<L, R>::value>::type* =         \ | 
| +                nullptr>                                                       \ | 
| +  CheckedNumeric<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 CheckedNumeric. */     \ | 
| +  template <typename L>                                                        \ | 
| +  template <typename R>                                                        \ | 
| +  CheckedNumeric<L>& CheckedNumeric<L>::operator CMP_OP(const R rhs) {         \ | 
| +    return MathOp<CLASS##OP_NAME##Op>(rhs);                                    \ | 
| +  }                                                                            \ | 
| +  /* Variadic arithmetic functions that return CheckedNumeric. */              \ | 
| +  BASE_NUMERIC_ARITHMETIC_VARIADIC(CLASS, CL_ABBR, OP_NAME) | 
| + | 
| +}  // namespace internal | 
| +}  // namespace base | 
| + | 
| +#endif  // BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_ | 
|  |