// 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_CLAMPED_MATH_H_ #define BASE_NUMERICS_CLAMPED_MATH_H_ #include #include #include #include "base/numerics/clamped_math_impl.h" namespace base { namespace internal { template class ClampedNumeric { static_assert(std::is_arithmetic::value, "ClampedNumeric: T must be a numeric type."); public: using type = T; constexpr ClampedNumeric() : value_(0) {} // Copy constructor. template constexpr ClampedNumeric(const ClampedNumeric& rhs) : value_(saturated_cast(rhs.value_)) {} template friend class ClampedNumeric; // This is not an explicit constructor because we implicitly upgrade regular // numerics to ClampedNumerics to make them easier to use. template constexpr ClampedNumeric(Src value) // NOLINT(runtime/explicit) : value_(saturated_cast(value)) { static_assert(std::is_arithmetic::value, "Argument must be numeric."); } // This is not an explicit constructor because we want a seamless conversion // from StrictNumeric types. template constexpr ClampedNumeric( StrictNumeric value) // NOLINT(runtime/explicit) : value_(saturated_cast(static_cast(value))) {} // Returns a ClampedNumeric of the specified type, cast from the current // ClampedNumeric, and saturated to the destination type. template constexpr ClampedNumeric::type> Cast() const { return *this; } // Prototypes for the supported arithmetic operator overloads. template constexpr ClampedNumeric& operator+=(const Src rhs); template constexpr ClampedNumeric& operator-=(const Src rhs); template constexpr ClampedNumeric& operator*=(const Src rhs); template constexpr ClampedNumeric& operator/=(const Src rhs); template constexpr ClampedNumeric& operator%=(const Src rhs); template constexpr ClampedNumeric& operator<<=(const Src rhs); template constexpr ClampedNumeric& operator>>=(const Src rhs); template constexpr ClampedNumeric& operator&=(const Src rhs); template constexpr ClampedNumeric& operator|=(const Src rhs); template constexpr ClampedNumeric& operator^=(const Src rhs); constexpr ClampedNumeric operator-() const { // The negation of two's complement int min is int min, so that's the // only overflow case where we will saturate. return ClampedNumeric(SaturatedNegWrapper(value_)); } constexpr ClampedNumeric operator~() const { return ClampedNumeric(InvertWrapper(value_)); } constexpr ClampedNumeric Abs() const { // The negation of two's complement int min is int min, so that's the // only overflow case where we will saturate. return ClampedNumeric(SaturatedAbsWrapper(value_)); } template constexpr ClampedNumeric::type> Max( const U rhs) const { using result_type = typename MathWrapper::type; return ClampedNumeric( ClampedMaxOp::Do(value_, Wrapper::value(rhs))); } template constexpr ClampedNumeric::type> Min( const U rhs) const { using result_type = typename MathWrapper::type; return ClampedNumeric( ClampedMinOp::Do(value_, Wrapper::value(rhs))); } // This function is available only for integral types. It returns an unsigned // integer of the same width as the source type, containing the absolute value // of the source, and properly handling signed min. constexpr ClampedNumeric::type> UnsignedAbs() const { return ClampedNumeric::type>( SafeUnsignedAbs(value_)); } constexpr ClampedNumeric& operator++() { *this += 1; return *this; } constexpr ClampedNumeric operator++(int) { ClampedNumeric value = *this; *this += 1; return value; } constexpr ClampedNumeric& operator--() { *this -= 1; return *this; } constexpr ClampedNumeric operator--(int) { ClampedNumeric value = *this; *this -= 1; return value; } // These perform the actual math operations on the ClampedNumerics. // Binary arithmetic operations. template