1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* Provides saturation arithmetics for scalar types. */
9 #ifndef mozilla_Saturate_h
10 #define mozilla_Saturate_h
12 #include "mozilla/Attributes.h"
13 #include "mozilla/Move.h"
14 #include "mozilla/TypeTraits.h"
22 * |SaturateOp<T>| wraps scalar values for saturation arithmetics. Usage:
26 * ++SaturateOp<uint32_t>(value); // value is 2
27 * --SaturateOp<uint32_t>(value); // value is 1
28 * --SaturateOp<uint32_t>(value); // value is 0
29 * --SaturateOp<uint32_t>(value); // value is still 0
31 * Please add new operators when required.
33 * |SaturateOp<T>| will saturate at the minimum and maximum values of
34 * type T. If you need other bounds, implement a clamped-type class and
35 * specialize the type traits accordingly.
41 explicit SaturateOp(T
& aValue
)
44 // We should actually check for |std::is_scalar<T>::value| to be
45 // true, but this type trait is not available everywhere. Relax
46 // this assertion if you want to use floating point values as well.
47 static_assert(IsIntegral
<T
>::value
,
48 "Integral type required in instantiation");
51 // Add and subtract operators
53 T
operator+(const T
& aRhs
) const
55 return T(mValue
) += aRhs
;
58 T
operator-(const T
& aRhs
) const
60 return T(mValue
) -= aRhs
;
65 const T
& operator+=(const T
& aRhs
) const
67 const T min
= std::numeric_limits
<T
>::min();
68 const T max
= std::numeric_limits
<T
>::max();
70 if (aRhs
> static_cast<T
>(0)) {
71 mValue
= (max
- aRhs
) < mValue
? max
: mValue
+ aRhs
;
73 mValue
= (min
- aRhs
) > mValue
? min
: mValue
+ aRhs
;
78 const T
& operator-=(const T
& aRhs
) const
80 const T min
= std::numeric_limits
<T
>::min();
81 const T max
= std::numeric_limits
<T
>::max();
83 if (aRhs
> static_cast<T
>(0)) {
84 mValue
= (min
+ aRhs
) > mValue
? min
: mValue
- aRhs
;
86 mValue
= (max
+ aRhs
) < mValue
? max
: mValue
- aRhs
;
91 // Increment and decrement operators
93 const T
& operator++() const // prefix
95 return operator+=(static_cast<T
>(1));
98 T
operator++(int) const // postfix
100 const T
value(mValue
);
105 const T
& operator--() const // prefix
107 return operator-=(static_cast<T
>(1));
110 T
operator--(int) const // postfix
112 const T
value(mValue
);
118 SaturateOp(const SaturateOp
<T
>&) = delete;
119 SaturateOp(SaturateOp
<T
>&&) = delete;
120 SaturateOp
& operator=(const SaturateOp
<T
>&) = delete;
121 SaturateOp
& operator=(SaturateOp
<T
>&&) = delete;
127 * |Saturate<T>| is a value type for saturation arithmetics. It's
128 * build on top of |SaturateOp<T>|.
130 template <typename T
>
134 Saturate() = default;
135 MOZ_IMPLICIT
Saturate(const Saturate
<T
>&) = default;
137 MOZ_IMPLICIT
Saturate(Saturate
<T
>&& aValue
)
139 mValue
= std::move(aValue
.mValue
);
142 explicit Saturate(const T
& aValue
)
146 const T
& value() const
153 bool operator==(const Saturate
<T
>& aRhs
) const
155 return mValue
== aRhs
.mValue
;
158 bool operator!=(const Saturate
<T
>& aRhs
) const
160 return !operator==(aRhs
);
163 bool operator==(const T
& aRhs
) const
165 return mValue
== aRhs
;
168 bool operator!=(const T
& aRhs
) const
170 return !operator==(aRhs
);
173 // Assignment operators
175 Saturate
<T
>& operator=(const Saturate
<T
>&) = default;
177 Saturate
<T
>& operator=(Saturate
<T
>&& aRhs
)
179 mValue
= std::move(aRhs
.mValue
);
183 // Add and subtract operators
185 Saturate
<T
> operator+(const Saturate
<T
>& aRhs
) const
187 Saturate
<T
> lhs(mValue
);
188 return lhs
+= aRhs
.mValue
;
191 Saturate
<T
> operator+(const T
& aRhs
) const
193 Saturate
<T
> lhs(mValue
);
197 Saturate
<T
> operator-(const Saturate
<T
>& aRhs
) const
199 Saturate
<T
> lhs(mValue
);
200 return lhs
-= aRhs
.mValue
;
203 Saturate
<T
> operator-(const T
& aRhs
) const
205 Saturate
<T
> lhs(mValue
);
209 // Compound operators
211 Saturate
<T
>& operator+=(const Saturate
<T
>& aRhs
)
213 SaturateOp
<T
>(mValue
) += aRhs
.mValue
;
217 Saturate
<T
>& operator+=(const T
& aRhs
)
219 SaturateOp
<T
>(mValue
) += aRhs
;
223 Saturate
<T
>& operator-=(const Saturate
<T
>& aRhs
)
225 SaturateOp
<T
>(mValue
) -= aRhs
.mValue
;
229 Saturate
<T
>& operator-=(const T
& aRhs
)
231 SaturateOp
<T
>(mValue
) -= aRhs
;
235 // Increment and decrement operators
237 Saturate
<T
>& operator++() // prefix
239 ++SaturateOp
<T
>(mValue
);
243 Saturate
<T
> operator++(int) // postfix
245 return Saturate
<T
>(SaturateOp
<T
>(mValue
)++);
248 Saturate
<T
>& operator--() // prefix
250 --SaturateOp
<T
>(mValue
);
254 Saturate
<T
> operator--(int) // postfix
256 return Saturate
<T
>(SaturateOp
<T
>(mValue
)--);
263 } // namespace detail
265 typedef detail::Saturate
<int8_t> SaturateInt8
;
266 typedef detail::Saturate
<int16_t> SaturateInt16
;
267 typedef detail::Saturate
<int32_t> SaturateInt32
;
268 typedef detail::Saturate
<uint8_t> SaturateUint8
;
269 typedef detail::Saturate
<uint16_t> SaturateUint16
;
270 typedef detail::Saturate
<uint32_t> SaturateUint32
;
272 } // namespace mozilla
274 template<typename LhsT
, typename RhsT
>
276 operator==(LhsT aLhs
, const mozilla::detail::Saturate
<RhsT
>& aRhs
)
278 return aRhs
.operator==(static_cast<RhsT
>(aLhs
));
281 template<typename LhsT
, typename RhsT
>
283 operator!=(LhsT aLhs
, const mozilla::detail::Saturate
<RhsT
>& aRhs
)
285 return !(aLhs
== aRhs
);
288 #endif // mozilla_Saturate_h