2#include "overflow_int.hpp"
16template<std::
signed_
integral T>
17[[nodiscard]]
constexpr T saturate_add(T lhs, T rhs)
noexcept
19 using UT = std::make_unsigned_t<T>;
20 constexpr auto T_BIT =
sizeof(T) * CHAR_BIT;
24 if (overflow_add(lhs, rhs, &r)) {
25 r = sign_cast<T>((sign_cast<UT>(lhs) >> (T_BIT - 1)) + UT_MAX);
37template<std::
signed_
integral T>
38[[nodiscard]]
constexpr T saturate_sub(T lhs, T rhs)
noexcept
40 using UT = std::make_unsigned_t<T>;
41 constexpr auto T_BIT =
sizeof(T) * CHAR_BIT;
45 if (overflow_sub(lhs, rhs, &r)) {
46 r = sign_cast<T>((sign_cast<UT>(lhs) >> (T_BIT - 1)) + UT_MAX);
58template<std::
signed_
integral T>
59[[nodiscard]]
constexpr T saturate_mul(T lhs, T rhs)
noexcept
61 using UT = std::make_unsigned_t<T>;
62 constexpr auto T_BIT =
sizeof(T) * CHAR_BIT;
66 if (overflow_mul(lhs, rhs, &r)) {
67 r = sign_cast<T>((sign_cast<UT>(lhs ^ rhs) >> (T_BIT - 1)) + UT_MAX);
81template<std::
signed_
integral T>
82[[nodiscard]]
constexpr T saturate_div(T lhs, T rhs)
noexcept
84 using UT = std::make_unsigned_t<T>;
85 constexpr auto T_BIT =
sizeof(T) * CHAR_BIT;
89 if (overflow_div(lhs, rhs, &r)) {
90 r = sign_cast<T>((sign_cast<UT>(lhs ^ rhs) >> (T_BIT - 1)) + UT_MAX);
105template<std::
signed_
integral T>
106[[nodiscard]]
constexpr T saturate_mod(T lhs, T rhs)
110template<std::
signed_
integral T>
111[[nodiscard]]
constexpr T saturate_abs(T rhs)
noexcept
113 using UT = std::make_unsigned_t<T>;
117template<std::
signed_
integral T>
118struct saturated_int {
119 using value_type = T;
120 using unsigned_type = std::make_unsigned_t<value_type>;
122 constexpr static size_t value_bit =
sizeof(value_type) * CHAR_BIT;
125 constexpr static unsigned_type unsigned_int_max =
static_cast<unsigned_type
>(int_max);
129 constexpr saturated_int() noexcept = default;
130 constexpr saturated_int(saturated_int const &) noexcept = default;
131 constexpr saturated_int(saturated_int &&) noexcept = default;
132 constexpr saturated_int &operator=(saturated_int const &) noexcept = default;
133 constexpr saturated_int &operator=(saturated_int &&) noexcept = default;
134 [[nodiscard]] constexpr friend
bool operator==(saturated_int const &, saturated_int const &) noexcept = default;
135 [[nodiscard]] constexpr friend auto operator<=>(saturated_int const &, saturated_int const &) noexcept = default;
139 [[nodiscard]] constexpr friend saturated_int operator+(saturated_int const &lhs, saturated_int const &rhs) noexcept
141 return {saturate_add(lhs.v, rhs.v)};
144 [[nodiscard]]
constexpr friend saturated_int operator-(saturated_int
const &lhs, saturated_int
const &rhs)
noexcept
146 return {saturate_sub(lhs.v, rhs.v)};
149 [[nodiscard]]
constexpr friend saturated_int operator*(saturated_int
const &lhs, saturated_int
const &rhs)
noexcept
151 return {saturate_mul(lhs.v, rhs.v)};
154 [[nodiscard]]
constexpr friend saturated_int operator/(saturated_int
const &lhs, saturated_int
const &rhs)
noexcept
156 return {saturate_div{lhs.v, rhs.v};
DOXYGEN BUG.
Definition algorithm.hpp:13
geometry/margins.hpp
Definition cache.hpp:11