1pub fn quantize(value: f32, step: f32) -> f32 {
14 assert!(step > 0.0, "step must be positive");
15 let factor = 1.0 / step;
16 (value * factor).round() / factor
17}
18
19pub fn clamp(value: f32, min: f32, max: f32) -> f32 {
21 value.max(min).min(max)
22}
23
24pub fn nearest(value: f32, points: &[f32]) -> f32 {
27 points
28 .iter()
29 .map(|&p| (p, (p - value).abs()))
30 .min_by(|a, b| a.1.partial_cmp(&b.1).unwrap())
31 .map(|(p, _)| p)
32 .unwrap_or(f32::INFINITY)
33}
34
35pub fn principal_angle(angle: f32) -> f32 {
37 ((angle + 180.0) % 360.0) - 180.0
38}
39
40pub fn angle_to_axis(angle: f32) -> super::vector2::Axis {
42 let a = ((angle % 360.0) + 360.0) % 360.0;
43 let dist_horizontal = (a - 0.0)
44 .abs()
45 .min((a - 180.0).abs())
46 .min((a - 360.0).abs());
47 let dist_vertical = (a - 90.0).abs().min((a - 270.0).abs());
48 if dist_horizontal <= dist_vertical {
49 super::vector2::Axis::X
50 } else {
51 super::vector2::Axis::Y
52 }
53}
54
55pub fn is_uniform(arr: &[f32], tolerance: f32) -> bool {
57 if arr.len() <= 1 {
58 return true;
59 }
60 let first = arr[0];
61 if tolerance == 0.0 {
62 arr.iter().all(|&v| v == first)
63 } else {
64 arr.iter().all(|&v| (v - first).abs() <= tolerance)
65 }
66}
67
68pub fn mean(values: &[f32]) -> f32 {
70 assert!(!values.is_empty(), "cannot compute mean of empty slice");
71 let sum: f32 = values.iter().sum();
72 sum / values.len() as f32
73}
74
75pub fn combinations<T: Clone>(arr: &[T], k: usize) -> Vec<Vec<T>> {
77 if k == 0 {
78 return vec![vec![]];
79 }
80 if arr.is_empty() {
81 return vec![];
82 }
83 let (first, rest) = arr.split_first().unwrap();
84 let mut with_first: Vec<Vec<T>> = combinations(rest, k - 1)
85 .into_iter()
86 .map(|mut combo| {
87 combo.insert(0, first.clone());
88 combo
89 })
90 .collect();
91 let mut without_first = combinations(rest, k);
92 with_first.append(&mut without_first);
93 with_first
94}
95
96pub fn permutations<T: Clone>(arr: &[T], k: usize) -> Vec<Vec<T>> {
98 if k == 0 {
99 return vec![vec![]];
100 }
101 if arr.is_empty() {
102 return vec![];
103 }
104 let mut result = Vec::new();
105 for (idx, item) in arr.iter().enumerate() {
106 let mut rest = arr.to_vec();
107 rest.remove(idx);
108 for mut perm in permutations(&rest, k - 1) {
109 perm.insert(0, item.clone());
110 result.push(perm);
111 }
112 }
113 result
114}
115
116pub fn powerset<T: Clone>(arr: &[T], k: Option<usize>) -> Vec<Vec<T>> {
118 match k {
119 None => {
120 let mut result = vec![vec![]];
121 for size in 1..=arr.len() {
122 result.extend(combinations(arr, size));
123 }
124 result
125 }
126 Some(size) => {
127 if size > arr.len() {
128 vec![]
129 } else {
130 combinations(arr, size)
131 }
132 }
133 }
134}