16d528ed9Sopenharmony_ci// Copyright 2017 The Chromium Authors. All rights reserved. 26d528ed9Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 36d528ed9Sopenharmony_ci// found in the LICENSE file. 46d528ed9Sopenharmony_ci 56d528ed9Sopenharmony_ci#ifndef BASE_NUMERICS_CLAMPED_MATH_H_ 66d528ed9Sopenharmony_ci#define BASE_NUMERICS_CLAMPED_MATH_H_ 76d528ed9Sopenharmony_ci 86d528ed9Sopenharmony_ci#include <stddef.h> 96d528ed9Sopenharmony_ci 106d528ed9Sopenharmony_ci#include <limits> 116d528ed9Sopenharmony_ci#include <type_traits> 126d528ed9Sopenharmony_ci 136d528ed9Sopenharmony_ci#include "base/numerics/clamped_math_impl.h" 146d528ed9Sopenharmony_ci 156d528ed9Sopenharmony_cinamespace base { 166d528ed9Sopenharmony_cinamespace internal { 176d528ed9Sopenharmony_ci 186d528ed9Sopenharmony_citemplate <typename T> 196d528ed9Sopenharmony_ciclass ClampedNumeric { 206d528ed9Sopenharmony_ci static_assert(std::is_arithmetic<T>::value, 216d528ed9Sopenharmony_ci "ClampedNumeric<T>: T must be a numeric type."); 226d528ed9Sopenharmony_ci 236d528ed9Sopenharmony_ci public: 246d528ed9Sopenharmony_ci using type = T; 256d528ed9Sopenharmony_ci 266d528ed9Sopenharmony_ci constexpr ClampedNumeric() : value_(0) {} 276d528ed9Sopenharmony_ci 286d528ed9Sopenharmony_ci // Copy constructor. 296d528ed9Sopenharmony_ci template <typename Src> 306d528ed9Sopenharmony_ci constexpr ClampedNumeric(const ClampedNumeric<Src>& rhs) 316d528ed9Sopenharmony_ci : value_(saturated_cast<T>(rhs.value_)) {} 326d528ed9Sopenharmony_ci 336d528ed9Sopenharmony_ci template <typename Src> 346d528ed9Sopenharmony_ci friend class ClampedNumeric; 356d528ed9Sopenharmony_ci 366d528ed9Sopenharmony_ci // This is not an explicit constructor because we implicitly upgrade regular 376d528ed9Sopenharmony_ci // numerics to ClampedNumerics to make them easier to use. 386d528ed9Sopenharmony_ci template <typename Src> 396d528ed9Sopenharmony_ci constexpr ClampedNumeric(Src value) // NOLINT(runtime/explicit) 406d528ed9Sopenharmony_ci : value_(saturated_cast<T>(value)) { 416d528ed9Sopenharmony_ci static_assert(std::is_arithmetic<Src>::value, "Argument must be numeric."); 426d528ed9Sopenharmony_ci } 436d528ed9Sopenharmony_ci 446d528ed9Sopenharmony_ci // This is not an explicit constructor because we want a seamless conversion 456d528ed9Sopenharmony_ci // from StrictNumeric types. 466d528ed9Sopenharmony_ci template <typename Src> 476d528ed9Sopenharmony_ci constexpr ClampedNumeric( 486d528ed9Sopenharmony_ci StrictNumeric<Src> value) // NOLINT(runtime/explicit) 496d528ed9Sopenharmony_ci : value_(saturated_cast<T>(static_cast<Src>(value))) {} 506d528ed9Sopenharmony_ci 516d528ed9Sopenharmony_ci // Returns a ClampedNumeric of the specified type, cast from the current 526d528ed9Sopenharmony_ci // ClampedNumeric, and saturated to the destination type. 536d528ed9Sopenharmony_ci template <typename Dst> 546d528ed9Sopenharmony_ci constexpr ClampedNumeric<typename UnderlyingType<Dst>::type> Cast() const { 556d528ed9Sopenharmony_ci return *this; 566d528ed9Sopenharmony_ci } 576d528ed9Sopenharmony_ci 586d528ed9Sopenharmony_ci // Prototypes for the supported arithmetic operator overloads. 596d528ed9Sopenharmony_ci template <typename Src> 606d528ed9Sopenharmony_ci constexpr ClampedNumeric& operator+=(const Src rhs); 616d528ed9Sopenharmony_ci template <typename Src> 626d528ed9Sopenharmony_ci constexpr ClampedNumeric& operator-=(const Src rhs); 636d528ed9Sopenharmony_ci template <typename Src> 646d528ed9Sopenharmony_ci constexpr ClampedNumeric& operator*=(const Src rhs); 656d528ed9Sopenharmony_ci template <typename Src> 666d528ed9Sopenharmony_ci constexpr ClampedNumeric& operator/=(const Src rhs); 676d528ed9Sopenharmony_ci template <typename Src> 686d528ed9Sopenharmony_ci constexpr ClampedNumeric& operator%=(const Src rhs); 696d528ed9Sopenharmony_ci template <typename Src> 706d528ed9Sopenharmony_ci constexpr ClampedNumeric& operator<<=(const Src rhs); 716d528ed9Sopenharmony_ci template <typename Src> 726d528ed9Sopenharmony_ci constexpr ClampedNumeric& operator>>=(const Src rhs); 736d528ed9Sopenharmony_ci template <typename Src> 746d528ed9Sopenharmony_ci constexpr ClampedNumeric& operator&=(const Src rhs); 756d528ed9Sopenharmony_ci template <typename Src> 766d528ed9Sopenharmony_ci constexpr ClampedNumeric& operator|=(const Src rhs); 776d528ed9Sopenharmony_ci template <typename Src> 786d528ed9Sopenharmony_ci constexpr ClampedNumeric& operator^=(const Src rhs); 796d528ed9Sopenharmony_ci 806d528ed9Sopenharmony_ci constexpr ClampedNumeric operator-() const { 816d528ed9Sopenharmony_ci // The negation of two's complement int min is int min, so that's the 826d528ed9Sopenharmony_ci // only overflow case where we will saturate. 836d528ed9Sopenharmony_ci return ClampedNumeric<T>(SaturatedNegWrapper(value_)); 846d528ed9Sopenharmony_ci } 856d528ed9Sopenharmony_ci 866d528ed9Sopenharmony_ci constexpr ClampedNumeric operator~() const { 876d528ed9Sopenharmony_ci return ClampedNumeric<decltype(InvertWrapper(T()))>(InvertWrapper(value_)); 886d528ed9Sopenharmony_ci } 896d528ed9Sopenharmony_ci 906d528ed9Sopenharmony_ci constexpr ClampedNumeric Abs() const { 916d528ed9Sopenharmony_ci // The negation of two's complement int min is int min, so that's the 926d528ed9Sopenharmony_ci // only overflow case where we will saturate. 936d528ed9Sopenharmony_ci return ClampedNumeric<T>(SaturatedAbsWrapper(value_)); 946d528ed9Sopenharmony_ci } 956d528ed9Sopenharmony_ci 966d528ed9Sopenharmony_ci template <typename U> 976d528ed9Sopenharmony_ci constexpr ClampedNumeric<typename MathWrapper<ClampedMaxOp, T, U>::type> Max( 986d528ed9Sopenharmony_ci const U rhs) const { 996d528ed9Sopenharmony_ci using result_type = typename MathWrapper<ClampedMaxOp, T, U>::type; 1006d528ed9Sopenharmony_ci return ClampedNumeric<result_type>( 1016d528ed9Sopenharmony_ci ClampedMaxOp<T, U>::Do(value_, Wrapper<U>::value(rhs))); 1026d528ed9Sopenharmony_ci } 1036d528ed9Sopenharmony_ci 1046d528ed9Sopenharmony_ci template <typename U> 1056d528ed9Sopenharmony_ci constexpr ClampedNumeric<typename MathWrapper<ClampedMinOp, T, U>::type> Min( 1066d528ed9Sopenharmony_ci const U rhs) const { 1076d528ed9Sopenharmony_ci using result_type = typename MathWrapper<ClampedMinOp, T, U>::type; 1086d528ed9Sopenharmony_ci return ClampedNumeric<result_type>( 1096d528ed9Sopenharmony_ci ClampedMinOp<T, U>::Do(value_, Wrapper<U>::value(rhs))); 1106d528ed9Sopenharmony_ci } 1116d528ed9Sopenharmony_ci 1126d528ed9Sopenharmony_ci // This function is available only for integral types. It returns an unsigned 1136d528ed9Sopenharmony_ci // integer of the same width as the source type, containing the absolute value 1146d528ed9Sopenharmony_ci // of the source, and properly handling signed min. 1156d528ed9Sopenharmony_ci constexpr ClampedNumeric<typename UnsignedOrFloatForSize<T>::type> 1166d528ed9Sopenharmony_ci UnsignedAbs() const { 1176d528ed9Sopenharmony_ci return ClampedNumeric<typename UnsignedOrFloatForSize<T>::type>( 1186d528ed9Sopenharmony_ci SafeUnsignedAbs(value_)); 1196d528ed9Sopenharmony_ci } 1206d528ed9Sopenharmony_ci 1216d528ed9Sopenharmony_ci constexpr ClampedNumeric& operator++() { 1226d528ed9Sopenharmony_ci *this += 1; 1236d528ed9Sopenharmony_ci return *this; 1246d528ed9Sopenharmony_ci } 1256d528ed9Sopenharmony_ci 1266d528ed9Sopenharmony_ci constexpr ClampedNumeric operator++(int) { 1276d528ed9Sopenharmony_ci ClampedNumeric value = *this; 1286d528ed9Sopenharmony_ci *this += 1; 1296d528ed9Sopenharmony_ci return value; 1306d528ed9Sopenharmony_ci } 1316d528ed9Sopenharmony_ci 1326d528ed9Sopenharmony_ci constexpr ClampedNumeric& operator--() { 1336d528ed9Sopenharmony_ci *this -= 1; 1346d528ed9Sopenharmony_ci return *this; 1356d528ed9Sopenharmony_ci } 1366d528ed9Sopenharmony_ci 1376d528ed9Sopenharmony_ci constexpr ClampedNumeric operator--(int) { 1386d528ed9Sopenharmony_ci ClampedNumeric value = *this; 1396d528ed9Sopenharmony_ci *this -= 1; 1406d528ed9Sopenharmony_ci return value; 1416d528ed9Sopenharmony_ci } 1426d528ed9Sopenharmony_ci 1436d528ed9Sopenharmony_ci // These perform the actual math operations on the ClampedNumerics. 1446d528ed9Sopenharmony_ci // Binary arithmetic operations. 1456d528ed9Sopenharmony_ci template <template <typename, typename, typename> class M, 1466d528ed9Sopenharmony_ci typename L, 1476d528ed9Sopenharmony_ci typename R> 1486d528ed9Sopenharmony_ci static constexpr ClampedNumeric MathOp(const L lhs, const R rhs) { 1496d528ed9Sopenharmony_ci using Math = typename MathWrapper<M, L, R>::math; 1506d528ed9Sopenharmony_ci return ClampedNumeric<T>( 1516d528ed9Sopenharmony_ci Math::template Do<T>(Wrapper<L>::value(lhs), Wrapper<R>::value(rhs))); 1526d528ed9Sopenharmony_ci } 1536d528ed9Sopenharmony_ci 1546d528ed9Sopenharmony_ci // Assignment arithmetic operations. 1556d528ed9Sopenharmony_ci template <template <typename, typename, typename> class M, typename R> 1566d528ed9Sopenharmony_ci constexpr ClampedNumeric& MathOp(const R rhs) { 1576d528ed9Sopenharmony_ci using Math = typename MathWrapper<M, T, R>::math; 1586d528ed9Sopenharmony_ci *this = 1596d528ed9Sopenharmony_ci ClampedNumeric<T>(Math::template Do<T>(value_, Wrapper<R>::value(rhs))); 1606d528ed9Sopenharmony_ci return *this; 1616d528ed9Sopenharmony_ci } 1626d528ed9Sopenharmony_ci 1636d528ed9Sopenharmony_ci template <typename Dst> 1646d528ed9Sopenharmony_ci constexpr operator Dst() const { 1656d528ed9Sopenharmony_ci return saturated_cast<typename ArithmeticOrUnderlyingEnum<Dst>::type>( 1666d528ed9Sopenharmony_ci value_); 1676d528ed9Sopenharmony_ci } 1686d528ed9Sopenharmony_ci 1696d528ed9Sopenharmony_ci // This method extracts the raw integer value without saturating it to the 1706d528ed9Sopenharmony_ci // destination type as the conversion operator does. This is useful when 1716d528ed9Sopenharmony_ci // e.g. assigning to an auto type or passing as a deduced template parameter. 1726d528ed9Sopenharmony_ci constexpr T RawValue() const { return value_; } 1736d528ed9Sopenharmony_ci 1746d528ed9Sopenharmony_ci private: 1756d528ed9Sopenharmony_ci T value_; 1766d528ed9Sopenharmony_ci 1776d528ed9Sopenharmony_ci // These wrappers allow us to handle state the same way for both 1786d528ed9Sopenharmony_ci // ClampedNumeric and POD arithmetic types. 1796d528ed9Sopenharmony_ci template <typename Src> 1806d528ed9Sopenharmony_ci struct Wrapper { 1816d528ed9Sopenharmony_ci static constexpr Src value(Src value) { 1826d528ed9Sopenharmony_ci return static_cast<typename UnderlyingType<Src>::type>(value); 1836d528ed9Sopenharmony_ci } 1846d528ed9Sopenharmony_ci }; 1856d528ed9Sopenharmony_ci}; 1866d528ed9Sopenharmony_ci 1876d528ed9Sopenharmony_ci// Convience wrapper to return a new ClampedNumeric from the provided arithmetic 1886d528ed9Sopenharmony_ci// or ClampedNumericType. 1896d528ed9Sopenharmony_citemplate <typename T> 1906d528ed9Sopenharmony_ciconstexpr ClampedNumeric<typename UnderlyingType<T>::type> MakeClampedNum( 1916d528ed9Sopenharmony_ci const T value) { 1926d528ed9Sopenharmony_ci return value; 1936d528ed9Sopenharmony_ci} 1946d528ed9Sopenharmony_ci 1956d528ed9Sopenharmony_ci// Overload the ostream output operator to make logging work nicely. 1966d528ed9Sopenharmony_citemplate <typename T> 1976d528ed9Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const ClampedNumeric<T>& value) { 1986d528ed9Sopenharmony_ci os << static_cast<T>(value); 1996d528ed9Sopenharmony_ci return os; 2006d528ed9Sopenharmony_ci} 2016d528ed9Sopenharmony_ci 2026d528ed9Sopenharmony_ci// These implement the variadic wrapper for the math operations. 2036d528ed9Sopenharmony_citemplate <template <typename, typename, typename> class M, 2046d528ed9Sopenharmony_ci typename L, 2056d528ed9Sopenharmony_ci typename R> 2066d528ed9Sopenharmony_ciconstexpr ClampedNumeric<typename MathWrapper<M, L, R>::type> ClampMathOp( 2076d528ed9Sopenharmony_ci const L lhs, 2086d528ed9Sopenharmony_ci const R rhs) { 2096d528ed9Sopenharmony_ci using Math = typename MathWrapper<M, L, R>::math; 2106d528ed9Sopenharmony_ci return ClampedNumeric<typename Math::result_type>::template MathOp<M>(lhs, 2116d528ed9Sopenharmony_ci rhs); 2126d528ed9Sopenharmony_ci} 2136d528ed9Sopenharmony_ci 2146d528ed9Sopenharmony_ci// General purpose wrapper template for arithmetic operations. 2156d528ed9Sopenharmony_citemplate <template <typename, typename, typename> class M, 2166d528ed9Sopenharmony_ci typename L, 2176d528ed9Sopenharmony_ci typename R, 2186d528ed9Sopenharmony_ci typename... Args> 2196d528ed9Sopenharmony_ciconstexpr ClampedNumeric<typename ResultType<M, L, R, Args...>::type> 2206d528ed9Sopenharmony_ciClampMathOp(const L lhs, const R rhs, const Args... args) { 2216d528ed9Sopenharmony_ci return ClampMathOp<M>(ClampMathOp<M>(lhs, rhs), args...); 2226d528ed9Sopenharmony_ci} 2236d528ed9Sopenharmony_ci 2246d528ed9Sopenharmony_ciBASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Add, +, +=) 2256d528ed9Sopenharmony_ciBASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Sub, -, -=) 2266d528ed9Sopenharmony_ciBASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Mul, *, *=) 2276d528ed9Sopenharmony_ciBASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Div, /, /=) 2286d528ed9Sopenharmony_ciBASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Mod, %, %=) 2296d528ed9Sopenharmony_ciBASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Lsh, <<, <<=) 2306d528ed9Sopenharmony_ciBASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Rsh, >>, >>=) 2316d528ed9Sopenharmony_ciBASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, And, &, &=) 2326d528ed9Sopenharmony_ciBASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Or, |, |=) 2336d528ed9Sopenharmony_ciBASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Xor, ^, ^=) 2346d528ed9Sopenharmony_ciBASE_NUMERIC_ARITHMETIC_VARIADIC(Clamped, Clamp, Max) 2356d528ed9Sopenharmony_ciBASE_NUMERIC_ARITHMETIC_VARIADIC(Clamped, Clamp, Min) 2366d528ed9Sopenharmony_ciBASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsLess, <) 2376d528ed9Sopenharmony_ciBASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsLessOrEqual, <=) 2386d528ed9Sopenharmony_ciBASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsGreater, >) 2396d528ed9Sopenharmony_ciBASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsGreaterOrEqual, >=) 2406d528ed9Sopenharmony_ciBASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsEqual, ==) 2416d528ed9Sopenharmony_ciBASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsNotEqual, !=) 2426d528ed9Sopenharmony_ci 2436d528ed9Sopenharmony_ci} // namespace internal 2446d528ed9Sopenharmony_ci 2456d528ed9Sopenharmony_ciusing internal::ClampAdd; 2466d528ed9Sopenharmony_ciusing internal::ClampAnd; 2476d528ed9Sopenharmony_ciusing internal::ClampDiv; 2486d528ed9Sopenharmony_ciusing internal::ClampedNumeric; 2496d528ed9Sopenharmony_ciusing internal::ClampLsh; 2506d528ed9Sopenharmony_ciusing internal::ClampMax; 2516d528ed9Sopenharmony_ciusing internal::ClampMin; 2526d528ed9Sopenharmony_ciusing internal::ClampMod; 2536d528ed9Sopenharmony_ciusing internal::ClampMul; 2546d528ed9Sopenharmony_ciusing internal::ClampOr; 2556d528ed9Sopenharmony_ciusing internal::ClampRsh; 2566d528ed9Sopenharmony_ciusing internal::ClampSub; 2576d528ed9Sopenharmony_ciusing internal::ClampXor; 2586d528ed9Sopenharmony_ciusing internal::MakeClampedNum; 2596d528ed9Sopenharmony_ci 2606d528ed9Sopenharmony_ci} // namespace base 2616d528ed9Sopenharmony_ci 2626d528ed9Sopenharmony_ci#endif // BASE_NUMERICS_CLAMPED_MATH_H_ 263