--- a/src/measures/delta.rs Sun Apr 27 15:03:51 2025 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,320 +0,0 @@ -/*! -This module implementes delta measures, i.e., single spikes $\alpha \delta_x$ for some -location $x$ and mass $\alpha$. -*/ - -use super::base::*; -use crate::types::*; -use std::ops::{Div, Mul, DivAssign, MulAssign, Neg}; -use serde::ser::{Serialize, Serializer, SerializeStruct}; -use alg_tools::norms::Norm; -use alg_tools::linops::{Mapping, Linear}; -use alg_tools::instance::{Instance, Space}; - -/// Representation of a delta measure. -/// -/// This is a single spike $\alpha \delta\_x$ for some location $x$ in `Domain` and -/// a mass $\alpha$ in `F`. -#[derive(Clone,Copy,Debug)] -pub struct DeltaMeasure<Domain, F : Num> { - // This causes [`csv`] to crash. - //#[serde(flatten)] - /// Location of the spike - pub x : Domain, - /// Mass of the spike - pub α : F -} - -const COORDINATE_NAMES : &'static [&'static str] = &[ - "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7" -]; - -// Need to manually implement serialisation as [`csv`] writer fails on -// structs with nested arrays as well as with #[serde(flatten)]. -impl<F : Num, const N : usize> Serialize for DeltaMeasure<Loc<F, N>, F> -where - F: Serialize, -{ - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: Serializer, - { - assert!(N <= COORDINATE_NAMES.len()); - - let mut s = serializer.serialize_struct("DeltaMeasure", N+1)?; - for (i, e) in (0..).zip(self.x.iter()) { - s.serialize_field(COORDINATE_NAMES[i], e)?; - } - s.serialize_field("weight", &self.α)?; - s.end() - } -} - - -impl<Domain, F : Float> Measure<F> for DeltaMeasure<Domain, F> { - type Domain = Domain; -} - -impl<Domain, F : Float> Norm<F, Radon> for DeltaMeasure<Domain, F> { - #[inline] - fn norm(&self, _ : Radon) -> F { - self.α.abs() - } -} - -// impl<Domain : PartialEq, F : Float> Dist<F, Radon> for DeltaMeasure<Domain, F> { -// #[inline] -// fn dist(&self, other : &Self, _ : Radon) -> F { -// if self.x == other. x { -// (self.α - other.α).abs() -// } else { -// self.α.abs() + other.α.abs() -// } -// } -// } - -impl<Domain, G, F : Num> Mapping<G> for DeltaMeasure<Domain, F> -where - Domain : Space, - G::Codomain : Mul<F, Output=G::Codomain>, - G : Mapping<Domain> + Clone + Space, - for<'b> &'b Domain : Instance<Domain>, -{ - type Codomain = G::Codomain; - - #[inline] - fn apply<I : Instance<G>>(&self, g : I) -> Self::Codomain { - g.eval(|g̃| g̃.apply(&self.x) * self.α) - } -} - -impl<Domain, G, F : Num> Linear<G> for DeltaMeasure<Domain, F> -where - Domain : Space, - G::Codomain : Mul<F, Output=G::Codomain>, - G : Mapping<Domain> + Clone + Space, - for<'b> &'b Domain : Instance<Domain>, -{ } - -// /// Partial blanket implementation of [`DeltaMeasure`] as a linear functional of [`Mapping`]s. -// /// A full blanket implementation is not possible due to annoying Rust limitations: only [`Apply`] -// /// on a reference is implemented, but a consuming [`Apply`] has to be implemented on a case-by-case -// /// basis, not because an implementation could not be written, but because the Rust trait system -// /// chokes up. -// impl<Domain, G, F : Num, V> Linear<G> for DeltaMeasure<Domain, F> -// where G: for<'a> Apply<&'a Domain, Output = V>, -// V : Mul<F>, -// Self: Apply<G, Output = <V as Mul<F>>::Output> { -// type Codomain = <V as Mul<F>>::Output; -// } - -// impl<'b, Domain, G, F : Num, V> Apply<&'b G> for DeltaMeasure<Domain, F> -// where G: for<'a> Apply<&'a Domain, Output = V>, -// V : Mul<F> { -// type Output = <V as Mul<F>>::Output; - -// #[inline] -// fn apply(&self, g : &'b G) -> Self::Output { -// g.apply(&self.x) * self.α -// } -// } - -// /// Implementation of the necessary apply for BTFNs -// mod btfn_apply { -// use super::*; -// use alg_tools::bisection_tree::{BTFN, BTImpl, SupportGenerator, LocalAnalysis}; - -// impl<F : Float, BT, G, V, const N : usize> Apply<BTFN<F, G, BT, N>> -// for DeltaMeasure<Loc<F, N>, F> -// where BT : BTImpl<F, N>, -// G : SupportGenerator<F, N, Id=BT::Data>, -// G::SupportType : LocalAnalysis<F, BT::Agg, N> + for<'a> Apply<&'a Loc<F, N>, Output = V>, -// V : std::iter::Sum + Mul<F> { - -// type Output = <V as Mul<F>>::Output; - -// #[inline] -// fn apply(&self, g : BTFN<F, G, BT, N>) -> Self::Output { -// g.apply(&self.x) * self.α -// } -// } -// } - - -impl<D, Domain, F : Num> From<(D, F)> for DeltaMeasure<Domain, F> -where D : Into<Domain> { - #[inline] - fn from((x, α) : (D, F)) -> Self { - DeltaMeasure{x: x.into(), α: α} - } -} - -impl<'a, Domain : Clone, F : Num> From<&'a DeltaMeasure<Domain, F>> for DeltaMeasure<Domain, F> { - #[inline] - fn from(d : &'a DeltaMeasure<Domain, F>) -> Self { - d.clone() - } -} - - -impl<Domain, F : Num> DeltaMeasure<Domain, F> { - /// Set the mass of the spike. - #[inline] - pub fn set_mass(&mut self, α : F) { - self.α = α - } - - /// Set the location of the spike. - #[inline] - pub fn set_location(&mut self, x : Domain) { - self.x = x - } - - /// Get the mass of the spike. - #[inline] - pub fn get_mass(&self) -> F { - self.α - } - - /// Get a mutable reference to the mass of the spike. - #[inline] - pub fn get_mass_mut(&mut self) -> &mut F { - &mut self.α - } - - /// Get a reference to the location of the spike. - #[inline] - pub fn get_location(&self) -> &Domain { - &self.x - } - - /// Get a mutable reference to the location of the spike. - #[inline] - pub fn get_location_mut(&mut self) -> &mut Domain { - &mut self.x - } -} - -impl<Domain, F : Num> IntoIterator for DeltaMeasure<Domain, F> { - type Item = Self; - type IntoIter = std::iter::Once<Self>; - - #[inline] - fn into_iter(self) -> Self::IntoIter { - std::iter::once(self) - } -} - -impl<'a, Domain, F : Num> IntoIterator for &'a DeltaMeasure<Domain, F> { - type Item = Self; - type IntoIter = std::iter::Once<Self>; - - #[inline] - fn into_iter(self) -> Self::IntoIter { - std::iter::once(self) - } -} - - -macro_rules! make_delta_scalarop_rhs { - ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { - impl<F : Num, Domain> $trait<F> for DeltaMeasure<Domain, F> { - type Output = Self; - fn $fn(mut self, b : F) -> Self { - self.α.$fn_assign(b); - self - } - } - - impl<'a, F : Num, Domain> $trait<&'a F> for DeltaMeasure<Domain, F> { - type Output = Self; - fn $fn(mut self, b : &'a F) -> Self { - self.α.$fn_assign(*b); - self - } - } - - impl<'b, F : Num, Domain : Clone> $trait<F> for &'b DeltaMeasure<Domain, F> { - type Output = DeltaMeasure<Domain, F>; - fn $fn(self, b : F) -> Self::Output { - DeltaMeasure { α : self.α.$fn(b), x : self.x.clone() } - } - } - - impl<'a, 'b, F : Num, Domain : Clone> $trait<&'a F> for &'b DeltaMeasure<Domain, F> { - type Output = DeltaMeasure<Domain, F>; - fn $fn(self, b : &'a F) -> Self::Output { - DeltaMeasure { α : self.α.$fn(*b), x : self.x.clone() } - } - } - - impl<F : Num, Domain> $trait_assign<F> for DeltaMeasure<Domain, F> { - fn $fn_assign(&mut self, b : F) { - self.α.$fn_assign(b) - } - } - - impl<'a, F : Num, Domain> $trait_assign<&'a F> for DeltaMeasure<Domain, F> { - fn $fn_assign(&mut self, b : &'a F) { - self.α.$fn_assign(*b) - } - } - } -} - -make_delta_scalarop_rhs!(Mul, mul, MulAssign, mul_assign); -make_delta_scalarop_rhs!(Div, div, DivAssign, div_assign); - -macro_rules! make_delta_scalarop_lhs { - ($trait:ident, $fn:ident; $($f:ident)+) => { $( - impl<Domain> $trait<DeltaMeasure<Domain, $f>> for $f { - type Output = DeltaMeasure<Domain, $f>; - fn $fn(self, mut δ : DeltaMeasure<Domain, $f>) -> Self::Output { - δ.α = self.$fn(δ.α); - δ - } - } - - impl<'a, Domain : Clone> $trait<&'a DeltaMeasure<Domain, $f>> for $f { - type Output = DeltaMeasure<Domain, $f>; - fn $fn(self, δ : &'a DeltaMeasure<Domain, $f>) -> Self::Output { - DeltaMeasure{ x : δ.x.clone(), α : self.$fn(δ.α) } - } - } - - impl<'b, Domain> $trait<DeltaMeasure<Domain, $f>> for &'b $f { - type Output = DeltaMeasure<Domain, $f>; - fn $fn(self, mut δ : DeltaMeasure<Domain, $f>) -> Self::Output { - δ.α = self.$fn(δ.α); - δ - } - } - - impl<'a, 'b, Domain : Clone> $trait<&'a DeltaMeasure<Domain, $f>> for &'b $f { - type Output = DeltaMeasure<Domain, $f>; - fn $fn(self, δ : &'a DeltaMeasure<Domain, $f>) -> Self::Output { - DeltaMeasure{ x : δ.x.clone(), α : self.$fn(δ.α) } - } - } - )+ } -} - -make_delta_scalarop_lhs!(Mul, mul; f32 f64 i8 i16 i32 i64 isize u8 u16 u32 u64 usize); -make_delta_scalarop_lhs!(Div, div; f32 f64 i8 i16 i32 i64 isize u8 u16 u32 u64 usize); - -macro_rules! make_delta_unary { - ($trait:ident, $fn:ident, $type:ty) => { - impl<'a, F : Num + Neg<Output=F>, Domain : Clone> Neg for $type { - type Output = DeltaMeasure<Domain, F>; - fn $fn(self) -> Self::Output { - let mut tmp = self.clone(); - tmp.α = tmp.α.$fn(); - tmp - } - } - } -} - -make_delta_unary!(Neg, neg, DeltaMeasure<Domain, F>); -make_delta_unary!(Neg, neg, &'a DeltaMeasure<Domain, F>); -