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}