intervals_rs/interval_limit.rs
1use std::cmp::Ordering;
2use std::fmt::{Display, Formatter, Debug};
3
4use crate::LimitValue;
5use std::hash::Hash;
6
7/// A struct that represents a "limit" in an interval.
8///
9/// In order to understand this struct, it is important to correctly recognize the distinction between `limit` and `value`.
10/// The limit is the value represented by this struct `self`, and the value represented by `value` is the limit value.
11///
12/// When a limit is "closed", it means that the limit itself is not considered to be exceeded.
13/// An "open" limit means that it is considered to be exceeded.
14///
15/// An infinite limit is an unbounded limit, and we express this state by saying that `value` is `Limitless`.
16/// Infinite limits are always considered to be open.
17/// Conversely, a limit that is not an infinite limit (one whose `value` is not `Limitless`) is called a finite limit.
18///
19/// The lower limit represents the limit where values below (or below) the limit are considered to be exceeded,
20/// and the upper limit represents the limit where values above (or above) the limit are considered to be exceeded.
21///
22/// closed: if the limit is closed `true
23/// lower: `true` for the lower limit, `false` for the upper limit
24/// value: limit value, in the case of Limitless, it indicates that there is no limit.
25#[derive(Debug, Clone, Hash, Eq, Ord)]
26pub struct IntervalLimit<T: Display + Clone + Hash + Ord> {
27 closed: bool,
28 lower: bool,
29 value: LimitValue<T>,
30}
31
32impl<T: Display + Clone + Hash + Eq + Ord + PartialEq + PartialOrd> PartialEq for IntervalLimit<T> {
33 fn eq(&self, other: &Self) -> bool {
34 self.partial_cmp(other) == Some(Ordering::Equal)
35 }
36}
37
38impl<T: Display + Clone + Hash + Eq + Ord + PartialEq + PartialOrd> PartialOrd
39 for IntervalLimit<T>
40{
41 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
42 if self.value.is_limitless() && other.value.is_limitless() {
43 if self.lower == other.lower {
44 Some(Ordering::Equal)
45 } else {
46 self.lower_to_ordering(Some(Ordering::Less), Some(Ordering::Greater))
47 }
48 } else if self.value.is_limitless() {
49 self.lower_to_ordering(Some(Ordering::Less), Some(Ordering::Greater))
50 } else if other.value.is_limitless() {
51 other.lower_to_ordering(Some(Ordering::Greater), Some(Ordering::Less))
52 } else if self.value == other.value {
53 if self.lower && other.lower {
54 if self.closed ^ other.closed {
55 self.closed_to_ordering(Some(Ordering::Less), Some(Ordering::Greater))
56 } else {
57 Some(Ordering::Equal)
58 }
59 } else if !self.lower && !other.lower {
60 if self.closed ^ other.closed {
61 self.closed_to_ordering(Some(Ordering::Greater), Some(Ordering::Less))
62 } else {
63 Some(Ordering::Equal)
64 }
65 } else {
66 self.lower_to_ordering(Some(Ordering::Less), Some(Ordering::Greater))
67 }
68 } else {
69 self.value.partial_cmp(&other.value)
70 }
71 }
72}
73
74impl<T: Display + Clone + Hash + Eq + Ord + PartialEq + PartialOrd> IntervalLimit<T> {
75 /// Verify whether this limit is closed or not.
76 ///
77 /// - return: if it is closed, `true`, otherwise `false`.
78 pub fn is_closed(&self) -> bool {
79 self.closed
80 }
81
82 /// Verify whether this limit is open or not.
83 ///
84 /// - return: if it is open, `true`, otherwise `false`.
85 pub fn is_open(&self) -> bool {
86 !self.closed
87 }
88
89 /// Verify whether or not this limit is the lower side limit.
90 ///
91 /// - return: `true` for an lower limit, `false` otherwise
92 pub fn is_lower(&self) -> bool {
93 self.lower
94 }
95
96 /// Verify whether or not this limit is the upper side limit.
97 ///
98 /// - return: `true` for an upper limit, `false` otherwise
99 pub fn is_upper(&self) -> bool {
100 !self.lower
101 }
102
103 /// Verify whether this limit is an infinite limit.
104 ///
105 /// - return: if it is an infinite limit, it is `true`, otherwise it is `false
106 pub fn is_infinity(&self) -> bool {
107 self.value.is_limitless()
108 }
109
110 /// Verify whether this limit is an finite limit.
111 ///
112 /// - return: if it is an finite limit, it is `true`, otherwise it is `false
113 pub fn is_finite(&self) -> bool {
114 self.value.is_limit()
115 }
116
117 /// Get limit value.
118 ///
119 /// - return: limit value
120 pub fn as_value(&self) -> &LimitValue<T> {
121 &self.value
122 }
123
124 /// Generate a limit
125 ///
126 /// - params
127 /// - closed: if the limit is closed `true
128 /// - lower: `true` for the lower limit, `false` for the upper limit
129 /// - value: limit value, in the case of Limitless, it indicates that there is no limit.
130 /// - return: a new limit
131 pub fn new(closed: bool, lower: bool, value: LimitValue<T>) -> Self {
132 Self {
133 closed: if value.is_limitless() { false } else { closed },
134 lower,
135 value,
136 }
137 }
138
139 /// Generate a lower limit
140 ///
141 /// - params
142 /// - closed: if the limit is closed `true
143 /// - value: limit value, in the case of Limitless, it indicates that there is no limit.
144 /// - return: a new limit
145 pub fn lower(closed: bool, value: LimitValue<T>) -> Self {
146 Self::new(closed, true, value)
147 }
148
149 /// Generate a upper limit
150 ///
151 /// - params
152 /// - closed: if the limit is closed `true
153 /// - value: limit value, in the case of Limitless, it indicates that there is no limit.
154 /// - return: a new limit
155 pub fn upper(closed: bool, value: LimitValue<T>) -> Self {
156 Self::new(closed, false, value)
157 }
158
159 fn lower_to_ordering<A>(&self, t: A, f: A) -> A {
160 if self.lower {
161 t
162 } else {
163 f
164 }
165 }
166
167 fn closed_to_ordering<A>(&self, t: A, f: A) -> A {
168 if self.closed {
169 t
170 } else {
171 f
172 }
173 }
174}
175
176impl<T: Display + Clone + Hash + Eq + Ord + PartialEq + PartialOrd> Display for IntervalLimit<T> {
177 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
178 write!(
179 f,
180 "IntervalLimit({}, {}, {})",
181 self.closed, self.lower, self.value
182 )
183 }
184}