HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
saturated.hpp
1
2#include "overflow_int.hpp"
3#include <concepts>
4
5#pragma once
6
7namespace hi {
8inline namespace v1 {
9
16template<std::signed_integral T>
17[[nodiscard]] constexpr T saturate_add(T lhs, T rhs) noexcept
18{
19 using UT = std::make_unsigned_t<T>;
20 constexpr auto T_BIT = sizeof(T) * CHAR_BIT;
21 constexpr auto UT_MAX = sign_cast<UT>(std::numeric_limits<T>::max());
22
23 auto r = T{};
24 if (overflow_add(lhs, rhs, &r)) {
25 r = sign_cast<T>((sign_cast<UT>(lhs) >> (T_BIT - 1)) + UT_MAX);
26 }
27
28 return r;
29}
30
37template<std::signed_integral T>
38[[nodiscard]] constexpr T saturate_sub(T lhs, T rhs) noexcept
39{
40 using UT = std::make_unsigned_t<T>;
41 constexpr auto T_BIT = sizeof(T) * CHAR_BIT;
42 constexpr auto UT_MAX = sign_cast<UT>(std::numeric_limits<T>::max());
43
44 auto r = T{};
45 if (overflow_sub(lhs, rhs, &r)) {
46 r = sign_cast<T>((sign_cast<UT>(lhs) >> (T_BIT - 1)) + UT_MAX);
47 }
48
49 return r;
50}
51
58template<std::signed_integral T>
59[[nodiscard]] constexpr T saturate_mul(T lhs, T rhs) noexcept
60{
61 using UT = std::make_unsigned_t<T>;
62 constexpr auto T_BIT = sizeof(T) * CHAR_BIT;
63 constexpr auto UT_MAX = sign_cast<UT>(std::numeric_limits<T>::max());
64
65 auto r = T{};
66 if (overflow_mul(lhs, rhs, &r)) {
67 r = sign_cast<T>((sign_cast<UT>(lhs ^ rhs) >> (T_BIT - 1)) + UT_MAX);
68 }
69
70 return r;
71}
72
81template<std::signed_integral T>
82[[nodiscard]] constexpr T saturate_div(T lhs, T rhs) noexcept
83{
84 using UT = std::make_unsigned_t<T>;
85 constexpr auto T_BIT = sizeof(T) * CHAR_BIT;
86 constexpr auto UT_MAX = sign_cast<UT>(std::numeric_limits<T>::max());
87
88 auto r = T{};
89 if (overflow_div(lhs, rhs, &r)) {
90 r = sign_cast<T>((sign_cast<UT>(lhs ^ rhs) >> (T_BIT - 1)) + UT_MAX);
91 }
92
93 return r;
94}
95
105template<std::signed_integral T>
106[[nodiscard]] constexpr T saturate_mod(T lhs, T rhs)
107{
108}
109
110template<std::signed_integral T>
111[[nodiscard]] constexpr T saturate_abs(T rhs) noexcept
112{
113 using UT = std::make_unsigned_t<T>;
114
115}
116
117template<std::signed_integral T>
118struct saturated_int {
119 using value_type = T;
120 using unsigned_type = std::make_unsigned_t<value_type>;
121
122 constexpr static size_t value_bit = sizeof(value_type) * CHAR_BIT;
123 constexpr static value_type int_max = std::numeric_limits<value_type>::max();
124 constexpr static value_type int_min = std::numeric_limits<value_type>::min();
125 constexpr static unsigned_type unsigned_int_max = static_cast<unsigned_type>(int_max);
126
127 value_type v = 0;
128
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;
136
137
138
139 [[nodiscard]] constexpr friend saturated_int operator+(saturated_int const &lhs, saturated_int const &rhs) noexcept
140 {
141 return {saturate_add(lhs.v, rhs.v)};
142 }
143
144 [[nodiscard]] constexpr friend saturated_int operator-(saturated_int const &lhs, saturated_int const &rhs) noexcept
145 {
146 return {saturate_sub(lhs.v, rhs.v)};
147 }
148
149 [[nodiscard]] constexpr friend saturated_int operator*(saturated_int const &lhs, saturated_int const &rhs) noexcept
150 {
151 return {saturate_mul(lhs.v, rhs.v)};
152 }
153
154 [[nodiscard]] constexpr friend saturated_int operator/(saturated_int const &lhs, saturated_int const &rhs) noexcept
155 {
156 return {saturate_div{lhs.v, rhs.v};
157 }
158
159};
160
161
162}}
163
DOXYGEN BUG.
Definition algorithm.hpp:13
geometry/margins.hpp
Definition cache.hpp:11
T max(T... args)
T min(T... args)