--- a/src/measures/discrete.rs Thu Aug 29 00:00:00 2024 -0500 +++ b/src/measures/discrete.rs Tue Dec 31 09:25:45 2024 -0500 @@ -11,9 +11,11 @@ use alg_tools::norms::Norm; use alg_tools::tabledump::TableDump; -use alg_tools::linops::{Apply, Linear}; +use alg_tools::linops::{Mapping, Linear}; use alg_tools::iter::{MapF,Mappable}; use alg_tools::nalgebra_support::ToNalgebraRealField; +use alg_tools::collection::Collection; +use alg_tools::instance::{Instance, Decomposition, MyCow, EitherDecomp, Space}; use crate::types::*; use super::base::*; @@ -29,6 +31,8 @@ pub(super) spikes : Vec<DeltaMeasure<Domain, F>>, } +pub type RNDM<F, const N : usize> = DiscreteMeasure<Loc<F, N>, F>; + /// Iterator over the [`DeltaMeasure`] spikes of a [`DiscreteMeasure`]. pub type SpikeIter<'a, Domain, F> = std::slice::Iter<'a, DeltaMeasure<Domain, F>>; @@ -109,6 +113,13 @@ self.spikes.iter_mut().zip(iter).for_each(|(δ, α)| δ.set_mass(α)); } + /// Update the locations of all the spikes to those produced by an iterator. + #[inline] + pub fn set_locations<'a, I : Iterator<Item=&'a Domain>>(&mut self, iter : I) + where Domain : 'static + Clone { + self.spikes.iter_mut().zip(iter.cloned()).for_each(|(δ, α)| δ.set_location(α)); + } + // /// Map the masses of all the spikes using a function and an iterator // #[inline] // pub fn zipmap_masses< @@ -190,7 +201,7 @@ impl<Domain, F : Num> IntoIterator for DiscreteMeasure<Domain, F> { type Item = DeltaMeasure<Domain, F>; - type IntoIter = <Vec<DeltaMeasure<Domain, F>> as IntoIterator>::IntoIter; + type IntoIter = std::vec::IntoIter<DeltaMeasure<Domain, F>>; #[inline] fn into_iter(self) -> Self::IntoIter { @@ -198,6 +209,60 @@ } } +impl<'a, Domain, F : Num> IntoIterator for &'a DiscreteMeasure<Domain, F> { + type Item = &'a DeltaMeasure<Domain, F>; + type IntoIter = SpikeIter<'a, Domain, F>; + + #[inline] + fn into_iter(self) -> Self::IntoIter { + self.spikes.iter() + } +} + +impl<Domain, F : Num> Sum<DeltaMeasure<Domain, F>> for DiscreteMeasure<Domain, F> { + // Required method + fn sum<I>(iter: I) -> Self + where + I : Iterator<Item = DeltaMeasure<Domain, F>> + { + Self::from_iter(iter) + } +} + +impl<'a, Domain : Clone, F : Num> Sum<&'a DeltaMeasure<Domain, F>> + for DiscreteMeasure<Domain, F> +{ + // Required method + fn sum<I>(iter: I) -> Self + where + I : Iterator<Item = &'a DeltaMeasure<Domain, F>> + { + Self::from_iter(iter.cloned()) + } +} + +impl<Domain, F : Num> Sum<DiscreteMeasure<Domain, F>> for DiscreteMeasure<Domain, F> { + // Required method + fn sum<I>(iter: I) -> Self + where + I : Iterator<Item = DiscreteMeasure<Domain, F>> + { + Self::from_iter(iter.map(|μ| μ.into_iter()).flatten()) + } +} + +impl<'a, Domain : Clone, F : Num> Sum<&'a DiscreteMeasure<Domain, F>> + for DiscreteMeasure<Domain, F> +{ + // Required method + fn sum<I>(iter: I) -> Self + where + I : Iterator<Item = &'a DiscreteMeasure<Domain, F>> + { + Self::from_iter(iter.map(|μ| μ.iter_spikes()).flatten().cloned()) + } +} + impl<Domain : Clone, F : Float> DiscreteMeasure<Domain, F> { /// Computes `μ1 ← θ * μ1 - ζ * μ2`, pruning entries where both `μ1` (`self`) and `μ2` have // zero weight. `μ2` will contain copy of pruned original `μ1` without arithmetic performed. @@ -312,6 +377,45 @@ } } +impl<Domain, F : Num> From<Vec<DeltaMeasure<Domain, F>>> +for DiscreteMeasure<Domain, F> { + #[inline] + fn from(spikes : Vec<DeltaMeasure<Domain, F>>) -> Self { + DiscreteMeasure{ spikes } + } +} + +impl<'a, Domain, F : Num, D> From<&'a [D]> +for DiscreteMeasure<Domain, F> +where &'a D : Into<DeltaMeasure<Domain, F>> { + #[inline] + fn from(list : &'a [D]) -> Self { + list.into_iter().map(|d| d.into()).collect() + } +} + + +impl<Domain, F : Num> From<DeltaMeasure<Domain, F>> +for DiscreteMeasure<Domain, F> { + #[inline] + fn from(δ : DeltaMeasure<Domain, F>) -> Self { + DiscreteMeasure{ + spikes : vec!(δ) + } + } +} + +impl<'a, Domain : Clone, F : Num> From<&'a DeltaMeasure<Domain, F>> +for DiscreteMeasure<Domain, F> { + #[inline] + fn from(δ : &'a DeltaMeasure<Domain, F>) -> Self { + DiscreteMeasure{ + spikes : vec!(δ.clone()) + } + } +} + + impl<Domain, F : Num, D : Into<DeltaMeasure<Domain, F>>> FromIterator<D> for DiscreteMeasure<Domain, F> { #[inline] @@ -371,19 +475,28 @@ } } -impl<Domain, G, F : Num, Y : Sum + Mul<F, Output=Y>> Apply<G> for DiscreteMeasure<Domain, F> -where G: for<'a> Apply<&'a Domain, Output = Y> { - type Output = Y; +impl<Domain, G, F : Num> Mapping<G> for DiscreteMeasure<Domain, F> +where + Domain : Space, + G::Codomain : Sum + Mul<F, Output=G::Codomain>, + G : Mapping<Domain, Codomain=F> + Clone + Space, + for<'b> &'b Domain : Instance<Domain>, +{ + type Codomain = G::Codomain; + #[inline] - fn apply(&self, g : G) -> Y { - self.spikes.iter().map(|m| g.apply(&m.x) * m.α).sum() + fn apply<I : Instance<G>>(&self, g : I) -> Self::Codomain { + g.eval(|g| self.spikes.iter().map(|m| g.apply(&m.x) * m.α).sum()) } } -impl<Domain, G, F : Num, Y : Sum + Mul<F, Output=Y>> Linear<G> for DiscreteMeasure<Domain, F> -where G : for<'a> Apply<&'a Domain, Output = Y> { - type Codomain = Y; -} +impl<Domain, G, F : Num> Linear<G> for DiscreteMeasure<Domain, F> +where + Domain : Space, + G::Codomain : Sum + Mul<F, Output=G::Codomain>, + G : Mapping<Domain, Codomain=F> + Clone + Space, + for<'b> &'b Domain : Instance<Domain>, +{ } /// Helper trait for constructing arithmetic operations for combinations @@ -391,6 +504,7 @@ trait Lift<F : Num, Domain> { type Producer : Iterator<Item=DeltaMeasure<Domain, F>>; + #[allow(dead_code)] /// Lifts `self` into a [`DiscreteMeasure`]. fn lift(self) -> DiscreteMeasure<Domain, F>; @@ -687,3 +801,217 @@ make_discrete_scalarop_lhs!(Mul, mul; f32 f64 i8 i16 i32 i64 isize u8 u16 u32 u64 usize); make_discrete_scalarop_lhs!(Div, div; f32 f64 i8 i16 i32 i64 isize u8 u16 u32 u64 usize); + +impl<F : Num, Domain> Collection for DiscreteMeasure<Domain, F> { + type Element = DeltaMeasure<Domain, F>; + type RefsIter<'a> = std::slice::Iter<'a, Self::Element> where Self : 'a; + + #[inline] + fn iter_refs(&self) -> Self::RefsIter<'_> { + self.iter_spikes() + } +} + +impl<Domain : Clone, F : Num> Space for DiscreteMeasure<Domain, F> { + type Decomp = MeasureDecomp; +} + +pub type SpikeSlice<'b, Domain, F> = &'b [DeltaMeasure<Domain, F>]; + +pub type EitherSlice<'b, Domain, F> = EitherDecomp< + Vec<DeltaMeasure<Domain, F>>, + SpikeSlice<'b, Domain, F> +>; + +impl<F : Num, Domain : Clone> Decomposition<DiscreteMeasure<Domain, F>> for MeasureDecomp { + type Decomposition<'b> = EitherSlice<'b, Domain, F> where DiscreteMeasure<Domain, F> : 'b; + type Reference<'b> = SpikeSlice<'b, Domain, F> where DiscreteMeasure<Domain, F> : 'b; + + /// Left the lightweight reference type into a full decomposition type. + fn lift<'b>(r : Self::Reference<'b>) -> Self::Decomposition<'b> { + EitherDecomp::Borrowed(r) + } +} + +impl<F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp> +for DiscreteMeasure<Domain, F> +{ + fn decompose<'b>(self) + -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b> + where Self : 'b, DiscreteMeasure<Domain, F> : 'b { + EitherDecomp::Owned(self.spikes) + } + + fn ref_instance(&self) + -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_> + { + self.spikes.as_slice() + } + + fn cow<'b>(self) -> MyCow<'b, DiscreteMeasure<Domain, F>> where Self : 'b { + MyCow::Owned(self) + } + + fn own(self) -> DiscreteMeasure<Domain, F> { + self + } +} + +impl<'a, F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp> +for &'a DiscreteMeasure<Domain, F> +{ + fn decompose<'b>(self) + -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b> + where Self : 'b, DiscreteMeasure<Domain, F> : 'b { + EitherDecomp::Borrowed(self.spikes.as_slice()) + } + + fn ref_instance(&self) + -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_> + { + self.spikes.as_slice() + } + + fn cow<'b>(self) -> MyCow<'b, DiscreteMeasure<Domain, F>> where Self : 'b { + MyCow::Borrowed(self) + } + + fn own(self) -> DiscreteMeasure<Domain, F> { + self.clone() + } +} + +impl<'a, F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp> +for EitherSlice<'a, Domain, F> +{ + fn decompose<'b>(self) + -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b> + where Self : 'b, DiscreteMeasure<Domain, F> : 'b { + self + } + + fn ref_instance(&self) + -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_> + { + match self { + EitherDecomp::Owned(v) => v.as_slice(), + EitherDecomp::Borrowed(s) => s, + } + } + + fn own(self) -> DiscreteMeasure<Domain, F> { + match self { + EitherDecomp::Owned(v) => v.into(), + EitherDecomp::Borrowed(s) => s.into(), + } + } +} + +impl<'a, F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp> +for &'a EitherSlice<'a, Domain, F> +{ + fn decompose<'b>(self) + -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b> + where Self : 'b, DiscreteMeasure<Domain, F> : 'b { + match self { + EitherDecomp::Owned(v) => EitherDecomp::Borrowed(v.as_slice()), + EitherDecomp::Borrowed(s) => EitherDecomp::Borrowed(s), + } + } + + fn ref_instance(&self) + -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_> + { + match self { + EitherDecomp::Owned(v) => v.as_slice(), + EitherDecomp::Borrowed(s) => s, + } + } + + fn own(self) -> DiscreteMeasure<Domain, F> { + match self { + EitherDecomp::Owned(v) => v.as_slice(), + EitherDecomp::Borrowed(s) => s + }.into() + } +} + +impl<'a, F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp> +for SpikeSlice<'a, Domain, F> +{ + fn decompose<'b>(self) + -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b> + where Self : 'b, DiscreteMeasure<Domain, F> : 'b { + EitherDecomp::Borrowed(self) + } + + fn ref_instance(&self) + -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_> + { + self + } + + fn own(self) -> DiscreteMeasure<Domain, F> { + self.into() + } +} + +impl<'a, F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp> +for &'a SpikeSlice<'a, Domain, F> +{ + fn decompose<'b>(self) + -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b> + where Self : 'b, DiscreteMeasure<Domain, F> : 'b { + EitherDecomp::Borrowed(*self) + } + + fn ref_instance(&self) + -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_> + { + *self + } + + fn own(self) -> DiscreteMeasure<Domain, F> { + (*self).into() + } +} + +impl<F : Num, Domain : Clone > Instance<DiscreteMeasure<Domain, F>, MeasureDecomp> +for DeltaMeasure<Domain, F> +{ + fn decompose<'b>(self) + -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b> + where Self : 'b, DiscreteMeasure<Domain, F> : 'b { + EitherDecomp::Owned(vec![self]) + } + + fn ref_instance(&self) + -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_> + { + std::slice::from_ref(self) + } + + fn own(self) -> DiscreteMeasure<Domain, F> { + self.into() + } +} + +impl<'a, F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp> +for &'a DeltaMeasure<Domain, F> +{ + fn decompose<'b>(self) + -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b> + where Self : 'b, DiscreteMeasure<Domain, F> : 'b { + EitherDecomp::Borrowed(std::slice::from_ref(self)) + } + + fn ref_instance(&self) + -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_> + { + std::slice::from_ref(*self) + } + + fn own(self) -> DiscreteMeasure<Domain, F> { + self.into() + } +}