1use crate::{SplitInplace, SplitProcess};
2
3#[derive(Clone, Debug, Default)]
7pub struct Interpolator<P>(pub P);
8impl<X: Copy, Y, C: SplitProcess<Option<X>, Y, S>, S, const N: usize> SplitProcess<X, [Y; N], S>
9 for Interpolator<C>
10{
11 fn process(&self, state: &mut S, x: X) -> [Y; N] {
12 core::array::from_fn(|i| self.0.process(state, (i == 0).then_some(x)))
13 }
14}
15impl<X: Copy, C, S> SplitInplace<X, S> for Interpolator<C> where Self: SplitProcess<X, X, S> {}
16
17#[derive(Clone, Debug, Default)]
22pub struct Decimator<P>(pub P);
23impl<X: Copy, Y, C: SplitProcess<X, Option<Y>, S>, S, const N: usize> SplitProcess<[X; N], Y, S>
24 for Decimator<C>
25{
26 fn process(&self, state: &mut S, x: [X; N]) -> Y {
27 const { assert!(N > 0) }
28 x.into_iter()
29 .find_map(|x| self.0.process(state, x))
30 .unwrap()
31 }
32}
33impl<X: Copy, C, S> SplitInplace<X, S> for Decimator<C> where Self: SplitProcess<X, X, S> {}
34
35#[derive(Clone, Debug, Default)]
37pub struct Map<P>(pub P);
38impl<X: Copy, Y, C: SplitProcess<X, Y, S>, S> SplitProcess<Option<X>, Option<Y>, S> for Map<C> {
39 fn process(&self, state: &mut S, x: Option<X>) -> Option<Y> {
40 x.map(|x| self.0.process(state, x))
41 }
42}
43impl<X: Copy, Y, C: SplitProcess<X, Y, S>, S, E: Copy> SplitProcess<Result<X, E>, Result<Y, E>, S>
44 for Map<C>
45{
46 fn process(&self, state: &mut S, x: Result<X, E>) -> Result<Y, E> {
47 x.map(|x| self.0.process(state, x))
48 }
49}
50impl<X: Copy, C: SplitInplace<X, S>, S> SplitInplace<X, S> for Map<C> where
51 Self: SplitProcess<X, X, S>
52{
53}
54
55#[derive(Debug, Copy, Clone, Default)]
60pub struct Chunk<P>(pub P);
61impl<C: SplitProcess<X, Y, S>, S, X: Copy, Y, const N: usize> SplitProcess<[X; N], [Y; N], S>
62 for Chunk<C>
63{
64 fn process(&self, state: &mut S, x: [X; N]) -> [Y; N] {
65 x.map(|x| self.0.process(state, x))
66 }
67
68 fn block(&self, state: &mut S, x: &[[X; N]], y: &mut [[Y; N]]) {
69 self.0.block(state, x.as_flattened(), y.as_flattened_mut())
70 }
71}
72impl<C: SplitInplace<X, S>, S, X: Copy, const N: usize> SplitInplace<[X; N], S> for Chunk<C> {
73 fn inplace(&self, state: &mut S, xy: &mut [[X; N]]) {
74 self.0.inplace(state, xy.as_flattened_mut())
75 }
76}
77
78#[derive(Debug, Copy, Clone, Default)]
83pub struct ChunkIn<P, const R: usize>(pub P);
84impl<C: SplitProcess<[X; R], Y, S>, S, X: Copy, Y, const N: usize, const R: usize, const M: usize>
85 SplitProcess<[X; N], [Y; M], S> for ChunkIn<C, R>
86{
87 fn process(&self, state: &mut S, x: [X; N]) -> [Y; M] {
88 const { assert!(R * M == N) }
89 let (x, []) = x.as_chunks() else {
90 unreachable!()
91 };
92 core::array::from_fn(|i| self.0.process(state, x[i]))
93 }
94
95 fn block(&self, state: &mut S, x: &[[X; N]], y: &mut [[Y; M]]) {
96 const { assert!(R * M == N) }
97 let (x, []) = x.as_flattened().as_chunks() else {
98 unreachable!()
99 };
100 self.0.block(state, x, y.as_flattened_mut())
101 }
102}
103impl<C: SplitInplace<[X; 1], S>, S, X: Copy, const N: usize> SplitInplace<[X; N], S>
104 for ChunkIn<C, 1>
105where
106 Self: SplitProcess<[X; N], [X; N], S>,
107{
108 fn inplace(&self, state: &mut S, xy: &mut [[X; N]]) {
109 let (xy, []) = xy.as_flattened_mut().as_chunks_mut() else {
110 unreachable!()
111 };
112 self.0.inplace(state, xy)
113 }
114}
115
116#[derive(Debug, Copy, Clone, Default)]
121pub struct ChunkOut<P, const R: usize>(pub P);
122impl<C, S, X: Copy, Y: Default + Copy, const N: usize, const R: usize, const M: usize>
123 SplitProcess<[X; N], [Y; M], S> for ChunkOut<C, R>
124where
125 C: SplitProcess<X, [Y; R], S>,
126{
127 fn process(&self, state: &mut S, x: [X; N]) -> [Y; M] {
128 const { assert!(R * N == M) }
129 let mut y = [Y::default(); M];
132 let (yy, []) = y.as_chunks_mut() else {
133 unreachable!()
134 };
135 for (x, y) in x.into_iter().zip(yy) {
136 *y = self.0.process(state, x);
137 }
138 y
139 }
140
141 fn block(&self, state: &mut S, x: &[[X; N]], y: &mut [[Y; M]]) {
142 const { assert!(R * N == M) }
143 let (y, []) = y.as_flattened_mut().as_chunks_mut() else {
144 unreachable!()
145 };
146 self.0.block(state, x.as_flattened(), y)
147 }
148}
149impl<C: SplitInplace<[X; 1], S>, S, X: Copy, const N: usize> SplitInplace<[X; N], S>
150 for ChunkOut<C, 1>
151where
152 Self: SplitProcess<[X; N], [X; N], S>,
153{
154 fn inplace(&self, state: &mut S, xy: &mut [[X; N]]) {
155 let (xy, []) = xy.as_flattened_mut().as_chunks_mut() else {
156 unreachable!()
157 };
158 self.0.inplace(state, xy)
159 }
160}
161
162#[derive(Debug, Copy, Clone, Default)]
167pub struct ChunkInOut<P, const Q: usize, const R: usize>(pub P);
168impl<
169 C,
170 S,
171 X: Copy,
172 Y: Default + Copy,
173 const Q: usize,
174 const N: usize,
175 const R: usize,
176 const M: usize,
177> SplitProcess<[X; N], [Y; M], S> for ChunkInOut<C, Q, R>
178where
179 C: SplitProcess<[X; Q], [Y; R], S>,
180{
181 fn process(&self, state: &mut S, x: [X; N]) -> [Y; M] {
182 const { assert!(N.is_multiple_of(Q)) }
183 const { assert!(M.is_multiple_of(R)) }
184 let mut y = [Y::default(); M];
186 let (yy, []) = y.as_chunks_mut() else {
187 unreachable!()
188 };
189 let (x, []) = x.as_chunks() else {
190 unreachable!()
191 };
192 for (x, y) in x.iter().zip(yy) {
193 *y = self.0.process(state, *x);
194 }
195 y
196 }
197
198 fn block(&self, state: &mut S, x: &[[X; N]], y: &mut [[Y; M]]) {
199 const { assert!(N.is_multiple_of(Q)) }
200 const { assert!(M.is_multiple_of(R)) }
201 let (x, []) = x.as_flattened().as_chunks() else {
202 unreachable!()
203 };
204 let (y, []) = y.as_flattened_mut().as_chunks_mut() else {
205 unreachable!()
206 };
207 self.0.block(state, x, y)
208 }
209}
210impl<C: SplitInplace<[X; 1], S>, S, X: Copy, const N: usize> SplitInplace<[X; N], S>
211 for ChunkInOut<C, 1, 1>
212where
213 Self: SplitProcess<[X; N], [X; N], S>,
214{
215 fn inplace(&self, state: &mut S, xy: &mut [[X; N]]) {
216 let (xy, []) = xy.as_flattened_mut().as_chunks_mut() else {
217 unreachable!()
218 };
219 self.0.inplace(state, xy)
220 }
221}