use crate::{
LaneMajor, SplitInplace, SplitProcess, SplitViewInplace, SplitViewProcess, View, ViewMut,
};
use core::marker::PhantomData;
impl<X: Copy, Y: Copy, C0, C1, S0, S1> SplitProcess<X, Y, (S0, S1)> for (C0, C1)
where
C0: SplitProcess<X, Y, S0>,
C1: SplitInplace<Y, S1>,
{
fn process(&self, state: &mut (S0, S1), x: X) -> Y {
self.1
.process(&mut state.1, self.0.process(&mut state.0, x))
}
fn block(&self, state: &mut (S0, S1), x: &[X], y: &mut [Y]) {
self.0.block(&mut state.0, x, y);
self.1.inplace(&mut state.1, y);
}
}
impl<X: Copy, C0, C1, S0, S1> SplitInplace<X, (S0, S1)> for (C0, C1)
where
C0: SplitInplace<X, S0>,
C1: SplitInplace<X, S1>,
{
fn inplace(&self, state: &mut (S0, S1), xy: &mut [X]) {
self.0.inplace(&mut state.0, xy);
self.1.inplace(&mut state.1, xy);
}
}
impl<X: Copy, C, S> SplitProcess<X, X, [S]> for [C]
where
C: SplitInplace<X, S>,
{
fn process(&self, state: &mut [S], x: X) -> X {
debug_assert_eq!(self.len(), state.len());
self.iter()
.zip(state.iter_mut())
.fold(x, |x, (c, s)| c.process(s, x))
}
fn block(&self, state: &mut [S], x: &[X], y: &mut [X]) {
debug_assert_eq!(self.len(), state.len());
if let Some(((c0, c), (s0, s))) = self.split_first().zip(state.split_first_mut()) {
c0.block(s0, x, y);
for (c, s) in c.iter().zip(s) {
c.inplace(s, y);
}
} else {
y.copy_from_slice(x);
}
}
}
impl<X: Copy, C, S> SplitInplace<X, [S]> for [C]
where
C: SplitInplace<X, S>,
{
fn inplace(&self, state: &mut [S], xy: &mut [X]) {
debug_assert_eq!(self.len(), state.len());
for (c, s) in self.iter().zip(state.iter_mut()) {
c.inplace(s, xy);
}
}
}
impl<X: Copy, Y: Copy, C, S, const N: usize> SplitProcess<X, Y, [S; N]> for [C; N]
where
C: SplitProcess<X, Y, S> + SplitInplace<Y, S>,
{
fn process(&self, state: &mut [S; N], x: X) -> Y {
const { assert!(N > 0) }
let Some(((c0, c), (s0, s))) = self.split_first().zip(state.split_first_mut()) else {
unreachable!()
};
c.iter()
.zip(s.iter_mut())
.fold(c0.process(s0, x), |x, (c, s)| c.process(s, x))
}
fn block(&self, state: &mut [S; N], x: &[X], y: &mut [Y]) {
const { assert!(N > 0) }
let Some(((c0, c), (s0, s))) = self.split_first().zip(state.split_first_mut()) else {
unreachable!()
};
c0.block(s0, x, y);
for (c, s) in c.iter().zip(s.iter_mut()) {
c.inplace(s, y)
}
}
}
impl<X: Copy, C, S, const N: usize> SplitInplace<X, [S; N]> for [C; N]
where
C: SplitInplace<X, S>,
{
fn inplace(&self, state: &mut [S; N], xy: &mut [X]) {
self.as_ref().inplace(state.as_mut(), xy)
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(transparent)]
pub struct Minor<C: ?Sized, U> {
_intermediate: PhantomData<U>,
inner: C,
}
impl<C, U> Minor<C, U> {
#[must_use]
pub const fn new(inner: C) -> Self {
Self {
inner,
_intermediate: PhantomData,
}
}
#[must_use]
pub fn into_inner(self) -> C {
self.inner
}
#[must_use]
pub fn inner(&self) -> &C {
&self.inner
}
}
impl<X: Copy, U: Copy, Y, C0, C1, S0, S1> SplitProcess<X, Y, (S0, S1)> for Minor<(C0, C1), U>
where
C0: SplitProcess<X, U, S0>,
C1: SplitProcess<U, Y, S1>,
{
fn process(&self, state: &mut (S0, S1), x: X) -> Y {
self.inner
.1
.process(&mut state.1, self.inner.0.process(&mut state.0, x))
}
}
impl<X: Copy, C, S> SplitProcess<X, X, [S]> for Minor<[C], X>
where
C: SplitProcess<X, X, S>,
{
fn process(&self, state: &mut [S], x: X) -> X {
debug_assert_eq!(self.inner.len(), state.len());
self.inner
.iter()
.zip(state.iter_mut())
.fold(x, |x, (c, s)| c.process(s, x))
}
}
impl<X: Copy, Y: Copy, C, S, const N: usize> SplitProcess<X, Y, [S; N]> for Minor<[C; N], Y>
where
C: SplitProcess<X, Y, S> + SplitProcess<Y, Y, S>,
{
fn process(&self, state: &mut [S; N], x: X) -> Y {
const { assert!(N > 0) }
let Some(((c0, c), (s0, s))) = self.inner.split_first().zip(state.split_first_mut()) else {
unreachable!()
};
c.iter()
.zip(s.iter_mut())
.fold(c0.process(s0, x), |x, (c, s)| c.process(s, x))
}
}
impl<X, U, C, S> SplitInplace<X, S> for Minor<C, U>
where
X: Copy,
Self: SplitProcess<X, X, S>,
{
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Parallel<P>(P);
impl<P> Parallel<P> {
#[must_use]
pub const fn new(inner: P) -> Self {
Self(inner)
}
#[must_use]
pub fn into_inner(self) -> P {
self.0
}
}
impl<X0: Copy, X1: Copy, Y0, Y1, C0, C1, S0, S1> SplitProcess<(X0, X1), (Y0, Y1), (S0, S1)>
for Parallel<(C0, C1)>
where
C0: SplitProcess<X0, Y0, S0>,
C1: SplitProcess<X1, Y1, S1>,
{
fn process(&self, state: &mut (S0, S1), x: (X0, X1)) -> (Y0, Y1) {
(
self.0.0.process(&mut state.0, x.0),
self.0.1.process(&mut state.1, x.1),
)
}
}
impl<X: Copy, Y, C0, C1, S0, S1> SplitProcess<[X; 2], [Y; 2], (S0, S1)> for Parallel<(C0, C1)>
where
C0: SplitProcess<X, Y, S0>,
C1: SplitProcess<X, Y, S1>,
{
fn process(&self, state: &mut (S0, S1), x: [X; 2]) -> [Y; 2] {
[
self.0.0.process(&mut state.0, x[0]),
self.0.1.process(&mut state.1, x[1]),
]
}
}
impl<X: Copy, Y, C, S, const N: usize> SplitProcess<[X; N], [Y; N], [S; N]> for Parallel<[C; N]>
where
C: SplitProcess<X, Y, S>,
{
fn process(&self, state: &mut [S; N], x: [X; N]) -> [Y; N] {
core::array::from_fn(|i| self.0[i].process(&mut state[i], x[i]))
}
}
impl<X, C, S> SplitInplace<X, S> for Parallel<C>
where
X: Copy,
Self: SplitProcess<X, X, S>,
{
}
#[derive(Clone, Copy, Debug, Default)]
pub struct ByLane<C>(C);
impl<C> ByLane<C> {
#[must_use]
pub const fn new(inner: C) -> Self {
Self(inner)
}
#[must_use]
pub fn into_inner(self) -> C {
self.0
}
}
impl<X: Copy, Y, C0, C1, S0, S1> SplitProcess<[X; 2], [Y; 2], (S0, S1)> for ByLane<(C0, C1)>
where
C0: SplitProcess<X, Y, S0>,
C1: SplitProcess<X, Y, S1>,
{
fn process(&self, state: &mut (S0, S1), x: [X; 2]) -> [Y; 2] {
[
self.0.0.process(&mut state.0, x[0]),
self.0.1.process(&mut state.1, x[1]),
]
}
}
impl<'a, 'b, X: Copy, Y, C0, C1, S0, S1>
SplitViewProcess<View<'a, X, LaneMajor, 2>, ViewMut<'b, Y, LaneMajor, 2>, (S0, S1)>
for ByLane<(C0, C1)>
where
C0: SplitProcess<X, Y, S0>,
C1: SplitProcess<X, Y, S1>,
{
fn process_view(
&self,
state: &mut (S0, S1),
x: View<'a, X, LaneMajor, 2>,
mut y: ViewMut<'b, Y, LaneMajor, 2>,
) {
debug_assert_eq!(x.frames(), y.frames());
self.0.0.block(&mut state.0, x.lane(0), y.lane_mut(0));
self.0.1.block(&mut state.1, x.lane(1), y.lane_mut(1));
}
}
impl<X: Copy, Y, C, S, const N: usize> SplitProcess<[X; N], [Y; N], [S; N]> for ByLane<[C; N]>
where
C: SplitProcess<X, Y, S>,
{
fn process(&self, state: &mut [S; N], x: [X; N]) -> [Y; N] {
core::array::from_fn(|i| self.0[i].process(&mut state[i], x[i]))
}
}
impl<'a, 'b, X: Copy, Y, C, S, const N: usize>
SplitViewProcess<View<'a, X, LaneMajor, N>, ViewMut<'b, Y, LaneMajor, N>, [S; N]>
for ByLane<[C; N]>
where
C: SplitProcess<X, Y, S>,
{
fn process_view(
&self,
state: &mut [S; N],
x: View<'a, X, LaneMajor, N>,
mut y: ViewMut<'b, Y, LaneMajor, N>,
) {
debug_assert_eq!(x.frames(), y.frames());
for ((c, s), i) in self.0.iter().zip(state.iter_mut()).zip(0..) {
c.block(s, x.lane(i), y.lane_mut(i))
}
}
}
impl<X, C, S> SplitInplace<X, S> for ByLane<C>
where
X: Copy,
Self: SplitProcess<X, X, S>,
{
}
impl<'a, X: Copy, C0, C1, S0, S1> SplitViewInplace<ViewMut<'a, X, LaneMajor, 2>, (S0, S1)>
for ByLane<(C0, C1)>
where
C0: SplitInplace<X, S0>,
C1: SplitInplace<X, S1>,
{
fn inplace_view(&self, state: &mut (S0, S1), mut xy: ViewMut<'a, X, LaneMajor, 2>) {
self.0.0.inplace(&mut state.0, xy.lane_mut(0));
self.0.1.inplace(&mut state.1, xy.lane_mut(1));
}
}
impl<'a, X: Copy, C, S, const N: usize> SplitViewInplace<ViewMut<'a, X, LaneMajor, N>, [S; N]>
for ByLane<[C; N]>
where
C: SplitInplace<X, S>,
{
fn inplace_view(&self, state: &mut [S; N], mut xy: ViewMut<'a, X, LaneMajor, N>) {
for ((c, s), i) in self.0.iter().zip(state.iter_mut()).zip(0..) {
c.inplace(s, xy.lane_mut(i));
}
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Lanes<C>(C);
impl<C> Lanes<C> {
#[must_use]
pub const fn new(inner: C) -> Self {
Self(inner)
}
#[must_use]
pub fn into_inner(self) -> C {
self.0
}
}
impl<X: Copy, Y, C, S, const N: usize> SplitProcess<[X; N], [Y; N], [S; N]> for Lanes<C>
where
C: SplitProcess<X, Y, S>,
{
fn process(&self, state: &mut [S; N], x: [X; N]) -> [Y; N] {
core::array::from_fn(|i| self.0.process(&mut state[i], x[i]))
}
}
impl<'a, 'b, X: Copy, Y, C, S, const N: usize>
SplitViewProcess<View<'a, X, LaneMajor, N>, ViewMut<'b, Y, LaneMajor, N>, [S; N]> for Lanes<C>
where
C: SplitProcess<X, Y, S>,
{
fn process_view(
&self,
state: &mut [S; N],
x: View<'a, X, LaneMajor, N>,
mut y: ViewMut<'b, Y, LaneMajor, N>,
) {
debug_assert_eq!(x.frames(), y.frames());
for (state, i) in state.iter_mut().zip(0..) {
self.0.block(state, x.lane(i), y.lane_mut(i))
}
}
}
impl<X, C, S> SplitInplace<X, S> for Lanes<C>
where
X: Copy,
Self: SplitProcess<X, X, S>,
{
}
impl<'a, X: Copy, C, S, const N: usize> SplitViewInplace<ViewMut<'a, X, LaneMajor, N>, [S; N]>
for Lanes<C>
where
C: SplitInplace<X, S>,
{
fn inplace_view(&self, state: &mut [S; N], mut xy: ViewMut<'a, X, LaneMajor, N>) {
for (state, i) in state.iter_mut().zip(0..) {
self.0.inplace(state, xy.lane_mut(i));
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Major<P: ?Sized, U> {
_buf: PhantomData<U>,
inner: P,
}
impl<P, U> Major<P, U> {
#[must_use]
pub const fn new(inner: P) -> Self {
Self {
inner,
_buf: PhantomData,
}
}
#[must_use]
pub fn into_inner(self) -> P {
self.inner
}
#[must_use]
pub fn inner(&self) -> &P {
&self.inner
}
}
impl<X: Copy, U: Copy + Default, Y, C0, C1, S0, S1, const N: usize> SplitProcess<X, Y, (S0, S1)>
for Major<(C0, C1), [U; N]>
where
C0: SplitProcess<X, U, S0>,
C1: SplitProcess<U, Y, S1>,
{
fn process(&self, state: &mut (S0, S1), x: X) -> Y {
self.inner
.1
.process(&mut state.1, self.inner.0.process(&mut state.0, x))
}
fn block(&self, state: &mut (S0, S1), x: &[X], y: &mut [Y]) {
debug_assert_eq!(x.len(), y.len());
let mut u = [U::default(); N];
let (x, xr) = x.as_chunks::<N>();
let (y, yr) = y.as_chunks_mut::<N>();
for (x, y) in x.iter().zip(y) {
self.inner.0.block(&mut state.0, x, &mut u);
self.inner.1.block(&mut state.1, &u, y);
}
let ur = &mut u[..xr.len()];
self.inner.0.block(&mut state.0, xr, ur);
self.inner.1.block(&mut state.1, ur, yr);
}
}
impl<X: Copy, U: Copy + Default, C0, C1, S0, S1, const N: usize> SplitInplace<X, (S0, S1)>
for Major<(C0, C1), [U; N]>
where
C0: SplitProcess<X, U, S0>,
C1: SplitProcess<U, X, S1>,
{
fn inplace(&self, state: &mut (S0, S1), xy: &mut [X]) {
let mut u = [U::default(); N];
let (xy, xyr) = xy.as_chunks_mut::<N>();
for xy in xy {
self.inner.0.block(&mut state.0, xy, &mut u);
self.inner.1.block(&mut state.1, &u, xy);
}
let ur = &mut u[..xyr.len()];
self.inner.0.block(&mut state.0, xyr, ur);
self.inner.1.block(&mut state.1, ur, xyr);
}
}