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