physdes/
interval_ai.rs

1use std::cmp::PartialOrd;
2use std::marker::PhantomData;
3
4trait Overlaps<T> {
5    fn overlaps(&self, other: &T) -> bool;
6}
7
8trait Contains<T> {
9    fn contains(&self, other: &T) -> bool;
10}
11
12impl<T: PartialOrd> Overlaps<Interval<T>> for Interval<T> {
13    fn overlaps(&self, other: &Interval<T>) -> bool {
14        !(self < other || other < self)
15    }
16}
17
18impl<T: PartialOrd> Contains<Interval<T>> for Interval<T> {
19    fn contains(&self, other: &Interval<T>) -> bool {
20        self.lb <= other.lb && other.ub <= self.ub
21    }
22}
23
24impl<T: PartialOrd> Contains<T> for Interval<T> {
25    fn contains(&self, other: &T) -> bool {
26        self.lb <= *other && *other <= self.ub
27    }
28}
29
30/// The `Interval` struct represents a range of values with a lower bound (`lb`) and an upper bound
31/// (`ub`).
32///
33/// Properties:
34///
35/// * `lb`: The `lb` property represents the lower bound of the interval. It is of type `T`, which is a
36/// generic type that must implement the `PartialOrd` trait. This means that the type `T` must be able
37/// to be compared for ordering.
38/// * `ub`: The `ub` property represents the upper bound of the interval. It is of type `T`, which is a
39/// generic type that must implement the `PartialOrd` trait. The `PartialOrd` trait allows for
40/// comparison between values of type `T`.
41/// * `_marker`: The `_marker` field is a marker field that is used to indicate that the generic type
42/// `T` is used in the struct. It is typically used when you want to associate a type parameter with a
43/// struct, but you don't actually need to store any values of that type in the struct.
44#[derive(Debug)]
45pub struct Interval<T: PartialOrd> {
46    pub lb: T,
47    pub ub: T,
48    pub _marker: PhantomData<T>,
49}
50
51impl<T: PartialOrd> Interval<T> {
52    /// The function `new` creates a new instance of a struct with given lower and upper bounds.
53    ///
54    /// Arguments:
55    ///
56    /// * `lb`: The `lb` parameter represents the lower bound value. It is of type `T`, which means it
57    /// can be any type that implements the necessary traits for the struct.
58    /// * `ub`: The `ub` parameter represents the upper bound value. It is of type `T`, which means it
59    /// can be any type that implements the necessary traits for the struct.
60    ///
61    /// Returns:
62    ///
63    /// The `new` function is returning an instance of the struct `Self`.
64    ///
65    /// # Examples
66    ///
67    /// ```
68    /// use physdes::interval_ai::Interval;
69    /// use std::marker::PhantomData;
70    ///
71    /// assert_eq!(Interval::new(1, 2), Interval { lb: 1, ub: 2, _marker: PhantomData });
72    /// assert_eq!(Interval::new(2, 1), Interval { lb: 2, ub: 1, _marker: PhantomData });
73    /// ```
74    pub fn new(lb: T, ub: T) -> Self {
75        Self {
76            lb,
77            ub,
78            _marker: PhantomData,
79        }
80    }
81}
82
83impl<T: PartialOrd> PartialOrd for Interval<T> {
84    /// The function `partial_cmp` compares the lower bound of `self` with the upper bound of `other`
85    /// and returns the result as an `Option` of `Ordering`.
86    ///
87    /// Arguments:
88    ///
89    /// * `other`: The `other` parameter is a reference to another object of the same type as `self`.
90    ///
91    /// Returns:
92    ///
93    /// an `Option` containing a `std::cmp::Ordering` value.
94    ///
95    /// # Examples
96    ///
97    /// ```
98    /// use physdes::interval_ai::Interval;
99    /// use std::marker::PhantomData;
100    /// assert_eq!(Interval::new(1, 2).partial_cmp(&Interval::new(2, 3)), Some(std::cmp::Ordering::Less));
101    /// ```
102    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
103        self.lb.partial_cmp(&other.ub)
104    }
105}
106
107impl<T: PartialOrd> PartialEq for Interval<T> {
108    /// The function checks if two objects have equal values for their "lb" and "ub" fields.
109    ///
110    /// Arguments:
111    ///
112    /// * `other`: The `other` parameter is a reference to another object of the same type as `Self`. In
113    /// this case, `Self` refers to the type of the object implementing the `eq` method.
114    ///
115    /// Returns:
116    ///
117    /// A boolean value is being returned.
118    ///
119    /// # Examples
120    ///
121    /// ```
122    /// use physdes::interval_ai::Interval;
123    /// assert_eq!(Interval::new(1, 2), Interval::new(1, 2));
124    /// ```
125    fn eq(&self, other: &Self) -> bool {
126        self.lb == other.lb && self.ub == other.ub
127    }
128}
129
130pub fn overlap<T: PartialOrd>(lhs: &Interval<T>, rhs: &Interval<T>) -> bool {
131    lhs.overlaps(rhs) || rhs.overlaps(lhs) || lhs == rhs
132}
133
134pub fn contain<T: PartialOrd>(lhs: &Interval<T>, rhs: &Interval<T>) -> bool {
135    lhs.contains(rhs) && !rhs.contains(lhs)
136}
137
138#[cfg(test)]
139mod tests {
140    use super::*;
141
142    #[test]
143    fn test_interval() {
144        let a = Interval::new(4, 8);
145        let b = Interval::new(5, 6);
146        assert!(!overlap(&a, &b));
147        assert!(!overlap(&b, &a));
148        // assert!(!contain(&a, &b));
149        assert!(a.contains(&4));
150        assert!(a.contains(&8));
151        assert!(a.contains(&b));
152        assert_eq!(a, a);
153        assert_eq!(b, b);
154        assert_ne!(a, b);
155        assert_ne!(b, a);
156        assert!(overlap(&a, &a));
157        assert!(overlap(&b, &b));
158        assert!(!contain(&a, &a));
159        assert!(!contain(&b, &b));
160        // assert!(a.overlaps(&b));
161        // assert!(b.overlaps(&a));
162    }
163}