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