| 48 } |
42 } |
| 49 ts.end() |
43 ts.end() |
| 50 } |
44 } |
| 51 } |
45 } |
| 52 |
46 |
| 53 impl<A : Num, const N : usize> FixedLength<N> for Cube<A,N> { |
47 impl<A: Num, const N: usize> FixedLength<N> for Cube<N, A> { |
| 54 type Iter = std::array::IntoIter<[A; 2], N>; |
48 type Iter = std::array::IntoIter<[A; 2], N>; |
| 55 type Elem = [A; 2]; |
49 type Elem = [A; 2]; |
| 56 #[inline] |
50 #[inline] |
| 57 fn fl_iter(self) -> Self::Iter { |
51 fn fl_iter(self) -> Self::Iter { |
| 58 self.0.into_iter() |
52 self.0.into_iter() |
| 59 } |
53 } |
| 60 } |
54 } |
| 61 |
55 |
| 62 impl<A : Num, const N : usize> FixedLengthMut<N> for Cube<A,N> { |
56 impl<A: Num, const N: usize> FixedLengthMut<N> for Cube<N, A> { |
| 63 type IterMut<'a> = std::slice::IterMut<'a, [A; 2]>; |
57 type IterMut<'a> = std::slice::IterMut<'a, [A; 2]>; |
| 64 #[inline] |
58 #[inline] |
| 65 fn fl_iter_mut(&mut self) -> Self::IterMut<'_> { |
59 fn fl_iter_mut(&mut self) -> Self::IterMut<'_> { |
| 66 self.0.iter_mut() |
60 self.0.iter_mut() |
| 67 } |
61 } |
| 68 } |
62 } |
| 69 |
63 |
| 70 impl<'a, A : Num, const N : usize> FixedLength<N> for &'a Cube<A,N> { |
64 impl<'a, A: Num, const N: usize> FixedLength<N> for &'a Cube<N, A> { |
| 71 type Iter = std::slice::Iter<'a, [A; 2]>; |
65 type Iter = std::slice::Iter<'a, [A; 2]>; |
| 72 type Elem = &'a [A; 2]; |
66 type Elem = &'a [A; 2]; |
| 73 #[inline] |
67 #[inline] |
| 74 fn fl_iter(self) -> Self::Iter { |
68 fn fl_iter(self) -> Self::Iter { |
| 75 self.0.iter() |
69 self.0.iter() |
| 76 } |
70 } |
| 77 } |
71 } |
| 78 |
72 |
| 79 |
|
| 80 /// Iterator for [`Cube`] corners. |
73 /// Iterator for [`Cube`] corners. |
| 81 pub struct CubeCornersIter<'a, U : Num, const N : usize> { |
74 pub struct CubeCornersIter<'a, U: Num, const N: usize> { |
| 82 index : usize, |
75 index: usize, |
| 83 cube : &'a Cube<U, N>, |
76 cube: &'a Cube<N, U>, |
| 84 } |
77 } |
| 85 |
78 |
| 86 impl<'a, U : Num, const N : usize> Iterator for CubeCornersIter<'a, U, N> { |
79 impl<'a, U: Num, const N: usize> Iterator for CubeCornersIter<'a, U, N> { |
| 87 type Item = Loc<U, N>; |
80 type Item = Loc<N, U>; |
| 88 #[inline] |
81 #[inline] |
| 89 fn next(&mut self) -> Option<Self::Item> { |
82 fn next(&mut self) -> Option<Self::Item> { |
| 90 if self.index >= N { |
83 if self.index >= N { |
| 91 None |
84 None |
| 92 } else { |
85 } else { |
| 93 let i = self.index; |
86 let i = self.index; |
| 94 self.index += 1; |
87 self.index += 1; |
| 95 let arr = self.cube.map_indexed(|k, a, b| if (i>>k)&1 == 0 { a } else { b }); |
88 let arr = self |
| |
89 .cube |
| |
90 .map_indexed(|k, a, b| if (i >> k) & 1 == 0 { a } else { b }); |
| 96 Some(arr.into()) |
91 Some(arr.into()) |
| 97 } |
92 } |
| 98 } |
93 } |
| 99 } |
94 } |
| 100 |
95 |
| 101 impl<U : Num, const N : usize> Cube<U, N> { |
96 impl<U: Num, const N: usize> Cube<N, U> { |
| 102 /// Maps `f` over the triples $\\{(i, a\_i, b\_i)\\}\_{i=1}^N$ |
97 /// Maps `f` over the triples $\\{(i, a\_i, b\_i)\\}\_{i=1}^N$ |
| 103 /// of the cube $∏_{i=1}^N [a_i, b_i)$. |
98 /// of the cube $∏_{i=1}^N [a_i, b_i)$. |
| 104 #[inline] |
99 #[inline] |
| 105 pub fn map_indexed<T>(&self, f : impl Fn(usize, U, U) -> T) -> [T; N] { |
100 pub fn map_indexed<T>(&self, f: impl Fn(usize, U, U) -> T) -> [T; N] { |
| 106 map1_indexed(self, |i, &[a, b]| f(i, a, b)) |
101 map1_indexed(self, |i, &[a, b]| f(i, a, b)) |
| 107 } |
102 } |
| 108 |
103 |
| 109 /// Maps `f` over the tuples $\\{(a\_i, b\_i)\\}\_{i=1}^N$ |
104 /// Maps `f` over the tuples $\\{(a\_i, b\_i)\\}\_{i=1}^N$ |
| 110 /// of the cube $∏_{i=1}^N [a_i, b_i)$. |
105 /// of the cube $∏_{i=1}^N [a_i, b_i)$. |
| 111 #[inline] |
106 #[inline] |
| 112 pub fn map<T>(&self, f : impl Fn(U, U) -> T) -> [T; N] { |
107 pub fn map<T>(&self, f: impl Fn(U, U) -> T) -> [T; N] { |
| 113 map1(self, |&[a, b]| f(a, b)) |
108 map1(self, |&[a, b]| f(a, b)) |
| 114 } |
109 } |
| 115 |
110 |
| 116 /// Iterates over the start and end coordinates $\{(a_i, b_i)\}_{i=1}^N$ of the cube along |
111 /// Iterates over the start and end coordinates $\{(a_i, b_i)\}_{i=1}^N$ of the cube along |
| 117 /// each dimension. |
112 /// each dimension. |
| 118 #[inline] |
113 #[inline] |
| 119 pub fn iter_coords(&self) -> std::slice::Iter<'_, [U; 2]> { |
114 pub fn iter_coords(&self) -> std::slice::Iter<'_, [U; 2]> { |
| 120 self.0.iter() |
115 self.0.iter() |
| 121 } |
116 } |
| 122 |
117 |
| 123 /// Returns the “start” coordinate $a_i$ of the cube $∏_{i=1}^N [a_i, b_i)$. |
118 /// Returns the “start” coordinate $a_i$ of the cube $∏_{i=1}^N [a_i, b_i)$. |
| 124 #[inline] |
119 #[inline] |
| 125 pub fn start(&self, i : usize) -> U { |
120 pub fn start(&self, i: usize) -> U { |
| 126 self.0[i][0] |
121 self.0[i][0] |
| 127 } |
122 } |
| 128 |
123 |
| 129 /// Returns the end coordinate $a_i$ of the cube $∏_{i=1}^N [a_i, b_i)$. |
124 /// Returns the end coordinate $a_i$ of the cube $∏_{i=1}^N [a_i, b_i)$. |
| 130 #[inline] |
125 #[inline] |
| 131 pub fn end(&self, i : usize) -> U { |
126 pub fn end(&self, i: usize) -> U { |
| 132 self.0[i][1] |
127 self.0[i][1] |
| 133 } |
128 } |
| 134 |
129 |
| 135 /// Returns the “start” $(a_1, … ,a_N)$ of the cube $∏_{i=1}^N [a_i, b_i)$ |
130 /// Returns the “start” $(a_1, … ,a_N)$ of the cube $∏_{i=1}^N [a_i, b_i)$ |
| 136 /// spanned between $(a_1, … ,a_N)$ and $(b_1, … ,b_N)$. |
131 /// spanned between $(a_1, … ,a_N)$ and $(b_1, … ,b_N)$. |
| 137 #[inline] |
132 #[inline] |
| 138 pub fn span_start(&self) -> Loc<U, N> { |
133 pub fn span_start(&self) -> Loc<N, U> { |
| 139 Loc::new(self.map(|a, _b| a)) |
134 Loc::new(self.map(|a, _b| a)) |
| 140 } |
135 } |
| 141 |
136 |
| 142 /// Returns the end $(b_1, … ,b_N)$ of the cube $∏_{i=1}^N [a_i, b_i)$ |
137 /// Returns the end $(b_1, … ,b_N)$ of the cube $∏_{i=1}^N [a_i, b_i)$ |
| 143 /// spanned between $(a_1, … ,a_N)$ and $(b_1, … ,b_N)$. |
138 /// spanned between $(a_1, … ,a_N)$ and $(b_1, … ,b_N)$. |
| 144 #[inline] |
139 #[inline] |
| 145 pub fn span_end(&self) -> Loc<U, N> { |
140 pub fn span_end(&self) -> Loc<N, U> { |
| 146 Loc::new(self.map(|_a, b| b)) |
141 Loc::new(self.map(|_a, b| b)) |
| 147 } |
142 } |
| 148 |
143 |
| 149 /// Iterates over the corners $\{(c_1, … ,c_N) | c_i ∈ \{a_i, b_i\}\}$ of the cube |
144 /// Iterates over the corners $\{(c_1, … ,c_N) | c_i ∈ \{a_i, b_i\}\}$ of the cube |
| 150 /// $∏_{i=1}^N [a_i, b_i)$. |
145 /// $∏_{i=1}^N [a_i, b_i)$. |
| 151 #[inline] |
146 #[inline] |
| 152 pub fn iter_corners(&self) -> CubeCornersIter<'_, U, N> { |
147 pub fn iter_corners(&self) -> CubeCornersIter<'_, U, N> { |
| 153 CubeCornersIter{ index : 0, cube : self } |
148 CubeCornersIter { |
| |
149 index: 0, |
| |
150 cube: self, |
| |
151 } |
| 154 } |
152 } |
| 155 |
153 |
| 156 /// Returns the width-`N`-tuple $(b_1-a_1, … ,b_N-a_N)$ of the cube $∏_{i=1}^N [a_i, b_i)$. |
154 /// Returns the width-`N`-tuple $(b_1-a_1, … ,b_N-a_N)$ of the cube $∏_{i=1}^N [a_i, b_i)$. |
| 157 #[inline] |
155 #[inline] |
| 158 pub fn width(&self) -> Loc<U, N> { |
156 pub fn width(&self) -> Loc<N, U> { |
| 159 Loc::new(self.map(|a, b| b-a)) |
157 Loc::new(self.map(|a, b| b - a)) |
| 160 } |
158 } |
| 161 |
159 |
| 162 /// Translates the cube $∏_{i=1}^N [a_i, b_i)$ by the `shift` $(s_1, … , s_N)$ to |
160 /// Translates the cube $∏_{i=1}^N [a_i, b_i)$ by the `shift` $(s_1, … , s_N)$ to |
| 163 /// $∏_{i=1}^N [a_i+s_i, b_i+s_i)$. |
161 /// $∏_{i=1}^N [a_i+s_i, b_i+s_i)$. |
| 164 #[inline] |
162 #[inline] |
| 165 pub fn shift(&self, shift : &Loc<U, N>) -> Self { |
163 pub fn shift(&self, shift: &Loc<N, U>) -> Self { |
| 166 let mut cube = self.clone(); |
164 let mut cube = self.clone(); |
| 167 for i in 0..N { |
165 for i in 0..N { |
| 168 cube.0[i][0] += shift[i]; |
166 cube.0[i][0] += shift[i]; |
| 169 cube.0[i][1] += shift[i]; |
167 cube.0[i][1] += shift[i]; |
| 170 } |
168 } |
| 171 cube |
169 cube |
| 172 } |
170 } |
| 173 |
171 |
| 174 /// Creates a new cube from an array. |
172 /// Creates a new cube from an array. |
| 175 #[inline] |
173 #[inline] |
| 176 pub fn new(data : [[U; 2]; N]) -> Self { |
174 pub fn new(data: [[U; 2]; N]) -> Self { |
| 177 Cube(data) |
175 Cube(data) |
| 178 } |
176 } |
| 179 } |
177 } |
| 180 |
178 |
| 181 impl<F : Float, const N : usize> Cube<F, N> { |
179 impl<F: Float, const N: usize> Cube<N, F> { |
| 182 /// Returns the centre of the cube |
180 /// Returns the centre of the cube |
| 183 pub fn center(&self) -> Loc<F, N> { |
181 pub fn center(&self) -> Loc<N, F> { |
| 184 map1(self, |&[a, b]| (a + b) / F::TWO).into() |
182 map1(self, |&[a, b]| (a + b) / F::TWO).into() |
| 185 } |
183 } |
| 186 } |
184 } |
| 187 |
185 |
| 188 impl<U : Num> Cube<U, 1> { |
186 impl<U: Num> Cube<1, U> { |
| 189 /// Get the corners of the cube. |
187 /// Get the corners of the cube. |
| 190 /// |
188 /// |
| 191 /// TODO: generic implementation once const-generics can be involved in |
189 /// TODO: generic implementation once const-generics can be involved in |
| 192 /// calculations. |
190 /// calculations. |
| 193 #[inline] |
191 #[inline] |
| 194 pub fn corners(&self) -> [Loc<U, 1>; 2] { |
192 pub fn corners(&self) -> [Loc<1, U>; 2] { |
| 195 let [[a, b]] = self.0; |
193 let [[a, b]] = self.0; |
| 196 [a.into(), b.into()] |
194 [a.into(), b.into()] |
| 197 } |
195 } |
| 198 } |
196 } |
| 199 |
197 |
| 200 impl<U : Num> Cube<U, 2> { |
198 impl<U: Num> Cube<2, U> { |
| 201 /// Get the corners of the cube in counter-clockwise order. |
199 /// Get the corners of the cube in counter-clockwise order. |
| 202 /// |
200 /// |
| 203 /// TODO: generic implementation once const-generics can be involved in |
201 /// TODO: generic implementation once const-generics can be involved in |
| 204 /// calculations. |
202 /// calculations. |
| 205 #[inline] |
203 #[inline] |
| 206 pub fn corners(&self) -> [Loc<U, 2>; 4] { |
204 pub fn corners(&self) -> [Loc<2, U>; 4] { |
| 207 let [[a1, b1], [a2, b2]]=self.0; |
205 let [[a1, b1], [a2, b2]] = self.0; |
| 208 [[a1, a2].into(), |
206 [ |
| 209 [b1, a2].into(), |
207 [a1, a2].into(), |
| 210 [b1, b2].into(), |
208 [b1, a2].into(), |
| 211 [a1, b2].into()] |
209 [b1, b2].into(), |
| 212 } |
210 [a1, b2].into(), |
| 213 } |
211 ] |
| 214 |
212 } |
| 215 impl<U : Num> Cube<U, 3> { |
213 } |
| |
214 |
| |
215 impl<U: Num> Cube<3, U> { |
| 216 /// Get the corners of the cube. |
216 /// Get the corners of the cube. |
| 217 /// |
217 /// |
| 218 /// TODO: generic implementation once const-generics can be involved in |
218 /// TODO: generic implementation once const-generics can be involved in |
| 219 /// calculations. |
219 /// calculations. |
| 220 #[inline] |
220 #[inline] |
| 221 pub fn corners(&self) -> [Loc<U, 3>; 8] { |
221 pub fn corners(&self) -> [Loc<3, U>; 8] { |
| 222 let [[a1, b1], [a2, b2], [a3, b3]]=self.0; |
222 let [[a1, b1], [a2, b2], [a3, b3]] = self.0; |
| 223 [[a1, a2, a3].into(), |
223 [ |
| 224 [b1, a2, a3].into(), |
224 [a1, a2, a3].into(), |
| 225 [b1, b2, a3].into(), |
225 [b1, a2, a3].into(), |
| 226 [a1, b2, a3].into(), |
226 [b1, b2, a3].into(), |
| 227 [a1, b2, b3].into(), |
227 [a1, b2, a3].into(), |
| 228 [b1, b2, b3].into(), |
228 [a1, b2, b3].into(), |
| 229 [b1, a2, b3].into(), |
229 [b1, b2, b3].into(), |
| 230 [a1, a2, b3].into()] |
230 [b1, a2, b3].into(), |
| |
231 [a1, a2, b3].into(), |
| |
232 ] |
| 231 } |
233 } |
| 232 } |
234 } |
| 233 |
235 |
| 234 // TODO: Implement Add and Sub of Loc to Cube, and Mul and Div by U : Num. |
236 // TODO: Implement Add and Sub of Loc to Cube, and Mul and Div by U : Num. |
| 235 |
237 |
| 236 impl<U : Num, const N : usize> From<[[U; 2]; N]> for Cube<U, N> { |
238 impl<U: Num, const N: usize> From<[[U; 2]; N]> for Cube<N, U> { |
| 237 #[inline] |
239 #[inline] |
| 238 fn from(data : [[U; 2]; N]) -> Self { |
240 fn from(data: [[U; 2]; N]) -> Self { |
| 239 Cube(data) |
241 Cube(data) |
| 240 } |
242 } |
| 241 } |
243 } |
| 242 |
244 |
| 243 impl<U : Num, const N : usize> From<Cube<U, N>> for [[U; 2]; N] { |
245 impl<U: Num, const N: usize> From<Cube<N, U>> for [[U; 2]; N] { |
| 244 #[inline] |
246 #[inline] |
| 245 fn from(Cube(data) : Cube<U, N>) -> Self { |
247 fn from(Cube(data): Cube<N, U>) -> Self { |
| 246 data |
248 data |
| 247 } |
249 } |
| 248 } |
250 } |
| 249 |
251 |
| 250 |
252 impl<U, const N: usize> Cube<N, U> |
| 251 impl<U, const N : usize> Cube<U, N> where U : Num + PartialOrd { |
253 where |
| |
254 U: Num + PartialOrd, |
| |
255 { |
| 252 /// Checks whether the cube is non-degenerate, i.e., the start coordinate |
256 /// Checks whether the cube is non-degenerate, i.e., the start coordinate |
| 253 /// of each axis is strictly less than the end coordinate. |
257 /// of each axis is strictly less than the end coordinate. |
| 254 #[inline] |
258 #[inline] |
| 255 pub fn nondegenerate(&self) -> bool { |
259 pub fn nondegenerate(&self) -> bool { |
| 256 self.0.iter().all(|range| range[0] < range[1]) |
260 self.0.iter().all(|range| range[0] < range[1]) |
| 257 } |
261 } |
| 258 |
262 |
| 259 /// Checks whether the cube intersects some `other` cube. |
263 /// Checks whether the cube intersects some `other` cube. |
| 260 /// Matching boundary points are not counted, so `U` is ideally a [`Float`]. |
264 /// Matching boundary points are not counted, so `U` is ideally a [`Float`]. |
| 261 #[inline] |
265 #[inline] |
| 262 pub fn intersects(&self, other : &Cube<U, N>) -> bool { |
266 pub fn intersects(&self, other: &Cube<N, U>) -> bool { |
| 263 self.iter_coords().zip(other.iter_coords()).all(|([a1, b1], [a2, b2])| { |
267 self.iter_coords() |
| 264 a1 < b2 && a2 < b1 |
268 .zip(other.iter_coords()) |
| 265 }) |
269 .all(|([a1, b1], [a2, b2])| a1 < b2 && a2 < b1) |
| 266 } |
270 } |
| 267 |
271 |
| 268 /// Checks whether the cube contains some `other` cube. |
272 /// Checks whether the cube contains some `other` cube. |
| 269 pub fn contains_set(&self, other : &Cube<U, N>) -> bool { |
273 pub fn contains_set(&self, other: &Cube<N, U>) -> bool { |
| 270 self.iter_coords().zip(other.iter_coords()).all(|([a1, b1], [a2, b2])| { |
274 self.iter_coords() |
| 271 a1 <= a2 && b1 >= b2 |
275 .zip(other.iter_coords()) |
| 272 }) |
276 .all(|([a1, b1], [a2, b2])| a1 <= a2 && b1 >= b2) |
| 273 } |
277 } |
| 274 |
278 |
| 275 /// Produces the point of minimum $ℓ^p$-norm within the cube `self` for any $p$-norm. |
279 /// Produces the point of minimum $ℓ^p$-norm within the cube `self` for any $p$-norm. |
| 276 /// This is the point where each coordinate is closest to zero. |
280 /// This is the point where each coordinate is closest to zero. |
| 277 #[inline] |
281 #[inline] |
| 278 pub fn minnorm_point(&self) -> Loc<U, N> { |
282 pub fn minnorm_point(&self) -> Loc<N, U> { |
| 279 let z = U::ZERO; |
283 let z = U::ZERO; |
| 280 // As always, we assume that a ≤ b. |
284 // As always, we assume that a ≤ b. |
| 281 self.map(|a, b| { |
285 self.map(|a, b| { |
| 282 debug_assert!(a <= b); |
286 debug_assert!(a <= b); |
| 283 match (a < z, z < b) { |
287 match (a < z, z < b) { |
| 284 (false, _) => a, |
288 (false, _) => a, |
| 285 (_, false) => b, |
289 (_, false) => b, |
| 286 (true, true) => z |
290 (true, true) => z, |
| 287 } |
291 } |
| 288 }).into() |
292 }) |
| |
293 .into() |
| 289 } |
294 } |
| 290 |
295 |
| 291 /// Produces the point of maximum $ℓ^p$-norm within the cube `self` for any $p$-norm. |
296 /// Produces the point of maximum $ℓ^p$-norm within the cube `self` for any $p$-norm. |
| 292 /// This is the point where each coordinate is furthest from zero. |
297 /// This is the point where each coordinate is furthest from zero. |
| 293 #[inline] |
298 #[inline] |
| 294 pub fn maxnorm_point(&self) -> Loc<U, N> { |
299 pub fn maxnorm_point(&self) -> Loc<N, U> { |
| 295 let z = U::ZERO; |
300 let z = U::ZERO; |
| 296 // As always, we assume that a ≤ b. |
301 // As always, we assume that a ≤ b. |
| 297 self.map(|a, b| { |
302 self.map(|a, b| { |
| 298 debug_assert!(a <= b); |
303 debug_assert!(a <= b); |
| 299 match (a < z, z < b) { |
304 match (a < z, z < b) { |
| 300 (false, _) => b, |
305 (false, _) => b, |
| 301 (_, false) => a, |
306 (_, false) => a, |
| 302 // A this stage we must have a < 0 (so U must be signed), and want to check |
307 // A this stage we must have a < 0 (so U must be signed), and want to check |
| 303 // whether |a| > |b|. We can do this without assuming U to actually implement |
308 // whether |a| > |b|. We can do this without assuming U to actually implement |
| 304 // `Neg` by comparing whether 0 > a + b. |
309 // `Neg` by comparing whether 0 > a + b. |
| 305 (true, true) => if z > a + b { a } else { b } |
310 (true, true) => { |
| |
311 if z > a + b { |
| |
312 a |
| |
313 } else { |
| |
314 b |
| |
315 } |
| |
316 } |
| 306 } |
317 } |
| 307 }).into() |
318 }) |
| |
319 .into() |
| 308 } |
320 } |
| 309 } |
321 } |
| 310 |
322 |
| 311 macro_rules! impl_common { |
323 macro_rules! impl_common { |
| 312 ($($t:ty)*, $min:ident, $max:ident) => { $( |
324 ($($t:ty)*, $min:ident, $max:ident) => { $( |
| 313 impl<const N : usize> SetOrd for Cube<$t, N> { |
325 impl<const N : usize> SetOrd for Cube<N, $t> { |
| 314 #[inline] |
326 #[inline] |
| 315 fn common(&self, other : &Self) -> Self { |
327 fn common(&self, other : &Self) -> Self { |
| 316 map2(self, other, |&[a1, b1], &[a2, b2]| { |
328 map2(self, other, |&[a1, b1], &[a2, b2]| { |
| 317 debug_assert!(a1 <= b1 && a2 <= b2); |
329 debug_assert!(a1 <= b1 && a2 <= b2); |
| 318 [a1.$min(a2), b1.$max(b2)] |
330 [a1.$min(a2), b1.$max(b2)] |