physdes/
interval.rs

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