1*6777b538SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_NUMERICS_CLAMPED_MATH_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_NUMERICS_CLAMPED_MATH_H_
7*6777b538SAndroid Build Coastguard Worker
8*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard Worker #include <limits>
11*6777b538SAndroid Build Coastguard Worker #include <type_traits>
12*6777b538SAndroid Build Coastguard Worker
13*6777b538SAndroid Build Coastguard Worker #include "base/numerics/clamped_math_impl.h"
14*6777b538SAndroid Build Coastguard Worker
15*6777b538SAndroid Build Coastguard Worker namespace base {
16*6777b538SAndroid Build Coastguard Worker namespace internal {
17*6777b538SAndroid Build Coastguard Worker
18*6777b538SAndroid Build Coastguard Worker template <typename T>
19*6777b538SAndroid Build Coastguard Worker class ClampedNumeric {
20*6777b538SAndroid Build Coastguard Worker static_assert(std::is_arithmetic_v<T>,
21*6777b538SAndroid Build Coastguard Worker "ClampedNumeric<T>: T must be a numeric type.");
22*6777b538SAndroid Build Coastguard Worker
23*6777b538SAndroid Build Coastguard Worker public:
24*6777b538SAndroid Build Coastguard Worker using type = T;
25*6777b538SAndroid Build Coastguard Worker
ClampedNumeric()26*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric() : value_(0) {}
27*6777b538SAndroid Build Coastguard Worker
28*6777b538SAndroid Build Coastguard Worker // Copy constructor.
29*6777b538SAndroid Build Coastguard Worker template <typename Src>
ClampedNumeric(const ClampedNumeric<Src> & rhs)30*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric(const ClampedNumeric<Src>& rhs)
31*6777b538SAndroid Build Coastguard Worker : value_(saturated_cast<T>(rhs.value_)) {}
32*6777b538SAndroid Build Coastguard Worker
33*6777b538SAndroid Build Coastguard Worker template <typename Src>
34*6777b538SAndroid Build Coastguard Worker friend class ClampedNumeric;
35*6777b538SAndroid Build Coastguard Worker
36*6777b538SAndroid Build Coastguard Worker // Strictly speaking, this is not necessary, but declaring this allows class
37*6777b538SAndroid Build Coastguard Worker // template argument deduction to be used so that it is possible to simply
38*6777b538SAndroid Build Coastguard Worker // write `ClampedNumeric(777)` instead of `ClampedNumeric<int>(777)`.
39*6777b538SAndroid Build Coastguard Worker // NOLINTNEXTLINE(google-explicit-constructor)
ClampedNumeric(T value)40*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric(T value) : value_(value) {}
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker // This is not an explicit constructor because we implicitly upgrade regular
43*6777b538SAndroid Build Coastguard Worker // numerics to ClampedNumerics to make them easier to use.
44*6777b538SAndroid Build Coastguard Worker template <typename Src>
45*6777b538SAndroid Build Coastguard Worker // NOLINTNEXTLINE(google-explicit-constructor)
ClampedNumeric(Src value)46*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric(Src value) : value_(saturated_cast<T>(value)) {
47*6777b538SAndroid Build Coastguard Worker static_assert(UnderlyingType<Src>::is_numeric, "Argument must be numeric.");
48*6777b538SAndroid Build Coastguard Worker }
49*6777b538SAndroid Build Coastguard Worker
50*6777b538SAndroid Build Coastguard Worker // This is not an explicit constructor because we want a seamless conversion
51*6777b538SAndroid Build Coastguard Worker // from StrictNumeric types.
52*6777b538SAndroid Build Coastguard Worker template <typename Src>
53*6777b538SAndroid Build Coastguard Worker // NOLINTNEXTLINE(google-explicit-constructor)
ClampedNumeric(StrictNumeric<Src> value)54*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric(StrictNumeric<Src> value)
55*6777b538SAndroid Build Coastguard Worker : value_(saturated_cast<T>(static_cast<Src>(value))) {}
56*6777b538SAndroid Build Coastguard Worker
57*6777b538SAndroid Build Coastguard Worker // Returns a ClampedNumeric of the specified type, cast from the current
58*6777b538SAndroid Build Coastguard Worker // ClampedNumeric, and saturated to the destination type.
59*6777b538SAndroid Build Coastguard Worker template <typename Dst>
Cast()60*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric<typename UnderlyingType<Dst>::type> Cast() const {
61*6777b538SAndroid Build Coastguard Worker return *this;
62*6777b538SAndroid Build Coastguard Worker }
63*6777b538SAndroid Build Coastguard Worker
64*6777b538SAndroid Build Coastguard Worker // Prototypes for the supported arithmetic operator overloads.
65*6777b538SAndroid Build Coastguard Worker template <typename Src>
66*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric& operator+=(const Src rhs);
67*6777b538SAndroid Build Coastguard Worker template <typename Src>
68*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric& operator-=(const Src rhs);
69*6777b538SAndroid Build Coastguard Worker template <typename Src>
70*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric& operator*=(const Src rhs);
71*6777b538SAndroid Build Coastguard Worker template <typename Src>
72*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric& operator/=(const Src rhs);
73*6777b538SAndroid Build Coastguard Worker template <typename Src>
74*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric& operator%=(const Src rhs);
75*6777b538SAndroid Build Coastguard Worker template <typename Src>
76*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric& operator<<=(const Src rhs);
77*6777b538SAndroid Build Coastguard Worker template <typename Src>
78*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric& operator>>=(const Src rhs);
79*6777b538SAndroid Build Coastguard Worker template <typename Src>
80*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric& operator&=(const Src rhs);
81*6777b538SAndroid Build Coastguard Worker template <typename Src>
82*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric& operator|=(const Src rhs);
83*6777b538SAndroid Build Coastguard Worker template <typename Src>
84*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric& operator^=(const Src rhs);
85*6777b538SAndroid Build Coastguard Worker
86*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric operator-() const {
87*6777b538SAndroid Build Coastguard Worker // The negation of two's complement int min is int min, so that's the
88*6777b538SAndroid Build Coastguard Worker // only overflow case where we will saturate.
89*6777b538SAndroid Build Coastguard Worker return ClampedNumeric<T>(SaturatedNegWrapper(value_));
90*6777b538SAndroid Build Coastguard Worker }
91*6777b538SAndroid Build Coastguard Worker
92*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric operator~() const {
93*6777b538SAndroid Build Coastguard Worker return ClampedNumeric<decltype(InvertWrapper(T()))>(InvertWrapper(value_));
94*6777b538SAndroid Build Coastguard Worker }
95*6777b538SAndroid Build Coastguard Worker
Abs()96*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric Abs() const {
97*6777b538SAndroid Build Coastguard Worker // The negation of two's complement int min is int min, so that's the
98*6777b538SAndroid Build Coastguard Worker // only overflow case where we will saturate.
99*6777b538SAndroid Build Coastguard Worker return ClampedNumeric<T>(SaturatedAbsWrapper(value_));
100*6777b538SAndroid Build Coastguard Worker }
101*6777b538SAndroid Build Coastguard Worker
102*6777b538SAndroid Build Coastguard Worker template <typename U>
Max(const U rhs)103*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric<typename MathWrapper<ClampedMaxOp, T, U>::type> Max(
104*6777b538SAndroid Build Coastguard Worker const U rhs) const {
105*6777b538SAndroid Build Coastguard Worker using result_type = typename MathWrapper<ClampedMaxOp, T, U>::type;
106*6777b538SAndroid Build Coastguard Worker return ClampedNumeric<result_type>(
107*6777b538SAndroid Build Coastguard Worker ClampedMaxOp<T, U>::Do(value_, Wrapper<U>::value(rhs)));
108*6777b538SAndroid Build Coastguard Worker }
109*6777b538SAndroid Build Coastguard Worker
110*6777b538SAndroid Build Coastguard Worker template <typename U>
Min(const U rhs)111*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric<typename MathWrapper<ClampedMinOp, T, U>::type> Min(
112*6777b538SAndroid Build Coastguard Worker const U rhs) const {
113*6777b538SAndroid Build Coastguard Worker using result_type = typename MathWrapper<ClampedMinOp, T, U>::type;
114*6777b538SAndroid Build Coastguard Worker return ClampedNumeric<result_type>(
115*6777b538SAndroid Build Coastguard Worker ClampedMinOp<T, U>::Do(value_, Wrapper<U>::value(rhs)));
116*6777b538SAndroid Build Coastguard Worker }
117*6777b538SAndroid Build Coastguard Worker
118*6777b538SAndroid Build Coastguard Worker // This function is available only for integral types. It returns an unsigned
119*6777b538SAndroid Build Coastguard Worker // integer of the same width as the source type, containing the absolute value
120*6777b538SAndroid Build Coastguard Worker // of the source, and properly handling signed min.
121*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric<typename UnsignedOrFloatForSize<T>::type>
UnsignedAbs()122*6777b538SAndroid Build Coastguard Worker UnsignedAbs() const {
123*6777b538SAndroid Build Coastguard Worker return ClampedNumeric<typename UnsignedOrFloatForSize<T>::type>(
124*6777b538SAndroid Build Coastguard Worker SafeUnsignedAbs(value_));
125*6777b538SAndroid Build Coastguard Worker }
126*6777b538SAndroid Build Coastguard Worker
127*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric& operator++() {
128*6777b538SAndroid Build Coastguard Worker *this += 1;
129*6777b538SAndroid Build Coastguard Worker return *this;
130*6777b538SAndroid Build Coastguard Worker }
131*6777b538SAndroid Build Coastguard Worker
132*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric operator++(int) {
133*6777b538SAndroid Build Coastguard Worker ClampedNumeric value = *this;
134*6777b538SAndroid Build Coastguard Worker *this += 1;
135*6777b538SAndroid Build Coastguard Worker return value;
136*6777b538SAndroid Build Coastguard Worker }
137*6777b538SAndroid Build Coastguard Worker
138*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric& operator--() {
139*6777b538SAndroid Build Coastguard Worker *this -= 1;
140*6777b538SAndroid Build Coastguard Worker return *this;
141*6777b538SAndroid Build Coastguard Worker }
142*6777b538SAndroid Build Coastguard Worker
143*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric operator--(int) {
144*6777b538SAndroid Build Coastguard Worker ClampedNumeric value = *this;
145*6777b538SAndroid Build Coastguard Worker *this -= 1;
146*6777b538SAndroid Build Coastguard Worker return value;
147*6777b538SAndroid Build Coastguard Worker }
148*6777b538SAndroid Build Coastguard Worker
149*6777b538SAndroid Build Coastguard Worker // These perform the actual math operations on the ClampedNumerics.
150*6777b538SAndroid Build Coastguard Worker // Binary arithmetic operations.
151*6777b538SAndroid Build Coastguard Worker template <template <typename, typename> class M, typename L, typename R>
MathOp(const L lhs,const R rhs)152*6777b538SAndroid Build Coastguard Worker static constexpr ClampedNumeric MathOp(const L lhs, const R rhs) {
153*6777b538SAndroid Build Coastguard Worker using Math = typename MathWrapper<M, L, R>::math;
154*6777b538SAndroid Build Coastguard Worker return ClampedNumeric<T>(
155*6777b538SAndroid Build Coastguard Worker Math::template Do<T>(Wrapper<L>::value(lhs), Wrapper<R>::value(rhs)));
156*6777b538SAndroid Build Coastguard Worker }
157*6777b538SAndroid Build Coastguard Worker
158*6777b538SAndroid Build Coastguard Worker // Assignment arithmetic operations.
159*6777b538SAndroid Build Coastguard Worker template <template <typename, typename> class M, typename R>
MathOp(const R rhs)160*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric& MathOp(const R rhs) {
161*6777b538SAndroid Build Coastguard Worker using Math = typename MathWrapper<M, T, R>::math;
162*6777b538SAndroid Build Coastguard Worker *this =
163*6777b538SAndroid Build Coastguard Worker ClampedNumeric<T>(Math::template Do<T>(value_, Wrapper<R>::value(rhs)));
164*6777b538SAndroid Build Coastguard Worker return *this;
165*6777b538SAndroid Build Coastguard Worker }
166*6777b538SAndroid Build Coastguard Worker
167*6777b538SAndroid Build Coastguard Worker template <typename Dst>
Dst()168*6777b538SAndroid Build Coastguard Worker constexpr operator Dst() const {
169*6777b538SAndroid Build Coastguard Worker return saturated_cast<typename ArithmeticOrUnderlyingEnum<Dst>::type>(
170*6777b538SAndroid Build Coastguard Worker value_);
171*6777b538SAndroid Build Coastguard Worker }
172*6777b538SAndroid Build Coastguard Worker
173*6777b538SAndroid Build Coastguard Worker // This method extracts the raw integer value without saturating it to the
174*6777b538SAndroid Build Coastguard Worker // destination type as the conversion operator does. This is useful when
175*6777b538SAndroid Build Coastguard Worker // e.g. assigning to an auto type or passing as a deduced template parameter.
RawValue()176*6777b538SAndroid Build Coastguard Worker constexpr T RawValue() const { return value_; }
177*6777b538SAndroid Build Coastguard Worker
178*6777b538SAndroid Build Coastguard Worker private:
179*6777b538SAndroid Build Coastguard Worker T value_;
180*6777b538SAndroid Build Coastguard Worker
181*6777b538SAndroid Build Coastguard Worker // These wrappers allow us to handle state the same way for both
182*6777b538SAndroid Build Coastguard Worker // ClampedNumeric and POD arithmetic types.
183*6777b538SAndroid Build Coastguard Worker template <typename Src>
184*6777b538SAndroid Build Coastguard Worker struct Wrapper {
valueWrapper185*6777b538SAndroid Build Coastguard Worker static constexpr typename UnderlyingType<Src>::type value(Src value) {
186*6777b538SAndroid Build Coastguard Worker return value;
187*6777b538SAndroid Build Coastguard Worker }
188*6777b538SAndroid Build Coastguard Worker };
189*6777b538SAndroid Build Coastguard Worker };
190*6777b538SAndroid Build Coastguard Worker
191*6777b538SAndroid Build Coastguard Worker // Convenience wrapper to return a new ClampedNumeric from the provided
192*6777b538SAndroid Build Coastguard Worker // arithmetic or ClampedNumericType.
193*6777b538SAndroid Build Coastguard Worker template <typename T>
MakeClampedNum(const T value)194*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric<typename UnderlyingType<T>::type> MakeClampedNum(
195*6777b538SAndroid Build Coastguard Worker const T value) {
196*6777b538SAndroid Build Coastguard Worker return value;
197*6777b538SAndroid Build Coastguard Worker }
198*6777b538SAndroid Build Coastguard Worker
199*6777b538SAndroid Build Coastguard Worker // These implement the variadic wrapper for the math operations.
200*6777b538SAndroid Build Coastguard Worker template <template <typename, typename> class M, typename L, typename R>
ClampMathOp(const L lhs,const R rhs)201*6777b538SAndroid Build Coastguard Worker constexpr ClampedNumeric<typename MathWrapper<M, L, R>::type> ClampMathOp(
202*6777b538SAndroid Build Coastguard Worker const L lhs,
203*6777b538SAndroid Build Coastguard Worker const R rhs) {
204*6777b538SAndroid Build Coastguard Worker using Math = typename MathWrapper<M, L, R>::math;
205*6777b538SAndroid Build Coastguard Worker return ClampedNumeric<typename Math::result_type>::template MathOp<M>(lhs,
206*6777b538SAndroid Build Coastguard Worker rhs);
207*6777b538SAndroid Build Coastguard Worker }
208*6777b538SAndroid Build Coastguard Worker
209*6777b538SAndroid Build Coastguard Worker // General purpose wrapper template for arithmetic operations.
210*6777b538SAndroid Build Coastguard Worker template <template <typename, typename> class M,
211*6777b538SAndroid Build Coastguard Worker typename L,
212*6777b538SAndroid Build Coastguard Worker typename R,
213*6777b538SAndroid Build Coastguard Worker typename... Args>
ClampMathOp(const L lhs,const R rhs,const Args...args)214*6777b538SAndroid Build Coastguard Worker constexpr auto ClampMathOp(const L lhs, const R rhs, const Args... args) {
215*6777b538SAndroid Build Coastguard Worker return ClampMathOp<M>(ClampMathOp<M>(lhs, rhs), args...);
216*6777b538SAndroid Build Coastguard Worker }
217*6777b538SAndroid Build Coastguard Worker
218*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Add, +, +=)
219*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Sub, -, -=)
220*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Mul, *, *=)
221*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Div, /, /=)
222*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Mod, %, %=)
223*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Lsh, <<, <<=)
224*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Rsh, >>, >>=)
225*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, And, &, &=)
226*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Or, |, |=)
227*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Xor, ^, ^=)
228*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_VARIADIC(Clamped, Clamp, Max)
229*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_VARIADIC(Clamped, Clamp, Min)
230*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsLess, <)
231*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsLessOrEqual, <=)
232*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsGreater, >)
233*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsGreaterOrEqual, >=)
234*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsEqual, ==)
235*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsNotEqual, !=)
236*6777b538SAndroid Build Coastguard Worker
237*6777b538SAndroid Build Coastguard Worker } // namespace internal
238*6777b538SAndroid Build Coastguard Worker
239*6777b538SAndroid Build Coastguard Worker using internal::ClampAdd;
240*6777b538SAndroid Build Coastguard Worker using internal::ClampAnd;
241*6777b538SAndroid Build Coastguard Worker using internal::ClampDiv;
242*6777b538SAndroid Build Coastguard Worker using internal::ClampedNumeric;
243*6777b538SAndroid Build Coastguard Worker using internal::ClampLsh;
244*6777b538SAndroid Build Coastguard Worker using internal::ClampMax;
245*6777b538SAndroid Build Coastguard Worker using internal::ClampMin;
246*6777b538SAndroid Build Coastguard Worker using internal::ClampMod;
247*6777b538SAndroid Build Coastguard Worker using internal::ClampMul;
248*6777b538SAndroid Build Coastguard Worker using internal::ClampOr;
249*6777b538SAndroid Build Coastguard Worker using internal::ClampRsh;
250*6777b538SAndroid Build Coastguard Worker using internal::ClampSub;
251*6777b538SAndroid Build Coastguard Worker using internal::ClampXor;
252*6777b538SAndroid Build Coastguard Worker using internal::MakeClampedNum;
253*6777b538SAndroid Build Coastguard Worker
254*6777b538SAndroid Build Coastguard Worker } // namespace base
255*6777b538SAndroid Build Coastguard Worker
256*6777b538SAndroid Build Coastguard Worker #endif // BASE_NUMERICS_CLAMPED_MATH_H_
257