7#include "../utility/utility.hpp"
8#include "../SIMD/module.hpp"
9#include "../macros.hpp"
29template<numeric_limited T>
33 using bound_type = simd<value_type, 2>;
48 if constexpr (std::is_floating_point_v<value_type>) {
55 hi_axiom(holds_invariant());
63 [[nodiscard]]
constexpr interval(value_type lower, value_type upper) noexcept : v(lower, -upper)
65 hi_axiom(holds_invariant());
73 [[nodiscard]]
constexpr static interval raw(bound_type bounds)
noexcept
77 hi_axiom(r.holds_invariant());
81 [[nodiscard]]
constexpr bool holds_invariant() const noexcept
90 [[nodiscard]]
constexpr value_type
lower() const noexcept
99 [[nodiscard]]
constexpr value_type
upper() const noexcept
108 [[nodiscard]]
constexpr value_type
delta() const noexcept
110 return upper() - lower();
117 [[nodiscard]]
constexpr bool is_value() const noexcept
126 [[nodiscard]]
constexpr bool is_range() const noexcept
133 template<numeric_limited T>
141 template<numeric_limited T>
151 operator bool() const noexcept
153 return v[0] != 0 or v[1] != 0;
156 [[nodiscard]]
constexpr interval operator-() const noexcept
158 return interval::raw(v.yx());
161 [[nodiscard]]
constexpr interval operator+(interval
const &rhs)
const noexcept
163 return interval::raw(v + rhs.v);
166 [[nodiscard]]
constexpr interval operator-(interval
const &rhs)
const noexcept
168 return *
this + (-rhs);
171 [[nodiscard]]
constexpr interval operator*(interval
const &rhs)
const noexcept
173 hilet ge_zero = ge(v, bound_type{});
174 hilet lt_zero = ~ge_zero;
176 hilet ac = (ge_zero & rhs.v.xx()) | (lt_zero & -rhs.v.yy());
177 hilet db = (ge_zero & rhs.v.yy()) | (lt_zero & -rhs.v.xx());
179 hilet ac_mul = ac * v;
180 hilet db_mul = db * v;
182 return raw(
min(ac_mul, db_mul.yx()));
189 hi_axiom(v[0] >= 0 and rhs.v[0] >= 0);
191 return raw(v * neg<0b10>(rhs.v));
194 [[nodiscard]]
constexpr interval operator/(
interval const &rhs)
const noexcept
196 if (rhs.v[0] <= 0 and 0 <= rhs.v[1]) {
201 hilet rhs_ge_zero = ge(rhs.v, bound_type{});
202 hilet rhs_lt_zero = ~rhs_ge_zero;
204 hilet b_ma = (rhs_ge_zero & v.yy()) | (rhs_lt_zero & -v.xx());
205 hilet a_mb = -b_ma.yx();
207 hilet a_mb_mul = a_mb / rhs.v;
208 hilet b_ma_mul = b_ma / rhs.v;
210 return raw(
min(a_mb, b_ma));
213 [[nodiscard]]
constexpr interval operator%(interval
const &rhs)
const noexcept
215 if (rhs.v[0] <= 0 and 0 <= rhs.v[1]) {
221 hilet rhs_abs = abs(rhs);
224 }
else if (v[1] > 0) {
227 return raw(rhs_abs.yy());
231 [[nodiscard]]
friend constexpr interval reciprocal(interval
const &rhs)
noexcept
233 if (rhs.v[0] <= 0 and 0 <= rhs.v[1]) {
238 return raw(bound_type::broadcast(value_type{-1}) / rhs.yx());
241 [[nodiscard]]
friend constexpr interval abs(interval
const &rhs)
noexcept
244 r[0] =
std::max({value_type{0}, rhs.v[0], rhs.v[1]});
245 r[1] =
std::min(rhs.v[0], rhs.v[1]);
249 [[nodiscard]]
friend constexpr interval square(interval
const &rhs)
noexcept
251 hilet abs_rhs = abs(rhs);
252 return abs_rhs.positive_mul(abs_rhs);
255 interval &operator+=(interval
const &rhs)
noexcept
257 return *
this = *
this + rhs;
260 interval &operator-=(interval
const &rhs)
noexcept
262 return *
this = *
this - rhs;
265 interval &
operator*=(interval
const &rhs)
noexcept
267 return *
this = *
this * rhs;
270 [[nodiscard]]
friend constexpr bool operator==(value_type
const &lhs, interval
const &rhs)
noexcept
272 return rhs.
lower() <= lhs and lhs <= rhs.
upper();
275 [[nodiscard]]
friend constexpr auto operator<=>(value_type
const &lhs, interval
const &rhs)
noexcept
277 if constexpr (std::is_floating_point_v<value_type>) {
278 if (lhs < rhs.
lower()) {
279 return std::partial_ordering::less;
280 }
else if (lhs > rhs.
upper()) {
281 return std::partial_ordering::greater;
282 }
else if (lhs >= rhs.
lower() and lhs <= rhs.
upper()) {
283 return std::partial_ordering::equivalent;
285 return std::partial_ordering::unordered;
288 if (lhs < rhs.
lower()) {
289 return std::weak_ordering::less;
290 }
else if (lhs > rhs.
upper()) {
291 return std::weak_ordering::greater;
293 return std::weak_ordering::equivalent;
305 return ge(v, other.v) == 0b11;
DOXYGEN BUG.
Definition algorithm.hpp:16
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
constexpr Lhs & operator*=(Lhs &lhs, Rhs const &rhs) noexcept
Inplace geometric translation.
Definition transform.hpp:432
Interval arithmetic.
Definition interval.hpp:30
constexpr bool is_range() const noexcept
Check if the interval is a range of values.
Definition interval.hpp:126
constexpr interval(value_type lower, value_type upper) noexcept
Construct an interval from a lower and upper bounds.
Definition interval.hpp:63
constexpr interval positive_mul(interval const &rhs) const noexcept
Multiply two positive intervals.
Definition interval.hpp:187
constexpr value_type delta() const noexcept
The distance between lower and upper bound.
Definition interval.hpp:108
constexpr value_type lower() const noexcept
Get the lower bound of the interval.
Definition interval.hpp:90
static constexpr interval raw(bound_type bounds) noexcept
Construct an interval from a bound_type value.
Definition interval.hpp:73
constexpr value_type upper() const noexcept
Get the upper bound of the interval.
Definition interval.hpp:99
constexpr bool is_fully_inside(interval const &other) const noexcept
Check if the current interval is fully inside the other interval.
Definition interval.hpp:303
constexpr bool type_contains_range() const noexcept
Check if a given type can hold all values in the interval.
Definition interval.hpp:134
constexpr bool range_contains_type() const noexcept
Check if all the values in a type is inside the interval.
Definition interval.hpp:142
constexpr interval() noexcept
Default construct an interval.
Definition interval.hpp:46
constexpr bool is_value() const noexcept
Check if the interval is one value.
Definition interval.hpp:117