7#include "utility/module.hpp"
8#include "SIMD/module.hpp"
15namespace hi::inline
v1 {
26template<numeric_limited T>
30 using bound_type = simd<value_type, 2>;
45 if constexpr (std::is_floating_point_v<value_type>) {
60 [[nodiscard]]
constexpr interval(value_type lower, value_type upper) noexcept : v(lower, -upper)
70 [[nodiscard]]
static constexpr interval raw(bound_type bounds)
noexcept
78 [[nodiscard]]
constexpr bool holds_invariant() const noexcept
87 [[nodiscard]]
constexpr value_type
lower() const noexcept
96 [[nodiscard]]
constexpr value_type
upper() const noexcept
105 [[nodiscard]]
constexpr value_type
delta() const noexcept
107 return upper() - lower();
114 [[nodiscard]]
constexpr bool is_value() const noexcept
123 [[nodiscard]]
constexpr bool is_range() const noexcept
130 template<numeric_limited T>
138 template<numeric_limited T>
148 operator bool() const noexcept
150 return v[0] != 0 or v[1] != 0;
153 [[nodiscard]]
constexpr interval operator-() const noexcept
155 return interval::raw(v.yx());
158 [[nodiscard]]
constexpr interval operator+(interval
const &rhs)
const noexcept
160 return interval::raw(v + rhs.v);
163 [[nodiscard]]
constexpr interval operator-(interval
const &rhs)
const noexcept
165 return *
this + (-rhs);
168 [[nodiscard]]
constexpr interval operator*(interval
const &rhs)
const noexcept
170 hilet ge_zero = ge(v, bound_type{});
171 hilet lt_zero = ~ge_zero;
173 hilet ac = (ge_zero & rhs.v.xx()) | (lt_zero & -rhs.v.yy());
174 hilet db = (ge_zero & rhs.v.yy()) | (lt_zero & -rhs.v.xx());
176 hilet ac_mul = ac * v;
177 hilet db_mul = db * v;
179 return raw(
min(ac_mul, db_mul.yx()));
186 hi_axiom(v[0] >= 0 and rhs.v[0] >= 0);
188 return raw(v * neg<0b10>(rhs.v));
191 [[nodiscard]]
constexpr interval operator/(
interval const &rhs)
const noexcept
193 if (rhs.v[0] <= 0 and 0 <= rhs.v[1]) {
198 hilet rhs_ge_zero = ge(rhs.v, bound_type{});
199 hilet rhs_lt_zero = ~rhs_ge_zero;
201 hilet b_ma = (rhs_ge_zero & v.yy()) | (rhs_lt_zero & -v.xx());
202 hilet a_mb = -b_ma.yx();
204 hilet a_mb_mul = a_mb / rhs.v;
205 hilet b_ma_mul = b_ma / rhs.v;
207 return raw(
min(a_mb, b_ma));
210 [[nodiscard]]
constexpr interval operator%(interval
const &rhs)
const noexcept
212 if (rhs.v[0] <= 0 and 0 <= rhs.v[1]) {
218 hilet rhs_abs = abs(rhs);
221 }
else if (v[1] > 0) {
224 return raw(rhs_abs.yy());
228 [[nodiscard]]
friend constexpr interval reciprocal(interval
const &rhs)
noexcept
230 if (rhs.v[0] <= 0 and 0 <= rhs.v[1]) {
235 return raw(bound_type::broadcast(value_type{-1}) / rhs.yx());
238 [[nodiscard]]
friend constexpr interval abs(interval
const &rhs)
noexcept
241 r[0] =
std::max({value_type{0}, rhs.v[0], rhs.v[1]});
242 r[1] =
std::min(rhs.v[0], rhs.v[1]);
246 [[nodiscard]]
friend constexpr interval
square(interval
const &rhs)
noexcept
248 hilet abs_rhs = abs(rhs);
249 return abs_rhs.positive_mul(abs_rhs);
252 interval &operator+=(interval
const &rhs)
noexcept
254 return *
this = *
this + rhs;
257 interval &operator-=(interval
const &rhs)
noexcept
259 return *
this = *
this - rhs;
262 interval &operator*=(interval
const &rhs)
noexcept
264 return *
this = *
this * rhs;
267 [[nodiscard]]
friend constexpr bool operator==(value_type
const &lhs, interval
const &rhs)
noexcept
269 return rhs.
lower() <= lhs and lhs <= rhs.
upper();
272 [[nodiscard]]
friend constexpr auto operator<=>(value_type
const &lhs, interval
const &rhs)
noexcept
274 if constexpr (std::is_floating_point_v<value_type>) {
275 if (lhs < rhs.
lower()) {
276 return std::partial_ordering::less;
277 }
else if (lhs > rhs.
upper()) {
278 return std::partial_ordering::greater;
279 }
else if (lhs >= rhs.
lower() and lhs <= rhs.
upper()) {
280 return std::partial_ordering::equivalent;
282 return std::partial_ordering::unordered;
285 if (lhs < rhs.
lower()) {
286 return std::weak_ordering::less;
287 }
else if (lhs > rhs.
upper()) {
288 return std::weak_ordering::greater;
290 return std::weak_ordering::equivalent;
302 return ge(v, other.v) == 0b11;
306using finterval = interval<float>;
307using dinterval = interval<double>;
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:238
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:13
@ square
<square> asian compatibility forms.
Interval arithmetic.
Definition interval.hpp:27
constexpr bool is_range() const noexcept
Check if the interval is a range of values.
Definition interval.hpp:123
constexpr interval(value_type lower, value_type upper) noexcept
Construct an interval from a lower and upper bounds.
Definition interval.hpp:60
constexpr interval positive_mul(interval const &rhs) const noexcept
Multiply two positive intervals.
Definition interval.hpp:184
constexpr value_type delta() const noexcept
The distance between lower and upper bound.
Definition interval.hpp:105
constexpr value_type lower() const noexcept
Get the lower bound of the interval.
Definition interval.hpp:87
static constexpr interval raw(bound_type bounds) noexcept
Construct an interval from a bound_type value.
Definition interval.hpp:70
constexpr value_type upper() const noexcept
Get the upper bound of the interval.
Definition interval.hpp:96
constexpr bool is_fully_inside(interval const &other) const noexcept
Check if the current interval is fully inside the other interval.
Definition interval.hpp:300
constexpr bool type_contains_range() const noexcept
Check if a given type can hold all values in the interval.
Definition interval.hpp:131
constexpr bool range_contains_type() const noexcept
Check if all the values in a type is inside the interval.
Definition interval.hpp:139
constexpr interval() noexcept
Default construct an interval.
Definition interval.hpp:43
constexpr bool is_value() const noexcept
Check if the interval is one value.
Definition interval.hpp:114