diff -r efa60bc4f743 -r b087e3eab191 src/measures/discrete.rs --- 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>, } +pub type RNDM = DiscreteMeasure, F>; + /// Iterator over the [`DeltaMeasure`] spikes of a [`DiscreteMeasure`]. pub type SpikeIter<'a, Domain, F> = std::slice::Iter<'a, DeltaMeasure>; @@ -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>(&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 IntoIterator for DiscreteMeasure { type Item = DeltaMeasure; - type IntoIter = > as IntoIterator>::IntoIter; + type IntoIter = std::vec::IntoIter>; #[inline] fn into_iter(self) -> Self::IntoIter { @@ -198,6 +209,60 @@ } } +impl<'a, Domain, F : Num> IntoIterator for &'a DiscreteMeasure { + type Item = &'a DeltaMeasure; + type IntoIter = SpikeIter<'a, Domain, F>; + + #[inline] + fn into_iter(self) -> Self::IntoIter { + self.spikes.iter() + } +} + +impl Sum> for DiscreteMeasure { + // Required method + fn sum(iter: I) -> Self + where + I : Iterator> + { + Self::from_iter(iter) + } +} + +impl<'a, Domain : Clone, F : Num> Sum<&'a DeltaMeasure> + for DiscreteMeasure +{ + // Required method + fn sum(iter: I) -> Self + where + I : Iterator> + { + Self::from_iter(iter.cloned()) + } +} + +impl Sum> for DiscreteMeasure { + // Required method + fn sum(iter: I) -> Self + where + I : Iterator> + { + Self::from_iter(iter.map(|μ| μ.into_iter()).flatten()) + } +} + +impl<'a, Domain : Clone, F : Num> Sum<&'a DiscreteMeasure> + for DiscreteMeasure +{ + // Required method + fn sum(iter: I) -> Self + where + I : Iterator> + { + Self::from_iter(iter.map(|μ| μ.iter_spikes()).flatten().cloned()) + } +} + impl DiscreteMeasure { /// 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 From>> +for DiscreteMeasure { + #[inline] + fn from(spikes : Vec>) -> Self { + DiscreteMeasure{ spikes } + } +} + +impl<'a, Domain, F : Num, D> From<&'a [D]> +for DiscreteMeasure +where &'a D : Into> { + #[inline] + fn from(list : &'a [D]) -> Self { + list.into_iter().map(|d| d.into()).collect() + } +} + + +impl From> +for DiscreteMeasure { + #[inline] + fn from(δ : DeltaMeasure) -> Self { + DiscreteMeasure{ + spikes : vec!(δ) + } + } +} + +impl<'a, Domain : Clone, F : Num> From<&'a DeltaMeasure> +for DiscreteMeasure { + #[inline] + fn from(δ : &'a DeltaMeasure) -> Self { + DiscreteMeasure{ + spikes : vec!(δ.clone()) + } + } +} + + impl>> FromIterator for DiscreteMeasure { #[inline] @@ -371,19 +475,28 @@ } } -impl> Apply for DiscreteMeasure -where G: for<'a> Apply<&'a Domain, Output = Y> { - type Output = Y; +impl Mapping for DiscreteMeasure +where + Domain : Space, + G::Codomain : Sum + Mul, + G : Mapping + Clone + Space, + for<'b> &'b Domain : Instance, +{ + type Codomain = G::Codomain; + #[inline] - fn apply(&self, g : G) -> Y { - self.spikes.iter().map(|m| g.apply(&m.x) * m.α).sum() + fn apply>(&self, g : I) -> Self::Codomain { + g.eval(|g| self.spikes.iter().map(|m| g.apply(&m.x) * m.α).sum()) } } -impl> Linear for DiscreteMeasure -where G : for<'a> Apply<&'a Domain, Output = Y> { - type Codomain = Y; -} +impl Linear for DiscreteMeasure +where + Domain : Space, + G::Codomain : Sum + Mul, + G : Mapping + Clone + Space, + for<'b> &'b Domain : Instance, +{ } /// Helper trait for constructing arithmetic operations for combinations @@ -391,6 +504,7 @@ trait Lift { type Producer : Iterator>; + #[allow(dead_code)] /// Lifts `self` into a [`DiscreteMeasure`]. fn lift(self) -> DiscreteMeasure; @@ -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 Collection for DiscreteMeasure { + type Element = DeltaMeasure; + type RefsIter<'a> = std::slice::Iter<'a, Self::Element> where Self : 'a; + + #[inline] + fn iter_refs(&self) -> Self::RefsIter<'_> { + self.iter_spikes() + } +} + +impl Space for DiscreteMeasure { + type Decomp = MeasureDecomp; +} + +pub type SpikeSlice<'b, Domain, F> = &'b [DeltaMeasure]; + +pub type EitherSlice<'b, Domain, F> = EitherDecomp< + Vec>, + SpikeSlice<'b, Domain, F> +>; + +impl Decomposition> for MeasureDecomp { + type Decomposition<'b> = EitherSlice<'b, Domain, F> where DiscreteMeasure : 'b; + type Reference<'b> = SpikeSlice<'b, Domain, F> where DiscreteMeasure : '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 Instance, MeasureDecomp> +for DiscreteMeasure +{ + fn decompose<'b>(self) + -> >>::Decomposition<'b> + where Self : 'b, DiscreteMeasure : 'b { + EitherDecomp::Owned(self.spikes) + } + + fn ref_instance(&self) + -> >>::Reference<'_> + { + self.spikes.as_slice() + } + + fn cow<'b>(self) -> MyCow<'b, DiscreteMeasure> where Self : 'b { + MyCow::Owned(self) + } + + fn own(self) -> DiscreteMeasure { + self + } +} + +impl<'a, F : Num, Domain : Clone> Instance, MeasureDecomp> +for &'a DiscreteMeasure +{ + fn decompose<'b>(self) + -> >>::Decomposition<'b> + where Self : 'b, DiscreteMeasure : 'b { + EitherDecomp::Borrowed(self.spikes.as_slice()) + } + + fn ref_instance(&self) + -> >>::Reference<'_> + { + self.spikes.as_slice() + } + + fn cow<'b>(self) -> MyCow<'b, DiscreteMeasure> where Self : 'b { + MyCow::Borrowed(self) + } + + fn own(self) -> DiscreteMeasure { + self.clone() + } +} + +impl<'a, F : Num, Domain : Clone> Instance, MeasureDecomp> +for EitherSlice<'a, Domain, F> +{ + fn decompose<'b>(self) + -> >>::Decomposition<'b> + where Self : 'b, DiscreteMeasure : 'b { + self + } + + fn ref_instance(&self) + -> >>::Reference<'_> + { + match self { + EitherDecomp::Owned(v) => v.as_slice(), + EitherDecomp::Borrowed(s) => s, + } + } + + fn own(self) -> DiscreteMeasure { + match self { + EitherDecomp::Owned(v) => v.into(), + EitherDecomp::Borrowed(s) => s.into(), + } + } +} + +impl<'a, F : Num, Domain : Clone> Instance, MeasureDecomp> +for &'a EitherSlice<'a, Domain, F> +{ + fn decompose<'b>(self) + -> >>::Decomposition<'b> + where Self : 'b, DiscreteMeasure : 'b { + match self { + EitherDecomp::Owned(v) => EitherDecomp::Borrowed(v.as_slice()), + EitherDecomp::Borrowed(s) => EitherDecomp::Borrowed(s), + } + } + + fn ref_instance(&self) + -> >>::Reference<'_> + { + match self { + EitherDecomp::Owned(v) => v.as_slice(), + EitherDecomp::Borrowed(s) => s, + } + } + + fn own(self) -> DiscreteMeasure { + match self { + EitherDecomp::Owned(v) => v.as_slice(), + EitherDecomp::Borrowed(s) => s + }.into() + } +} + +impl<'a, F : Num, Domain : Clone> Instance, MeasureDecomp> +for SpikeSlice<'a, Domain, F> +{ + fn decompose<'b>(self) + -> >>::Decomposition<'b> + where Self : 'b, DiscreteMeasure : 'b { + EitherDecomp::Borrowed(self) + } + + fn ref_instance(&self) + -> >>::Reference<'_> + { + self + } + + fn own(self) -> DiscreteMeasure { + self.into() + } +} + +impl<'a, F : Num, Domain : Clone> Instance, MeasureDecomp> +for &'a SpikeSlice<'a, Domain, F> +{ + fn decompose<'b>(self) + -> >>::Decomposition<'b> + where Self : 'b, DiscreteMeasure : 'b { + EitherDecomp::Borrowed(*self) + } + + fn ref_instance(&self) + -> >>::Reference<'_> + { + *self + } + + fn own(self) -> DiscreteMeasure { + (*self).into() + } +} + +impl Instance, MeasureDecomp> +for DeltaMeasure +{ + fn decompose<'b>(self) + -> >>::Decomposition<'b> + where Self : 'b, DiscreteMeasure : 'b { + EitherDecomp::Owned(vec![self]) + } + + fn ref_instance(&self) + -> >>::Reference<'_> + { + std::slice::from_ref(self) + } + + fn own(self) -> DiscreteMeasure { + self.into() + } +} + +impl<'a, F : Num, Domain : Clone> Instance, MeasureDecomp> +for &'a DeltaMeasure +{ + fn decompose<'b>(self) + -> >>::Decomposition<'b> + where Self : 'b, DiscreteMeasure : 'b { + EitherDecomp::Borrowed(std::slice::from_ref(self)) + } + + fn ref_instance(&self) + -> >>::Reference<'_> + { + std::slice::from_ref(*self) + } + + fn own(self) -> DiscreteMeasure { + self.into() + } +}