use std::marker::PhantomData;
use crate::{fold_settings::FoldSettings, misc::{Bool, ComposeRefFn, Fun}};
pub trait FoldSimplification<T,D: Clone> : Clone + Copy {
type D2: Clone;
fn op(&self, a: Self::D2, b: Self::D2, settings: impl FoldSettings<T,D>) -> Self::D2;
fn simplify(&self, delta: &D) -> Self::D2;
fn empty(&self, settings: impl FoldSettings<T,D>) -> Self::D2;
fn delta_of(&self, value: &T, settings: impl FoldSettings<T,D>) -> Self::D2;
type Compose<D3: Clone,
Simplifier: for<'x> Fun<&'x Self::D2,D3> + Copy,
OP2: Fun<(D3,D3),D3> + Copy>
: FoldSimplification<T,D,D2 = D3>;
fn compose<D3: Clone,
Simplifier: for<'x> Fun<&'x Self::D2,D3> + Copy,
OP2: Fun<(D3,D3),D3> + Copy>(self, simplifier: Simplifier, op2: OP2) -> Self::Compose<D3,Simplifier,OP2>;
type ComposeWithShortcut<D3: Clone,
Simplifier: for<'x> Fun<&'x Self::D2,D3> + Copy,
OP2: Fun<(D3,D3),D3> + Copy,
EmptyShortcut: Fun<(),D3> + Copy,
DeltaShortcut: for<'x> Fun<&'x T, D3> + Copy>
: FoldSimplification<T,D,D2 = D3>;
fn compose_with_shortcut<D3: Clone,
Simplifier: for<'x> Fun<&'x Self::D2,D3> + Copy,
OP2: Fun<(D3,D3),D3> + Copy,
EmptyShortcut: Fun<(),D3> + Copy,
DeltaShortcut: for<'x> Fun<&'x T, D3> + Copy>(self, simplifier: Simplifier, op2: OP2,empty_shortcut: EmptyShortcut, delta_shortcut: DeltaShortcut) -> Self::ComposeWithShortcut<D3,Simplifier,OP2,EmptyShortcut,DeltaShortcut>;
type ComposeAfterOther<D0: Clone,Other: FoldSimplification<T,D0,D2=D>> : FoldSimplification<T,D0,D2=Self::D2>;
fn compose_after_other<D0: Clone,Other: FoldSimplification<T,D0,D2=D>>(self,other: Other) -> Self::ComposeAfterOther<D0,Other>;
type WithSize : FoldSimplification<T,(usize,D),D2=(usize,Self::D2)>;
fn with_size(self) -> Self::WithSize;
fn op_cswap<Reversed: Bool>(&self, a: Self::D2, b: Self::D2,settings: impl FoldSettings<T,D>) -> Self::D2 {
if Reversed::b {
self.op(b,a,settings)
} else {
self.op(a,b,settings)
}
}
}
impl<T,D: Clone> FoldSimplification<T, D> for () {
type D2 = D;
fn op(&self, a: Self::D2, b: Self::D2, settings: impl FoldSettings<T,D>) -> Self::D2 {
settings.op(a,b)
}
fn simplify(&self, delta: &D) -> Self::D2 {
delta.clone()
}
fn empty(&self, settings: impl FoldSettings<T,D>) -> Self::D2 {
settings.empty()
}
fn delta_of(&self, value: &T, settings: impl FoldSettings<T,D>) -> Self::D2 {
settings.delta_of(value)
}
type Compose<D3: Clone,
Simplifier: for<'x> Fun<&'x Self::D2,D3> + Copy,
OP2: Fun<(D3,D3),D3> + Copy>
= SimplificationWithoutShortcut<T,D,D3,Simplifier,OP2>;
fn compose<D3: Clone,
Simplifier: for<'x> Fun<&'x Self::D2,D3> + Copy,
OP2: Fun<(D3,D3),D3> + Copy>(self, simplifier: Simplifier, op2: OP2) -> Self::Compose<D3,Simplifier,OP2> {
SimplificationWithoutShortcut { simplifier, op2, _m: PhantomData }
}
type ComposeWithShortcut<D3: Clone,
Simplifier: for<'x> Fun<&'x Self::D2,D3> + Copy,
OP2: Fun<(D3,D3),D3> + Copy,
EmptyShortcut: Fun<(),D3> + Copy,
DeltaShortcut: for<'x> Fun<&'x T, D3> + Copy>
= SimplificationWithShortcut<T,D,D3,Simplifier,OP2,EmptyShortcut,DeltaShortcut>;
fn compose_with_shortcut<D3: Clone,
Simplifier: for<'x> Fun<&'x Self::D2,D3> + Copy,
OP2: Fun<(D3,D3),D3> + Copy,
EmptyShortcut: Fun<(),D3> + Copy,
DeltaShortcut: for<'x> Fun<&'x T, D3> + Copy>(self, simplifier: Simplifier, op2: OP2,empty_shortcut: EmptyShortcut, delta_shortcut: DeltaShortcut) -> Self::ComposeWithShortcut<D3,Simplifier,OP2,EmptyShortcut,DeltaShortcut> {
SimplificationWithShortcut{ simplifier, op2, empty_shortcut, delta_shortcut, _m: PhantomData }
}
type ComposeAfterOther<D0: Clone,Other: FoldSimplification<T,D0,D2=D>> = Other;
fn compose_after_other<D0: Clone,Other: FoldSimplification<T,D0,D2=D>>(self,other: Other) -> Self::ComposeAfterOther<D0,Other> {
other
}
type WithSize = ();
fn with_size(self) -> Self::WithSize {}
}
pub struct SimplificationWithoutShortcut<T,D: Clone, D2: Clone,
Simplifier: for<'x> Fun<&'x D,D2> + Copy,
OP2: Fun<(D2,D2),D2> + Copy> {
pub simplifier: Simplifier,
pub op2: OP2,
#[allow(missing_docs)]
pub _m: PhantomData<(fn(&D)->D2,fn(&T)->D2)>
}
impl<T, D: Clone, D2: Clone, Simplifier: for<'x> Fun<&'x D,D2> + Copy, OP2: Fun<(D2,D2),D2> + Copy> Copy for SimplificationWithoutShortcut<T, D, D2, Simplifier, OP2> {}
impl<T, D: Clone, D2: Clone, Simplifier: for<'x> Fun<&'x D,D2> + Copy, OP2: Fun<(D2,D2),D2> + Copy>
Clone for SimplificationWithoutShortcut<T, D, D2, Simplifier, OP2> {
fn clone(&self) -> Self {
Self { simplifier: self.simplifier.clone(), op2: self.op2.clone(), _m: self._m.clone() }
}
}
impl<T, D: Clone, D2: Clone, Simplifier: for<'x> Fun<&'x D,D2> + Copy, OP2: Fun<(D2,D2),D2> + Copy>
FoldSimplification<T,D> for SimplificationWithoutShortcut<T, D, D2, Simplifier, OP2> {
type D2 = D2;
fn op(&self, a: Self::D2, b: Self::D2, _: impl FoldSettings<T,D>) -> Self::D2 {
self.op2.apply((a,b))
}
fn simplify(&self, delta: &D) -> Self::D2 {
self.simplifier.apply(delta)
}
fn empty(&self, settings: impl FoldSettings<T,D>) -> Self::D2 {
self.simplifier.apply(&settings.empty())
}
fn delta_of(&self, value: &T, settings: impl FoldSettings<T,D>) -> Self::D2 {
self.simplifier.apply(&settings.delta_of(value))
}
type Compose<D3: Clone,
Simplifier2: for<'x> Fun<&'x Self::D2,D3> + Copy,
OP3: Fun<(D3,D3),D3> + Copy>
= SimplificationWithoutShortcut<T,D,D3,ComposeRefFn<Simplifier2,Simplifier,D2>,OP3>;
fn compose<D3: Clone,
Simplifier2: for<'x> Fun<&'x Self::D2,D3> + Copy,
OP3: Fun<(D3,D3),D3> + Copy>(self, simplifier2: Simplifier2, op3: OP3) -> Self::Compose<D3,Simplifier2,OP3> {
SimplificationWithoutShortcut {
simplifier: ComposeRefFn(simplifier2,self.simplifier,PhantomData),
op2: op3,
_m: PhantomData,
}
}
type ComposeWithShortcut<D3: Clone,
Simplifier2: for<'x> Fun<&'x Self::D2,D3> + Copy,
OP3: Fun<(D3,D3),D3> + Copy,
EmptyShortcut: Fun<(),D3> + Copy,
DeltaShortcut: for<'x> Fun<&'x T, D3> + Copy>
= SimplificationWithShortcut<T,D,D3,
ComposeRefFn<Simplifier2,Simplifier,D2>,
OP3,
EmptyShortcut,
DeltaShortcut>;
fn compose_with_shortcut<D3: Clone,
Simplifier2: for<'x> Fun<&'x Self::D2,D3> + Copy,
OP3: Fun<(D3,D3),D3> + Copy,
EmptyShortcut: Fun<(),D3> + Copy,
DeltaShortcut: for<'x> Fun<&'x T, D3> + Copy>(self, simplifier: Simplifier2, op2: OP3, empty_shortcut: EmptyShortcut, delta_shortcut: DeltaShortcut) -> Self::ComposeWithShortcut<D3,Simplifier2,OP3,EmptyShortcut,DeltaShortcut> {
SimplificationWithShortcut {
simplifier: ComposeRefFn(simplifier, self.simplifier, PhantomData),
op2,
empty_shortcut,
delta_shortcut,
_m: PhantomData
}
}
type ComposeAfterOther<D0: Clone,Other: FoldSimplification<T,D0,D2=D>> = Other::Compose<D2,Simplifier,OP2>;
fn compose_after_other<D0: Clone,Other: FoldSimplification<T,D0,D2=D>>(self,other: Other) -> Self::ComposeAfterOther<D0,Other> {
other.compose(self.simplifier,self.op2)
}
type WithSize = SimplificationWithoutShortcut<T,(usize,D),(usize,D2),KeepSizeAnd<Simplifier>,AddSizesAnd<OP2>>;
fn with_size(self) -> Self::WithSize {
SimplificationWithoutShortcut {
simplifier: KeepSizeAnd(self.simplifier),
op2: AddSizesAnd(self.op2),
_m: PhantomData,
}
}
}
pub struct SimplificationWithShortcut<T,D: Clone, D2: Clone,
Simplifier: for<'x> Fun<&'x D,D2> + Copy,
OP2: Fun<(D2,D2),D2> + Copy,
EmptyShortcut: Fun<(),D2> + Copy,
DeltaShortcut: for<'x> Fun<&'x T, D2> + Copy> {
pub simplifier: Simplifier,
pub op2: OP2,
pub empty_shortcut: EmptyShortcut,
pub delta_shortcut: DeltaShortcut,
#[allow(missing_docs)]
pub _m: PhantomData<(fn(&D)->D2,fn(&T)->D2)>
}
impl<T, D: Clone, D2: Clone, Simplifier: for<'x> Fun<&'x D,D2> + Copy, OP2: Fun<(D2,D2),D2> + Copy, EmptyShortcut: Fun<(),D2> + Copy, DeltaShortcut: for<'x> Fun<&'x T, D2> + Copy>
Clone for SimplificationWithShortcut<T, D, D2, Simplifier, OP2, EmptyShortcut, DeltaShortcut> {
fn clone(&self) -> Self {
Self { simplifier: self.simplifier.clone(), op2: self.op2.clone(), empty_shortcut: self.empty_shortcut.clone(), delta_shortcut: self.delta_shortcut.clone(), _m: self._m.clone() }
}
}
impl<T, D: Clone, D2: Clone, Simplifier: for<'x> Fun<&'x D,D2> + Copy, OP2: Fun<(D2,D2),D2> + Copy, EmptyShortcut: Fun<(),D2> + Copy, DeltaShortcut: for<'x> Fun<&'x T, D2> + Copy> Copy for SimplificationWithShortcut<T, D, D2, Simplifier, OP2, EmptyShortcut, DeltaShortcut> {}
impl<T, D: Clone, D2: Clone, Simplifier: for<'x> Fun<&'x D,D2> + Copy, OP2: Fun<(D2,D2),D2> + Copy, EmptyShortcut: Fun<(),D2> + Copy, DeltaShortcut: for<'x> Fun<&'x T, D2> + Copy>
FoldSimplification<T,D> for SimplificationWithShortcut<T, D, D2, Simplifier, OP2, EmptyShortcut, DeltaShortcut> {
type D2 = D2;
fn op(&self, a: Self::D2, b: Self::D2, _: impl FoldSettings<T,D>) -> Self::D2 {
self.op2.apply((a,b))
}
fn simplify(&self, delta: &D) -> Self::D2 {
self.simplifier.apply(delta)
}
fn empty(&self, _: impl FoldSettings<T,D>) -> Self::D2 {
self.empty_shortcut.apply(())
}
fn delta_of(&self, value: &T, _: impl FoldSettings<T,D>) -> Self::D2 {
self.delta_shortcut.apply(value)
}
type Compose<D3: Clone,
Simplifier2: for<'x> Fun<&'x Self::D2,D3> + Copy,
OP3: Fun<(D3,D3),D3> + Copy>
= SimplificationWithShortcut<T,D,D3,
ComposeRefFn<Simplifier2,Simplifier,D2>,
OP3,
ComposeRefFn<Simplifier2,EmptyShortcut,D2>,
ComposeRefFn<Simplifier2,DeltaShortcut,D2>>;
fn compose<D3: Clone,
Simplifier2: for<'x> Fun<&'x Self::D2,D3> + Copy,
OP3: Fun<(D3,D3),D3> + Copy>(self, simplifier: Simplifier2, op2: OP3) -> Self::Compose<D3,Simplifier2,OP3> {
SimplificationWithShortcut {
simplifier: ComposeRefFn(simplifier, self.simplifier, PhantomData),
op2: op2,
empty_shortcut: ComposeRefFn(simplifier, self.empty_shortcut, PhantomData),
delta_shortcut: ComposeRefFn(simplifier, self.delta_shortcut, PhantomData),
_m: PhantomData
}
}
type ComposeWithShortcut<D3: Clone,
Simplifier2: for<'x> Fun<&'x Self::D2,D3> + Copy,
OP3: Fun<(D3,D3),D3> + Copy,
EmptyShortcut2: Fun<(),D3> + Copy,
DeltaShortcut2: for<'x> Fun<&'x T, D3> + Copy>
= SimplificationWithShortcut<T,D,D3,
ComposeRefFn<Simplifier2,Simplifier,D2>,
OP3,
EmptyShortcut2,
DeltaShortcut2>;
fn compose_with_shortcut<D3: Clone,
Simplifier2: for<'x> Fun<&'x Self::D2,D3> + Copy,
OP3: Fun<(D3,D3),D3> + Copy,
EmptyShortcut2: Fun<(),D3> + Copy,
DeltaShortcut2: for<'x> Fun<&'x T, D3> + Copy>(self, simplifier: Simplifier2, op2: OP3,empty_shortcut: EmptyShortcut2, delta_shortcut: DeltaShortcut2) -> Self::ComposeWithShortcut<D3,Simplifier2,OP3,EmptyShortcut2,DeltaShortcut2> {
SimplificationWithShortcut{
simplifier: ComposeRefFn(simplifier, self.simplifier, PhantomData),
op2,
empty_shortcut,
delta_shortcut,
_m: PhantomData
}
}
type ComposeAfterOther<D0: Clone,Other: FoldSimplification<T,D0,D2=D>> = Other::ComposeWithShortcut<D2,Simplifier,OP2,EmptyShortcut,DeltaShortcut>;
fn compose_after_other<D0: Clone,Other: FoldSimplification<T,D0,D2=D>>(self,other: Other) -> Self::ComposeAfterOther<D0,Other> {
other.compose_with_shortcut(self.simplifier, self.op2, self.empty_shortcut, self.delta_shortcut)
}
type WithSize = SimplificationWithShortcut<T,(usize,D),(usize,D2),
KeepSizeAnd<Simplifier>,
AddSizesAnd<OP2>,
AlwaysAnd<0,EmptyShortcut>,
AlwaysAnd<1,DeltaShortcut>>;
fn with_size(self) -> Self::WithSize {
SimplificationWithShortcut {
simplifier: KeepSizeAnd(self.simplifier),
op2: AddSizesAnd(self.op2),
empty_shortcut: AlwaysAnd(self.empty_shortcut),
delta_shortcut: AlwaysAnd(self.delta_shortcut),
_m: PhantomData,
}
}
}
#[derive(Clone,Copy)]
pub struct SizeIgnoreFn;
impl<'a,U,D: Clone> Fun<&'a (U,D),D> for SizeIgnoreFn {
fn apply(&self,a: &'a (U,D)) -> D {
a.1.clone()
}
}
pub struct OpFromSettings<T,D: Clone,S: FoldSettings<T,D>> {
pub settings: S,
#[allow(missing_docs)]
pub _m: PhantomData<(T,fn(D,D)->D)>
}
impl<T, D: Clone, S: FoldSettings<T,D>> Copy for OpFromSettings<T, D, S> {}
impl<T, D: Clone, S: FoldSettings<T,D>> Fun<(D,D),D> for OpFromSettings<T, D, S> {
fn apply(&self,(a,b): (D,D)) -> D {
self.settings.op(a,b)
}
}
impl<T, D: Clone, S: FoldSettings<T,D>> Clone for OpFromSettings<T, D, S> {
fn clone(&self) -> Self {
Self { settings: self.settings.clone(), _m: self._m.clone() }
}
}
pub type IgnoringSize<T,D,Settings> = SimplificationWithoutShortcut<T,(usize,D),D,SizeIgnoreFn,OpFromSettings<T,D,Settings>>;
#[derive(Clone,Copy)]
pub struct KeepSizeAnd<F>(pub F);
impl<'x,U: Copy,D: Clone, D2: Clone, F: for<'a> Fun<&'a D,D2>> Fun<&'x (U,D),(U,D2)> for KeepSizeAnd<F> {
fn apply(&self,a: &'x (U,D)) -> (U,D2) {
(a.0,self.0.apply(&a.1))
}
}
#[derive(Clone,Copy)]
pub struct AddSizesAnd<OP>(pub OP);
impl<U: core::ops::Add<Output = U> + Copy,D, OP: Fun<(D,D),D>> Fun<((U,D),(U,D)),(U,D)> for AddSizesAnd<OP> {
fn apply(&self,((n1,d1),(n2,d2)): ((U,D),(U,D))) -> (U,D) {
(n1 + n2, self.0.apply((d1,d2)))
}
}
#[derive(Clone,Copy)]
pub struct AlwaysAnd<const N: usize, F>(pub F);
impl<const N: usize, D, I, F: Fun<I,D>> Fun<I,(usize,D)> for AlwaysAnd<N,F> {
fn apply(&self,a: I) -> (usize,D) {
(N,self.0.apply(a))
}
}