7#include "int_overflow.hpp"
8#include "../utility/utility.hpp"
9#include "../macros.hpp"
10#include <system_error>
17namespace hi::inline
v1 {
51template<
typename T, on_overflow_t OnOverflow>
70template<
typename T, on_overflow_t OnOverflow,
typename U>
71T safe_convert(U
const &rhs)
noexcept(OnOverflow != on_overflow_t::Throw)
75 hilet overflow = convert_overflow(rhs, &r);
76 return safe_handle_overflow<T, OnOverflow>(r, overflow, rhs >= 0);
79template<on_overflow_t OnOverflow,
typename T,
typename U>
80make_promote_t<T, U> safe_add(T
const &lhs, U
const &rhs)
noexcept(OnOverflow != on_overflow_t::Throw)
82 make_promote_t<T, U> r;
83 hilet lhs_ =
static_cast<make_promote_t<T, U>
>(lhs);
84 hilet rhs_ =
static_cast<make_promote_t<T, U>
>(rhs);
86 hilet overflow = add_overflow(lhs_, rhs_, &r);
87 return safe_handle_overflow<T, OnOverflow>(r, overflow, rhs_ >= 0);
90template<on_overflow_t OnOverflow,
typename T,
typename U>
91make_promote_t<T, U> safe_sub(T
const &lhs, U
const &rhs)
noexcept(OnOverflow != on_overflow_t::Throw)
93 make_promote_t<T, U> r;
94 hilet lhs_ =
static_cast<make_promote_t<T, U>
>(lhs);
95 hilet rhs_ =
static_cast<make_promote_t<T, U>
>(rhs);
97 hilet overflow = sub_overflow(lhs_, rhs_, &r);
98 return safe_handle_overflow<T, OnOverflow>(r, overflow, rhs_ >= 0);
101template<on_overflow_t OnOverflow,
typename T,
typename U>
102make_promote_t<T, U> safe_mul(T
const &lhs, U
const &rhs)
noexcept(OnOverflow != on_overflow_t::Throw)
104 make_promote_t<T, U> r;
105 hilet lhs_ =
static_cast<make_promote_t<T, U>
>(lhs);
106 hilet rhs_ =
static_cast<make_promote_t<T, U>
>(rhs);
109 return safe_handle_overflow<T, OnOverflow>(r, overflow, rhs_ >= 0);
112template<
typename T, on_overflow_t OnOverflow = on_overflow_t::Assert>
114 using value_type = T;
119 safe_int() : value(0) {}
120 ~safe_int() =
default;
121 safe_int(safe_int
const &) =
default;
122 safe_int(safe_int &&) =
default;
123 safe_int &operator=(safe_int
const &) =
default;
124 safe_int &operator=(safe_int &&) =
default;
126 explicit safe_int(std::integral
auto const &other)
noexcept(OnOverflow !=
on_overflow_t::Throw) :
127 value(safe_convert<T, OnOverflow>(other))
131 explicit safe_int(std::floating_point
auto const &other)
noexcept(OnOverflow !=
on_overflow_t::Throw) :
132 value(safe_convert<T, OnOverflow>(other))
136 template<
typename O, on_overflow_t OtherOnOverflow>
137 explicit safe_int(safe_int<O, OtherOnOverflow>
const &other)
noexcept(OnOverflow !=
on_overflow_t::Throw) :
138 value(safe_convert<T, OnOverflow>(other.value))
142 safe_int &operator=(std::integral
auto const &other)
noexcept(OnOverflow !=
on_overflow_t::Throw)
144 value = safe_convert<T, OnOverflow>(other);
148 template<
typename O, on_overflow_t OtherOnOverflow>
149 safe_int &operator=(safe_int<O, OtherOnOverflow>
const &other)
noexcept(OnOverflow !=
on_overflow_t::Throw)
151 value = safe_convert<T, OnOverflow>(other.value);
155 template<std::
integral O>
158 return safe_convert<O, OnOverflow>(value);
161 template<std::
floating_po
int O>
162 explicit operator O()
const noexcept
164 return static_cast<O
>(value);
168#define TEMPLATE(op) \
169 template<typename T, on_overflow_t TO, typename U, on_overflow_t UO> \
170 bool operator op(safe_int<T, TO> const &lhs, safe_int<U, UO> const &rhs) noexcept \
172 return lhs.value op rhs.value; \
175 template<typename T, on_overflow_t TO, typename U> \
176 bool operator op(safe_int<T, TO> const &lhs, U const &rhs) noexcept \
178 return lhs.value op rhs; \
180 template<typename T, typename U, on_overflow_t UO> \
181 bool operator op(T const &lhs, safe_int<U, UO> const &rhs) noexcept \
183 return lhs op rhs.value; \
194#define TEMPLATE(op, func) \
195 template<typename T, on_overflow_t TO, typename U, on_overflow_t UO> \
196 safe_int<make_promote_t<T, U>, TO | UO> operator op(safe_int<T, TO> const &lhs, safe_int<U, UO> const &rhs) noexcept( \
197 (TO | UO) != on_overflow_t::Throw) \
199 return safe_int<make_promote_t<T, U>, TO | UO>{func<TO | UO>(lhs.value, rhs.value)}; \
202 template<typename T, on_overflow_t TO, typename U> \
203 safe_int<make_promote_t<T, U>, TO> operator op(safe_int<T, TO> const &lhs, U const &rhs) noexcept( \
204 TO != on_overflow_t::Throw) \
206 return safe_int<make_promote_t<T, U>, TO>{func<TO>(lhs.value, rhs)}; \
209 template<typename T, typename U, on_overflow_t UO> \
210 safe_int<make_promote_t<T, U>, UO> operator op(T const &lhs, safe_int<U, UO> const &rhs) noexcept( \
211 UO != on_overflow_t::Throw) \
213 return safe_int<make_promote_t<T, U>, UO>{func<UO>(lhs, rhs.value)}; \
DOXYGEN BUG.
Definition algorithm.hpp:16
T safe_handle_overflow(T value, bool overflow, bool is_positive) noexcept(OnOverflow !=on_overflow_t::Throw)
Definition safe_int.hpp:52
bool mul_overflow(T lhs, T rhs, T *r) noexcept
Multiply with overflow detection.
Definition int_overflow.hpp:99
on_overflow_t
Definition safe_int.hpp:19
@ Axiom
On overflow assert and teminate in debug, assume in release.
Definition safe_int.hpp:27
@ Throw
On overflow throw an exception.
Definition safe_int.hpp:21
@ Assert
On overflow assert and terminate.
Definition safe_int.hpp:25
@ Saturate
On overflow saturate the result in the appropiate direction.
Definition safe_int.hpp:23
geometry/margins.hpp
Definition lookahead_iterator.hpp:5
Definition safe_int.hpp:113