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