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