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}