fyrox_core/
numeric_range.rs1use crate::num_traits::Num;
22use rand::distributions::uniform::SampleUniform;
23use rand::Rng;
24use std::ops::Range;
25
26fn min<T>(a: T, b: T) -> T
27where
28 T: PartialOrd,
29{
30 if a > b {
31 b
32 } else {
33 a
34 }
35}
36
37fn max<T>(a: T, b: T) -> T
38where
39 T: PartialOrd,
40{
41 if a > b {
42 a
43 } else {
44 b
45 }
46}
47
48pub trait RangeExt<T>
49where
50 T: Num + PartialOrd + SampleUniform + Copy,
51{
52 fn random<R: Rng>(&self, rng: &mut R) -> T;
53
54 fn clamp_value(&self, value: &mut T) -> T;
55}
56
57impl<T: Num + PartialOrd + SampleUniform + Copy> RangeExt<T> for Range<T> {
58 #[inline]
59 fn random<R: Rng>(&self, rng: &mut R) -> T {
60 let start = min(self.start, self.end);
61 let end = max(self.start, self.end);
62 if start == end {
63 start
64 } else {
65 rng.gen_range(Range { start, end })
66 }
67 }
68
69 #[inline]
70 fn clamp_value(&self, value: &mut T) -> T {
71 let start = min(self.start, self.end);
72 let end = max(self.start, self.end);
73
74 if *value < start {
75 start
76 } else if *value > end {
77 end
78 } else {
79 *value
80 }
81 }
82}
83
84#[cfg(test)]
85mod test {
86 use rand::thread_rng;
87
88 use super::*;
89
90 #[test]
91 fn test_random() {
92 let mut rng = thread_rng();
93
94 let res = (1..10).random(&mut rng);
95 assert!((1..=10).contains(&res));
96
97 let res = Range { start: 10, end: 1 }.random(&mut rng);
98 assert!((1..=10).contains(&res));
99
100 let res = (1..1).random(&mut rng);
101 assert!(res == 1);
102 }
103
104 #[test]
105 fn test_clamp_value() {
106 let res = (1..10).clamp_value(&mut 5);
107 assert_eq!(res, 5);
108
109 let res = (1..10).clamp_value(&mut 0);
110 assert_eq!(res, 1);
111
112 let res = (1..10).clamp_value(&mut 11);
113 assert_eq!(res, 10);
114 }
115}