physdes/interval.rs
1use crate::generic::{Contain, Displacement, MinDist, Overlap};
2
3use std::cmp::{Eq, PartialEq, PartialOrd};
4use std::fmt::{Display, Formatter, Result as FmtResult};
5use std::marker::PhantomData;
6use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
7
8/// The `Interval` struct represents a range of values with a lower bound (`lb`) and an upper bound
9/// (`ub`).
10///
11/// ```svgbob
12/// lb ub
13/// |---------|
14/// *=========*-----> T
15/// ```
16///
17/// Properties:
18///
19/// * `lb`: The `lb` property represents the lower bound of the interval. It is of type `T`, which is a
20/// generic type that must implement the `PartialOrd` trait. This means that the type `T` must be able
21/// to be compared for ordering.
22/// * `ub`: The `ub` property represents the upper bound of the interval. It is of type `T`, which is a
23/// generic type that must implement the `PartialOrd` trait. The `PartialOrd` trait allows for
24/// comparison between values of type `T`.
25/// * `_marker`: The `_marker` field is a marker field that is used to indicate that the generic type
26/// `T` is used in the struct. It is typically used when you want to associate a type parameter with a
27/// struct, but you don't actually need to store any values of that type in the struct.
28///
29/// # Examples
30///
31/// ```
32/// use physdes::interval::Interval;
33/// use std::marker::PhantomData;
34///
35/// let interval = Interval::new(1, 5);
36/// assert_eq!(interval.lb, 1);
37/// assert_eq!(interval.ub, 5);
38/// ```
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
41pub struct Interval<T> {
42 pub lb: T,
43 pub ub: T,
44 pub _marker: PhantomData<T>,
45}
46
47impl<T> Interval<T> {
48 /// The function `new` creates a new instance of a struct with given lower and upper bounds.
49 ///
50 /// Arguments:
51 ///
52 /// * `lb`: The `lb` parameter represents the lower bound value. It is of type `T`, which means it
53 /// can be any type that implements the necessary traits for the struct.
54 /// * `ub`: The `ub` parameter represents the upper bound value. It is of type `T`, which means it
55 /// can be any type that implements the necessary traits for the struct.
56 ///
57 /// Returns:
58 ///
59 /// The `new` function is returning an instance of the struct `Self`.
60 ///
61 /// # Examples
62 ///
63 /// ```
64 /// use physdes::interval::Interval;
65 /// use std::marker::PhantomData;
66 ///
67 /// let interval = Interval::new(1, 5);
68 /// assert_eq!(interval.lb, 1);
69 /// assert_eq!(interval.ub, 5);
70 ///
71 /// let interval = Interval::new(5, 1); // Invalid interval but still created
72 /// assert_eq!(interval.lb, 5);
73 /// assert_eq!(interval.ub, 1);
74 /// ```
75 #[inline]
76 pub const fn new(lb: T, ub: T) -> Self {
77 Self {
78 lb,
79 ub,
80 _marker: PhantomData,
81 }
82 }
83}
84
85impl<T: Copy> Interval<T> {
86 /// The function `lb` returns the value of the field `lb` from the struct.
87 ///
88 /// Returns:
89 ///
90 /// The `lb` method is returning the value of the `lb` field of the struct or object that the method
91 /// is being called on.
92 #[inline]
93 pub const fn lb(&self) -> T {
94 self.lb
95 }
96
97 /// This Rust function returns the value of the field `ub`.
98 ///
99 /// Returns:
100 ///
101 /// The `ub` field of the struct is being returned.
102 #[inline]
103 pub const fn ub(&self) -> T {
104 self.ub
105 }
106}
107
108impl<T: PartialOrd> Interval<T> {
109 /// The function `is_invalid` checks if the lower bound is greater than the upper bound.
110 ///
111 /// Returns:
112 ///
113 /// The `is_invalid` function is returning a boolean value based on the comparison `self.lb >
114 /// self.ub`. If `self.lb` is greater than `self.ub`, it will return `true`, indicating that the
115 /// values are invalid. Otherwise, it will return `false`.
116 ///
117 /// # Examples
118 ///
119 /// ```
120 /// use physdes::interval::Interval;
121 ///
122 /// let valid_interval = Interval::new(1, 5);
123 /// assert!(!valid_interval.is_invalid());
124 ///
125 /// let invalid_interval = Interval::new(5, 1);
126 /// assert!(invalid_interval.is_invalid());
127 /// ```
128 #[inline]
129 pub fn is_invalid(&self) -> bool {
130 self.lb > self.ub
131 }
132}
133
134impl<T: Copy + Sub<Output = T>> Interval<T> {
135 /// The `length` function calculates the difference between the upper bound (`ub`) and lower bound
136 /// (`lb`) of a value.
137 ///
138 /// Returns:
139 ///
140 /// The `length` method is returning the difference between the `ub` (upper bound) and `lb` (lower
141 /// bound) values of the struct instance.
142 ///
143 /// # Examples
144 ///
145 /// ```
146 /// use physdes::interval::Interval;
147 ///
148 /// let interval = Interval::new(2, 8);
149 /// assert_eq!(interval.length(), 6);
150 ///
151 /// let interval = Interval::new(-3, 5);
152 /// assert_eq!(interval.length(), 8);
153 /// ```
154 #[inline]
155 pub fn length(&self) -> T {
156 self.ub - self.lb
157 }
158}
159
160impl<T> Display for Interval<T>
161where
162 T: PartialOrd + Copy + Display,
163{
164 /// The function `fmt` in Rust is used to format a struct by writing its lower bound and upper bound
165 /// values in square brackets.
166 ///
167 /// Arguments:
168 ///
169 /// * `f`: The `f` parameter in the `fmt` function is a mutable reference to a `Formatter` struct.
170 /// This `Formatter` struct is used for formatting and writing output.
171 ///
172 /// Returns:
173 ///
174 /// The `fmt` method is returning a `FmtResult`, which is an alias for `Result<(), Error>`.
175 #[inline]
176 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
177 write!(f, "[{}, {}]", self.lb, self.ub)
178 }
179}
180
181impl<T: Sub<Output = T>> Sub for Interval<T> {
182 type Output = Self;
183
184 fn sub(self, other: Self) -> Self::Output {
185 Self {
186 lb: self.lb - other.lb,
187 ub: self.ub - other.ub,
188 _marker: PhantomData,
189 }
190 }
191}
192
193impl<T> Neg for Interval<T>
194where
195 T: Copy + Neg<Output = T>,
196{
197 type Output = Interval<T>;
198
199 #[inline]
200 fn neg(self) -> Self::Output {
201 Interval {
202 lb: -self.ub,
203 ub: -self.lb,
204 _marker: self._marker,
205 }
206 }
207}
208
209impl<T> AddAssign<T> for Interval<T>
210where
211 T: Copy + AddAssign<T>,
212{
213 /// The `add_assign` function in Rust adds a value to both the lower and upper bounds of a data
214 /// structure.
215 ///
216 /// Arguments:
217 ///
218 /// * `rhs`: The `rhs` parameter in the `add_assign` function represents the right-hand side operand
219 /// that will be added to the `lb` and `ub` fields of the struct or object on which the method is
220 /// called.
221 #[inline]
222 fn add_assign(&mut self, rhs: T) {
223 self.lb += rhs;
224 self.ub += rhs;
225 }
226}
227
228impl<T> Add<T> for Interval<T>
229where
230 T: Copy + Add<Output = T>,
231{
232 type Output = Interval<T>;
233
234 /// The `add` function in Rust adds a value to both the lower and upper bounds of an `Interval`
235 /// struct.
236 ///
237 /// Arguments:
238 ///
239 /// * `rhs`: The `rhs` parameter in the `add` function represents the right-hand side operand that
240 /// will be added to the current `Interval` instance.
241 #[inline]
242 fn add(self, rhs: T) -> Self::Output {
243 Interval {
244 lb: self.lb + rhs,
245 ub: self.ub + rhs,
246 _marker: self._marker,
247 }
248 }
249}
250
251impl<T> SubAssign<T> for Interval<T>
252where
253 T: Copy + SubAssign<T>,
254{
255 /// The `sub_assign` function subtracts a value from both the lower and upper bounds of a variable.
256 ///
257 /// Arguments:
258 ///
259 /// * `rhs`: `rhs` is a parameter of type `T` that is passed by value to the `sub_assign` function.
260 /// It is used to subtract its value from both `self.lb` and `self.ub` in the function
261 /// implementation.
262 #[inline]
263 fn sub_assign(&mut self, rhs: T) {
264 self.lb -= rhs;
265 self.ub -= rhs;
266 }
267}
268
269impl<T: Add<Output = T>> Add for Interval<T> {
270 type Output = Self;
271
272 fn add(self, other: Self) -> Self::Output {
273 Self {
274 lb: self.lb + other.lb,
275 ub: self.ub + other.ub,
276 _marker: PhantomData,
277 }
278 }
279}
280
281impl<T> Sub<T> for Interval<T>
282where
283 T: Copy + Sub<Output = T>,
284{
285 type Output = Interval<T>;
286
287 /// The function subtracts a value from both the lower and upper bounds of an interval.
288 ///
289 /// Arguments:
290 ///
291 /// * `rhs`: The `rhs` parameter in the code snippet represents the right-hand side operand that
292 /// will be subtracted from the interval's lower bound (`lb`) and upper bound (`ub`) values.
293 #[inline]
294 fn sub(self, rhs: T) -> Self::Output {
295 Interval {
296 lb: self.lb - rhs,
297 ub: self.ub - rhs,
298 _marker: self._marker,
299 }
300 }
301}
302
303impl<T> MulAssign<T> for Interval<T>
304where
305 T: Copy + MulAssign<T>,
306{
307 /// The `mul_assign` function in Rust multiplies both the lower and upper bounds of a range by a
308 /// given value.
309 ///
310 /// Arguments:
311 ///
312 /// * `rhs`: The `rhs` parameter in the `mul_assign` function represents the value that will be
313 /// multiplied with the `lb` and `ub` fields of the struct or object on which the method is called.
314 #[inline]
315 fn mul_assign(&mut self, rhs: T) {
316 self.lb *= rhs;
317 self.ub *= rhs;
318 }
319}
320
321impl<T> Mul<T> for Interval<T>
322where
323 T: Copy + Mul<Output = T>,
324{
325 type Output = Interval<T>;
326
327 /// The `mul` function in Rust defines multiplication for an `Interval` type.
328 ///
329 /// Arguments:
330 ///
331 /// * `rhs`: The `rhs` parameter in the `mul` function represents the right-hand side operand that
332 /// will be multiplied with the `Interval` instance on which the method is called.
333 #[inline]
334 fn mul(self, rhs: T) -> Self::Output {
335 Interval {
336 lb: self.lb * rhs,
337 ub: self.ub * rhs,
338 _marker: self._marker,
339 }
340 }
341}
342
343/// The above code is defining a trait named `Enlarge` in Rust. This trait has an associated type
344/// `Output` and a method `enlarge_with` that takes a reference to `self` and a parameter `alpha` of
345/// type `T`. The method returns an object of type `Output`. This trait can be implemented for types to
346/// provide the functionality of enlarging or modifying the object with the provided `alpha` value.
347pub trait Enlarge<Alpha> {
348 type Output;
349
350 fn enlarge_with(&self, alpha: Alpha) -> Self::Output;
351}
352
353impl Enlarge<i32> for i32 {
354 type Output = Interval<i32>;
355
356 /// The `enlarge_with` function takes an integer `alpha` and returns an `Interval` struct with lower
357 /// bound as `self - alpha` and upper bound as `self + alpha`.
358 ///
359 /// Arguments:
360 ///
361 /// * `alpha`: The `alpha` parameter in the `enlarge_with` function represents the amount by which
362 /// the interval should be enlarged. It is an `i32` type, which means it is an integer value.
363 ///
364 /// Returns:
365 ///
366 /// An `Interval<i32>` struct is being returned.
367 #[inline]
368 fn enlarge_with(&self, alpha: i32) -> Interval<i32> {
369 Interval {
370 lb: *self - alpha,
371 ub: *self + alpha,
372 _marker: PhantomData,
373 }
374 }
375}
376
377impl<T> Enlarge<T> for Interval<T>
378where
379 T: Copy + Add<Output = T> + Sub<Output = T>,
380{
381 type Output = Interval<T>;
382
383 /// The `enlarge_with` function in Rust enlarges an interval by adding a specified value to its
384 /// lower bound and subtracting the same value from its upper bound.
385 ///
386 /// Arguments:
387 ///
388 /// * `alpha`: The `alpha` parameter in the `enlarge_with` function represents the amount by which
389 /// the lower bound (`lb`) and upper bound (`ub`) of an `Interval` struct are adjusted. The lower
390 /// bound is decreased by `alpha` and the upper bound is increased by `alpha`, effectively enlarg
391 ///
392 /// Returns:
393 ///
394 /// The `enlarge_with` method is returning a new `Interval` instance with the lower bound (`lb`)
395 /// decreased by `alpha` and the upper bound (`ub`) increased by `alpha`. The `_marker` field is
396 /// copied from the original `Interval` instance.
397 #[inline]
398 fn enlarge_with(&self, alpha: T) -> Self {
399 Interval {
400 lb: self.lb - alpha,
401 ub: self.ub + alpha,
402 _marker: self._marker,
403 }
404 }
405}
406
407impl<T: PartialOrd> PartialOrd for Interval<T> {
408 /// The function `partial_cmp` compares the lower bound of `self` with the upper bound of `other`
409 /// and returns the result as an `Option` of `Ordering`.
410 ///
411 /// Arguments:
412 ///
413 /// * `other`: The `other` parameter is a reference to another object of the same type as `self`.
414 ///
415 /// Returns:
416 ///
417 /// an `Option` containing a `std::cmp::Ordering` value.
418 ///
419 /// # Examples
420 ///
421 /// ```
422 /// use physdes::interval::Interval;
423 /// use std::marker::PhantomData;
424 /// assert_eq!(Interval::new(1, 2).partial_cmp(&Interval::new(3, 4)), Some(std::cmp::Ordering::Less));
425 /// ```
426 #[inline]
427 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
428 if self.ub < other.lb {
429 Some(std::cmp::Ordering::Less)
430 } else if other.ub < self.lb {
431 Some(std::cmp::Ordering::Greater)
432 } else {
433 Some(std::cmp::Ordering::Equal)
434 }
435 }
436}
437
438/// The `impl<T: PartialOrd> Overlap<Interval<T>> for Interval<T>` block is implementing the `Overlap`
439/// trait for the `Interval<T>` struct.
440impl<T: PartialOrd> Overlap<Interval<T>> for Interval<T> {
441 /// The `overlaps` function in Rust checks if two intervals overlap with each other.
442 ///
443 /// Arguments:
444 ///
445 /// * `other`: The `other` parameter in the `overlaps` function represents another interval that you
446 /// want to check for overlap with the interval on which the method is called.
447 ///
448 /// Returns:
449 ///
450 /// The `overlaps` function is returning a boolean value, which indicates whether the interval
451 /// `self` overlaps with the interval `other`. If there is an overlap between the two intervals, the
452 /// function will return `true`, otherwise it will return `false`.
453 #[inline]
454 fn overlaps(&self, other: &Interval<T>) -> bool {
455 self.ub >= other.lb && other.ub >= self.lb
456 }
457}
458
459impl<T: PartialOrd> Overlap<T> for Interval<T> {
460 /// The `overlaps` function in Rust checks if two values overlap within a range.
461 ///
462 /// Arguments:
463 ///
464 /// * `other`: The `other` parameter is a reference to an object of type `T`, which is the same type
465 /// as the object that the method `overlaps` is being called on.
466 ///
467 /// Returns:
468 ///
469 /// The `overlaps` function is returning a boolean value, which indicates whether the range
470 /// represented by `self` overlaps with the range represented by `other`.
471 #[inline]
472 fn overlaps(&self, other: &T) -> bool {
473 self.ub >= *other && *other >= self.lb
474 }
475}
476
477impl<T: PartialOrd> Overlap<Interval<T>> for T {
478 /// The `overlaps` function in Rust checks if two intervals overlap with each other.
479 ///
480 /// Arguments:
481 ///
482 /// * `other`: The `other` parameter is a reference to an `Interval<T>` struct, which represents
483 /// another interval. The `Interval<T>` struct likely contains two fields, `lb` and `ub`,
484 /// representing the lower and upper bounds of the interval, respectively. The `overlaps` method is
485 /// used to
486 ///
487 /// Returns:
488 ///
489 /// The `overlaps` function is returning a boolean value. It checks if the current interval (`self`)
490 /// overlaps with another interval (`other`) by comparing their lower bounds and upper bounds. If
491 /// there is any overlap between the two intervals, it returns `true`, otherwise it returns `false`.
492 #[inline]
493 fn overlaps(&self, other: &Interval<T>) -> bool {
494 *self >= other.lb && other.ub >= *self
495 }
496}
497
498/// The `impl<T: PartialOrd> Contain<Interval<T>> for Interval<T>` block is implementing the `Contain`
499/// trait for the `Interval<T>` struct.
500impl<T: PartialOrd> Contain<Interval<T>> for Interval<T> {
501 /// The `contains` function in Rust checks if one interval contains another interval.
502 ///
503 /// Arguments:
504 ///
505 /// * `other`: The `other` parameter is a reference to an `Interval<T>` object that is being
506 /// compared to the current `Interval<T>` object.
507 ///
508 /// Returns:
509 ///
510 /// The `contains` method is returning a boolean value, which indicates whether the interval `self`
511 /// contains the interval `other`. It checks if the lower bound of `self` is less than or equal to
512 /// the lower bound of `other`, and if the upper bound of `other` is less than or equal to the upper
513 /// bound of `self`. If both conditions are true, it returns `true
514 #[inline]
515 fn contains(&self, other: &Interval<T>) -> bool {
516 self.lb <= other.lb && other.ub <= self.ub
517 }
518}
519
520/// The `impl<T: PartialOrd> Contain<T> for Interval<T>` block is implementing the `Contain` trait for
521/// the `Interval<T>` struct.
522impl<T: PartialOrd> Contain<T> for Interval<T> {
523 /// The function checks if a value is within a specified range.
524 ///
525 /// Arguments:
526 ///
527 /// * `other`: The `other` parameter is a reference to a value of type `T`, which is the same type
528 /// as the elements stored in the struct or data structure that contains the `contains` method. The
529 /// method checks if the value referenced by `other` falls within the range defined by the lower
530 /// bound (`
531 ///
532 /// Returns:
533 ///
534 /// A boolean value is being returned, indicating whether the value `other` is within the range
535 /// defined by `self.lb` and `self.ub`.
536 #[inline]
537 fn contains(&self, other: &T) -> bool {
538 self.lb <= *other && *other <= self.ub
539 }
540}
541
542impl<T: PartialOrd> Contain<Interval<T>> for T {
543 /// The function `contains` always returns `false` and takes a reference to another `Interval` as
544 /// input.
545 ///
546 /// Arguments:
547 ///
548 /// * `_other`: The `_other` parameter is a reference to an `Interval` object of the same type `T`
549 /// as the current object.
550 ///
551 /// Returns:
552 ///
553 /// The `contains` function is returning a boolean value `false`.
554 #[inline]
555 fn contains(&self, _other: &Interval<T>) -> bool {
556 false
557 }
558}
559
560impl<T> Displacement<Interval<T>> for Interval<T>
561where
562 T: Displacement<T, Output = T>,
563{
564 type Output = Interval<T>;
565
566 /// The `displace` function in Rust calculates the displacement between two intervals.
567 ///
568 /// Arguments:
569 ///
570 /// * `other`: The `other` parameter in the `displace` function represents another `Interval` object
571 /// of the same type as `self`. It is used to displace the lower bound and upper bound of the
572 /// current `Interval` object (`self`) by the corresponding lower and upper bounds of the `other`
573 #[inline]
574 fn displace(&self, other: &Interval<T>) -> Self::Output {
575 Self::Output::new(self.lb.displace(&other.lb), self.ub.displace(&other.ub))
576 }
577}
578
579impl MinDist<Interval<i32>> for Interval<i32> {
580 /// The `min_dist_with` function calculates the minimum distance between two intervals of integers.
581 ///
582 /// Arguments:
583 ///
584 /// * `other`: The `min_dist_with` function calculates the minimum distance between two intervals.
585 /// The `self` interval is represented by the lower bound `lb` and upper bound `ub` of the current
586 /// instance, while the `other` interval is passed as a reference to an `Interval<i32>`.
587 ///
588 /// Returns:
589 ///
590 /// The `min_dist_with` function returns the minimum distance between two intervals. It calculates
591 /// the distance based on the upper and lower bounds of the intervals. If the upper bound of the
592 /// first interval is less than the lower bound of the second interval, it returns the difference
593 /// between the lower bound of the second interval and the upper bound of the first interval. If the
594 /// upper bound of the second interval is less
595 #[inline]
596 fn min_dist_with(&self, other: &Interval<i32>) -> u32 {
597 if self.ub < other.lb {
598 (other.lb - self.ub) as u32
599 } else if other.ub < self.lb {
600 (self.lb - other.ub) as u32
601 } else {
602 0
603 }
604 }
605}
606
607impl MinDist<i32> for Interval<i32> {
608 /// This Rust function calculates the minimum distance between a value and a range defined by lower
609 /// and upper bounds.
610 ///
611 /// Arguments:
612 ///
613 /// * `other`: The `other` parameter in the `min_dist_with` function is a reference to an `i32`
614 /// value. This parameter is used to calculate the minimum distance between the current instance
615 /// (self) and the provided `i32` value.
616 ///
617 /// Returns:
618 ///
619 /// The `min_dist_with` function returns the minimum distance between the value represented by
620 /// `self` and the value referenced by `other`. If the value referenced by `other` is greater than
621 /// the upper bound (`ub`) of `self`, it returns the difference between `other` and `ub`. If the
622 /// value referenced by `other` is less than the lower bound (`lb`) of `self
623 #[inline]
624 fn min_dist_with(&self, other: &i32) -> u32 {
625 if self.ub < *other {
626 (*other - self.ub) as u32
627 } else if *other < self.lb {
628 (self.lb - *other) as u32
629 } else {
630 0
631 }
632 }
633}
634
635impl MinDist<Interval<i32>> for i32 {
636 /// This Rust function calculates the minimum distance between two intervals of integers.
637 ///
638 /// Arguments:
639 ///
640 /// * `other`: The `min_dist_with` function calculates the minimum distance between two intervals.
641 /// The `self` interval is compared with the `other` interval to determine the minimum distance
642 /// between them.
643 ///
644 /// Returns:
645 ///
646 /// The `min_dist_with` function returns the minimum distance between two intervals. If the lower
647 /// bound of `self` is less than the lower bound of `other`, it returns the difference between the
648 /// lower bounds as a `u32`. If the upper bound of `other` is less than the upper bound of `self`,
649 /// it returns the difference between the upper bounds as a `u32`. Otherwise
650 #[inline]
651 fn min_dist_with(&self, other: &Interval<i32>) -> u32 {
652 if *self < other.lb {
653 (other.lb - *self) as u32
654 } else if other.ub < *self {
655 (*self - other.ub) as u32
656 } else {
657 0
658 }
659 }
660}
661
662/// The above code is defining a trait named `Hull` in Rust. This trait has a generic type `T` that must
663/// be sized. It also has an associated type `Output`. The trait has a method `hull_with` that takes a
664/// reference to another object of type `T` and returns an object of type `Output`. This trait can be
665/// implemented for different types to provide the `hull_with` functionality.
666pub trait Hull<T: ?Sized> {
667 type Output;
668
669 fn hull_with(&self, other: &T) -> Self::Output;
670}
671
672impl Hull<i32> for i32 {
673 type Output = Interval<i32>;
674
675 /// The function `hull_with` calculates the lower and upper bounds between two values.
676 ///
677 /// Arguments:
678 ///
679 /// * `other`: The `other` parameter in the `hull_with` function is a reference to an `i32` type.
680 /// This parameter is used to calculate the lower bound (`lb`) and upper bound (`ub`) values for the
681 /// output struct.
682 #[inline]
683 fn hull_with(&self, other: &i32) -> Self::Output {
684 if *self < *other {
685 Interval::new(*self, *other)
686 } else {
687 Interval::new(*other, *self)
688 }
689 }
690}
691
692impl<T> Hull<Interval<T>> for Interval<T>
693where
694 T: Copy + Ord,
695{
696 type Output = Interval<T>;
697
698 /// The `hull_with` function calculates the hull (bounding interval) of two intervals by taking the
699 /// minimum lower bound and maximum upper bound.
700 ///
701 /// Arguments:
702 ///
703 /// * `other`: `other` is a reference to an `Interval<T>` object that is being passed as a parameter
704 /// to the `hull_with` method.
705 #[inline]
706 fn hull_with(&self, other: &Interval<T>) -> Self::Output {
707 Self::Output {
708 lb: self.lb.min(other.lb),
709 ub: self.ub.max(other.ub),
710 _marker: self._marker,
711 }
712 }
713}
714
715impl<T> Hull<T> for Interval<T>
716where
717 T: Copy + Ord,
718{
719 type Output = Interval<T>;
720
721 /// The `hull_with` function calculates the hull (minimum and maximum values) between two values.
722 ///
723 /// Arguments:
724 ///
725 /// * `other`: The `other` parameter is a reference to a value of type `T`, which is the same type
726 /// as the values stored in the struct implementing the `hull_with` method. In this method, the
727 /// `other` value is used to update the lower bound (`lb`) and upper bound (`
728 #[inline]
729 fn hull_with(&self, other: &T) -> Self::Output {
730 Self::Output {
731 lb: self.lb.min(*other),
732 ub: self.ub.max(*other),
733 _marker: self._marker,
734 }
735 }
736}
737
738impl<T> Hull<Interval<T>> for T
739where
740 T: Copy + Ord,
741{
742 type Output = Interval<T>;
743
744 /// The `hull_with` function in Rust calculates the convex hull of two intervals.
745 ///
746 /// Arguments:
747 ///
748 /// * `other`: The `other` parameter in the `hull_with` function is a reference to an `Interval<T>`
749 /// object.
750 #[inline]
751 fn hull_with(&self, other: &Interval<T>) -> Self::Output {
752 other.hull_with(self)
753 }
754}
755
756/// The above code is defining a trait in Rust called `Intersect`. This trait has one associated type
757/// `Output` and one method `intersect_with` that takes a reference to another object of type `T` and
758/// returns an object of type `Output`. This trait can be implemented for various types to provide
759/// custom intersection behavior.
760pub trait Intersect<T: ?Sized> {
761 type Output;
762
763 fn intersect_with(&self, other: &T) -> Self::Output;
764}
765
766impl Intersect<i32> for i32 {
767 type Output = Interval<i32>;
768
769 /// The `intersect_with` function calculates the intersection of two values by finding the maximum
770 /// lower bound and minimum upper bound.
771 ///
772 /// Arguments:
773 ///
774 /// * `other`: The `other` parameter in the `intersect_with` function is a reference to an `i32`
775 /// type. This parameter is used to find the intersection between the current instance (self) and
776 /// the provided `i32` value.
777 #[inline]
778 fn intersect_with(&self, other: &i32) -> Self::Output {
779 Self::Output {
780 lb: (*self).max(*other),
781 ub: (*self).min(*other),
782 _marker: PhantomData,
783 }
784 }
785}
786
787impl<T> Intersect<Interval<T>> for Interval<T>
788where
789 T: Copy + Ord,
790{
791 type Output = Interval<T>;
792
793 /// The `intersect_with` function returns the intersection of two intervals by finding the maximum
794 /// lower bound and minimum upper bound between them.
795 ///
796 /// Arguments:
797 ///
798 /// * `other`: The `other` parameter is a reference to an `Interval<T>` object, which is used to
799 /// intersect with the current `Interval<T>` object. The `intersect_with` method calculates the
800 /// intersection of the two intervals and returns a new `Interval<T>` object as the output.
801 #[inline]
802 fn intersect_with(&self, other: &Interval<T>) -> Self::Output {
803 Self::Output {
804 lb: self.lb.max(other.lb),
805 ub: self.ub.min(other.ub),
806 _marker: self._marker,
807 }
808 }
809}
810
811impl<T> Intersect<T> for Interval<T>
812where
813 T: Copy + Ord,
814{
815 type Output = Interval<T>;
816
817 /// The `intersect_with` function calculates the intersection of two values.
818 ///
819 /// Arguments:
820 ///
821 /// * `other`: The `other` parameter is a reference to an object of type `T`, which is the same type
822 /// as the object on which the `intersect_with` method is being called. The method calculates the
823 /// intersection of the object's lower bound (`lb`) and upper bound (`ub`) with the corresponding
824 /// values
825 #[inline]
826 fn intersect_with(&self, other: &T) -> Self::Output {
827 Self::Output {
828 lb: self.lb.max(*other),
829 ub: self.ub.min(*other),
830 _marker: self._marker,
831 }
832 }
833}
834
835impl<T> Intersect<Interval<T>> for T
836where
837 T: Copy + Ord,
838{
839 type Output = Interval<T>;
840
841 /// The `intersect_with` function in Rust swaps the receiver and argument before calling the
842 /// `intersect_with` method on the argument.
843 ///
844 /// Arguments:
845 ///
846 /// * `other`: The `other` parameter in the `intersect_with` function represents another
847 /// `Interval<T>` that you want to intersect with the current interval.
848 #[inline]
849 fn intersect_with(&self, other: &Interval<T>) -> Self::Output {
850 other.intersect_with(self)
851 }
852}
853
854#[cfg(test)]
855mod tests {
856 use super::*;
857
858 #[test]
859 fn test_interval() {
860 let interval_a = Interval::new(4, 8);
861 let interval_b = Interval::new(5, 6);
862
863 assert!(interval_a <= interval_b);
864 assert!(interval_b <= interval_a);
865 assert!(interval_a >= interval_b);
866 assert!(interval_b >= interval_a);
867
868 assert!(interval_a.overlaps(&interval_b));
869 assert!(interval_b.overlaps(&interval_a));
870 // assert!(!contain(&interval_a, &interval_b));
871 assert!(interval_a.contains(&4));
872 assert!(interval_a.contains(&8));
873 assert!(interval_a.contains(&interval_b));
874 assert_eq!(interval_a, interval_a);
875 assert_eq!(interval_b, interval_b);
876 assert_ne!(interval_a, interval_b);
877 assert_ne!(interval_b, interval_a);
878 assert!(interval_a.overlaps(&interval_a));
879 assert!(interval_b.overlaps(&interval_b));
880 assert!(interval_a.contains(&interval_a));
881 assert!(interval_b.contains(&interval_b));
882 assert!(interval_a.overlaps(&interval_b));
883 assert!(interval_b.overlaps(&interval_a));
884 }
885
886 #[test]
887 fn test_hull_more_cases() {
888 let interval_a = Interval::new(3, 5);
889 let interval_b = Interval::new(1, 7);
890 assert_eq!(interval_a.hull_with(&interval_b), Interval::new(1, 7));
891
892 let interval_c = Interval::new(-2, 2);
893 assert_eq!(interval_a.hull_with(&interval_c), Interval::new(-2, 5));
894
895 let val_d = 4;
896 assert_eq!(interval_a.hull_with(&val_d), Interval::new(3, 5));
897
898 let val_e = 8;
899 assert_eq!(interval_a.hull_with(&val_e), Interval::new(3, 8));
900
901 let val_f = 0;
902 assert_eq!(interval_a.hull_with(&val_f), Interval::new(0, 5));
903 }
904
905 #[test]
906 fn test_interval1() {
907 let interval_a = Interval::new(4, 5);
908 let interval_b = Interval::new(6, 8);
909 assert!(interval_a < interval_b);
910 assert!(!(interval_b == interval_a));
911 assert!(interval_b != interval_a);
912 }
913
914 #[test]
915 fn test_interval2() {
916 let interval_a = Interval::new(4, 8);
917 let interval_b = Interval::new(5, 6);
918
919 assert!(interval_a.contains(&4));
920 assert!(interval_a.contains(&8));
921 assert!(interval_a.contains(&interval_b));
922 // assert!(interval_a.intersect_with(&8) == Interval::new(8, 8));
923 // assert!(interval_a.intersect_with(interval_b) == interval_b);
924 assert!(!interval_b.contains(&interval_a));
925 assert!(interval_a.overlaps(&interval_b));
926 assert!(interval_b.overlaps(&interval_a));
927 }
928
929 #[test]
930 fn test_interval3() {
931 let interval_a = Interval::new(3, 4);
932 assert!(interval_a.lb == 3);
933 assert!(interval_a.ub == 4);
934 // assert!(interval_a.length() == 1);
935 assert!(interval_a.contains(&3));
936 assert!(interval_a.contains(&4));
937 assert!(!interval_a.contains(&5));
938 assert!(interval_a.contains(&Interval::new(3, 4)));
939 assert!(!interval_a.contains(&Interval::new(3, 5)));
940 assert!(!interval_a.contains(&Interval::new(2, 3)));
941 assert!(!interval_a.contains(&2));
942 assert!(interval_a.contains(&4));
943 assert!(!interval_a.contains(&5));
944 }
945
946 #[test]
947 fn test_arithmetic() {
948 let mut interval_a = Interval::new(3, 5);
949 // interval_b = Interval::new(5, 7);
950 // interval_c = Interval::new(7, 8);
951 assert_eq!(interval_a + 1, Interval::new(4, 6));
952 assert_eq!(interval_a - 1, Interval::new(2, 4));
953 assert_eq!(interval_a * 2, Interval::new(6, 10));
954 assert!(-interval_a == Interval::new(-5, -3));
955 interval_a += 1;
956 assert!(interval_a == Interval::new(4, 6));
957 interval_a -= 1;
958 assert!(interval_a == Interval::new(3, 5));
959 interval_a *= 2;
960 assert!(interval_a == Interval::new(6, 10));
961 }
962
963 #[test]
964 fn test_overlap() {
965 let interval_a = Interval::new(3, 5);
966 let interval_b = Interval::new(5, 7);
967 let interval_c = Interval::new(7, 8);
968 assert!(interval_a.overlaps(&interval_b));
969 assert!(interval_b.overlaps(&interval_c));
970 assert!(!interval_a.overlaps(&interval_c));
971 assert!(!interval_c.overlaps(&interval_a));
972
973 let val_d = 4;
974 assert!(interval_a.overlaps(&val_d));
975 assert!(!interval_a.overlaps(&6));
976 assert!(val_d.overlaps(&interval_a));
977 assert!(val_d.overlaps(&val_d));
978 }
979
980 #[test]
981 fn test_contains() {
982 let interval_a = Interval::new(3, 5);
983 let interval_b = Interval::new(5, 7);
984 let interval_c = Interval::new(7, 8);
985 assert!(!interval_a.contains(&interval_b));
986 assert!(!interval_b.contains(&interval_c));
987 assert!(!interval_a.contains(&interval_c));
988 assert!(!interval_c.contains(&interval_a));
989
990 let val_d = 4;
991 assert!(interval_a.contains(&val_d));
992 assert!(!interval_a.contains(&6));
993 assert!(!val_d.contains(&interval_a));
994 assert!(val_d.contains(&val_d));
995 }
996
997 #[test]
998 fn test_intersect() {
999 let interval_a = Interval::new(3, 5);
1000 let interval_b = Interval::new(5, 7);
1001 let interval_c = Interval::new(7, 8);
1002 assert_eq!(interval_a.intersect_with(&interval_b), Interval::new(5, 5));
1003 assert_eq!(interval_b.intersect_with(&interval_c), Interval::new(7, 7));
1004 assert!(interval_a.intersect_with(&interval_c).is_invalid());
1005 assert_eq!(interval_a.intersect_with(&interval_b), Interval::new(5, 5));
1006 assert_eq!(interval_b.intersect_with(&interval_c), Interval::new(7, 7));
1007 let val_d = 4;
1008 assert_eq!(interval_a.intersect_with(&val_d), Interval::new(4, 4));
1009 assert!(interval_a.intersect_with(&6).is_invalid());
1010 assert_eq!(interval_a.intersect_with(&val_d), Interval::new(4, 4));
1011 assert_eq!(val_d.intersect_with(&interval_a), Interval::new(4, 4));
1012 assert_eq!(val_d.intersect_with(&val_d), Interval::new(4, 4));
1013 }
1014
1015 #[test]
1016 fn test_hull() {
1017 let interval_a = Interval::new(3, 5);
1018 let interval_b = Interval::new(5, 7);
1019 let interval_c = Interval::new(7, 8);
1020 assert_eq!(interval_a.hull_with(&interval_b), Interval::new(3, 7));
1021 assert_eq!(interval_b.hull_with(&interval_c), Interval::new(5, 8));
1022 assert_eq!(interval_a.hull_with(&interval_c), Interval::new(3, 8));
1023 let val_d = 4;
1024 assert_eq!(interval_a.hull_with(&val_d), Interval::new(3, 5));
1025 assert_eq!(interval_a.hull_with(&6), Interval::new(3, 6));
1026 // assert_eq!(hull(interval_a, val_d), Interval::new(3, 5));
1027 // assert_eq!(hull(interval_a, 6), Interval::new(3, 6));
1028 // assert_eq!(hull(val_d, interval_a), Interval::new(3, 5));
1029 // assert!(hull(6, interval_a) == Interval::new(3, 6));
1030 // assert!(hull(val_d, 6) == Interval::new(4, 6));
1031 }
1032
1033 #[test]
1034 fn test_min_dist() {
1035 let interval_a = Interval::new(3, 5);
1036 let interval_b = Interval::new(5, 7);
1037 let interval_c = Interval::new(7, 8);
1038 assert_eq!(interval_a.min_dist_with(&interval_b), 0);
1039 assert_eq!(interval_a.min_dist_with(&interval_c), 2);
1040 assert_eq!(interval_b.min_dist_with(&interval_c), 0);
1041 let val_d = 4;
1042 assert_eq!(interval_a.min_dist_with(&val_d), 0);
1043 assert_eq!(val_d.min_dist_with(&interval_a), 0);
1044 assert_eq!(interval_a.min_dist_with(&6), 1);
1045 assert_eq!(6.min_dist_with(&interval_a), 1);
1046 }
1047
1048 #[test]
1049 fn test_displacement() {
1050 let interval_a = Interval::new(3, 5);
1051 let interval_b = Interval::new(5, 7);
1052 let interval_c = Interval::new(7, 8);
1053 assert_eq!(interval_a.displace(&interval_b), Interval::new(-2, -2));
1054 assert_eq!(interval_a.displace(&interval_c), Interval::new(-4, -3));
1055 assert_eq!(interval_b.displace(&interval_c), Interval::new(-2, -1));
1056 let val_d = 4;
1057 assert_eq!(val_d.displace(&val_d), 0);
1058 assert_eq!(val_d.displace(&6), -2);
1059 assert_eq!(6.displace(&val_d), 2);
1060 }
1061
1062 #[test]
1063 fn test_enlarge() {
1064 let interval_a = Interval::new(3, 5);
1065 assert!(interval_a.enlarge_with(2) == Interval::new(1, 7));
1066 let val_d = 4;
1067 assert_eq!(val_d.enlarge_with(6), Interval::new(-2, 10));
1068 assert_eq!(6.enlarge_with(val_d), Interval::new(2, 10));
1069 }
1070}
1071
1072#[test]
1073fn test_interval_length() {
1074 let interval = Interval::new(3, 8);
1075 assert_eq!(interval.length(), 5);
1076
1077 let interval2 = Interval::new(-2, 3);
1078 assert_eq!(interval2.length(), 5);
1079}
1080
1081#[test]
1082fn test_interval_display() {
1083 let interval = Interval::new(3, 8);
1084 let display_str = format!("{}", interval);
1085 assert_eq!(display_str, "[3, 8]");
1086
1087 let interval2 = Interval::new(-5, 10);
1088 let display_str2 = format!("{}", interval2);
1089 assert_eq!(display_str2, "[-5, 10]");
1090}
1091
1092#[test]
1093fn test_interval_sub_interval() {
1094 let interval_a = Interval::new(5, 10);
1095 let interval_b = Interval::new(2, 3);
1096 let result = interval_a - interval_b;
1097 assert_eq!(result, Interval::new(3, 7));
1098}
1099
1100#[test]
1101fn test_interval_add_interval() {
1102 let interval_a = Interval::new(1, 3);
1103 let interval_b = Interval::new(2, 5);
1104 let result = interval_a + interval_b;
1105 assert_eq!(result, Interval::new(3, 8));
1106}
1107
1108#[test]
1109fn test_interval_is_invalid() {
1110 let valid_interval = Interval::new(1, 5);
1111 assert!(!valid_interval.is_invalid());
1112
1113 let invalid_interval = Interval::new(5, 1);
1114 assert!(invalid_interval.is_invalid());
1115}
1116
1117#[test]
1118fn test_interval_sub_assign_interval() {
1119 let mut interval = Interval::new(10, 20);
1120 interval -= 3;
1121 assert_eq!(interval, Interval::new(7, 17));
1122}
1123
1124#[test]
1125fn test_interval_hull_t_for_t() {
1126 let val = 5;
1127 let interval = Interval::new(3, 8);
1128 // T as Hull<Interval<T>>
1129 let result = val.hull_with(&interval);
1130 assert_eq!(result.lb, 3);
1131 assert_eq!(result.ub, 8);
1132}
1133
1134#[test]
1135fn test_interval_contains_interval_t() {
1136 let interval = Interval::new(3, 8);
1137 // Contain<Interval<T>> for T - always returns false
1138 let val = 5;
1139 assert!(!val.contains(&interval));
1140}
1141
1142#[test]
1143fn test_interval_overlap_interval_t() {
1144 // Overlap<Interval<T>> for T
1145 let val = 5;
1146 let interval = Interval::new(3, 8);
1147 assert!(val.overlaps(&interval));
1148
1149 let val2 = 10;
1150 assert!(!val2.overlaps(&interval));
1151}
1152
1153#[test]
1154fn test_interval_partial_cmp_greater() {
1155 let interval_a = Interval::new(8, 10);
1156 let interval_b = Interval::new(3, 5);
1157 // interval_a is greater than interval_b (no overlap, ub > other.lb)
1158 let cmp = interval_a.partial_cmp(&interval_b);
1159 assert_eq!(cmp, Some(std::cmp::Ordering::Greater));
1160}