Skip to main content

physdes/
interval.rs

1use crate::generic::{Contain, Displacement, MinDist, Overlap};
2
3use std::cmp::{Eq, PartialEq, PartialOrd};
4use std::fmt::{Display, Formatter, Result as FmtResult};
5use std::marker::PhantomData;
6use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
7
8/// The `Interval` struct represents a range of values with a lower bound (`lb`) and an upper bound
9/// (`ub`).
10///
11/// ```svgbob
12///  lb        ub
13///   |---------|
14///   *=========*-----> T
15/// ```
16///
17/// Properties:
18///
19/// * `lb`: The `lb` property represents the lower bound of the interval. It is of type `T`, which is a
20///   generic type that must implement the `PartialOrd` trait. This means that the type `T` must be able
21///   to be compared for ordering.
22/// * `ub`: The `ub` property represents the upper bound of the interval. It is of type `T`, which is a
23///   generic type that must implement the `PartialOrd` trait. The `PartialOrd` trait allows for
24///   comparison between values of type `T`.
25/// * `_marker`: The `_marker` field is a marker field that is used to indicate that the generic type
26///   `T` is used in the struct. It is typically used when you want to associate a type parameter with a
27///   struct, but you don't actually need to store any values of that type in the struct.
28///
29/// # Examples
30///
31/// ```
32/// use physdes::interval::Interval;
33/// use std::marker::PhantomData;
34///
35/// let interval = Interval::new(1, 5);
36/// assert_eq!(interval.lb, 1);
37/// assert_eq!(interval.ub, 5);
38/// ```
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
41pub struct Interval<T> {
42    pub lb: T,
43    pub ub: T,
44    pub _marker: PhantomData<T>,
45}
46
47impl<T> Interval<T> {
48    /// The function `new` creates a new instance of a struct with given lower and upper bounds.
49    ///
50    /// Arguments:
51    ///
52    /// * `lb`: The `lb` parameter represents the lower bound value. It is of type `T`, which means it
53    ///   can be any type that implements the necessary traits for the struct.
54    /// * `ub`: The `ub` parameter represents the upper bound value. It is of type `T`, which means it
55    ///   can be any type that implements the necessary traits for the struct.
56    ///
57    /// Returns:
58    ///
59    /// The `new` function is returning an instance of the struct `Self`.
60    ///
61    /// # Examples
62    ///
63    /// ```
64    /// use physdes::interval::Interval;
65    /// use std::marker::PhantomData;
66    ///
67    /// let interval = Interval::new(1, 5);
68    /// assert_eq!(interval.lb, 1);
69    /// assert_eq!(interval.ub, 5);
70    ///
71    /// let interval = Interval::new(5, 1);  // Invalid interval but still created
72    /// assert_eq!(interval.lb, 5);
73    /// assert_eq!(interval.ub, 1);
74    /// ```
75    #[inline]
76    pub const fn new(lb: T, ub: T) -> Self {
77        Self {
78            lb,
79            ub,
80            _marker: PhantomData,
81        }
82    }
83}
84
85impl<T: Copy> Interval<T> {
86    /// The function `lb` returns the value of the field `lb` from the struct.
87    ///
88    /// Returns:
89    ///
90    /// The `lb` method is returning the value of the `lb` field of the struct or object that the method
91    /// is being called on.
92    #[inline]
93    pub const fn lb(&self) -> T {
94        self.lb
95    }
96
97    /// This Rust function returns the value of the field `ub`.
98    ///
99    /// Returns:
100    ///
101    /// The `ub` field of the struct is being returned.
102    #[inline]
103    pub const fn ub(&self) -> T {
104        self.ub
105    }
106}
107
108impl<T: PartialOrd> Interval<T> {
109    /// The function `is_invalid` checks if the lower bound is greater than the upper bound.
110    ///
111    /// Returns:
112    ///
113    /// The `is_invalid` function is returning a boolean value based on the comparison `self.lb >
114    /// self.ub`. If `self.lb` is greater than `self.ub`, it will return `true`, indicating that the
115    /// values are invalid. Otherwise, it will return `false`.
116    ///
117    /// # Examples
118    ///
119    /// ```
120    /// use physdes::interval::Interval;
121    ///
122    /// let valid_interval = Interval::new(1, 5);
123    /// assert!(!valid_interval.is_invalid());
124    ///
125    /// let invalid_interval = Interval::new(5, 1);
126    /// assert!(invalid_interval.is_invalid());
127    /// ```
128    #[inline]
129    pub fn is_invalid(&self) -> bool {
130        self.lb > self.ub
131    }
132}
133
134impl<T: Copy + Sub<Output = T>> Interval<T> {
135    /// The `length` function calculates the difference between the upper bound (`ub`) and lower bound
136    /// (`lb`) of a value.
137    ///
138    /// Returns:
139    ///
140    /// The `length` method is returning the difference between the `ub` (upper bound) and `lb` (lower
141    /// bound) values of the struct instance.
142    ///
143    /// # Examples
144    ///
145    /// ```
146    /// use physdes::interval::Interval;
147    ///
148    /// let interval = Interval::new(2, 8);
149    /// assert_eq!(interval.length(), 6);
150    ///
151    /// let interval = Interval::new(-3, 5);
152    /// assert_eq!(interval.length(), 8);
153    /// ```
154    #[inline]
155    pub fn length(&self) -> T {
156        self.ub - self.lb
157    }
158}
159
160impl<T> Display for Interval<T>
161where
162    T: PartialOrd + Copy + Display,
163{
164    /// The function `fmt` in Rust is used to format a struct by writing its lower bound and upper bound
165    /// values in square brackets.
166    ///
167    /// Arguments:
168    ///
169    /// * `f`: The `f` parameter in the `fmt` function is a mutable reference to a `Formatter` struct.
170    ///   This `Formatter` struct is used for formatting and writing output.
171    ///
172    /// Returns:
173    ///
174    /// The `fmt` method is returning a `FmtResult`, which is an alias for `Result<(), Error>`.
175    #[inline]
176    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
177        write!(f, "[{}, {}]", self.lb, self.ub)
178    }
179}
180
181impl<T: Sub<Output = T>> Sub for Interval<T> {
182    type Output = Self;
183
184    fn sub(self, other: Self) -> Self::Output {
185        Self {
186            lb: self.lb - other.lb,
187            ub: self.ub - other.ub,
188            _marker: PhantomData,
189        }
190    }
191}
192
193impl<T> Neg for Interval<T>
194where
195    T: Copy + Neg<Output = T>,
196{
197    type Output = Interval<T>;
198
199    #[inline]
200    fn neg(self) -> Self::Output {
201        Interval {
202            lb: -self.ub,
203            ub: -self.lb,
204            _marker: self._marker,
205        }
206    }
207}
208
209impl<T> AddAssign<T> for Interval<T>
210where
211    T: Copy + AddAssign<T>,
212{
213    /// The `add_assign` function in Rust adds a value to both the lower and upper bounds of a data
214    /// structure.
215    ///
216    /// Arguments:
217    ///
218    /// * `rhs`: The `rhs` parameter in the `add_assign` function represents the right-hand side operand
219    ///   that will be added to the `lb` and `ub` fields of the struct or object on which the method is
220    ///   called.
221    #[inline]
222    fn add_assign(&mut self, rhs: T) {
223        self.lb += rhs;
224        self.ub += rhs;
225    }
226}
227
228impl<T> Add<T> for Interval<T>
229where
230    T: Copy + Add<Output = T>,
231{
232    type Output = Interval<T>;
233
234    /// The `add` function in Rust adds a value to both the lower and upper bounds of an `Interval`
235    /// struct.
236    ///
237    /// Arguments:
238    ///
239    /// * `rhs`: The `rhs` parameter in the `add` function represents the right-hand side operand that
240    ///   will be added to the current `Interval` instance.
241    #[inline]
242    fn add(self, rhs: T) -> Self::Output {
243        Interval {
244            lb: self.lb + rhs,
245            ub: self.ub + rhs,
246            _marker: self._marker,
247        }
248    }
249}
250
251impl<T> SubAssign<T> for Interval<T>
252where
253    T: Copy + SubAssign<T>,
254{
255    /// The `sub_assign` function subtracts a value from both the lower and upper bounds of a variable.
256    ///
257    /// Arguments:
258    ///
259    /// * `rhs`: `rhs` is a parameter of type `T` that is passed by value to the `sub_assign` function.
260    ///   It is used to subtract its value from both `self.lb` and `self.ub` in the function
261    ///   implementation.
262    #[inline]
263    fn sub_assign(&mut self, rhs: T) {
264        self.lb -= rhs;
265        self.ub -= rhs;
266    }
267}
268
269impl<T: Add<Output = T>> Add for Interval<T> {
270    type Output = Self;
271
272    fn add(self, other: Self) -> Self::Output {
273        Self {
274            lb: self.lb + other.lb,
275            ub: self.ub + other.ub,
276            _marker: PhantomData,
277        }
278    }
279}
280
281impl<T> Sub<T> for Interval<T>
282where
283    T: Copy + Sub<Output = T>,
284{
285    type Output = Interval<T>;
286
287    /// The function subtracts a value from both the lower and upper bounds of an interval.
288    ///
289    /// Arguments:
290    ///
291    /// * `rhs`: The `rhs` parameter in the code snippet represents the right-hand side operand that
292    ///   will be subtracted from the interval's lower bound (`lb`) and upper bound (`ub`) values.
293    #[inline]
294    fn sub(self, rhs: T) -> Self::Output {
295        Interval {
296            lb: self.lb - rhs,
297            ub: self.ub - rhs,
298            _marker: self._marker,
299        }
300    }
301}
302
303impl<T> MulAssign<T> for Interval<T>
304where
305    T: Copy + MulAssign<T>,
306{
307    /// The `mul_assign` function in Rust multiplies both the lower and upper bounds of a range by a
308    /// given value.
309    ///
310    /// Arguments:
311    ///
312    /// * `rhs`: The `rhs` parameter in the `mul_assign` function represents the value that will be
313    ///   multiplied with the `lb` and `ub` fields of the struct or object on which the method is called.
314    #[inline]
315    fn mul_assign(&mut self, rhs: T) {
316        self.lb *= rhs;
317        self.ub *= rhs;
318    }
319}
320
321impl<T> Mul<T> for Interval<T>
322where
323    T: Copy + Mul<Output = T>,
324{
325    type Output = Interval<T>;
326
327    /// The `mul` function in Rust defines multiplication for an `Interval` type.
328    ///
329    /// Arguments:
330    ///
331    /// * `rhs`: The `rhs` parameter in the `mul` function represents the right-hand side operand that
332    ///   will be multiplied with the `Interval` instance on which the method is called.
333    #[inline]
334    fn mul(self, rhs: T) -> Self::Output {
335        Interval {
336            lb: self.lb * rhs,
337            ub: self.ub * rhs,
338            _marker: self._marker,
339        }
340    }
341}
342
343/// The above code is defining a trait named `Enlarge` in Rust. This trait has an associated type
344/// `Output` and a method `enlarge_with` that takes a reference to `self` and a parameter `alpha` of
345/// type `T`. The method returns an object of type `Output`. This trait can be implemented for types to
346/// provide the functionality of enlarging or modifying the object with the provided `alpha` value.
347pub trait Enlarge<Alpha> {
348    type Output;
349
350    fn enlarge_with(&self, alpha: Alpha) -> Self::Output;
351}
352
353impl Enlarge<i32> for i32 {
354    type Output = Interval<i32>;
355
356    /// The `enlarge_with` function takes an integer `alpha` and returns an `Interval` struct with lower
357    /// bound as `self - alpha` and upper bound as `self + alpha`.
358    ///
359    /// Arguments:
360    ///
361    /// * `alpha`: The `alpha` parameter in the `enlarge_with` function represents the amount by which
362    ///   the interval should be enlarged. It is an `i32` type, which means it is an integer value.
363    ///
364    /// Returns:
365    ///
366    /// An `Interval<i32>` struct is being returned.
367    #[inline]
368    fn enlarge_with(&self, alpha: i32) -> Interval<i32> {
369        Interval {
370            lb: *self - alpha,
371            ub: *self + alpha,
372            _marker: PhantomData,
373        }
374    }
375}
376
377impl<T> Enlarge<T> for Interval<T>
378where
379    T: Copy + Add<Output = T> + Sub<Output = T>,
380{
381    type Output = Interval<T>;
382
383    /// The `enlarge_with` function in Rust enlarges an interval by adding a specified value to its
384    /// lower bound and subtracting the same value from its upper bound.
385    ///
386    /// Arguments:
387    ///
388    /// * `alpha`: The `alpha` parameter in the `enlarge_with` function represents the amount by which
389    ///   the lower bound (`lb`) and upper bound (`ub`) of an `Interval` struct are adjusted. The lower
390    ///   bound is decreased by `alpha` and the upper bound is increased by `alpha`, effectively enlarg
391    ///
392    /// Returns:
393    ///
394    /// The `enlarge_with` method is returning a new `Interval` instance with the lower bound (`lb`)
395    /// decreased by `alpha` and the upper bound (`ub`) increased by `alpha`. The `_marker` field is
396    /// copied from the original `Interval` instance.
397    #[inline]
398    fn enlarge_with(&self, alpha: T) -> Self {
399        Interval {
400            lb: self.lb - alpha,
401            ub: self.ub + alpha,
402            _marker: self._marker,
403        }
404    }
405}
406
407impl<T: PartialOrd> PartialOrd for Interval<T> {
408    /// The function `partial_cmp` compares the lower bound of `self` with the upper bound of `other`
409    /// and returns the result as an `Option` of `Ordering`.
410    ///
411    /// Arguments:
412    ///
413    /// * `other`: The `other` parameter is a reference to another object of the same type as `self`.
414    ///
415    /// Returns:
416    ///
417    /// an `Option` containing a `std::cmp::Ordering` value.
418    ///
419    /// # Examples
420    ///
421    /// ```
422    /// use physdes::interval::Interval;
423    /// use std::marker::PhantomData;
424    /// assert_eq!(Interval::new(1, 2).partial_cmp(&Interval::new(3, 4)), Some(std::cmp::Ordering::Less));
425    /// ```
426    #[inline]
427    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
428        if self.ub < other.lb {
429            Some(std::cmp::Ordering::Less)
430        } else if other.ub < self.lb {
431            Some(std::cmp::Ordering::Greater)
432        } else {
433            Some(std::cmp::Ordering::Equal)
434        }
435    }
436}
437
438/// The `impl<T: PartialOrd> Overlap<Interval<T>> for Interval<T>` block is implementing the `Overlap`
439/// trait for the `Interval<T>` struct.
440impl<T: PartialOrd> Overlap<Interval<T>> for Interval<T> {
441    /// The `overlaps` function in Rust checks if two intervals overlap with each other.
442    ///
443    /// Arguments:
444    ///
445    /// * `other`: The `other` parameter in the `overlaps` function represents another interval that you
446    ///   want to check for overlap with the interval on which the method is called.
447    ///
448    /// Returns:
449    ///
450    /// The `overlaps` function is returning a boolean value, which indicates whether the interval
451    /// `self` overlaps with the interval `other`. If there is an overlap between the two intervals, the
452    /// function will return `true`, otherwise it will return `false`.
453    #[inline]
454    fn overlaps(&self, other: &Interval<T>) -> bool {
455        self.ub >= other.lb && other.ub >= self.lb
456    }
457}
458
459impl<T: PartialOrd> Overlap<T> for Interval<T> {
460    /// The `overlaps` function in Rust checks if two values overlap within a range.
461    ///
462    /// Arguments:
463    ///
464    /// * `other`: The `other` parameter is a reference to an object of type `T`, which is the same type
465    ///   as the object that the method `overlaps` is being called on.
466    ///
467    /// Returns:
468    ///
469    /// The `overlaps` function is returning a boolean value, which indicates whether the range
470    /// represented by `self` overlaps with the range represented by `other`.
471    #[inline]
472    fn overlaps(&self, other: &T) -> bool {
473        self.ub >= *other && *other >= self.lb
474    }
475}
476
477impl<T: PartialOrd> Overlap<Interval<T>> for T {
478    /// The `overlaps` function in Rust checks if two intervals overlap with each other.
479    ///
480    /// Arguments:
481    ///
482    /// * `other`: The `other` parameter is a reference to an `Interval<T>` struct, which represents
483    ///   another interval. The `Interval<T>` struct likely contains two fields, `lb` and `ub`,
484    ///   representing the lower and upper bounds of the interval, respectively. The `overlaps` method is
485    ///   used to
486    ///
487    /// Returns:
488    ///
489    /// The `overlaps` function is returning a boolean value. It checks if the current interval (`self`)
490    /// overlaps with another interval (`other`) by comparing their lower bounds and upper bounds. If
491    /// there is any overlap between the two intervals, it returns `true`, otherwise it returns `false`.
492    #[inline]
493    fn overlaps(&self, other: &Interval<T>) -> bool {
494        *self >= other.lb && other.ub >= *self
495    }
496}
497
498/// The `impl<T: PartialOrd> Contain<Interval<T>> for Interval<T>` block is implementing the `Contain`
499/// trait for the `Interval<T>` struct.
500impl<T: PartialOrd> Contain<Interval<T>> for Interval<T> {
501    /// The `contains` function in Rust checks if one interval contains another interval.
502    ///
503    /// Arguments:
504    ///
505    /// * `other`: The `other` parameter is a reference to an `Interval<T>` object that is being
506    ///   compared to the current `Interval<T>` object.
507    ///
508    /// Returns:
509    ///
510    /// The `contains` method is returning a boolean value, which indicates whether the interval `self`
511    /// contains the interval `other`. It checks if the lower bound of `self` is less than or equal to
512    /// the lower bound of `other`, and if the upper bound of `other` is less than or equal to the upper
513    /// bound of `self`. If both conditions are true, it returns `true
514    #[inline]
515    fn contains(&self, other: &Interval<T>) -> bool {
516        self.lb <= other.lb && other.ub <= self.ub
517    }
518}
519
520/// The `impl<T: PartialOrd> Contain<T> for Interval<T>` block is implementing the `Contain` trait for
521/// the `Interval<T>` struct.
522impl<T: PartialOrd> Contain<T> for Interval<T> {
523    /// The function checks if a value is within a specified range.
524    ///
525    /// Arguments:
526    ///
527    /// * `other`: The `other` parameter is a reference to a value of type `T`, which is the same type
528    ///   as the elements stored in the struct or data structure that contains the `contains` method. The
529    ///   method checks if the value referenced by `other` falls within the range defined by the lower
530    ///   bound (`
531    ///
532    /// Returns:
533    ///
534    /// A boolean value is being returned, indicating whether the value `other` is within the range
535    /// defined by `self.lb` and `self.ub`.
536    #[inline]
537    fn contains(&self, other: &T) -> bool {
538        self.lb <= *other && *other <= self.ub
539    }
540}
541
542impl<T: PartialOrd> Contain<Interval<T>> for T {
543    /// The function `contains` always returns `false` and takes a reference to another `Interval` as
544    /// input.
545    ///
546    /// Arguments:
547    ///
548    /// * `_other`: The `_other` parameter is a reference to an `Interval` object of the same type `T`
549    ///   as the current object.
550    ///
551    /// Returns:
552    ///
553    /// The `contains` function is returning a boolean value `false`.
554    #[inline]
555    fn contains(&self, _other: &Interval<T>) -> bool {
556        false
557    }
558}
559
560impl<T> Displacement<Interval<T>> for Interval<T>
561where
562    T: Displacement<T, Output = T>,
563{
564    type Output = Interval<T>;
565
566    /// The `displace` function in Rust calculates the displacement between two intervals.
567    ///
568    /// Arguments:
569    ///
570    /// * `other`: The `other` parameter in the `displace` function represents another `Interval` object
571    ///   of the same type as `self`. It is used to displace the lower bound and upper bound of the
572    ///   current `Interval` object (`self`) by the corresponding lower and upper bounds of the `other`
573    #[inline]
574    fn displace(&self, other: &Interval<T>) -> Self::Output {
575        Self::Output::new(self.lb.displace(&other.lb), self.ub.displace(&other.ub))
576    }
577}
578
579impl MinDist<Interval<i32>> for Interval<i32> {
580    /// The `min_dist_with` function calculates the minimum distance between two intervals of integers.
581    ///
582    /// Arguments:
583    ///
584    /// * `other`: The `min_dist_with` function calculates the minimum distance between two intervals.
585    ///   The `self` interval is represented by the lower bound `lb` and upper bound `ub` of the current
586    ///   instance, while the `other` interval is passed as a reference to an `Interval<i32>`.
587    ///
588    /// Returns:
589    ///
590    /// The `min_dist_with` function returns the minimum distance between two intervals. It calculates
591    /// the distance based on the upper and lower bounds of the intervals. If the upper bound of the
592    /// first interval is less than the lower bound of the second interval, it returns the difference
593    /// between the lower bound of the second interval and the upper bound of the first interval. If the
594    /// upper bound of the second interval is less
595    #[inline]
596    fn min_dist_with(&self, other: &Interval<i32>) -> u32 {
597        if self.ub < other.lb {
598            (other.lb - self.ub) as u32
599        } else if other.ub < self.lb {
600            (self.lb - other.ub) as u32
601        } else {
602            0
603        }
604    }
605}
606
607impl MinDist<i32> for Interval<i32> {
608    /// This Rust function calculates the minimum distance between a value and a range defined by lower
609    /// and upper bounds.
610    ///
611    /// Arguments:
612    ///
613    /// * `other`: The `other` parameter in the `min_dist_with` function is a reference to an `i32`
614    ///   value. This parameter is used to calculate the minimum distance between the current instance
615    ///   (self) and the provided `i32` value.
616    ///
617    /// Returns:
618    ///
619    /// The `min_dist_with` function returns the minimum distance between the value represented by
620    /// `self` and the value referenced by `other`. If the value referenced by `other` is greater than
621    /// the upper bound (`ub`) of `self`, it returns the difference between `other` and `ub`. If the
622    /// value referenced by `other` is less than the lower bound (`lb`) of `self
623    #[inline]
624    fn min_dist_with(&self, other: &i32) -> u32 {
625        if self.ub < *other {
626            (*other - self.ub) as u32
627        } else if *other < self.lb {
628            (self.lb - *other) as u32
629        } else {
630            0
631        }
632    }
633}
634
635impl MinDist<Interval<i32>> for i32 {
636    /// This Rust function calculates the minimum distance between two intervals of integers.
637    ///
638    /// Arguments:
639    ///
640    /// * `other`: The `min_dist_with` function calculates the minimum distance between two intervals.
641    ///   The `self` interval is compared with the `other` interval to determine the minimum distance
642    ///   between them.
643    ///
644    /// Returns:
645    ///
646    /// The `min_dist_with` function returns the minimum distance between two intervals. If the lower
647    /// bound of `self` is less than the lower bound of `other`, it returns the difference between the
648    /// lower bounds as a `u32`. If the upper bound of `other` is less than the upper bound of `self`,
649    /// it returns the difference between the upper bounds as a `u32`. Otherwise
650    #[inline]
651    fn min_dist_with(&self, other: &Interval<i32>) -> u32 {
652        if *self < other.lb {
653            (other.lb - *self) as u32
654        } else if other.ub < *self {
655            (*self - other.ub) as u32
656        } else {
657            0
658        }
659    }
660}
661
662/// The above code is defining a trait named `Hull` in Rust. This trait has a generic type `T` that must
663/// be sized. It also has an associated type `Output`. The trait has a method `hull_with` that takes a
664/// reference to another object of type `T` and returns an object of type `Output`. This trait can be
665/// implemented for different types to provide the `hull_with` functionality.
666pub trait Hull<T: ?Sized> {
667    type Output;
668
669    fn hull_with(&self, other: &T) -> Self::Output;
670}
671
672impl Hull<i32> for i32 {
673    type Output = Interval<i32>;
674
675    /// The function `hull_with` calculates the lower and upper bounds between two values.
676    ///
677    /// Arguments:
678    ///
679    /// * `other`: The `other` parameter in the `hull_with` function is a reference to an `i32` type.
680    ///   This parameter is used to calculate the lower bound (`lb`) and upper bound (`ub`) values for the
681    ///   output struct.
682    #[inline]
683    fn hull_with(&self, other: &i32) -> Self::Output {
684        if *self < *other {
685            Interval::new(*self, *other)
686        } else {
687            Interval::new(*other, *self)
688        }
689    }
690}
691
692impl<T> Hull<Interval<T>> for Interval<T>
693where
694    T: Copy + Ord,
695{
696    type Output = Interval<T>;
697
698    /// The `hull_with` function calculates the hull (bounding interval) of two intervals by taking the
699    /// minimum lower bound and maximum upper bound.
700    ///
701    /// Arguments:
702    ///
703    /// * `other`: `other` is a reference to an `Interval<T>` object that is being passed as a parameter
704    ///   to the `hull_with` method.
705    #[inline]
706    fn hull_with(&self, other: &Interval<T>) -> Self::Output {
707        Self::Output {
708            lb: self.lb.min(other.lb),
709            ub: self.ub.max(other.ub),
710            _marker: self._marker,
711        }
712    }
713}
714
715impl<T> Hull<T> for Interval<T>
716where
717    T: Copy + Ord,
718{
719    type Output = Interval<T>;
720
721    /// The `hull_with` function calculates the hull (minimum and maximum values) between two values.
722    ///
723    /// Arguments:
724    ///
725    /// * `other`: The `other` parameter is a reference to a value of type `T`, which is the same type
726    ///   as the values stored in the struct implementing the `hull_with` method. In this method, the
727    ///   `other` value is used to update the lower bound (`lb`) and upper bound (`
728    #[inline]
729    fn hull_with(&self, other: &T) -> Self::Output {
730        Self::Output {
731            lb: self.lb.min(*other),
732            ub: self.ub.max(*other),
733            _marker: self._marker,
734        }
735    }
736}
737
738impl<T> Hull<Interval<T>> for T
739where
740    T: Copy + Ord,
741{
742    type Output = Interval<T>;
743
744    /// The `hull_with` function in Rust calculates the convex hull of two intervals.
745    ///
746    /// Arguments:
747    ///
748    /// * `other`: The `other` parameter in the `hull_with` function is a reference to an `Interval<T>`
749    ///   object.
750    #[inline]
751    fn hull_with(&self, other: &Interval<T>) -> Self::Output {
752        other.hull_with(self)
753    }
754}
755
756/// The above code is defining a trait in Rust called `Intersect`. This trait has one associated type
757/// `Output` and one method `intersect_with` that takes a reference to another object of type `T` and
758/// returns an object of type `Output`. This trait can be implemented for various types to provide
759/// custom intersection behavior.
760pub trait Intersect<T: ?Sized> {
761    type Output;
762
763    fn intersect_with(&self, other: &T) -> Self::Output;
764}
765
766impl Intersect<i32> for i32 {
767    type Output = Interval<i32>;
768
769    /// The `intersect_with` function calculates the intersection of two values by finding the maximum
770    /// lower bound and minimum upper bound.
771    ///
772    /// Arguments:
773    ///
774    /// * `other`: The `other` parameter in the `intersect_with` function is a reference to an `i32`
775    ///   type. This parameter is used to find the intersection between the current instance (self) and
776    ///   the provided `i32` value.
777    #[inline]
778    fn intersect_with(&self, other: &i32) -> Self::Output {
779        Self::Output {
780            lb: (*self).max(*other),
781            ub: (*self).min(*other),
782            _marker: PhantomData,
783        }
784    }
785}
786
787impl<T> Intersect<Interval<T>> for Interval<T>
788where
789    T: Copy + Ord,
790{
791    type Output = Interval<T>;
792
793    /// The `intersect_with` function returns the intersection of two intervals by finding the maximum
794    /// lower bound and minimum upper bound between them.
795    ///
796    /// Arguments:
797    ///
798    /// * `other`: The `other` parameter is a reference to an `Interval<T>` object, which is used to
799    ///   intersect with the current `Interval<T>` object. The `intersect_with` method calculates the
800    ///   intersection of the two intervals and returns a new `Interval<T>` object as the output.
801    #[inline]
802    fn intersect_with(&self, other: &Interval<T>) -> Self::Output {
803        Self::Output {
804            lb: self.lb.max(other.lb),
805            ub: self.ub.min(other.ub),
806            _marker: self._marker,
807        }
808    }
809}
810
811impl<T> Intersect<T> for Interval<T>
812where
813    T: Copy + Ord,
814{
815    type Output = Interval<T>;
816
817    /// The `intersect_with` function calculates the intersection of two values.
818    ///
819    /// Arguments:
820    ///
821    /// * `other`: The `other` parameter is a reference to an object of type `T`, which is the same type
822    ///   as the object on which the `intersect_with` method is being called. The method calculates the
823    ///   intersection of the object's lower bound (`lb`) and upper bound (`ub`) with the corresponding
824    ///   values
825    #[inline]
826    fn intersect_with(&self, other: &T) -> Self::Output {
827        Self::Output {
828            lb: self.lb.max(*other),
829            ub: self.ub.min(*other),
830            _marker: self._marker,
831        }
832    }
833}
834
835impl<T> Intersect<Interval<T>> for T
836where
837    T: Copy + Ord,
838{
839    type Output = Interval<T>;
840
841    /// The `intersect_with` function in Rust swaps the receiver and argument before calling the
842    /// `intersect_with` method on the argument.
843    ///
844    /// Arguments:
845    ///
846    /// * `other`: The `other` parameter in the `intersect_with` function represents another
847    ///   `Interval<T>` that you want to intersect with the current interval.
848    #[inline]
849    fn intersect_with(&self, other: &Interval<T>) -> Self::Output {
850        other.intersect_with(self)
851    }
852}
853
854#[cfg(test)]
855mod tests {
856    use super::*;
857
858    #[test]
859    fn test_interval() {
860        let interval_a = Interval::new(4, 8);
861        let interval_b = Interval::new(5, 6);
862
863        assert!(interval_a <= interval_b);
864        assert!(interval_b <= interval_a);
865        assert!(interval_a >= interval_b);
866        assert!(interval_b >= interval_a);
867
868        assert!(interval_a.overlaps(&interval_b));
869        assert!(interval_b.overlaps(&interval_a));
870        // assert!(!contain(&interval_a, &interval_b));
871        assert!(interval_a.contains(&4));
872        assert!(interval_a.contains(&8));
873        assert!(interval_a.contains(&interval_b));
874        assert_eq!(interval_a, interval_a);
875        assert_eq!(interval_b, interval_b);
876        assert_ne!(interval_a, interval_b);
877        assert_ne!(interval_b, interval_a);
878        assert!(interval_a.overlaps(&interval_a));
879        assert!(interval_b.overlaps(&interval_b));
880        assert!(interval_a.contains(&interval_a));
881        assert!(interval_b.contains(&interval_b));
882        assert!(interval_a.overlaps(&interval_b));
883        assert!(interval_b.overlaps(&interval_a));
884    }
885
886    #[test]
887    fn test_hull_more_cases() {
888        let interval_a = Interval::new(3, 5);
889        let interval_b = Interval::new(1, 7);
890        assert_eq!(interval_a.hull_with(&interval_b), Interval::new(1, 7));
891
892        let interval_c = Interval::new(-2, 2);
893        assert_eq!(interval_a.hull_with(&interval_c), Interval::new(-2, 5));
894
895        let val_d = 4;
896        assert_eq!(interval_a.hull_with(&val_d), Interval::new(3, 5));
897
898        let val_e = 8;
899        assert_eq!(interval_a.hull_with(&val_e), Interval::new(3, 8));
900
901        let val_f = 0;
902        assert_eq!(interval_a.hull_with(&val_f), Interval::new(0, 5));
903    }
904
905    #[test]
906    fn test_interval1() {
907        let interval_a = Interval::new(4, 5);
908        let interval_b = Interval::new(6, 8);
909        assert!(interval_a < interval_b);
910        assert!(!(interval_b == interval_a));
911        assert!(interval_b != interval_a);
912    }
913
914    #[test]
915    fn test_interval2() {
916        let interval_a = Interval::new(4, 8);
917        let interval_b = Interval::new(5, 6);
918
919        assert!(interval_a.contains(&4));
920        assert!(interval_a.contains(&8));
921        assert!(interval_a.contains(&interval_b));
922        // assert!(interval_a.intersect_with(&8) == Interval::new(8, 8));
923        // assert!(interval_a.intersect_with(interval_b) == interval_b);
924        assert!(!interval_b.contains(&interval_a));
925        assert!(interval_a.overlaps(&interval_b));
926        assert!(interval_b.overlaps(&interval_a));
927    }
928
929    #[test]
930    fn test_interval3() {
931        let interval_a = Interval::new(3, 4);
932        assert!(interval_a.lb == 3);
933        assert!(interval_a.ub == 4);
934        // assert!(interval_a.length() == 1);
935        assert!(interval_a.contains(&3));
936        assert!(interval_a.contains(&4));
937        assert!(!interval_a.contains(&5));
938        assert!(interval_a.contains(&Interval::new(3, 4)));
939        assert!(!interval_a.contains(&Interval::new(3, 5)));
940        assert!(!interval_a.contains(&Interval::new(2, 3)));
941        assert!(!interval_a.contains(&2));
942        assert!(interval_a.contains(&4));
943        assert!(!interval_a.contains(&5));
944    }
945
946    #[test]
947    fn test_arithmetic() {
948        let mut interval_a = Interval::new(3, 5);
949        // interval_b = Interval::new(5, 7);
950        // interval_c = Interval::new(7, 8);
951        assert_eq!(interval_a + 1, Interval::new(4, 6));
952        assert_eq!(interval_a - 1, Interval::new(2, 4));
953        assert_eq!(interval_a * 2, Interval::new(6, 10));
954        assert!(-interval_a == Interval::new(-5, -3));
955        interval_a += 1;
956        assert!(interval_a == Interval::new(4, 6));
957        interval_a -= 1;
958        assert!(interval_a == Interval::new(3, 5));
959        interval_a *= 2;
960        assert!(interval_a == Interval::new(6, 10));
961    }
962
963    #[test]
964    fn test_overlap() {
965        let interval_a = Interval::new(3, 5);
966        let interval_b = Interval::new(5, 7);
967        let interval_c = Interval::new(7, 8);
968        assert!(interval_a.overlaps(&interval_b));
969        assert!(interval_b.overlaps(&interval_c));
970        assert!(!interval_a.overlaps(&interval_c));
971        assert!(!interval_c.overlaps(&interval_a));
972
973        let val_d = 4;
974        assert!(interval_a.overlaps(&val_d));
975        assert!(!interval_a.overlaps(&6));
976        assert!(val_d.overlaps(&interval_a));
977        assert!(val_d.overlaps(&val_d));
978    }
979
980    #[test]
981    fn test_contains() {
982        let interval_a = Interval::new(3, 5);
983        let interval_b = Interval::new(5, 7);
984        let interval_c = Interval::new(7, 8);
985        assert!(!interval_a.contains(&interval_b));
986        assert!(!interval_b.contains(&interval_c));
987        assert!(!interval_a.contains(&interval_c));
988        assert!(!interval_c.contains(&interval_a));
989
990        let val_d = 4;
991        assert!(interval_a.contains(&val_d));
992        assert!(!interval_a.contains(&6));
993        assert!(!val_d.contains(&interval_a));
994        assert!(val_d.contains(&val_d));
995    }
996
997    #[test]
998    fn test_intersect() {
999        let interval_a = Interval::new(3, 5);
1000        let interval_b = Interval::new(5, 7);
1001        let interval_c = Interval::new(7, 8);
1002        assert_eq!(interval_a.intersect_with(&interval_b), Interval::new(5, 5));
1003        assert_eq!(interval_b.intersect_with(&interval_c), Interval::new(7, 7));
1004        assert!(interval_a.intersect_with(&interval_c).is_invalid());
1005        assert_eq!(interval_a.intersect_with(&interval_b), Interval::new(5, 5));
1006        assert_eq!(interval_b.intersect_with(&interval_c), Interval::new(7, 7));
1007        let val_d = 4;
1008        assert_eq!(interval_a.intersect_with(&val_d), Interval::new(4, 4));
1009        assert!(interval_a.intersect_with(&6).is_invalid());
1010        assert_eq!(interval_a.intersect_with(&val_d), Interval::new(4, 4));
1011        assert_eq!(val_d.intersect_with(&interval_a), Interval::new(4, 4));
1012        assert_eq!(val_d.intersect_with(&val_d), Interval::new(4, 4));
1013    }
1014
1015    #[test]
1016    fn test_hull() {
1017        let interval_a = Interval::new(3, 5);
1018        let interval_b = Interval::new(5, 7);
1019        let interval_c = Interval::new(7, 8);
1020        assert_eq!(interval_a.hull_with(&interval_b), Interval::new(3, 7));
1021        assert_eq!(interval_b.hull_with(&interval_c), Interval::new(5, 8));
1022        assert_eq!(interval_a.hull_with(&interval_c), Interval::new(3, 8));
1023        let val_d = 4;
1024        assert_eq!(interval_a.hull_with(&val_d), Interval::new(3, 5));
1025        assert_eq!(interval_a.hull_with(&6), Interval::new(3, 6));
1026        // assert_eq!(hull(interval_a, val_d), Interval::new(3, 5));
1027        // assert_eq!(hull(interval_a, 6), Interval::new(3, 6));
1028        // assert_eq!(hull(val_d, interval_a), Interval::new(3, 5));
1029        // assert!(hull(6, interval_a) == Interval::new(3, 6));
1030        // assert!(hull(val_d, 6) == Interval::new(4, 6));
1031    }
1032
1033    #[test]
1034    fn test_min_dist() {
1035        let interval_a = Interval::new(3, 5);
1036        let interval_b = Interval::new(5, 7);
1037        let interval_c = Interval::new(7, 8);
1038        assert_eq!(interval_a.min_dist_with(&interval_b), 0);
1039        assert_eq!(interval_a.min_dist_with(&interval_c), 2);
1040        assert_eq!(interval_b.min_dist_with(&interval_c), 0);
1041        let val_d = 4;
1042        assert_eq!(interval_a.min_dist_with(&val_d), 0);
1043        assert_eq!(val_d.min_dist_with(&interval_a), 0);
1044        assert_eq!(interval_a.min_dist_with(&6), 1);
1045        assert_eq!(6.min_dist_with(&interval_a), 1);
1046    }
1047
1048    #[test]
1049    fn test_displacement() {
1050        let interval_a = Interval::new(3, 5);
1051        let interval_b = Interval::new(5, 7);
1052        let interval_c = Interval::new(7, 8);
1053        assert_eq!(interval_a.displace(&interval_b), Interval::new(-2, -2));
1054        assert_eq!(interval_a.displace(&interval_c), Interval::new(-4, -3));
1055        assert_eq!(interval_b.displace(&interval_c), Interval::new(-2, -1));
1056        let val_d = 4;
1057        assert_eq!(val_d.displace(&val_d), 0);
1058        assert_eq!(val_d.displace(&6), -2);
1059        assert_eq!(6.displace(&val_d), 2);
1060    }
1061
1062    #[test]
1063    fn test_enlarge() {
1064        let interval_a = Interval::new(3, 5);
1065        assert!(interval_a.enlarge_with(2) == Interval::new(1, 7));
1066        let val_d = 4;
1067        assert_eq!(val_d.enlarge_with(6), Interval::new(-2, 10));
1068        assert_eq!(6.enlarge_with(val_d), Interval::new(2, 10));
1069    }
1070}
1071
1072#[test]
1073fn test_interval_length() {
1074    let interval = Interval::new(3, 8);
1075    assert_eq!(interval.length(), 5);
1076
1077    let interval2 = Interval::new(-2, 3);
1078    assert_eq!(interval2.length(), 5);
1079}
1080
1081#[test]
1082fn test_interval_display() {
1083    let interval = Interval::new(3, 8);
1084    let display_str = format!("{}", interval);
1085    assert_eq!(display_str, "[3, 8]");
1086
1087    let interval2 = Interval::new(-5, 10);
1088    let display_str2 = format!("{}", interval2);
1089    assert_eq!(display_str2, "[-5, 10]");
1090}
1091
1092#[test]
1093fn test_interval_sub_interval() {
1094    let interval_a = Interval::new(5, 10);
1095    let interval_b = Interval::new(2, 3);
1096    let result = interval_a - interval_b;
1097    assert_eq!(result, Interval::new(3, 7));
1098}
1099
1100#[test]
1101fn test_interval_add_interval() {
1102    let interval_a = Interval::new(1, 3);
1103    let interval_b = Interval::new(2, 5);
1104    let result = interval_a + interval_b;
1105    assert_eq!(result, Interval::new(3, 8));
1106}
1107
1108#[test]
1109fn test_interval_is_invalid() {
1110    let valid_interval = Interval::new(1, 5);
1111    assert!(!valid_interval.is_invalid());
1112
1113    let invalid_interval = Interval::new(5, 1);
1114    assert!(invalid_interval.is_invalid());
1115}
1116
1117#[test]
1118fn test_interval_sub_assign_interval() {
1119    let mut interval = Interval::new(10, 20);
1120    interval -= 3;
1121    assert_eq!(interval, Interval::new(7, 17));
1122}
1123
1124#[test]
1125fn test_interval_hull_t_for_t() {
1126    let val = 5;
1127    let interval = Interval::new(3, 8);
1128    // T as Hull<Interval<T>>
1129    let result = val.hull_with(&interval);
1130    assert_eq!(result.lb, 3);
1131    assert_eq!(result.ub, 8);
1132}
1133
1134#[test]
1135fn test_interval_contains_interval_t() {
1136    let interval = Interval::new(3, 8);
1137    // Contain<Interval<T>> for T - always returns false
1138    let val = 5;
1139    assert!(!val.contains(&interval));
1140}
1141
1142#[test]
1143fn test_interval_overlap_interval_t() {
1144    // Overlap<Interval<T>> for T
1145    let val = 5;
1146    let interval = Interval::new(3, 8);
1147    assert!(val.overlaps(&interval));
1148
1149    let val2 = 10;
1150    assert!(!val2.overlaps(&interval));
1151}
1152
1153#[test]
1154fn test_interval_partial_cmp_greater() {
1155    let interval_a = Interval::new(8, 10);
1156    let interval_b = Interval::new(3, 5);
1157    // interval_a is greater than interval_b (no overlap, ub > other.lb)
1158    let cmp = interval_a.partial_cmp(&interval_b);
1159    assert_eq!(cmp, Some(std::cmp::Ordering::Greater));
1160}