Skip to main content

int_interval/
traits.rs

1use core::{
2    fmt::Debug,
3    iter::Sum,
4    ops::{Add, Sub},
5};
6
7use crate::{OneTwo, ZeroOneTwo};
8
9pub(crate) mod forwarding;
10pub(crate) use forwarding::impl_co_forwarding;
11
12mod sealed;
13
14/// Built-in integer coordinate type accepted by closed-open intervals.
15pub trait IntPrimitive:
16    sealed::Int + Copy + Ord + Eq + Debug + Add<Output = Self> + Sub<Output = Self> + Sum<Self>
17{
18    fn as_f32(self) -> f32;
19    fn as_f64(self) -> f64;
20}
21
22impl<T> IntPrimitive for T
23where
24    T: sealed::Int + Copy + Ord + Eq + Debug + Add<Output = Self> + Sub<Output = Self> + Sum<Self>,
25{
26    #[inline]
27    fn as_f32(self) -> f32 {
28        sealed::Int::as_f32(self)
29    }
30
31    #[inline]
32    fn as_f64(self) -> f64 {
33        sealed::Int::as_f64(self)
34    }
35}
36
37/// Built-in unsigned integer type used for exact interval measures.
38pub trait UnsignedPrimitive:
39    sealed::Unsigned
40    + Copy
41    + Ord
42    + Eq
43    + Debug
44    + Default
45    + Add<Output = Self>
46    + Sub<Output = Self>
47    + Sum<Self>
48{
49    fn as_f32(self) -> f32;
50    fn as_f64(self) -> f64;
51}
52
53impl<T> UnsignedPrimitive for T
54where
55    T: sealed::Unsigned
56        + Copy
57        + Ord
58        + Eq
59        + Debug
60        + Default
61        + Add<Output = Self>
62        + Sub<Output = Self>
63        + Sum<Self>,
64{
65    #[inline]
66    fn as_f32(self) -> f32 {
67        sealed::Int::as_f32(self)
68    }
69
70    #[inline]
71    fn as_f64(self) -> f64 {
72        sealed::Int::as_f64(self)
73    }
74}
75
76/// Primitive types associated with a closed-open integer interval.
77pub trait COPrimitive {
78    type CoordType: IntPrimitive;
79    type MeasureType: UnsignedPrimitive;
80}
81
82/// Construction capability for a valid closed-open interval.
83///
84/// Implementations must preserve the invariant:
85///
86/// ```text
87/// start < end_excl
88/// ```
89pub trait COConstruct: COPrimitive + Sized {
90    /// Constructs `[start, end_excl)`, returning `None` for an empty or
91    /// reversed interval.
92    fn try_new(start: Self::CoordType, end_excl: Self::CoordType) -> Option<Self>;
93
94    /// Constructs `[start, end_excl)` without checking the interval invariant.
95    ///
96    /// # Safety
97    ///
98    /// The caller must guarantee that:
99    ///
100    /// ```text
101    /// start < end_excl
102    /// ```
103    unsafe fn new_unchecked(start: Self::CoordType, end_excl: Self::CoordType) -> Self;
104}
105
106/// Construction capability based on a midpoint and an exact interval measure.
107///
108/// `len` is represented by the interval's exact unsigned measure type.
109pub trait COMidpointConstruct: COConstruct {
110    /// Constructs an interval centered around `mid` with exact length `len`.
111    ///
112    /// Returns `None` when `len` is zero or when the resulting bounds cannot
113    /// be represented by `CoordType`.
114    fn checked_from_midpoint_len(mid: Self::CoordType, len: Self::MeasureType) -> Option<Self>;
115
116    /// Constructs an interval centered around `mid` with saturating endpoint
117    /// arithmetic.
118    ///
119    /// Returns `None` when `len` is zero or saturation collapses the result
120    /// into an empty interval.
121    fn saturating_from_midpoint_len(mid: Self::CoordType, len: Self::MeasureType) -> Option<Self>;
122}
123
124/// Boundary access capability for a closed-open interval.
125pub trait COBounds: COPrimitive + Copy + Ord + Eq + core::fmt::Debug {
126    /// Returns the inclusive lower bound.
127    fn start(self) -> Self::CoordType;
128
129    /// Returns the exclusive upper bound.
130    fn end_excl(self) -> Self::CoordType;
131
132    /// Returns the inclusive upper bound.
133    ///
134    /// This is the greatest coordinate contained in the interval.
135    fn end_incl(self) -> Self::CoordType;
136}
137
138/// Containment and overlap predicates for closed-open intervals.
139pub trait COPredicates: COBounds {
140    /// Returns whether `x` is contained in this interval.
141    fn contains(self, x: Self::CoordType) -> bool;
142
143    /// Returns whether `other` is fully contained in this interval.
144    fn contains_interval(self, other: Self) -> bool;
145
146    /// Returns whether this interval and `other` overlap with positive length.
147    fn intersects(self, other: Self) -> bool;
148
149    /// Returns whether this interval and `other` touch at exactly one boundary
150    /// without overlapping.
151    fn is_adjacent(self, other: Self) -> bool;
152
153    /// Returns whether this interval and `other` overlap or are adjacent.
154    fn is_contiguous_with(self, other: Self) -> bool;
155}
156
157/// Range projection capability for a closed-open interval.
158///
159/// The returned range has the same half-open semantics as the interval:
160///
161/// ```text
162/// [start, end_excl) -> start..end_excl
163/// ```
164pub trait CORange: COBounds + Sized {
165    /// Returns the standard-library half-open range represented by this
166    /// interval.
167    fn to_range(self) -> core::ops::Range<Self::CoordType>;
168
169    /// Returns the standard-library range used to iterate covered coordinates.
170    ///
171    /// This is equivalent to `self.to_range()`.
172    #[inline]
173    fn iter(self) -> core::ops::Range<Self::CoordType> {
174        self.to_range()
175    }
176}
177
178/// Algebraic operations for closed-open intervals.
179pub trait COAlgebra: COConstruct + COBounds + COPredicates {
180    /// Returns the overlapping region of two intervals, if any.
181    fn intersection(self, other: Self) -> Option<Self>;
182
183    /// Returns the smallest interval containing both intervals.
184    fn convex_hull(self, other: Self) -> Self;
185
186    /// Returns the interval strictly between two separated intervals.
187    ///
188    /// Returns `None` when the intervals overlap or are adjacent.
189    fn between(self, other: Self) -> Option<Self>;
190
191    /// Returns the union of two intervals.
192    ///
193    /// Contiguous intervals are merged into one interval; otherwise the two
194    /// intervals are returned in ascending order.
195    fn union(self, other: Self) -> OneTwo<Self>;
196
197    /// Returns `self \ other`.
198    ///
199    /// The result may contain zero, one, or two residual intervals.
200    fn difference(self, other: Self) -> ZeroOneTwo<Self>;
201
202    /// Returns the symmetric difference of two intervals.
203    ///
204    /// The result contains points covered by exactly one operand and may
205    /// contain zero, one, or two intervals.
206    fn symmetric_difference(self, other: Self) -> ZeroOneTwo<Self>;
207}
208
209/// Exact measure capability for a closed-open interval.
210pub trait COMeasure: COPrimitive {
211    /// Returns the exact interval length.
212    fn len(self) -> Self::MeasureType;
213}
214
215/// Representative-position capability for a closed-open interval.
216pub trait COMidpoint: COPrimitive {
217    /// Returns the midpoint coordinate, using floor rounding where required.
218    fn midpoint(self) -> Self::CoordType;
219}
220
221/// Exact checked Minkowski operations whose images remain closed-open
222/// integer intervals.
223pub trait COCheckedMinkowskiLinear: COPrimitive + Sized {
224    /// Returns the exact Minkowski sum `self + other`.
225    fn checked_minkowski_add(self, other: Self) -> Option<Self>;
226
227    /// Returns the exact Minkowski subtraction `self - other`.
228    fn checked_minkowski_sub(self, other: Self) -> Option<Self>;
229
230    /// Returns the exact translation `self + scalar`.
231    fn checked_minkowski_add_scalar(self, scalar: Self::CoordType) -> Option<Self>;
232
233    /// Returns the exact translation `self - scalar`.
234    fn checked_minkowski_sub_scalar(self, scalar: Self::CoordType) -> Option<Self>;
235}
236
237/// Checked interval hulls of non-linear Minkowski images.
238///
239/// For discrete integer intervals, multiplication and division may produce
240/// non-contiguous point sets. These methods return a containing interval hull,
241/// not necessarily an exact image.
242pub trait COCheckedMinkowskiHull: COPrimitive + Sized {
243    /// Returns the interval hull containing every point in `self * other`.
244    fn checked_minkowski_mul_hull(self, other: Self) -> Option<Self>;
245
246    /// Returns the interval hull containing every point in `self / other`.
247    fn checked_minkowski_div_hull(self, other: Self) -> Option<Self>;
248
249    /// Returns the interval hull containing every point in `self * scalar`.
250    fn checked_minkowski_mul_scalar_hull(self, scalar: Self::CoordType) -> Option<Self>;
251
252    /// Returns the interval hull containing every point in `self / scalar`.
253    fn checked_minkowski_div_scalar_hull(self, scalar: Self::CoordType) -> Option<Self>;
254}
255
256/// Saturating Minkowski operations whose results remain closed-open integer
257/// intervals after endpoint arithmetic is clamped to the representable domain.
258///
259/// These methods apply saturating arithmetic to the interval bounds rather
260/// than returning an error on overflow or underflow.
261///
262/// When saturation clips a bound, the returned interval is the representable
263/// saturated result, not necessarily the exact unconstrained mathematical
264/// image.
265///
266/// Returns `None` when saturation collapses the resulting interval into an
267/// empty or otherwise invalid closed-open interval.
268pub trait COSaturatingMinkowskiLinear: COPrimitive + Sized {
269    /// Returns the saturated Minkowski sum `self + other`.
270    ///
271    /// Both result bounds are computed with saturating addition.
272    fn saturating_minkowski_add(self, other: Self) -> Option<Self>;
273
274    /// Returns the saturated Minkowski subtraction `self - other`.
275    ///
276    /// Both result bounds are computed with saturating subtraction.
277    fn saturating_minkowski_sub(self, other: Self) -> Option<Self>;
278
279    /// Returns the saturated translation `self + scalar`.
280    ///
281    /// Both interval bounds are shifted with saturating addition.
282    fn saturating_minkowski_add_scalar(self, scalar: Self::CoordType) -> Option<Self>;
283
284    /// Returns the saturated translation `self - scalar`.
285    ///
286    /// Both interval bounds are shifted with saturating subtraction.
287    fn saturating_minkowski_sub_scalar(self, scalar: Self::CoordType) -> Option<Self>;
288}
289
290/// Saturating interval hulls of non-linear Minkowski images.
291///
292/// For discrete integer intervals, multiplication and division may produce
293/// non-contiguous point sets. These methods first compute a containing
294/// interval hull and apply saturating endpoint arithmetic where needed.
295///
296/// When saturation clips a bound, the returned interval is a representable
297/// saturated hull rather than the exact unconstrained mathematical image.
298///
299/// Returns `None` when the operation is undefined, such as division by zero,
300/// or when saturation collapses the resulting hull into an empty or otherwise
301/// invalid closed-open interval.
302pub trait COSaturatingMinkowskiHull: COPrimitive + Sized {
303    /// Returns the saturated interval hull of `self * other`.
304    ///
305    /// Endpoint products are computed with saturating multiplication.
306    fn saturating_minkowski_mul_hull(self, other: Self) -> Option<Self>;
307
308    /// Returns the saturated interval hull of `self / other`.
309    ///
310    /// Returns `None` when the divisor interval contains zero in a position
311    /// that makes the interval division undefined.
312    fn saturating_minkowski_div_hull(self, other: Self) -> Option<Self>;
313
314    /// Returns the saturated interval hull of `self * scalar`.
315    ///
316    /// Endpoint products are computed with saturating multiplication.
317    fn saturating_minkowski_mul_scalar_hull(self, scalar: Self::CoordType) -> Option<Self>;
318
319    /// Returns the saturated interval hull of `self / scalar`.
320    ///
321    /// Returns `None` when `scalar` is zero.
322    fn saturating_minkowski_div_scalar_hull(self, scalar: Self::CoordType) -> Option<Self>;
323}
324
325/// Complete closed-open integer interval capability required by interval sets.
326pub trait IntCO: COConstruct + COBounds + COPredicates + COAlgebra + COMeasure {}
327
328impl<T> IntCO for T where T: COConstruct + COBounds + COPredicates + COAlgebra + COMeasure {}