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