inter_val/interval.rs
1use crate::bound_type::{Left, Right};
2use crate::traits::{BoundaryOf, Flip, IntoGeneral};
3use crate::{Bound, Exclusive, Inclusive, LeftBounded, RightBounded};
4
5/// Return type of `Interval::union()`.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub struct IntervalUnion<T, L: Flip, R: Flip> {
8 pub span: Interval<T, L, R>,
9 pub gap: Option<Interval<T, R::Flip, L::Flip>>,
10}
11impl<T, L: Flip, R: Flip> IntervalUnion<T, L, R> {
12 pub fn into_vec(self) -> Vec<Interval<T, L, R>> {
13 self.into_iter().collect()
14 }
15}
16impl<T, L: Flip, R: Flip> IntoIterator for IntervalUnion<T, L, R> {
17 type Item = Interval<T, L, R>;
18 type IntoIter = std::vec::IntoIter<Self::Item>;
19 fn into_iter(self) -> Self::IntoIter {
20 if let Some(gap) = self.gap {
21 let first = Interval {
22 left: self.span.left,
23 right: gap.left.flip(),
24 };
25 let second = Interval {
26 left: gap.right.flip(),
27 right: self.span.right,
28 };
29 vec![first, second].into_iter()
30 } else {
31 vec![self.span].into_iter()
32 }
33 }
34}
35
36/// Return type of `Interval::difference()`.
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38pub struct IntervalDifference<T, L: Flip, R: Flip> {
39 pub lower: Option<Interval<T, L, L::Flip>>,
40 pub upper: Option<Interval<T, R::Flip, R>>,
41}
42impl<T, L: Flip<Flip = R>, R: Flip<Flip = L>> IntervalDifference<T, L, R> {
43 pub fn into_vec(self) -> Vec<Interval<T, L, R>> {
44 self.into_iter().collect()
45 }
46}
47impl<T, L: Flip<Flip = R>, R: Flip<Flip = L>> IntoIterator for IntervalDifference<T, L, R> {
48 type Item = Interval<T, L, R>;
49 type IntoIter =
50 std::iter::Chain<std::option::IntoIter<Self::Item>, std::option::IntoIter<Self::Item>>;
51 fn into_iter(self) -> Self::IntoIter {
52 self.lower.into_iter().chain(self.upper)
53 }
54}
55
56fn is_valid_interval<T, L, R>(left: &LeftBounded<T, L>, right: &RightBounded<T, R>) -> bool
57where
58 T: PartialOrd,
59 L: BoundaryOf<Left>,
60 R: BoundaryOf<Right>,
61{
62 left.contains(&right.limit) && right.contains(&left.limit)
63}
64
65/// Interval like *[a, b]*, *(a, b)*, *[a, b)*, and *(a, b]* for any `PartialOrd` type.
66///
67/// * `T`: Numeric type bounding real number line. `T` should implements `PartialOrd`. `NaN` safety is not guaranteed when `T` is floating point type.
68/// * `L`: Left boundary type. Specify one of [`Inclusive`], [`Exclusive`], or [`BoundType`](crate::BoundType).
69/// * `R`: Right boundary type. Specify one of [`Inclusive`] [`Exclusive`], or [`BoundType`](crate::BoundType).
70/// * `Interval<T>` (= `Interval<T, Inclusive, Inclusive>`) represents a closed interval, i.e., *[a, b]*.
71/// * `Interval<T, Exclusive>` (= `Interval<T, Exclusive, Exclusive>`) represents a open interval, i.e., *(a, b)*.
72/// * `Interval<T, Inclusive, Exclusive>` represents a right half-open interval, i.e., *[a, b)*.
73/// * `Interval<T, Exclusive, Inclusive>` represents a left half-open interval, i.e., *(a, b]*.
74/// * `Interval<T, BoundType>` represents any of the above.
75///
76/// This type is considered as an interval on ℝ (real number line), even if an integer type is specified for `T`.
77///
78/// # Memory cost
79/// ```
80/// use inter_val::{Interval, Exclusive, Inclusive, BoundType};
81/// use std::mem::size_of;
82///
83/// // When bound type is statically determined, the size of the interval is just the size of two `T`.
84/// assert_eq!(size_of::<Interval<i32, Inclusive>>(), size_of::<i32>() * 2);
85/// assert_eq!(size_of::<Interval<f64, Exclusive>>(), size_of::<f64>() * 2);
86///
87/// // Size is larger when bound type is not statically determined.
88/// assert!(size_of::<Interval<i32, BoundType>>() >= (size_of::<i32>() + size_of::<BoundType>()) * 2);
89/// ```
90///
91/// # Properties
92/// ```txt
93/// lower_bound left . center right upper_bound
94/// ...------------>|<------- self -------------------->|<------------ ...
95/// inf sup
96/// [<------------ closure ------------>]
97/// (<----------- interior ---------->)
98/// ```
99///
100/// # Set operations
101/// ```txt
102/// |<------------- a ----------------->| . p |<-------- c -------->|
103/// |<--------------- b ------------------->|
104/// |<--- a.intersection(&b) --->|
105/// |<-- a.gap(&c) -->|
106/// |<------------- a.hull(p) ------------->|
107/// |<---------------------------------- a.span(&c) --------------------------->|
108/// |<--------------------------------->| + |<------------------->| a.union(&c)
109/// |<---->| a.difference(&b)
110/// |<- δ -+---- c.dilate(δ) ----+- δ ->|
111/// ```
112#[derive(Debug, Clone, Copy, PartialEq, Eq)]
113pub struct Interval<T, L = Inclusive, R = L> {
114 pub(crate) left: LeftBounded<T, L>,
115 pub(crate) right: RightBounded<T, R>,
116}
117
118impl<T, L, R> Interval<T, L, R> {
119 pub fn left(&self) -> &LeftBounded<T, L> {
120 &self.left
121 }
122 pub fn right(&self) -> &RightBounded<T, R> {
123 &self.right
124 }
125}
126impl<T: PartialOrd, L: BoundaryOf<Left>, R: BoundaryOf<Right>> Interval<T, L, R> {
127 fn new_(left: LeftBounded<T, L>, right: RightBounded<T, R>) -> Option<Self> {
128 is_valid_interval(&left, &right).then_some(Self { left, right })
129 }
130
131 /// Try to create a new interval. Return `None` if the interval is empty.
132 /// ```
133 /// use std::any::{Any, TypeId};
134 /// use inter_val::{Interval, BoundType, Exclusive, Inclusive};
135 ///
136 /// let a: Interval<i32, Inclusive, Exclusive> = Interval::try_new(0.into(), 3.into()).unwrap();
137 /// assert!(a.contains(&0));
138 /// assert!(a.contains(&2));
139 /// assert!(!a.contains(&3));
140 ///
141 /// let a = Interval::try_new(Exclusive.at(0), Inclusive.at(3)).unwrap();
142 /// assert_eq!(a.type_id(), TypeId::of::<Interval<i32, Exclusive, Inclusive>>());
143 ///
144 /// let a = Interval::try_new(BoundType::Exclusive.at(0), BoundType::Exclusive.at(3)).unwrap();
145 /// assert_eq!(a.type_id(), TypeId::of::<Interval<i32, BoundType, BoundType>>());
146 ///
147 /// assert!(Interval::try_new(Inclusive.at(3), Exclusive.at(0)).is_none()); // [3, 0) is empty.
148 /// assert!(Interval::try_new(Inclusive.at(3), Exclusive.at(3)).is_none()); // [3, 3) is empty.
149 /// assert!(Interval::try_new(Inclusive.at(3), Inclusive.at(3)).is_some()); // [3, 3] is not empty.
150 /// assert!(Interval::try_new(Exclusive.at(0), Exclusive.at(1)).is_some()); // (0, 1) is not empty.
151 /// ```
152 pub fn try_new(left: Bound<T, L>, right: Bound<T, R>) -> Option<Self> {
153 Self::new_(left.into(), right.into())
154 }
155
156 /// Create a new interval. Panics if the interval is empty.
157 /// ```
158 /// use std::any::{Any, TypeId};
159 /// use inter_val::{Interval, BoundType, Exclusive, Inclusive};
160 ///
161 /// let a: Interval<i32, Inclusive, Exclusive> = Interval::new(0.into(), 3.into());
162 /// assert!(a.contains(&0));
163 /// assert!(a.contains(&2));
164 /// assert!(!a.contains(&3));
165 ///
166 /// let a = Interval::new(Exclusive.at(0), Inclusive.at(3));
167 /// assert_eq!(a.type_id(), TypeId::of::<Interval<i32, Exclusive, Inclusive>>());
168 ///
169 /// let a = Interval::new(BoundType::Exclusive.at(0), BoundType::Exclusive.at(3));
170 /// assert_eq!(a.type_id(), TypeId::of::<Interval<i32, BoundType, BoundType>>());
171 /// ```
172 ///
173 /// # Panics
174 /// ```should_panic
175 /// # use inter_val::{Interval, Exclusive, Inclusive};
176 /// Interval::new(Inclusive.at(3), Exclusive.at(0)); // [3, 0) is empty.
177 /// ```
178 /// ```should_panic
179 /// # use inter_val::{Interval, Exclusive, Inclusive};
180 /// Interval::new(Inclusive.at(3), Exclusive.at(3)); // [3, 3) is empty.
181 /// ```
182 pub fn new(left: Bound<T, L>, right: Bound<T, R>) -> Self {
183 Self::try_new(left, right).expect("Invalid interval: left must be less than right.")
184 }
185
186 /// ```
187 /// use inter_val::{Interval, Exclusive, Inclusive};
188 /// let a: Interval<i32, Inclusive, Exclusive> = Interval::try_between(-2, 5).unwrap();
189 /// assert_eq!(a, Inclusive.at(-2).to(Exclusive.at(5)));
190 ///
191 /// let a: Interval<i32, Inclusive, Exclusive> = Interval::try_between(3, -1).unwrap();
192 /// assert_eq!(a, Inclusive.at(-1).to(Exclusive.at(3))); // Swaps left and right.
193 ///
194 /// assert!(Interval::<i32, Inclusive, Exclusive>::try_between(1, 1).is_none()); // [1, 1) is empty.
195 /// assert!(Interval::<i32, Inclusive, Inclusive>::try_between(1, 1).is_some()); // [1, 1] is not empty.
196 /// ```
197 pub fn try_between(a: T, b: T) -> Option<Self>
198 where
199 T: Into<Bound<T, L>> + Into<Bound<T, R>>,
200 {
201 if a < b {
202 Self::try_new(a.into(), b.into())
203 } else {
204 Self::try_new(b.into(), a.into())
205 }
206 }
207
208 /// ```
209 /// use inter_val::{Interval, Exclusive, Inclusive};
210 /// let a: Interval<i32, Inclusive, Exclusive> = Interval::between(-2, 5);
211 /// assert_eq!(a, Inclusive.at(-2).to(Exclusive.at(5)));
212 ///
213 /// let a: Interval<i32, Inclusive, Exclusive> = Interval::between(3, -1);
214 /// assert_eq!(a, Inclusive.at(-1).to(Exclusive.at(3))); // Swaps left and right.
215 ///
216 /// // Closed interval (bounded by `Inclusive`) never panics.
217 /// Interval::<i32, Inclusive, Inclusive>::between(1, 1); // Doesn't panic since [1, 1] is not empty.
218 /// ```
219 /// ```should_panic
220 /// # use inter_val::{Interval, Exclusive, Inclusive};
221 /// Interval::<i32, Inclusive, Exclusive>::between(1, 1); // Panics since [1, 1) is empty.
222 /// ```
223 pub fn between(a: T, b: T) -> Self
224 where
225 T: Into<Bound<T, L>> + Into<Bound<T, R>>,
226 {
227 Self::try_between(a, b).unwrap()
228 }
229
230 /// Shorthand of `.left().limit`
231 /// ```
232 /// use inter_val::{Interval, Exclusive, Inclusive};
233 /// let a = Interval::new(Exclusive.at(-1.0), Inclusive.at(1.0));
234 /// assert_eq!(a.inf(), &-1.0);
235 /// assert_eq!(a.inf(), &a.left().limit);
236 /// assert!(!a.contains(&-1.0));
237 /// ```
238 pub fn inf(&self) -> &T {
239 self.left.inf()
240 }
241
242 /// Shorthand of `.right().limit`
243 /// ```
244 /// use inter_val::{Interval, Exclusive, Inclusive};
245 /// let a = Interval::new(Inclusive.at(-1.0), Exclusive.at(1.0));
246 /// assert_eq!(a.sup(), &1.0);
247 /// assert_eq!(a.sup(), &a.right().limit);
248 /// assert!(!a.contains(&1.0));
249 /// ```
250 pub fn sup(&self) -> &T {
251 self.right.sup()
252 }
253
254 pub fn closure(self) -> Interval<T, Inclusive> {
255 Interval {
256 left: self.left.closure(),
257 right: self.right.closure(),
258 }
259 }
260
261 pub fn interior(self) -> Option<Interval<T, Exclusive>> {
262 Interval::<_, Exclusive>::new_(self.left.interior(), self.right.interior())
263 }
264
265 /// ```
266 /// use inter_val::{Interval, Inclusive, Exclusive};
267 /// let a = Inclusive.at(4).to(Exclusive.at(7));
268 /// let b = Exclusive.at(1.23).to(Inclusive.at(4.56));
269 /// assert!(a.contains(&4));
270 /// assert!(!a.contains(&7));
271 /// assert!(!b.contains(&1.23));
272 /// assert!(b.contains(&1.230000000001));
273 /// assert!(b.contains(&4.56));
274 /// ```
275 pub fn contains(&self, t: &T) -> bool {
276 self.left.contains(t) && self.right.contains(t)
277 }
278
279 /// ```
280 /// use inter_val::{Inclusive, Exclusive};
281 /// let a = Inclusive.at(4).to(Exclusive.at(7)); // [4, 7)
282 /// assert_eq!(a.dilate(2), Inclusive.at(2).to(Exclusive.at(9))); // [4-2, 7+2) = [2, 9)
283 /// assert_eq!(a.dilate(-1), Inclusive.at(5).to(Exclusive.at(6))); // [4+1, 7-1) = [5, 6)
284 /// ```
285 /// ```should_panic
286 /// use inter_val::{Inclusive, Exclusive};
287 /// let a = Inclusive.at(4).to(Exclusive.at(7)); // [4, 7)
288 /// a.dilate(-2); // panic! [4+2, 7-2) = [6, 5) is empty.
289 /// ```
290 pub fn dilate(self, delta: T) -> Self
291 where
292 T: Clone + std::ops::Add<Output = T> + std::ops::Sub<Output = T>,
293 {
294 Self::new_(self.left.dilate(delta.clone()), self.right.dilate(delta)).unwrap()
295 }
296
297 /// ```
298 /// use inter_val::{Interval, Inclusive, Exclusive};
299 /// let a = Inclusive.at(0).to(Exclusive.at(3));
300 /// let b = Inclusive.at(0).to(Exclusive.at(4));
301 /// let c = Inclusive.at(1).to(Exclusive.at(4));
302 /// assert!(a.includes(&a));
303 /// assert!(!a.includes(&b) && b.includes(&a));
304 /// assert!(!a.includes(&c) && !c.includes(&a));
305 /// ```
306 pub fn includes(&self, other: &Self) -> bool {
307 self.left.includes(&other.left) && self.right.includes(&other.right)
308 }
309
310 /// ```
311 /// use inter_val::{Interval, Inclusive, Exclusive};
312 /// let a = Inclusive.at(0).to(Exclusive.at(3));
313 /// let b = Inclusive.at(1).to(Exclusive.at(4));
314 /// let c = Inclusive.at(3).to(Exclusive.at(5));
315 /// assert!(a.overlaps(&a));
316 /// assert!(a.overlaps(&b) && b.overlaps(&a));
317 /// assert!(!a.overlaps(&c) && !c.overlaps(&a));
318 /// ```
319 pub fn overlaps(&self, other: &Self) -> bool {
320 let left = crate::half::partial_max(&self.left, &other.left);
321 let right = crate::half::partial_min(&self.right, &other.right);
322 is_valid_interval(left, right)
323 }
324
325 /// ```
326 /// use inter_val::{Interval, Inclusive, Exclusive};
327 /// let a = Inclusive.at(0).to(Exclusive.at(3));
328 /// let b = Inclusive.at(1).to(Exclusive.at(4));
329 /// let c = Inclusive.at(3).to(Exclusive.at(5));
330 /// assert_eq!(a.intersection(&a), Some(a));
331 /// assert_eq!(a.intersection(&b), Some(Inclusive.at(1).to(Exclusive.at(3))));
332 /// assert_eq!(a.intersection(&c), None);
333 /// ```
334 pub fn intersection(&self, other: &Self) -> Option<Self>
335 where
336 T: Clone,
337 {
338 Self::new_(
339 self.left.intersection(&other.left).clone(),
340 self.right.intersection(&other.right).clone(),
341 )
342 }
343
344 /// ```
345 /// use inter_val::{Interval, Inclusive, Exclusive};
346 /// let a = Inclusive.at(0).to(Exclusive.at(3));
347 /// let b = Inclusive.at(5).to(Exclusive.at(8));
348 /// assert_eq!(a.span(&b), Inclusive.at(0).to(Exclusive.at(8)));
349 /// ```
350 pub fn span(&self, other: &Self) -> Self
351 where
352 T: Clone,
353 {
354 Self {
355 left: self.left.union(&other.left).clone(),
356 right: self.right.union(&other.right).clone(),
357 }
358 }
359
360 /// ```
361 /// use inter_val::{Interval, Inclusive, Exclusive};
362 /// let a = Inclusive.at(0).to(Exclusive.at(3));
363 /// assert_eq!(a.hull(-2), Inclusive.at(-2).to(Exclusive.at(3)));
364 /// assert_eq!(a.hull(5), Inclusive.at(0).to(Exclusive.at(5)));
365 /// ```
366 pub fn hull(self, t: T) -> Self
367 where
368 T: Clone,
369 {
370 Self {
371 left: self.left.hull(t.clone()),
372 right: self.right.hull(t),
373 }
374 }
375
376 /// ```
377 /// use inter_val::{Interval, Inclusive, Exclusive};
378 /// let a = Inclusive.at(0).to(Exclusive.at(3));
379 /// let b = Inclusive.at(5).to(Exclusive.at(8));
380 /// assert_eq!(a.gap(&b).unwrap(), Inclusive.at(3).to(Exclusive.at(5)));
381 /// ```
382 pub fn gap(&self, other: &Self) -> Option<Interval<T, R::Flip, L::Flip>>
383 where
384 T: Clone,
385 L::Flip: BoundaryOf<Right>,
386 R::Flip: BoundaryOf<Left>,
387 {
388 Interval::new_(self.right.clone().flip(), other.left.clone().flip())
389 .or_else(|| Interval::new_(other.right.clone().flip(), self.left.clone().flip()))
390 }
391
392 /// ```
393 /// use inter_val::{Interval, Inclusive, Exclusive};
394 /// let a = Inclusive.at(0).to(Exclusive.at(3));
395 /// let b = Inclusive.at(5).to(Exclusive.at(8));
396 /// let union = a.union(&b);
397 /// assert_eq!(union.span, a.span(&b));
398 /// assert_eq!(union.gap, a.gap(&b));
399 /// let union_ints: Vec<Interval<_, _, _>> = union.into_iter().collect();
400 /// assert_eq!(union_ints.len(), 2);
401 /// assert_eq!(union_ints[0], a);
402 /// assert_eq!(union_ints[1], b);
403 /// ```
404 pub fn union(&self, other: &Self) -> IntervalUnion<T, L, R>
405 where
406 T: Clone,
407 L::Flip: BoundaryOf<Right>,
408 R::Flip: BoundaryOf<Left>,
409 {
410 IntervalUnion {
411 gap: self.gap(other),
412 span: self.span(other),
413 }
414 }
415
416 pub fn lower_bound(&self) -> RightBounded<T, L::Flip>
417 where
418 T: Clone,
419 {
420 self.left.clone().flip()
421 }
422
423 pub fn upper_bound(&self) -> LeftBounded<T, R::Flip>
424 where
425 T: Clone,
426 {
427 self.right.clone().flip()
428 }
429
430 /// ```
431 /// use inter_val::{Interval, Inclusive, Exclusive};
432 /// let a = Inclusive.at(2.1).to(Inclusive.at(5.3));
433 /// assert_eq!(a.measure(), 5.3 - 2.1);
434 ///
435 /// let a = Exclusive.at(0).to(Exclusive.at(1)); // (0, 1)
436 /// assert_eq!(a.measure(), 1);
437 /// ```
438 pub fn measure(&self) -> T
439 where
440 T: Clone + std::ops::Sub<Output = T>,
441 {
442 self.sup().clone() - self.inf().clone()
443 }
444
445 /// ```
446 /// use inter_val::{Inclusive, Exclusive};
447 /// let a = Exclusive.at(10).to(Inclusive.at(20)); // (10, 20]
448 /// assert!(a.step_by(2).eq(vec![12, 14, 16, 18, 20]));
449 /// ```
450 pub fn step_by(&self, step: T) -> impl Iterator<Item = T> + '_
451 where
452 T: Clone,
453 for<'a> T: std::ops::AddAssign<&'a T>,
454 {
455 self.left
456 .step_by(step)
457 .take_while(|t| self.right.contains(t))
458 }
459
460 /// ```
461 /// use inter_val::{Inclusive, Exclusive};
462 /// let a = Exclusive.at(10).to(Inclusive.at(20)); // (10, 20]
463 /// assert!(a.step_rev_by(2).eq(vec![20, 18, 16, 14, 12]));
464 /// ```
465 pub fn step_rev_by(&self, step: T) -> impl Iterator<Item = T> + '_
466 where
467 T: Clone,
468 for<'a> T: std::ops::SubAssign<&'a T>,
469 {
470 self.right
471 .step_rev_by(step)
472 .take_while(|t| self.left.contains(t))
473 }
474
475 /// ```
476 /// use inter_val::{Interval, Inclusive, Exclusive, Nullable};
477 /// let a = Inclusive.at(0).to(Exclusive.at(3)); // [0, 3)
478 /// let b = Inclusive.at(1).to(Exclusive.at(5)); // [1, 5)
479 /// let c = Inclusive.at(8).to(Exclusive.at(10)); // [8, 10)
480 /// let span = Interval::span_many(vec![a, b, c]).unwrap(); // [0, 10)
481 /// assert_eq!(span.left().limit, 0);
482 /// assert_eq!(span.right().limit, 10);
483 ///
484 /// // Sum for Nullable<Interval> can be used as well.
485 /// let sum: Nullable<Interval<_, _, _>> = vec![a, b, c].into_iter().sum();
486 /// assert_eq!(sum.unwrap(), span);
487 /// ```
488 pub fn span_many<A: std::borrow::Borrow<Self>>(
489 items: impl IntoIterator<Item = A>,
490 ) -> Option<Self>
491 where
492 T: Clone,
493 {
494 let mut items = items.into_iter();
495 let first = items.next()?.borrow().clone();
496 Some(items.fold(first, |acc, item| acc.span(item.borrow())))
497 }
498
499 /// ```
500 /// use inter_val::{Interval, Nullable};
501 /// let hull = Interval::<_>::hull_many(vec![3, 9, 2, 5]).unwrap(); // [2, 9]
502 /// assert_eq!(hull.inf(), &2);
503 /// assert_eq!(hull.sup(), &9);
504 ///
505 /// let hull = Interval::<_>::hull_many(vec![3.1, 9.2, 2.3, 5.4]).unwrap(); // [2.3, 9.2]
506 /// assert_eq!(hull.inf(), &2.3);
507 /// assert_eq!(hull.sup(), &9.2);
508 ///
509 /// // Sum for Nullable<Interval> can be used as well.
510 /// let a: Nullable<Interval<i32>> = vec![1, 6, 2, 8, 3].into_iter().sum();
511 /// assert_eq!(a.unwrap(), Interval::between(1, 8));
512 /// ```
513 pub fn hull_many(items: impl IntoIterator<Item = T>) -> Option<Self>
514 where
515 T: Clone + Into<Bound<T, L>> + Into<Bound<T, R>>,
516 {
517 let mut items = items.into_iter();
518 let mut left = items.next()?;
519 let mut right = left.clone();
520 for x in items {
521 if x < left {
522 left = x;
523 } else if right < x {
524 right = x;
525 }
526 }
527 Self::try_new(left.into(), right.into())
528 }
529}
530
531impl<T: PartialOrd, L: BoundaryOf<Left, Flip = R>, R: BoundaryOf<Right, Flip = L>>
532 Interval<T, L, R>
533{
534 /// Difference is defined only for `Interval<T, Inclusive, Exclusive>`, `Interval<T, Exclusive, Inclusive>`, and `Interval<T, BoundType>`.
535 /// ```
536 /// use inter_val::{Interval, Inclusive, Exclusive};
537 /// let a = Inclusive.at(0).to(Exclusive.at(3));
538 /// let b = Inclusive.at(1).to(Exclusive.at(4));
539 /// let diff = a.difference(&b);
540 /// assert!(diff.lower.is_some() && diff.upper.is_none());
541 /// assert_eq!(diff.lower.unwrap(), Inclusive.at(0).to(Exclusive.at(1)));
542 /// assert_eq!(diff.into_iter().collect::<Vec<_>>().len(), 1);
543 /// ```
544 pub fn difference(&self, other: &Self) -> IntervalDifference<T, L, R>
545 where
546 T: Clone,
547 {
548 IntervalDifference {
549 lower: Self::new_(self.left.clone(), other.lower_bound()),
550 upper: Self::new_(other.upper_bound(), self.right.clone()),
551 }
552 }
553}
554
555impl<T: PartialOrd + Clone> Interval<T, Inclusive, Exclusive> {
556 /// ```
557 /// use inter_val::{Inclusive, Exclusive};
558 /// let a = Inclusive.at(0).to(Exclusive.at(3)); // [0, 3)
559 /// let (b, c) = a.try_split_at(1); // [0, 1) and [1, 3)
560 /// assert_eq!(b, Some(Inclusive.at(0).to(Exclusive.at(1))));
561 /// assert_eq!(c, Some(Inclusive.at(1).to(Exclusive.at(3))));
562 ///
563 /// let (b, c) = a.try_split_at(0);
564 /// assert_eq!(b, None); // [0, 0) is empty.
565 /// assert_eq!(c, Some(a)); // [0, 3)
566 /// ```
567 pub fn try_split_at(&self, t: T) -> (Option<Self>, Option<Self>) {
568 if !self.left.contains(&t) {
569 return (None, Some(self.clone()));
570 }
571 if !self.right.contains(&t) {
572 return (Some(self.clone()), None);
573 }
574 let lower = Self::new_(self.left.clone(), Exclusive.at(t.clone()).into());
575 let upper = Self::new_(Inclusive.at(t).into(), self.right.clone());
576 (lower, upper)
577 }
578
579 /// ```
580 /// use inter_val::{Inclusive, Exclusive};
581 /// let a = Inclusive.at(0).to(Exclusive.at(3)); // [0, 3)
582 /// let (b, c) = a.split_at(1); // [0, 1) and [1, 3)
583 /// assert_eq!(b, Inclusive.at(0).to(Exclusive.at(1)));
584 /// assert_eq!(c, Inclusive.at(1).to(Exclusive.at(3)));
585 /// ```
586 /// ```should_panic
587 /// use inter_val::{Inclusive, Exclusive};
588 /// let a = Inclusive.at(0).to(Exclusive.at(3)); // [0, 3)
589 /// let (b, c) = a.split_at(0);
590 /// ```
591 pub fn split_at(&self, t: T) -> (Self, Self) {
592 assert!(self.contains(&t));
593 let lower = Self::new_(self.left.clone(), Exclusive.at(t.clone()).into());
594 let upper = Self::new_(Inclusive.at(t).into(), self.right.clone());
595 (lower.unwrap(), upper.unwrap())
596 }
597}
598
599impl<T: num::Float, L: BoundaryOf<Left>, R: BoundaryOf<Right>> Interval<T, L, R> {
600 /// ```
601 /// use inter_val::{Interval, Inclusive};
602 /// let a = Inclusive.at(2.1).to(Inclusive.at(5.3));
603 /// assert_eq!(a.center(), (2.1 + 5.3) / 2.0);
604 /// ```
605 pub fn center(&self) -> T {
606 (self.left.limit + self.right.limit) / (T::one() + T::one())
607 }
608
609 /// IoU - Intersection over Union.
610 /// ```
611 /// use inter_val::{Interval, Inclusive};
612 /// let a = Inclusive.at(0.0).to(Inclusive.at(1.0));
613 /// let b = Inclusive.at(0.0).to(Inclusive.at(2.0));
614 /// let c = Inclusive.at(1.0).to(Inclusive.at(2.0));
615 /// assert_eq!(a.iou(&a), 1.0);
616 /// assert_eq!(a.iou(&b), 0.5);
617 /// assert_eq!(a.iou(&c), 0.0);
618 /// ```
619 pub fn iou(&self, other: &Self) -> T {
620 self.intersection(other)
621 .map(|intersection| {
622 let union = self.span(other);
623 intersection.measure() / union.measure()
624 })
625 .unwrap_or(T::zero())
626 }
627
628 /// Linear interpolation.
629 /// ```
630 /// use inter_val::{Interval, Inclusive, Exclusive};
631 /// let a = Inclusive.at(2.0).to(Inclusive.at(4.0)); // [2, 4]
632 /// assert_eq!(a.lerp(0.0), 2.0);
633 /// assert_eq!(a.lerp(0.5), 3.0);
634 /// assert_eq!(a.lerp(1.0), 4.0);
635 /// assert_eq!(a.lerp(1.1), 4.2);
636 /// ```
637 pub fn lerp(&self, ratio: T) -> T {
638 (T::one() - ratio) * *self.inf() + ratio * *self.sup()
639 }
640
641 /// ```
642 /// use inter_val::{Interval, Inclusive, Exclusive};
643 /// let a = Inclusive.at(2.0).to(Inclusive.at(4.0)); // [2, 4]
644 /// let b = Inclusive.at(2.0).to(Exclusive.at(4.0)); // [2, 4)
645 /// let c = Exclusive.at(2.0).to(Inclusive.at(4.0)); // (2, 4]
646 /// assert!(a.step_uniform(4).eq(vec![2.0, 2.5, 3.0, 3.5, 4.0]));
647 /// assert!(b.step_uniform(4).eq(vec![2.0, 2.5, 3.0, 3.5]));
648 /// assert!(c.step_uniform(4).eq(vec![2.5, 3.0, 3.5, 4.0]));
649 /// ```
650 pub fn step_uniform(&self, n: usize) -> impl Iterator<Item = T> + '_ {
651 let step = self.measure() / T::from(n).unwrap();
652 let (mut i, mut t) = if self.left.bound_type.is_inclusive() {
653 (0, *self.inf())
654 } else {
655 (1, *self.inf() + step)
656 };
657 let last = if self.right.bound_type.is_inclusive() {
658 n
659 } else {
660 n - 1
661 };
662 std::iter::from_fn(move || {
663 let ret = (i <= last).then_some(t);
664 t = if i == n { *self.sup() } else { t + step };
665 i += 1;
666 ret
667 })
668 }
669}
670
671impl<T, L, R> Interval<T, L, R> {
672 /// Cast by `From<T>`.
673 /// ```
674 /// use inter_val::{Interval, Exclusive};
675 /// let src: Interval<i32, Exclusive> = Interval::between(0, 1); // open interval (0, 1)
676 /// let dst = src.cast::<f64>();
677 /// assert!(dst.contains(&0.5));
678 /// ```
679 pub fn cast<U: From<T>>(self) -> Interval<U, L, R> {
680 Interval {
681 left: self.left.cast(),
682 right: self.right.cast(),
683 }
684 }
685}
686
687impl<T: num::NumCast, L, R> Interval<T, L, R> {
688 /// Cast by `num::NumCast`.
689 /// ```
690 /// use inter_val::{Interval, Exclusive};
691 /// let src: Interval<f64> = Interval::between(1.2, 7.8); // closed interval [1.2, 7.8]
692 /// let dst = src.try_cast::<i32>().unwrap();
693 /// assert_eq!(dst.inf(), &1);
694 /// assert_eq!(dst.sup(), &7);
695 /// ```
696 pub fn try_cast<U: num::NumCast>(self) -> Option<Interval<U, L, R>> {
697 Some(Interval {
698 left: self.left.try_cast()?,
699 right: self.right.try_cast()?,
700 })
701 }
702}
703
704impl<T, L: IntoGeneral, R: IntoGeneral> IntoGeneral for Interval<T, L, R> {
705 type General = Interval<T, L::General, R::General>;
706 fn into_general(self) -> Self::General {
707 Interval {
708 left: self.left.into_general(),
709 right: self.right.into_general(),
710 }
711 }
712}
713
714/// ```
715/// use inter_val::{Interval, Exclusive, Inclusive, BoundType};
716///
717/// // Iterate Interval<i32, Exclusive, Inclusive>
718/// let items: Vec<_> = Exclusive.at(0).to(Inclusive.at(10)).into_iter().collect();
719/// assert_eq!(items.len(), 10);
720/// assert_eq!(items[0], 1);
721/// assert_eq!(items.last().unwrap(), &10);
722///
723/// // Iterate Interval<i32, BoundType, BoundType>
724/// let items: Vec<_> = (BoundType::Exclusive.at(0).to(BoundType::Inclusive.at(10)))
725/// .into_iter()
726/// .collect();
727/// assert_eq!(items.len(), 10);
728/// assert_eq!(items[0], 1);
729/// assert_eq!(items.last().unwrap(), &10);
730/// ```
731impl<T, L, R> IntoIterator for Interval<T, L, R>
732where
733 std::ops::RangeInclusive<T>: Iterator<Item = T>,
734 T: num::Integer + Clone,
735 L: BoundaryOf<Left>,
736 R: BoundaryOf<Right>,
737 for<'a> T: std::ops::AddAssign<&'a T> + std::ops::SubAssign<&'a T>,
738{
739 type Item = T;
740 type IntoIter = std::ops::RangeInclusive<T>;
741 fn into_iter(self) -> Self::IntoIter {
742 let first = self.left.step_by(T::one()).next().unwrap();
743 let last = self.right.step_rev_by(T::one()).next().unwrap();
744 first..=last
745 }
746}