1 /*! |
1 /*! |
2 Utilities for mapping over various container types. |
2 Utilities for mapping over various container types. |
3 */ |
3 */ |
4 |
4 |
|
5 use itertools::izip; |
5 #[cfg(feature = "nightly")] |
6 #[cfg(feature = "nightly")] |
6 use std::mem::MaybeUninit; |
7 use std::mem::MaybeUninit; |
7 use itertools::izip; |
|
8 |
8 |
9 /// Trait for a fixed-length container type. |
9 /// Trait for a fixed-length container type. |
10 /// |
10 /// |
11 /// Implemented by [`Loc`][crate::loc::Loc] vectors, [`Cube`][crate::sets::Cube]s, |
11 /// Implemented by [`Loc`][crate::loc::Loc] vectors, [`Cube`][crate::sets::Cube]s, |
12 /// and basic arrays. |
12 /// and basic arrays. |
13 pub trait FixedLength<const N : usize> { |
13 pub trait FixedLength<const N: usize> { |
14 /// Type of elements of the container. |
14 /// Type of elements of the container. |
15 type Elem; |
15 type Elem; |
16 /// Type of iterators over the elements of the container. |
16 /// Type of iterators over the elements of the container. |
17 type Iter : Iterator<Item = Self::Elem>; |
17 type Iter: Iterator<Item = Self::Elem>; |
18 |
18 |
19 /// Returns an iteartor over the elements of the container. |
19 /// Returns an iteartor over the elements of the container. |
20 fn fl_iter(self) -> Self::Iter; |
20 fn fl_iter(self) -> Self::Iter; |
21 } |
21 } |
22 |
22 |
23 /// Trait for a mutable fixed-length container type. |
23 /// Trait for a mutable fixed-length container type. |
24 pub trait FixedLengthMut<const N : usize> : FixedLength<N> { |
24 pub trait FixedLengthMut<const N: usize>: FixedLength<N> { |
25 /// Type of iterators over references to mutable elements of the container. |
25 /// Type of iterators over references to mutable elements of the container. |
26 type IterMut<'a> : Iterator<Item=&'a mut Self::Elem> where Self : 'a; |
26 type IterMut<'a>: Iterator<Item = &'a mut Self::Elem> |
|
27 where |
|
28 Self: 'a; |
27 |
29 |
28 /// Returns an iterator over mutable references to elements of the container. |
30 /// Returns an iterator over mutable references to elements of the container. |
29 fn fl_iter_mut(&mut self) -> Self::IterMut<'_>; |
31 fn fl_iter_mut(&mut self) -> Self::IterMut<'_>; |
30 } |
32 } |
31 |
33 |
32 impl<A, const N : usize> FixedLength<N> for [A; N] { |
34 impl<A, const N: usize> FixedLength<N> for [A; N] { |
33 type Elem = A; |
35 type Elem = A; |
34 type Iter = std::array::IntoIter<A, N>; |
36 type Iter = std::array::IntoIter<A, N>; |
35 #[inline] |
37 #[inline] |
36 fn fl_iter(self) -> Self::Iter { |
38 fn fl_iter(self) -> Self::Iter { |
37 self.into_iter() |
39 self.into_iter() |
38 } |
40 } |
39 } |
41 } |
40 |
42 |
41 impl<A, const N : usize> FixedLengthMut<N> for [A; N] { |
43 impl<A, const N: usize> FixedLengthMut<N> for [A; N] { |
42 type IterMut<'a> = std::slice::IterMut<'a, A> where A : 'a; |
44 type IterMut<'a> |
|
45 = std::slice::IterMut<'a, A> |
|
46 where |
|
47 A: 'a; |
43 #[inline] |
48 #[inline] |
44 fn fl_iter_mut(&mut self) -> Self::IterMut<'_> { |
49 fn fl_iter_mut(&mut self) -> Self::IterMut<'_> { |
45 self.iter_mut() |
50 self.iter_mut() |
46 } |
51 } |
47 } |
52 } |
48 |
53 |
49 impl<'a, A, const N : usize> FixedLength<N> for &'a [A; N] { |
54 impl<'a, A, const N: usize> FixedLength<N> for &'a [A; N] { |
50 type Elem = &'a A; |
55 type Elem = &'a A; |
51 type Iter = std::slice::Iter<'a, A>; |
56 type Iter = std::slice::Iter<'a, A>; |
52 #[inline] |
57 #[inline] |
53 fn fl_iter(self) -> Self::Iter { |
58 fn fl_iter(self) -> Self::Iter { |
54 self.iter() |
59 self.iter() |
193 }) |
197 }) |
194 } |
198 } |
195 } |
199 } |
196 |
200 |
197 /// Iterator returned by [`indexmap`][IndexMappable::indexmap] applied to an iterator. |
201 /// Iterator returned by [`indexmap`][IndexMappable::indexmap] applied to an iterator. |
198 pub struct IndexMap<I : Iterator<Item=A>, A, B, F : Fn(usize, A) -> B> { |
202 pub struct IndexMap<I: Iterator<Item = A>, A, B, F: Fn(usize, A) -> B> { |
199 iter : I, |
203 iter: I, |
200 f : F, |
204 f: F, |
201 j : usize, |
205 j: usize, |
202 } |
206 } |
203 |
207 |
204 impl<A, B, I : Iterator<Item=A>, F : Fn(usize, A) -> B> Iterator for IndexMap<I, A, B, F> { |
208 impl<A, B, I: Iterator<Item = A>, F: Fn(usize, A) -> B> Iterator for IndexMap<I, A, B, F> { |
205 type Item = B; |
209 type Item = B; |
206 #[inline] |
210 #[inline] |
207 fn next(&mut self) -> Option<B> { |
211 fn next(&mut self) -> Option<B> { |
208 self.iter.next().map(|a| { |
212 self.iter.next().map(|a| { |
209 let b = (self.f)(self.j, a); |
213 let b = (self.f)(self.j, a); |
210 self.j = self.j+1; |
214 self.j = self.j + 1; |
211 b |
215 b |
212 }) |
216 }) |
213 } |
217 } |
214 } |
218 } |
215 |
219 |
216 /// Trait for things that can be foldmapped. |
220 /// Trait for things that can be foldmapped. |
217 /// |
221 /// |
218 /// `A` is the type of elements of `Self`, and `J` the accumulator type for the folding. |
222 /// `A` is the type of elements of `Self`, and `J` the accumulator type for the folding. |
219 pub trait FoldMappable<A, J> : Sized { |
223 pub trait FoldMappable<A, J>: Sized { |
220 type Output<B, F> where F : Fn(J, A) -> (J, B); |
224 type Output<B, F> |
|
225 where |
|
226 F: Fn(J, A) -> (J, B); |
221 /// Fold and map over `self` with `f`. `j` is the initial accumulator for folding. |
227 /// Fold and map over `self` with `f`. `j` is the initial accumulator for folding. |
222 /// |
228 /// |
223 /// The output type depends on the implementation, but will generally have elements of |
229 /// The output type depends on the implementation, but will generally have elements of |
224 /// type `B`. |
230 /// type `B`. |
225 fn foldmap<B, F : Fn(J, A) -> (J, B)>(self, j : J, f : F) -> Self::Output<B, F>; |
231 fn foldmap<B, F: Fn(J, A) -> (J, B)>(self, j: J, f: F) -> Self::Output<B, F>; |
226 } |
232 } |
227 |
233 |
228 /// Trait for things that can be indexmapped. |
234 /// Trait for things that can be indexmapped. |
229 /// |
235 /// |
230 /// `A` is the type of elements of `Self`. |
236 /// `A` is the type of elements of `Self`. |
231 pub trait IndexMappable<A> : Sized { |
237 pub trait IndexMappable<A>: Sized { |
232 type Output<B, F> where F : Fn(usize, A) -> B; |
238 type Output<B, F> |
|
239 where |
|
240 F: Fn(usize, A) -> B; |
233 /// Map over element indices and elements of `self`. |
241 /// Map over element indices and elements of `self`. |
234 /// |
242 /// |
235 /// The output type depends on the implementation, but will generally have elements of |
243 /// The output type depends on the implementation, but will generally have elements of |
236 /// type `B`. |
244 /// type `B`. |
237 fn indexmap<B, F : Fn(usize, A) -> B>(self, f : F) -> Self::Output<B, F>; |
245 fn indexmap<B, F: Fn(usize, A) -> B>(self, f: F) -> Self::Output<B, F>; |
238 } |
246 } |
239 |
247 |
240 impl<'a, A, J : Copy> FoldMappable<&'a A, J> |
248 impl<'a, A, J: Copy> FoldMappable<&'a A, J> for std::slice::Iter<'a, A> { |
241 for std::slice::Iter<'a, A> { |
249 type Output<B, F> |
242 type Output<B, F> = FoldMap<Self, &'a A, B, J, F> where F : Fn(J, &'a A) -> (J, B); |
250 = FoldMap<Self, &'a A, B, J, F> |
243 #[inline] |
251 where |
244 fn foldmap<B, F : Fn(J, &'a A) -> (J, B)>(self, j : J, f : F) -> Self::Output<B, F> { |
252 F: Fn(J, &'a A) -> (J, B); |
245 FoldMap { iter : self, j, f } |
253 #[inline] |
246 } |
254 fn foldmap<B, F: Fn(J, &'a A) -> (J, B)>(self, j: J, f: F) -> Self::Output<B, F> { |
247 } |
255 FoldMap { iter: self, j, f } |
248 |
256 } |
249 impl<'a, A> IndexMappable<&'a A> |
257 } |
250 for std::slice::Iter<'a, A> { |
258 |
251 type Output<B, F> = IndexMap<Self, &'a A, B, F> where F : Fn(usize, &'a A) -> B; |
259 impl<'a, A> IndexMappable<&'a A> for std::slice::Iter<'a, A> { |
252 #[inline] |
260 type Output<B, F> |
253 fn indexmap<B, F : Fn(usize, &'a A) -> B>(self, f : F) -> Self::Output<B, F> { |
261 = IndexMap<Self, &'a A, B, F> |
254 IndexMap { iter : self, j : 0, f } |
262 where |
255 } |
263 F: Fn(usize, &'a A) -> B; |
256 } |
264 #[inline] |
257 |
265 fn indexmap<B, F: Fn(usize, &'a A) -> B>(self, f: F) -> Self::Output<B, F> { |
258 |
266 IndexMap { |
259 impl<A, J : Copy, const N : usize> FoldMappable<A, J> |
267 iter: self, |
260 for std::array::IntoIter<A, N> { |
268 j: 0, |
261 type Output<B, F> = FoldMap<Self, A, B, J, F> where F : Fn(J, A) -> (J, B); |
269 f, |
262 #[inline] |
270 } |
263 fn foldmap<B, F : Fn(J, A) -> (J, B)>(self, j : J, f : F) -> Self::Output<B, F> { |
271 } |
264 FoldMap { iter : self, j, f } |
272 } |
265 } |
273 |
266 } |
274 impl<A, J: Copy, const N: usize> FoldMappable<A, J> for std::array::IntoIter<A, N> { |
267 |
275 type Output<B, F> |
268 impl<'a, A, const N : usize> IndexMappable<A> |
276 = FoldMap<Self, A, B, J, F> |
269 for std::array::IntoIter<A, N> { |
277 where |
270 type Output<B, F> = IndexMap<Self, A, B, F> where F : Fn(usize, A) -> B; |
278 F: Fn(J, A) -> (J, B); |
271 #[inline] |
279 #[inline] |
272 fn indexmap<B, F : Fn(usize, A) -> B>(self, f : F) -> Self::Output<B, F> { |
280 fn foldmap<B, F: Fn(J, A) -> (J, B)>(self, j: J, f: F) -> Self::Output<B, F> { |
273 IndexMap { iter : self, j : 0, f } |
281 FoldMap { iter: self, j, f } |
274 } |
282 } |
275 } |
283 } |
276 |
284 |
277 impl<A, J : Copy, const N : usize> FoldMappable<A, J> for [A; N] { |
285 impl<'a, A, const N: usize> IndexMappable<A> for std::array::IntoIter<A, N> { |
278 type Output<B, F> = [B; N] where F : Fn(J, A) -> (J, B); |
286 type Output<B, F> |
279 #[inline] |
287 = IndexMap<Self, A, B, F> |
280 fn foldmap<B, F : Fn(J, A) -> (J, B)>(self, j : J, f : F) -> [B; N] { |
288 where |
|
289 F: Fn(usize, A) -> B; |
|
290 #[inline] |
|
291 fn indexmap<B, F: Fn(usize, A) -> B>(self, f: F) -> Self::Output<B, F> { |
|
292 IndexMap { |
|
293 iter: self, |
|
294 j: 0, |
|
295 f, |
|
296 } |
|
297 } |
|
298 } |
|
299 |
|
300 impl<A, J: Copy, const N: usize> FoldMappable<A, J> for [A; N] { |
|
301 type Output<B, F> |
|
302 = [B; N] |
|
303 where |
|
304 F: Fn(J, A) -> (J, B); |
|
305 #[inline] |
|
306 fn foldmap<B, F: Fn(J, A) -> (J, B)>(self, j: J, f: F) -> [B; N] { |
281 // //let mut res : [MaybeUninit<B>; N] = unsafe { MaybeUninit::uninit().assume_init() }; |
307 // //let mut res : [MaybeUninit<B>; N] = unsafe { MaybeUninit::uninit().assume_init() }; |
282 // let mut res = MaybeUninit::uninit_array::<N>(); |
308 // let mut res = MaybeUninit::uninit_array::<N>(); |
283 // for (a, i) in self.into_iter().zip(0..N) { |
309 // for (a, i) in self.into_iter().zip(0..N) { |
284 // let (jnew, b) = f(j, a); |
310 // let (jnew, b) = f(j, a); |
285 // unsafe { *(res.get_unchecked_mut(i)) = MaybeUninit::new(b) }; |
311 // unsafe { *(res.get_unchecked_mut(i)) = MaybeUninit::new(b) }; |