xref: /aosp_15_r20/external/cronet/base/numerics/clamped_math.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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