10#include "rapid/numeric_array.hpp"
17namespace hi::inline v1 {
28template<numeric_limited T>
47 if constexpr (std::is_floating_point_v<value_type>) {
54 hi_axiom(holds_invariant());
62 [[nodiscard]]
constexpr interval(value_type lower, value_type upper) noexcept : v(lower, -upper)
64 hi_axiom(holds_invariant());
76 hi_axiom(r.holds_invariant());
80 [[nodiscard]]
constexpr bool holds_invariant() const noexcept
89 [[nodiscard]]
constexpr value_type
lower() const noexcept
98 [[nodiscard]]
constexpr value_type
upper() const noexcept
107 [[nodiscard]]
constexpr value_type
delta() const noexcept
109 return upper() - lower();
116 [[nodiscard]]
constexpr bool is_value() const noexcept
125 [[nodiscard]]
constexpr bool is_range() const noexcept
132 template<numeric_limited T>
140 template<numeric_limited T>
150 operator bool() const noexcept
152 return v[0] != 0 or v[1] != 0;
155 [[nodiscard]]
constexpr interval operator-() const noexcept
157 return interval::raw(v.yx());
160 [[nodiscard]]
constexpr interval operator+(interval
const &rhs)
const noexcept
162 return interval::raw(v + rhs.v);
165 [[nodiscard]]
constexpr interval operator-(interval
const &rhs)
const noexcept
167 return *
this + (-rhs);
170 [[nodiscard]]
constexpr interval operator*(interval
const &rhs)
const noexcept
172 hilet ge_zero = ge(v, bound_type{});
173 hilet lt_zero = ~ge_zero;
175 hilet ac = (ge_zero & rhs.v.xx()) | (lt_zero & -rhs.v.yy());
176 hilet db = (ge_zero & rhs.v.yy()) | (lt_zero & -rhs.v.xx());
178 hilet ac_mul = ac * v;
179 hilet db_mul = db * v;
181 return raw(
min(ac_mul, db_mul.yx()));
188 hi_axiom(v[0] >= 0 and rhs.v[0] >= 0);
190 return raw(v * neg<0b10>(rhs.v));
193 [[nodiscard]]
constexpr interval operator/(
interval const &rhs)
const noexcept
195 if (rhs.v[0] <= 0 and 0 <= rhs.v[1]) {
200 hilet rhs_ge_zero = ge(rhs.v, bound_type{});
201 hilet rhs_lt_zero = ~rhs_ge_zero;
203 hilet b_ma = (rhs_ge_zero & v.yy()) | (rhs_lt_zero & -v.xx());
204 hilet a_mb = -b_ma.yx();
206 hilet a_mb_mul = a_mb / rhs.v;
207 hilet b_ma_mul = b_ma / rhs.v;
209 return raw(
min(a_mb, b_ma));
212 [[nodiscard]]
constexpr interval operator%(interval
const &rhs)
const noexcept
214 if (rhs.v[0] <= 0 and 0 <= rhs.v[1]) {
220 hilet rhs_abs = abs(rhs);
223 }
else if (v[1] > 0) {
226 return raw(rhs_abs.yy());
230 [[nodiscard]]
friend constexpr interval reciprocal(interval
const &rhs)
noexcept
232 if (rhs.v[0] <= 0 and 0 <= rhs.v[1]) {
237 return raw(bound_type::broadcast(value_type{-1}) / rhs.yx());
240 [[nodiscard]]
friend constexpr interval abs(interval
const &rhs)
noexcept
243 r[0] =
std::max({value_type{0}, rhs.v[0], rhs.v[1]});
244 r[1] =
std::min(rhs.v[0], rhs.v[1]);
248 [[nodiscard]]
friend constexpr interval square(interval
const &rhs)
noexcept
250 hilet abs_rhs = abs(rhs);
251 return abs_rhs.positive_mul(abs_rhs);
254 interval &operator+=(interval
const &rhs)
noexcept
256 return *
this = *
this + rhs;
259 interval &operator-=(interval
const &rhs)
noexcept
261 return *
this = *
this - rhs;
264 interval &operator*=(interval
const &rhs)
noexcept
266 return *
this = *
this * rhs;
269 [[nodiscard]]
friend constexpr bool operator==(value_type
const &lhs, interval
const &rhs)
noexcept
271 return rhs.
lower() <= lhs and lhs <= rhs.
upper();
274 [[nodiscard]]
friend constexpr auto operator<=>(value_type
const &lhs, interval
const &rhs)
noexcept
276 if constexpr (std::is_floating_point_v<value_type>) {
277 if (lhs < rhs.
lower()) {
278 return std::partial_ordering::less;
279 }
else if (lhs > rhs.
upper()) {
280 return std::partial_ordering::greater;
281 }
else if (lhs >= rhs.
lower() and lhs <= rhs.
upper()) {
282 return std::partial_ordering::equivalent;
284 return std::partial_ordering::unordered;
287 if (lhs < rhs.
lower()) {
288 return std::weak_ordering::less;
289 }
else if (lhs > rhs.
upper()) {
290 return std::weak_ordering::greater;
292 return std::weak_ordering::equivalent;
304 return ge(v, other.v) == 0b11;
308using finterval = interval<float>;
309using dinterval = interval<double>;
This file includes required definitions.
#define hilet
Invariant should be the default for variables.
Definition required.hpp:23
Interval arithmetic.
Definition interval.hpp:29
constexpr bool is_range() const noexcept
Check if the interval is a range of values.
Definition interval.hpp:125
constexpr interval(value_type lower, value_type upper) noexcept
Construct an interval from a lower and upper bounds.
Definition interval.hpp:62
constexpr interval positive_mul(interval const &rhs) const noexcept
Multiply two positive intervals.
Definition interval.hpp:186
constexpr value_type delta() const noexcept
The distance between lower and upper bound.
Definition interval.hpp:107
constexpr value_type lower() const noexcept
Get the lower bound of the interval.
Definition interval.hpp:89
static constexpr interval raw(bound_type bounds) noexcept
Construct an interval from a bound_type value.
Definition interval.hpp:72
constexpr value_type upper() const noexcept
Get the upper bound of the interval.
Definition interval.hpp:98
constexpr bool is_fully_inside(interval const &other) const noexcept
Check if the current interval is fully inside the other interval.
Definition interval.hpp:302
constexpr bool type_contains_range() const noexcept
Check if a given type can hold all values in the interval.
Definition interval.hpp:133
constexpr bool range_contains_type() const noexcept
Check if all the values in a type is inside the interval.
Definition interval.hpp:141
constexpr interval() noexcept
Default construct an interval.
Definition interval.hpp:45
constexpr bool is_value() const noexcept
Check if the interval is one value.
Definition interval.hpp:116