diff -r 9738b51d90d7 -r 4f468d35fa29 src/measures/discrete.rs --- a/src/measures/discrete.rs Sun Apr 27 15:03:51 2025 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1014 +0,0 @@ -//! This module implementes discrete measures. - -use std::ops::{ - Div,Mul,DivAssign,MulAssign,Neg, - Add,Sub,AddAssign,SubAssign, - Index,IndexMut, -}; -use std::iter::Sum; -use serde::ser::{Serializer, Serialize, SerializeSeq}; -use nalgebra::DVector; - -use alg_tools::norms::Norm; -use alg_tools::tabledump::TableDump; -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::*; -use super::delta::*; - -/// Representation of a discrete measure. -/// -/// This is the measure $μ = ∑_{k=1}^n α_k δ_{x_k}$, consisting of several -/// [`DeltaMeasure`], i.e., “spikes” $α_k δ_{x_k}$ with weights $\alpha_k$ in `F` at locations -/// $x_k$ in `Domain`. -#[derive(Clone,Debug)] -pub struct DiscreteMeasure { - 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>; - -/// Iterator over mutable [`DeltaMeasure`] spikes of a [`DiscreteMeasure`]. -pub type SpikeIterMut<'a, Domain, F> = std::slice::IterMut<'a, DeltaMeasure>; - -/// Iterator over the locations of the spikes of a [`DiscreteMeasure`]. -pub type LocationIter<'a, Domain, F> - = std::iter::Map, fn(&'a DeltaMeasure) -> &'a Domain>; - -/// Iterator over the masses of the spikes of a [`DiscreteMeasure`]. -pub type MassIter<'a, Domain, F> - = std::iter::Map, fn(&'a DeltaMeasure) -> F>; - -/// Iterator over the mutable locations of the spikes of a [`DiscreteMeasure`]. -pub type MassIterMut<'a, Domain, F> - = std::iter::Map, for<'r> fn(&'r mut DeltaMeasure) -> &'r mut F>; - -impl DiscreteMeasure { - /// Create a new zero measure (empty spike set). - pub fn new() -> Self { - DiscreteMeasure{ spikes : Vec::new() } - } - - /// Number of [`DeltaMeasure`] spikes in the measure - #[inline] - pub fn len(&self) -> usize { - self.spikes.len() - } - - /// Replace with the zero measure. - #[inline] - pub fn clear(&mut self) { - self.spikes.clear() - } - - /// Remove `i`:th spike, not maintaining order. - /// - /// Panics if indiex is out of bounds. - #[inline] - pub fn swap_remove(&mut self, i : usize) -> DeltaMeasure{ - self.spikes.swap_remove(i) - } - - /// Iterate over (references to) the [`DeltaMeasure`] spikes in this measure - #[inline] - pub fn iter_spikes(&self) -> SpikeIter<'_, Domain, F> { - self.spikes.iter() - } - - /// Iterate over mutable references to the [`DeltaMeasure`] spikes in this measure - #[inline] - pub fn iter_spikes_mut(&mut self) -> SpikeIterMut<'_, Domain, F> { - self.spikes.iter_mut() - } - - /// Iterate over the location of the spikes in this measure - #[inline] - pub fn iter_locations(&self) -> LocationIter<'_, Domain, F> { - self.iter_spikes().map(DeltaMeasure::get_location) - } - - /// Iterate over the masses of the spikes in this measure - #[inline] - pub fn iter_masses(&self) -> MassIter<'_, Domain, F> { - self.iter_spikes().map(DeltaMeasure::get_mass) - } - - /// Iterate over the masses of the spikes in this measure - #[inline] - pub fn iter_masses_mut(&mut self) -> MassIterMut<'_, Domain, F> { - self.iter_spikes_mut().map(DeltaMeasure::get_mass_mut) - } - - /// Update the masses of all the spikes to those produced by an iterator. - #[inline] - pub fn set_masses>(&mut self, iter : I) { - 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< - // I : Iterator, - // G : Fn(F, I::Item) -> F - // > (&mut self, iter : I, g : G) { - // self.spikes.iter_mut().zip(iter).for_each(|(δ, v)| δ.set_mass(g(δ.get_mass(), v))); - // } - - /// Prune all spikes with zero mass. - #[inline] - pub fn prune(&mut self) { - self.prune_by(|δ| δ.α != F::ZERO); - } - - /// Prune spikes by the predicate `g`. - #[inline] - pub fn prune_by) -> bool>(&mut self, g : G) { - self.spikes.retain(g); - } - - /// Add the spikes produced by `iter` to this measure. - #[inline] - pub fn extend>>( - &mut self, - iter : I - ) { - self.spikes.extend(iter); - } - - /// Add a spike to the measure - #[inline] - pub fn push(&mut self, δ : DeltaMeasure) { - self.spikes.push(δ); - } - - /// Iterate over triples of masses and locations of two discrete measures, which are assumed - /// to have equal locations of same spike indices. - pub fn both_matching<'a>(&'a self, other : &'a DiscreteMeasure) -> - impl Iterator { - let m = self.len().max(other.len()); - self.iter_spikes().map(Some).chain(std::iter::repeat(None)) - .zip(other.iter_spikes().map(Some).chain(std::iter::repeat(None))) - .take(m) - .map(|(oδ, orδ)| { - match (oδ, orδ) { - (Some(δ), Some(rδ)) => (δ.α, rδ.α, &δ.x), // Assumed δ.x=rδ.x - (Some(δ), None) => (δ.α, F::ZERO, &δ.x), - (None, Some(rδ)) => (F::ZERO, rδ.α, &rδ.x), - (None, None) => panic!("This cannot happen!"), - } - }) - } - - /// Subtract `other` from `self`, assuming equal locations of same spike indices - pub fn sub_matching(&self, other : &DiscreteMeasure) -> DiscreteMeasure - where Domain : Clone { - self.both_matching(other) - .map(|(α, β, x)| (x.clone(), α - β)) - .collect() - } - - /// Add `other` to `self`, assuming equal locations of same spike indices - pub fn add_matching(&self, other : &DiscreteMeasure) -> DiscreteMeasure - where Domain : Clone { - self.both_matching(other) - .map(|(α, β, x)| (x.clone(), α + β)) - .collect() - } - - /// Calculate the Radon-norm distance of `self` to `other`, - /// assuming equal locations of same spike indices. - pub fn dist_matching(&self, other : &DiscreteMeasure) -> F where F : Float { - self.both_matching(other) - .map(|(α, β, _)| (α-β).abs()) - .sum() - } -} - -impl IntoIterator for DiscreteMeasure { - type Item = DeltaMeasure; - type IntoIter = std::vec::IntoIter>; - - #[inline] - fn into_iter(self) -> Self::IntoIter { - self.spikes.into_iter() - } -} - -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 a pruned copy of pruned original `μ1` without arithmetic - /// performed. **This expects `self` and `μ2` to have matching coordinates in each index**. - // `μ2` can be than `self`, but not longer. - pub fn pruning_sub(&mut self, θ : F, ζ : F, μ2 : &mut Self) { - for δ in &self[μ2.len()..] { - μ2.push(DeltaMeasure{ x : δ.x.clone(), α : F::ZERO}); - } - debug_assert_eq!(self.len(), μ2.len()); - let mut dest = 0; - for i in 0..self.len() { - let α = self[i].α; - let α_new = θ * α - ζ * μ2[i].α; - if dest < i { - μ2[dest] = DeltaMeasure{ x : self[i].x.clone(), α }; - self[dest] = DeltaMeasure{ x : self[i].x.clone(), α : α_new }; - } else { - μ2[i].α = α; - self[i].α = α_new; - } - dest += 1; - } - self.spikes.truncate(dest); - μ2.spikes.truncate(dest); - } -} - -impl DiscreteMeasure { - /// Prune all spikes with mass absolute value less than the given `tolerance`. - #[inline] - pub fn prune_approx(&mut self, tolerance : F) { - self.spikes.retain(|δ| δ.α.abs() > tolerance); - } -} - -impl DiscreteMeasure { - /// Extracts the masses of the spikes as a [`DVector`]. - pub fn masses_dvector(&self) -> DVector { - DVector::from_iterator(self.len(), - self.iter_masses() - .map(|α| α.to_nalgebra_mixed())) - } - - /// Sets the masses of the spikes from the values of a [`DVector`]. - pub fn set_masses_dvector(&mut self, x : &DVector) { - self.set_masses(x.iter().map(|&α| F::from_nalgebra_mixed(α))); - } - - // /// Extracts the masses of the spikes as a [`Vec`]. - // pub fn masses_vec(&self) -> Vec { - // self.iter_masses() - // .map(|α| α.to_nalgebra_mixed()) - // .collect() - // } - - // /// Sets the masses of the spikes from the values of a [`Vec`]. - // pub fn set_masses_vec(&mut self, x : &Vec) { - // self.set_masses(x.iter().map(|&α| F::from_nalgebra_mixed(α))); - // } -} - -// impl Index for DiscreteMeasure { -// type Output = DeltaMeasure; -// #[inline] -// fn index(&self, i : usize) -> &Self::Output { -// self.spikes.index(i) -// } -// } - -// impl IndexMut for DiscreteMeasure { -// #[inline] -// fn index_mut(&mut self, i : usize) -> &mut Self::Output { -// self.spikes.index_mut(i) -// } -// } - -impl< - Domain, - F : Num, - I : std::slice::SliceIndex<[DeltaMeasure]> -> Index -for DiscreteMeasure { - type Output = ]>>::Output; - #[inline] - fn index(&self, i : I) -> &Self::Output { - self.spikes.index(i) - } -} - -impl< - Domain, - F : Num, - I : std::slice::SliceIndex<[DeltaMeasure]> -> IndexMut -for DiscreteMeasure { - #[inline] - fn index_mut(&mut self, i : I) -> &mut Self::Output { - self.spikes.index_mut(i) - } -} - - -impl>, const K : usize> From<[D; K]> -for DiscreteMeasure { - #[inline] - fn from(list : [D; K]) -> Self { - list.into_iter().collect() - } -} - -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] - fn from_iter(iter : T) -> Self - where T : IntoIterator { - DiscreteMeasure{ - spikes : iter.into_iter().map(|m| m.into()).collect() - } - } -} - -impl<'a, F : Num, const N : usize> TableDump<'a> -for DiscreteMeasure,F> -where DeltaMeasure, F> : Serialize + 'a { - type Iter = std::slice::Iter<'a, DeltaMeasure, F>>; - - // fn tabledump_headers(&'a self) -> Vec { - // let mut v : Vec = (0..N).map(|i| format!("x{}", i)).collect(); - // v.push("weight".into()); - // v - // } - - fn tabledump_entries(&'a self) -> Self::Iter { - // Ensure order matching the headers above - self.spikes.iter() - } -} - -// Need to manually implement serialisation for DeltaMeasure, F> [`csv`] writer fails on -// structs with nested arrays as well as with #[serde(flatten)]. -// Then derive no longer works for DiscreteMeasure -impl Serialize for DiscreteMeasure, F> -where - F: Serialize, -{ - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let mut s = serializer.serialize_seq(Some(self.spikes.len()))?; - for δ in self.spikes.iter() { - s.serialize_element(δ)?; - } - s.end() - } -} - -impl Measure for DiscreteMeasure { - type Domain = Domain; -} - -impl Norm for DiscreteMeasure -where DeltaMeasure : Norm { - #[inline] - fn norm(&self, _ : Radon) -> F { - self.spikes.iter().map(|m| m.norm(Radon)).sum() - } -} - -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 : I) -> Self::Codomain { - g.eval(|g| self.spikes.iter().map(|m| g.apply(&m.x) * m.α).sum()) - } -} - -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 -/// of [`DiscreteMeasure`] and [`DeltaMeasure`], and their references. -trait Lift { - type Producer : Iterator>; - - #[allow(dead_code)] - /// Lifts `self` into a [`DiscreteMeasure`]. - fn lift(self) -> DiscreteMeasure; - - /// Lifts `self` into a [`DiscreteMeasure`], apply either `f` or `f_mut` whether the type - /// this method is implemented for is a reference or or not. - fn lift_with(self, - f : impl Fn(&DeltaMeasure) -> DeltaMeasure, - f_mut : impl FnMut(&mut DeltaMeasure)) - -> DiscreteMeasure; - - /// Extend `self` into a [`DiscreteMeasure`] with the spikes produced by `iter`. - fn lift_extend>>( - self, - iter : I - ) -> DiscreteMeasure; - - /// Returns an iterator for producing copies of the spikes of `self`. - fn produce(self) -> Self::Producer; -} - -impl Lift for DiscreteMeasure { - type Producer = std::vec::IntoIter>; - - #[inline] - fn lift(self) -> DiscreteMeasure { self } - - fn lift_with(mut self, - _f : impl Fn(&DeltaMeasure) -> DeltaMeasure, - f_mut : impl FnMut(&mut DeltaMeasure)) - -> DiscreteMeasure { - self.spikes.iter_mut().for_each(f_mut); - self - } - - #[inline] - fn lift_extend>>( - mut self, - iter : I - ) -> DiscreteMeasure { - self.spikes.extend(iter); - self - } - - #[inline] - fn produce(self) -> Self::Producer { - self.spikes.into_iter() - } -} - -impl<'a, F : Num, Domain : Clone> Lift for &'a DiscreteMeasure { - type Producer = MapF>, DeltaMeasure>; - - #[inline] - fn lift(self) -> DiscreteMeasure { self.clone() } - - fn lift_with(self, - f : impl Fn(&DeltaMeasure) -> DeltaMeasure, - _f_mut : impl FnMut(&mut DeltaMeasure)) - -> DiscreteMeasure { - DiscreteMeasure{ spikes : self.spikes.iter().map(f).collect() } - } - - #[inline] - fn lift_extend>>( - self, - iter : I - ) -> DiscreteMeasure { - let mut res = self.clone(); - res.spikes.extend(iter); - res - } - - #[inline] - fn produce(self) -> Self::Producer { - // TODO: maybe not optimal to clone here and would benefit from - // a reference version of lift_extend. - self.spikes.iter().mapF(Clone::clone) - } -} - -impl Lift for DeltaMeasure { - type Producer = std::iter::Once>; - - #[inline] - fn lift(self) -> DiscreteMeasure { DiscreteMeasure { spikes : vec![self] } } - - #[inline] - fn lift_with(mut self, - _f : impl Fn(&DeltaMeasure) -> DeltaMeasure, - mut f_mut : impl FnMut(&mut DeltaMeasure)) - -> DiscreteMeasure { - f_mut(&mut self); - DiscreteMeasure{ spikes : vec![self] } - } - - #[inline] - fn lift_extend>>( - self, - iter : I - ) -> DiscreteMeasure { - let mut spikes = vec![self]; - spikes.extend(iter); - DiscreteMeasure{ spikes : spikes } - } - - #[inline] - fn produce(self) -> Self::Producer { - std::iter::once(self) - } -} - -impl<'a, F : Num, Domain : Clone> Lift for &'a DeltaMeasure { - type Producer = std::iter::Once>; - - #[inline] - fn lift(self) -> DiscreteMeasure { DiscreteMeasure { spikes : vec![self.clone()] } } - - #[inline] - fn lift_with(self, - f : impl Fn(&DeltaMeasure) -> DeltaMeasure, - _f_mut : impl FnMut(&mut DeltaMeasure)) - -> DiscreteMeasure { - DiscreteMeasure{ spikes : vec![f(self)] } - } - - #[inline] - fn lift_extend>>( - self, - iter : I - ) -> DiscreteMeasure { - let mut spikes = vec![self.clone()]; - spikes.extend(iter); - DiscreteMeasure{ spikes : spikes } - } - - #[inline] - fn produce(self) -> Self::Producer { - std::iter::once(self.clone()) - } -} - -macro_rules! make_discrete_addsub_assign { - ($rhs:ty) => { - // Discrete += (&)Discrete - impl<'a, F : Num, Domain : Clone> AddAssign<$rhs> - for DiscreteMeasure { - fn add_assign(&mut self, other : $rhs) { - self.spikes.extend(other.produce()); - } - } - - impl<'a, F : Num + Neg, Domain : Clone> SubAssign<$rhs> - for DiscreteMeasure { - fn sub_assign(&mut self, other : $rhs) { - self.spikes.extend(other.produce().map(|δ| -δ)); - } - } - } -} - -make_discrete_addsub_assign!(DiscreteMeasure); -make_discrete_addsub_assign!(&'a DiscreteMeasure); -make_discrete_addsub_assign!(DeltaMeasure); -make_discrete_addsub_assign!(&'a DeltaMeasure); - -macro_rules! make_discrete_addsub { - ($lhs:ty, $rhs:ty, $alt_order:expr) => { - impl<'a, 'b, F : Num, Domain : Clone> Add<$rhs> for $lhs { - type Output = DiscreteMeasure; - fn add(self, other : $rhs) -> DiscreteMeasure { - if !$alt_order { - self.lift_extend(other.produce()) - } else { - other.lift_extend(self.produce()) - } - } - } - - impl<'a, 'b, F : Num + Neg, Domain : Clone> Sub<$rhs> for $lhs { - type Output = DiscreteMeasure; - fn sub(self, other : $rhs) -> DiscreteMeasure { - self.lift_extend(other.produce().map(|δ| -δ)) - } - } - }; -} - -make_discrete_addsub!(DiscreteMeasure, DiscreteMeasure, false); -make_discrete_addsub!(DiscreteMeasure, &'b DiscreteMeasure, false); -make_discrete_addsub!(&'a DiscreteMeasure, DiscreteMeasure, true); -make_discrete_addsub!(&'a DiscreteMeasure, &'b DiscreteMeasure, false); -make_discrete_addsub!(DeltaMeasure, DiscreteMeasure, false); -make_discrete_addsub!(DeltaMeasure, &'b DiscreteMeasure, false); -make_discrete_addsub!(&'a DeltaMeasure, DiscreteMeasure, true); -make_discrete_addsub!(&'a DeltaMeasure, &'b DiscreteMeasure, false); -make_discrete_addsub!(DiscreteMeasure, DeltaMeasure, false); -make_discrete_addsub!(DiscreteMeasure, &'b DeltaMeasure, false); -make_discrete_addsub!(&'a DiscreteMeasure, DeltaMeasure, false); -make_discrete_addsub!(&'a DiscreteMeasure, &'b DeltaMeasure, false); -make_discrete_addsub!(DeltaMeasure, DeltaMeasure, false); -make_discrete_addsub!(DeltaMeasure, &'b DeltaMeasure, false); -make_discrete_addsub!(&'a DeltaMeasure, DeltaMeasure, false); -make_discrete_addsub!(&'a DeltaMeasure, &'b DeltaMeasure, false); - -macro_rules! make_discrete_scalarop_rhs { - ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { - make_discrete_scalarop_rhs!(@assign DiscreteMeasure, F, $trait_assign, $fn_assign); - make_discrete_scalarop_rhs!(@assign DiscreteMeasure, &'a F, $trait_assign, $fn_assign); - make_discrete_scalarop_rhs!(@new DiscreteMeasure, F, $trait, $fn, $fn_assign); - make_discrete_scalarop_rhs!(@new DiscreteMeasure, &'a F, $trait, $fn, $fn_assign); - make_discrete_scalarop_rhs!(@new &'b DiscreteMeasure, F, $trait, $fn, $fn_assign); - make_discrete_scalarop_rhs!(@new &'b DiscreteMeasure, &'a F, $trait, $fn, $fn_assign); - }; - - (@assign $lhs:ty, $rhs:ty, $trait_assign:ident, $fn_assign:ident) => { - impl<'a, 'b, F : Num, Domain> $trait_assign<$rhs> for $lhs { - fn $fn_assign(&mut self, b : $rhs) { - self.spikes.iter_mut().for_each(|δ| δ.$fn_assign(b)); - } - } - }; - (@new $lhs:ty, $rhs:ty, $trait:ident, $fn:ident, $fn_assign:ident) => { - impl<'a, 'b, F : Num, Domain : Clone> $trait<$rhs> for $lhs { - type Output = DiscreteMeasure; - fn $fn(self, b : $rhs) -> Self::Output { - self.lift_with(|δ| δ.$fn(b), |δ| δ.$fn_assign(b)) - } - } - }; -} - -make_discrete_scalarop_rhs!(Mul, mul, MulAssign, mul_assign); -make_discrete_scalarop_rhs!(Div, div, DivAssign, div_assign); - -macro_rules! make_discrete_unary { - ($trait:ident, $fn:ident, $type:ty) => { - impl<'a, F : Num + Neg, Domain : Clone> Neg for $type { - type Output = DiscreteMeasure; - fn $fn(self) -> Self::Output { - self.lift_with(|δ| δ.$fn(), |δ| δ.α = δ.α.$fn()) - } - } - } -} - -make_discrete_unary!(Neg, neg, DiscreteMeasure); -make_discrete_unary!(Neg, neg, &'a DiscreteMeasure); - -// impl Neg for DiscreteMeasure { -// type Output = Self; -// fn $fn(mut self, b : F) -> Self { -// self.lift().spikes.iter_mut().for_each(|δ| δ.neg(b)); -// self -// } -// } - -macro_rules! make_discrete_scalarop_lhs { - ($trait:ident, $fn:ident; $($f:ident)+) => { $( - impl $trait> for $f { - type Output = DiscreteMeasure; - fn $fn(self, mut v : DiscreteMeasure) -> Self::Output { - v.spikes.iter_mut().for_each(|δ| δ.α = self.$fn(δ.α)); - v - } - } - - impl<'a, Domain : Copy> $trait<&'a DiscreteMeasure> for $f { - type Output = DiscreteMeasure; - fn $fn(self, v : &'a DiscreteMeasure) -> Self::Output { - DiscreteMeasure{ - spikes : v.spikes.iter().map(|δ| self.$fn(δ)).collect() - } - } - } - - impl<'b, Domain> $trait> for &'b $f { - type Output = DiscreteMeasure; - fn $fn(self, mut v : DiscreteMeasure) -> Self::Output { - v.spikes.iter_mut().for_each(|δ| δ.α = self.$fn(δ.α)); - v - } - } - - impl<'a, 'b, Domain : Copy> $trait<&'a DiscreteMeasure> for &'b $f { - type Output = DiscreteMeasure; - fn $fn(self, v : &'a DiscreteMeasure) -> Self::Output { - DiscreteMeasure{ - spikes : v.spikes.iter().map(|δ| self.$fn(δ)).collect() - } - } - } - )+ } -} - -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() - } -}