interval.rs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. use std::{
  2. cmp::{max, min},
  3. fmt,
  4. ops::{Range, RangeInclusive, RangeTo, RangeToInclusive},
  5. };
  6. /// Representing a closed-open range;
  7. /// the interval [5, 7) is the set {5, 6}.
  8. ///
  9. /// It is an invariant that `start <= end`. An interval where `end < start` is
  10. /// considered empty.
  11. #[derive(Clone, Copy, PartialEq, Eq)]
  12. pub struct Interval {
  13. pub start: usize,
  14. pub end: usize,
  15. }
  16. impl Interval {
  17. /// Construct a new `Interval` representing the range [start..end).
  18. /// It is an invariant that `start <= end`.
  19. pub fn new(start: usize, end: usize) -> Interval {
  20. debug_assert!(start <= end);
  21. Interval { start, end }
  22. }
  23. pub fn start(&self) -> usize {
  24. self.start
  25. }
  26. pub fn end(&self) -> usize {
  27. self.end
  28. }
  29. pub fn start_end(&self) -> (usize, usize) {
  30. (self.start, self.end)
  31. }
  32. pub fn is_before(&self, val: usize) -> bool {
  33. self.end <= val
  34. }
  35. pub fn contains(&self, val: usize) -> bool {
  36. self.start <= val && val < self.end
  37. }
  38. pub fn contains_range(&self, start: usize, end: usize) -> bool {
  39. !self.intersect(Interval::new(start, end)).is_empty()
  40. }
  41. pub fn is_after(&self, val: usize) -> bool {
  42. self.start > val
  43. }
  44. pub fn is_empty(&self) -> bool {
  45. self.end <= self.start
  46. }
  47. pub fn intersect(&self, other: Interval) -> Interval {
  48. let start = max(self.start, other.start);
  49. let end = min(self.end, other.end);
  50. Interval {
  51. start,
  52. end: max(start, end),
  53. }
  54. }
  55. // the first half of self - other
  56. pub fn prefix(&self, other: Interval) -> Interval {
  57. Interval {
  58. start: min(self.start, other.start),
  59. end: min(self.end, other.start),
  60. }
  61. }
  62. // the second half of self - other
  63. pub fn suffix(&self, other: Interval) -> Interval {
  64. Interval {
  65. start: max(self.start, other.end),
  66. end: max(self.end, other.end),
  67. }
  68. }
  69. pub fn translate(&self, amount: usize) -> Interval {
  70. Interval {
  71. start: self.start + amount,
  72. end: self.end + amount,
  73. }
  74. }
  75. pub fn translate_neg(&self, amount: usize) -> Interval {
  76. debug_assert!(self.start >= amount);
  77. Interval {
  78. start: self.start - amount,
  79. end: self.end - amount,
  80. }
  81. }
  82. pub fn union(&self, other: Interval) -> Interval {
  83. if self.is_empty() {
  84. return other;
  85. }
  86. if other.is_empty() {
  87. return *self;
  88. }
  89. let start = min(self.start, other.start);
  90. let end = max(self.end, other.end);
  91. Interval { start, end }
  92. }
  93. pub fn size(&self) -> usize {
  94. self.end - self.start
  95. }
  96. }
  97. impl std::default::Default for Interval {
  98. fn default() -> Self {
  99. Interval::new(0, 0)
  100. }
  101. }
  102. impl fmt::Display for Interval {
  103. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  104. write!(f, "[{}, {})", self.start(), self.end())
  105. }
  106. }
  107. impl fmt::Debug for Interval {
  108. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  109. fmt::Display::fmt(self, f)
  110. }
  111. }
  112. impl From<Range<usize>> for Interval {
  113. fn from(src: Range<usize>) -> Interval {
  114. let Range { start, end } = src;
  115. Interval { start, end }
  116. }
  117. }
  118. impl From<RangeTo<usize>> for Interval {
  119. fn from(src: RangeTo<usize>) -> Interval {
  120. Interval::new(0, src.end)
  121. }
  122. }
  123. impl From<RangeInclusive<usize>> for Interval {
  124. fn from(src: RangeInclusive<usize>) -> Interval {
  125. Interval::new(*src.start(), src.end().saturating_add(1))
  126. }
  127. }
  128. impl From<RangeToInclusive<usize>> for Interval {
  129. fn from(src: RangeToInclusive<usize>) -> Interval {
  130. Interval::new(0, src.end.saturating_add(1))
  131. }
  132. }
  133. #[cfg(test)]
  134. mod tests {
  135. use crate::core::interval::Interval;
  136. #[test]
  137. fn contains() {
  138. let i = Interval::new(2, 42);
  139. assert!(!i.contains(1));
  140. assert!(i.contains(2));
  141. assert!(i.contains(3));
  142. assert!(i.contains(41));
  143. assert!(!i.contains(42));
  144. assert!(!i.contains(43));
  145. }
  146. #[test]
  147. fn before() {
  148. let i = Interval::new(2, 42);
  149. assert!(!i.is_before(1));
  150. assert!(!i.is_before(2));
  151. assert!(!i.is_before(3));
  152. assert!(!i.is_before(41));
  153. assert!(i.is_before(42));
  154. assert!(i.is_before(43));
  155. }
  156. #[test]
  157. fn after() {
  158. let i = Interval::new(2, 42);
  159. assert!(i.is_after(1));
  160. assert!(!i.is_after(2));
  161. assert!(!i.is_after(3));
  162. assert!(!i.is_after(41));
  163. assert!(!i.is_after(42));
  164. assert!(!i.is_after(43));
  165. }
  166. #[test]
  167. fn translate() {
  168. let i = Interval::new(2, 42);
  169. assert_eq!(Interval::new(5, 45), i.translate(3));
  170. assert_eq!(Interval::new(1, 41), i.translate_neg(1));
  171. }
  172. #[test]
  173. fn empty() {
  174. assert!(Interval::new(0, 0).is_empty());
  175. assert!(Interval::new(1, 1).is_empty());
  176. assert!(!Interval::new(1, 2).is_empty());
  177. }
  178. #[test]
  179. fn intersect() {
  180. assert_eq!(Interval::new(2, 3), Interval::new(1, 3).intersect(Interval::new(2, 4)));
  181. assert!(Interval::new(1, 2).intersect(Interval::new(2, 43)).is_empty());
  182. }
  183. #[test]
  184. fn prefix() {
  185. assert_eq!(Interval::new(1, 2), Interval::new(1, 4).prefix(Interval::new(2, 3)));
  186. }
  187. #[test]
  188. fn suffix() {
  189. assert_eq!(Interval::new(3, 4), Interval::new(1, 4).suffix(Interval::new(2, 3)));
  190. }
  191. #[test]
  192. fn size() {
  193. assert_eq!(40, Interval::new(2, 42).size());
  194. assert_eq!(0, Interval::new(1, 1).size());
  195. assert_eq!(1, Interval::new(1, 2).size());
  196. }
  197. }