1use crate::BaseInterval;
2use intfloat::IntFloat;
3use num_traits::{Num, ToPrimitive};
4use rust_decimal::Decimal;
5use std::cmp::PartialOrd;
6use std::fmt;
7use std::fmt::{Debug, Display, Formatter};
8
9#[derive(Clone, Copy, Hash, Eq, PartialEq)]
10pub struct Interval<T: Num, U: Num> {
24 lb: T,
25 ub: T,
26 val: U,
27}
28
29impl<T, U> Default for Interval<T, U>
30where
31 T: Num + PartialOrd + Clone,
32 U: Num,
33{
34 fn default() -> Self {
35 Interval {
36 lb: T::zero(),
37 ub: T::one(),
38 val: U::one(),
39 }
40 }
41}
42
43impl<T, U> Debug for Interval<T, U>
44where
45 T: Num + PartialOrd + Clone + Display,
46 U: Num + PartialOrd + Display,
47{
48 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
49 write!(f, "{}", self.print())
50 }
51}
52
53impl<T, U> Display for Interval<T, U>
54where
55 T: Num + PartialOrd + Clone + Display,
56 U: Num + PartialOrd + Display,
57{
58 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
59 write!(f, "{}", self.print())
60 }
61}
62
63impl<T, U> Interval<T, U>
64where
65 T: Num + PartialOrd + Clone + Display,
66 U: Num + PartialOrd + Display,
67{
68 pub fn new(lb: T, ub: T, val: U) -> Self {
69 if ub > lb {
70 Interval { lb, ub, val }
71 } else {
72 Interval {
73 lb: ub,
74 ub: lb,
75 val,
76 }
77 }
78 }
79
80 pub fn print(&self) -> String {
81 format!("[{};{}]x{}", self.lb, self.ub, self.val)
82 }
83
84 pub fn to_tuple(self) -> (T, T, U) {
85 (self.lb, self.ub, self.val)
86 }
87
88 pub fn get_bounds(self) -> (T, T) {
89 (self.lb, self.ub)
90 }
91
92 pub fn get_lb(self) -> T {
93 self.lb
94 }
95
96 pub fn get_ub(self) -> T {
97 self.ub
98 }
99
100 pub fn get_width(self) -> T {
101 self.ub - self.lb
102 }
103
104 pub fn get_value(self) -> U {
105 self.val
106 }
107
108 pub fn len(self) -> T {
109 self.ub - self.lb
110 }
111
112 pub fn contains(self, num: T) -> bool {
113 if (num >= self.lb) & (num <= self.ub) {
114 true
115 } else {
116 false
117 }
118 }
119
120 pub fn superset(self, other: Interval<T, U>) -> bool {
122 if (other.ub <= self.ub) && (other.lb >= self.lb) {
123 true
124 } else {
125 false
126 }
127 }
128
129 pub fn subset(self, other: Interval<T, U>) -> bool {
130 other.superset(self)
131 }
132
133 pub fn left_overlaps(&self, other: &Interval<T, U>) -> bool {
134 if (self.lb <= other.lb) & (self.ub <= other.ub) & (other.lb <= self.ub) {
135 true
136 } else {
137 false
138 }
139 }
140
141 pub fn right_overlaps(self, other: &Interval<T, U>) -> bool {
142 other.left_overlaps(&self)
143 }
144
145 pub fn overlaps(self, other: &Interval<T, U>) -> bool {
146 self.left_overlaps(other) || self.right_overlaps(other)
147 }
148
149 pub fn can_join(self, other: &Interval<T, U>) -> bool {
150 if ((self.ub == other.lb) || (other.ub == self.lb)) && (self.val == other.val) {
151 true
152 } else if (self.ub == other.ub) && (self.lb == other.lb) {
153 true
154 } else {
155 false
156 }
157 }
158
159 pub fn join(self, other: Interval<T, U>) -> Interval<T, U> {
160 if (self.ub == other.ub) && (self.lb == other.lb) {
163 return Interval::new(self.lb, self.ub, self.val + other.val);
164 }
165
166 let (lb, ub) = if self.lb < other.lb {
168 (self.lb, other.ub)
169 } else {
170 (other.lb, self.ub)
171 };
172 Interval::new(lb, ub, self.val)
173 }
174
175 pub fn can_join_as_set(self, other: &Interval<T, U>) -> bool {
176 if self.overlaps(other) {
177 true
178 } else {
179 false
180 }
181 }
182
183 pub fn join_ign_value(self, other: Interval<T, U>) -> Interval<T, U> {
184 let lb = if self.lb < other.lb {
185 self.lb
186 } else {
187 other.lb
188 };
189 let ub = if self.ub > other.ub {
190 self.ub
191 } else {
192 other.ub
193 };
194 Interval::new(lb, ub, U::one())
195 }
196
197 pub fn join_as_set(self, other: Interval<T, U>) -> BaseInterval<T> {
198 let lb = if self.lb < other.lb {
199 self.lb
200 } else {
201 other.lb
202 };
203 let ub = if self.ub > other.ub {
204 self.ub
205 } else {
206 other.ub
207 };
208 BaseInterval::new(lb, ub)
209 }
210
211 pub fn to_base(self) -> BaseInterval<T> {
212 BaseInterval::new(self.lb, self.ub)
213 }
214}
215
216impl<T> Interval<T, T>
217where
218 T: Num,
219{
220 pub fn get_total_value(self) -> T {
221 (self.ub - self.lb) * self.val
222 }
223}
224
225impl<T, U> Interval<T, U>
226where
227 T: Num + Clone + PartialOrd + Display,
228 U: Num + PartialOrd + ToPrimitive,
229{
230 pub fn val_to_count(self) -> Interval<T, usize> {
231 if self.val >= U::one() {
233 Interval::new(self.lb, self.ub, self.val.to_usize().unwrap())
234 } else {
235 Interval::new(self.lb, self.ub, 0)
236 }
237 }
238}
239
240impl Interval<IntFloat, IntFloat> {
241 pub fn to_f32(self) -> (f32, f32, f32) {
242 (
243 self.lb.to_f32().unwrap(),
244 self.ub.to_f32().unwrap(),
245 self.val.to_f32().unwrap(),
246 )
247 }
248}
249
250impl Interval<Decimal, Decimal> {
251 pub fn to_f32(self) -> (f32, f32, f32) {
252 (
253 self.lb.to_f32().unwrap(),
254 self.ub.to_f32().unwrap(),
255 self.val.to_f32().unwrap(),
256 )
257 }
258}
259
260#[cfg(test)]
261mod tests {
262 use super::*;
263 use intfloat::IntFloat;
264 use num_traits::{FromPrimitive, One};
265
266 #[test]
267 fn test_create_int_interval() {
268 let a = Interval::new(1, 2, 1);
269 assert_eq!(a.len(), 1);
270 assert_eq!(a.get_value(), 1)
271 }
272
273 #[test]
274 fn test_create_float_interval() {
275 let a = Interval::new(1.0, 4.0, 2.0);
276 assert_eq!(a.len(), 3.0);
277 assert_eq!(a.get_value(), 2.0);
278 assert_eq!(a.get_total_value(), 6.0)
279 }
280
281 #[test]
282 fn test_create_mixed_interval() {
283 let a = Interval::new(1.0, 2.0, 1);
284 assert_eq!(a.len(), 1.0);
285 assert_eq!(a.get_value(), 1)
286 }
287
288 #[test]
289 fn test_create_mixed_interval2() {
290 let a = Interval::new(1, 2, 1.0);
291 assert_eq!(a.len(), 1);
292 assert_eq!(a.get_value(), 1.0)
293 }
294
295 #[test]
296 fn test_create_intfloat_interval() {
297 let a = Interval::new(
298 IntFloat::one(),
299 IntFloat::from(3.0, 0),
300 IntFloat::from(3.0, 0),
301 );
302 assert_eq!(a.len(), IntFloat::from(2.0, 0));
303 assert_eq!(a.get_value(), IntFloat::from(3.0, 0));
304 assert_eq!(a.get_total_value(), IntFloat::from(6.0, 0))
305 }
306
307 #[test]
308 fn test_bounds() {
309 let a = Interval::new(3, 7, 2);
310 assert_eq!(a.to_tuple(), (3, 7, 2));
311 assert_eq!(a.get_bounds(), (3, 7));
312 assert_eq!(a.get_lb(), 3);
313 assert_eq!(a.get_ub(), 7);
314 assert_eq!(a.get_width(), 4);
315 }
316
317 #[test]
318 fn test_total_value() {
319 let a = Interval::new(3, 7, 2);
320 assert_eq!(a.get_total_value(), 8);
321 assert_eq!(a.get_value(), 2);
322 }
323
324 #[test]
325 fn test_contains() {
326 let a = Interval::new(3, 7, 2);
327 assert!(a.contains(4));
328 assert!(a.contains(3));
329 assert!(a.contains(7));
330 assert!(!a.contains(0));
331 }
332
333 #[test]
334 fn test_superset_subset() {
335 let a = Interval::new(3, 7, 2);
336 let b = Interval::new(4, 6, 1);
337
338 assert!(a.superset(b));
339 assert!(b.subset(a));
340 assert!(!a.subset(b));
341 assert!(!b.superset(a));
342 }
343
344 #[test]
345 fn test_overlaps() {
346 let a = Interval::new(3, 6, 1);
347 let b = Interval::new(4, 7, 2);
348
349 assert!(a.left_overlaps(&b));
350 assert!(b.right_overlaps(&a));
351 assert!(!a.right_overlaps(&b));
352 assert!(!b.left_overlaps(&a));
353 }
354
355 #[test]
356 fn test_join() {
357 let a = Interval::new(0, 2, 1);
358 let b = Interval::new(2, 4, 2);
359 let c = Interval::new(4, 6, 2);
360
361 assert!(!a.can_join(&b));
362 assert!(c.can_join(&b));
363 assert!(b.can_join(&c));
364 assert!(!a.can_join(&c));
365
366 let d = Interval::new(0, 2, 2);
367 let e = Interval::new(2, 6, 2);
368
369 assert_eq!(a.join(a), d);
370 assert_eq!(c.join(b), e);
371 }
372
373 #[test]
374 fn test_join_ign_value() {
375 let a = Interval::new(0, 2, 2);
376 let b = Interval::new(1, 4, 3);
377 let c = Interval::new(3, 6, 6);
378
379 assert!(a.can_join_as_set(&b));
380 assert!(c.can_join_as_set(&b));
381 assert!(b.can_join_as_set(&c));
382 assert!(!a.can_join_as_set(&c));
383
384 let d = BaseInterval::new(0, 4);
385 let e = BaseInterval::new(1, 6);
386 let d2 = Interval::new(0, 4, 1);
387 let e2 = Interval::new(1, 6, 1);
388
389 assert_eq!(a.join_as_set(b), d);
390 assert_eq!(c.join_as_set(b), e);
391
392 assert_eq!(a.join_ign_value(b), d2);
393 assert_eq!(c.join_ign_value(b), e2);
394 }
395
396 #[test]
397 fn test_val_to_count() {
398 let a = Interval::new(0, 2, 3.5);
399 let b = Interval::new(0, 2, 3);
400 assert_eq!(a.val_to_count(), b);
401
402 let c = Interval::new(0, 2, -3.5);
403 let d = Interval::new(0, 2, 0);
404 assert_eq!(c.val_to_count(), d);
405 }
406
407 #[test]
408 fn test_to_base() {
409 let a = Interval::new(0, 2, 3.5);
410 let b = BaseInterval::new(0, 2);
411 assert_eq!(a.to_base(), b)
412 }
413
414 #[test]
415 fn test_to_f32() {
416 let a = Interval::new(
417 Decimal::from_f32(1.2).unwrap(),
418 Decimal::from_f32(3.5).unwrap(),
419 Decimal::from_f32(2.5).unwrap(),
420 );
421 let b = Interval::new(
422 IntFloat::from(1.2, 1),
423 IntFloat::from(3.5, 1),
424 IntFloat::from(2.5, 1),
425 );
426 assert_eq!(a.to_f32(), b.to_f32());
427 }
428}