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