Sun, 02 Feb 2025 15:21:16 -0500
Symbol rename
| 0 | 1 | /*! |
| 2 | This module implementes delta measures, i.e., single spikes $\alpha \delta_x$ for some | |
| 3 | location $x$ and mass $\alpha$. | |
| 4 | */ | |
| 5 | ||
| 6 | use super::base::*; | |
| 7 | use crate::types::*; | |
| 8 | use std::ops::{Div, Mul, DivAssign, MulAssign, Neg}; | |
| 9 | use serde::ser::{Serialize, Serializer, SerializeStruct}; | |
| 35 | 10 | use alg_tools::norms::Norm; |
| 11 | use alg_tools::linops::{Mapping, Linear}; | |
| 12 | use alg_tools::instance::{Instance, Space}; | |
| 0 | 13 | |
| 14 | /// Representation of a delta measure. | |
| 15 | /// | |
| 16 | /// This is a single spike $\alpha \delta\_x$ for some location $x$ in `Domain` and | |
| 17 | /// a mass $\alpha$ in `F`. | |
| 18 | #[derive(Clone,Copy,Debug)] | |
| 19 | pub struct DeltaMeasure<Domain, F : Num> { | |
| 20 | // This causes [`csv`] to crash. | |
| 21 | //#[serde(flatten)] | |
| 22 | /// Location of the spike | |
| 23 | pub x : Domain, | |
| 24 | /// Mass of the spike | |
| 25 | pub α : F | |
| 26 | } | |
| 27 | ||
| 28 | const COORDINATE_NAMES : &'static [&'static str] = &[ | |
| 29 | "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7" | |
| 30 | ]; | |
| 31 | ||
| 32 | // Need to manually implement serialisation as [`csv`] writer fails on | |
| 33 | // structs with nested arrays as well as with #[serde(flatten)]. | |
| 34 | impl<F : Num, const N : usize> Serialize for DeltaMeasure<Loc<F, N>, F> | |
| 35 | where | |
| 36 | F: Serialize, | |
| 37 | { | |
| 38 | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | |
| 39 | where | |
| 40 | S: Serializer, | |
| 41 | { | |
| 42 | assert!(N <= COORDINATE_NAMES.len()); | |
| 43 | ||
| 44 | let mut s = serializer.serialize_struct("DeltaMeasure", N+1)?; | |
| 45 | for (i, e) in (0..).zip(self.x.iter()) { | |
| 46 | s.serialize_field(COORDINATE_NAMES[i], e)?; | |
| 47 | } | |
| 48 | s.serialize_field("weight", &self.α)?; | |
| 49 | s.end() | |
| 50 | } | |
| 51 | } | |
| 52 | ||
| 53 | ||
| 35 | 54 | impl<Domain, F : Float> Measure<F> for DeltaMeasure<Domain, F> { |
| 0 | 55 | type Domain = Domain; |
| 56 | } | |
| 57 | ||
| 35 | 58 | impl<Domain, F : Float> Norm<F, Radon> for DeltaMeasure<Domain, F> { |
| 0 | 59 | #[inline] |
| 60 | fn norm(&self, _ : Radon) -> F { | |
| 61 | self.α.abs() | |
| 62 | } | |
| 63 | } | |
| 64 | ||
| 35 | 65 | // impl<Domain : PartialEq, F : Float> Dist<F, Radon> for DeltaMeasure<Domain, F> { |
| 66 | // #[inline] | |
| 67 | // fn dist(&self, other : &Self, _ : Radon) -> F { | |
| 68 | // if self.x == other. x { | |
| 69 | // (self.α - other.α).abs() | |
| 70 | // } else { | |
| 71 | // self.α.abs() + other.α.abs() | |
| 72 | // } | |
| 73 | // } | |
| 74 | // } | |
| 75 | ||
| 76 | impl<Domain, G, F : Num> Mapping<G> for DeltaMeasure<Domain, F> | |
| 77 | where | |
| 78 | Domain : Space, | |
| 79 | G::Codomain : Mul<F, Output=G::Codomain>, | |
| 80 | G : Mapping<Domain> + Clone + Space, | |
| 81 | for<'b> &'b Domain : Instance<Domain>, | |
| 82 | { | |
| 83 | type Codomain = G::Codomain; | |
| 84 | ||
| 0 | 85 | #[inline] |
| 35 | 86 | fn apply<I : Instance<G>>(&self, g : I) -> Self::Codomain { |
| 87 | g.eval(|g̃| g̃.apply(&self.x) * self.α) | |
| 0 | 88 | } |
| 89 | } | |
| 90 | ||
| 35 | 91 | impl<Domain, G, F : Num> Linear<G> for DeltaMeasure<Domain, F> |
| 92 | where | |
| 93 | Domain : Space, | |
| 94 | G::Codomain : Mul<F, Output=G::Codomain>, | |
| 95 | G : Mapping<Domain> + Clone + Space, | |
| 96 | for<'b> &'b Domain : Instance<Domain>, | |
| 97 | { } | |
| 0 | 98 | |
| 99 | // /// Partial blanket implementation of [`DeltaMeasure`] as a linear functional of [`Mapping`]s. | |
| 100 | // /// A full blanket implementation is not possible due to annoying Rust limitations: only [`Apply`] | |
| 101 | // /// on a reference is implemented, but a consuming [`Apply`] has to be implemented on a case-by-case | |
| 102 | // /// basis, not because an implementation could not be written, but because the Rust trait system | |
| 103 | // /// chokes up. | |
| 104 | // impl<Domain, G, F : Num, V> Linear<G> for DeltaMeasure<Domain, F> | |
| 105 | // where G: for<'a> Apply<&'a Domain, Output = V>, | |
| 106 | // V : Mul<F>, | |
| 107 | // Self: Apply<G, Output = <V as Mul<F>>::Output> { | |
| 108 | // type Codomain = <V as Mul<F>>::Output; | |
| 109 | // } | |
| 110 | ||
| 111 | // impl<'b, Domain, G, F : Num, V> Apply<&'b G> for DeltaMeasure<Domain, F> | |
| 112 | // where G: for<'a> Apply<&'a Domain, Output = V>, | |
| 113 | // V : Mul<F> { | |
| 114 | // type Output = <V as Mul<F>>::Output; | |
| 115 | ||
| 116 | // #[inline] | |
| 117 | // fn apply(&self, g : &'b G) -> Self::Output { | |
| 118 | // g.apply(&self.x) * self.α | |
| 119 | // } | |
| 120 | // } | |
| 121 | ||
| 122 | // /// Implementation of the necessary apply for BTFNs | |
| 123 | // mod btfn_apply { | |
| 124 | // use super::*; | |
| 125 | // use alg_tools::bisection_tree::{BTFN, BTImpl, SupportGenerator, LocalAnalysis}; | |
| 126 | ||
| 127 | // impl<F : Float, BT, G, V, const N : usize> Apply<BTFN<F, G, BT, N>> | |
| 128 | // for DeltaMeasure<Loc<F, N>, F> | |
| 129 | // where BT : BTImpl<F, N>, | |
| 130 | // G : SupportGenerator<F, N, Id=BT::Data>, | |
| 131 | // G::SupportType : LocalAnalysis<F, BT::Agg, N> + for<'a> Apply<&'a Loc<F, N>, Output = V>, | |
| 132 | // V : std::iter::Sum + Mul<F> { | |
| 133 | ||
| 134 | // type Output = <V as Mul<F>>::Output; | |
| 135 | ||
| 136 | // #[inline] | |
| 137 | // fn apply(&self, g : BTFN<F, G, BT, N>) -> Self::Output { | |
| 138 | // g.apply(&self.x) * self.α | |
| 139 | // } | |
| 140 | // } | |
| 141 | // } | |
| 142 | ||
| 143 | ||
| 144 | impl<D, Domain, F : Num> From<(D, F)> for DeltaMeasure<Domain, F> | |
| 145 | where D : Into<Domain> { | |
| 146 | #[inline] | |
| 147 | fn from((x, α) : (D, F)) -> Self { | |
| 148 | DeltaMeasure{x: x.into(), α: α} | |
| 149 | } | |
| 150 | } | |
| 151 | ||
| 35 | 152 | impl<'a, Domain : Clone, F : Num> From<&'a DeltaMeasure<Domain, F>> for DeltaMeasure<Domain, F> { |
| 0 | 153 | #[inline] |
| 35 | 154 | fn from(d : &'a DeltaMeasure<Domain, F>) -> Self { |
| 155 | d.clone() | |
| 0 | 156 | } |
| 35 | 157 | } |
| 158 | ||
| 0 | 159 | |
| 160 | impl<Domain, F : Num> DeltaMeasure<Domain, F> { | |
| 161 | /// Set the mass of the spike. | |
| 162 | #[inline] | |
| 163 | pub fn set_mass(&mut self, α : F) { | |
| 164 | self.α = α | |
| 165 | } | |
| 166 | ||
| 167 | /// Set the location of the spike. | |
| 168 | #[inline] | |
| 169 | pub fn set_location(&mut self, x : Domain) { | |
| 170 | self.x = x | |
| 171 | } | |
| 172 | ||
| 173 | /// Get the mass of the spike. | |
| 174 | #[inline] | |
| 175 | pub fn get_mass(&self) -> F { | |
| 176 | self.α | |
| 177 | } | |
| 178 | ||
| 179 | /// Get a mutable reference to the mass of the spike. | |
| 180 | #[inline] | |
| 181 | pub fn get_mass_mut(&mut self) -> &mut F { | |
| 182 | &mut self.α | |
| 183 | } | |
| 184 | ||
| 185 | /// Get a reference to the location of the spike. | |
| 186 | #[inline] | |
| 187 | pub fn get_location(&self) -> &Domain { | |
| 188 | &self.x | |
| 189 | } | |
| 190 | ||
| 191 | /// Get a mutable reference to the location of the spike. | |
| 192 | #[inline] | |
| 193 | pub fn get_location_mut(&mut self) -> &mut Domain { | |
| 194 | &mut self.x | |
| 195 | } | |
| 196 | } | |
| 197 | ||
| 35 | 198 | impl<Domain, F : Num> IntoIterator for DeltaMeasure<Domain, F> { |
| 199 | type Item = Self; | |
| 200 | type IntoIter = std::iter::Once<Self>; | |
| 201 | ||
| 202 | #[inline] | |
| 203 | fn into_iter(self) -> Self::IntoIter { | |
| 204 | std::iter::once(self) | |
| 205 | } | |
| 206 | } | |
| 207 | ||
| 208 | impl<'a, Domain, F : Num> IntoIterator for &'a DeltaMeasure<Domain, F> { | |
| 209 | type Item = Self; | |
| 210 | type IntoIter = std::iter::Once<Self>; | |
| 211 | ||
| 212 | #[inline] | |
| 213 | fn into_iter(self) -> Self::IntoIter { | |
| 214 | std::iter::once(self) | |
| 215 | } | |
| 216 | } | |
| 217 | ||
| 0 | 218 | |
| 219 | macro_rules! make_delta_scalarop_rhs { | |
| 220 | ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { | |
| 221 | impl<F : Num, Domain> $trait<F> for DeltaMeasure<Domain, F> { | |
| 222 | type Output = Self; | |
| 223 | fn $fn(mut self, b : F) -> Self { | |
| 224 | self.α.$fn_assign(b); | |
| 225 | self | |
| 226 | } | |
| 227 | } | |
| 228 | ||
| 229 | impl<'a, F : Num, Domain> $trait<&'a F> for DeltaMeasure<Domain, F> { | |
| 230 | type Output = Self; | |
| 231 | fn $fn(mut self, b : &'a F) -> Self { | |
| 232 | self.α.$fn_assign(*b); | |
| 233 | self | |
| 234 | } | |
| 235 | } | |
| 236 | ||
| 237 | impl<'b, F : Num, Domain : Clone> $trait<F> for &'b DeltaMeasure<Domain, F> { | |
| 238 | type Output = DeltaMeasure<Domain, F>; | |
| 239 | fn $fn(self, b : F) -> Self::Output { | |
| 240 | DeltaMeasure { α : self.α.$fn(b), x : self.x.clone() } | |
| 241 | } | |
| 242 | } | |
| 243 | ||
| 244 | impl<'a, 'b, F : Num, Domain : Clone> $trait<&'a F> for &'b DeltaMeasure<Domain, F> { | |
| 245 | type Output = DeltaMeasure<Domain, F>; | |
| 246 | fn $fn(self, b : &'a F) -> Self::Output { | |
| 247 | DeltaMeasure { α : self.α.$fn(*b), x : self.x.clone() } | |
| 248 | } | |
| 249 | } | |
| 250 | ||
| 251 | impl<F : Num, Domain> $trait_assign<F> for DeltaMeasure<Domain, F> { | |
| 252 | fn $fn_assign(&mut self, b : F) { | |
| 253 | self.α.$fn_assign(b) | |
| 254 | } | |
| 255 | } | |
| 256 | ||
| 257 | impl<'a, F : Num, Domain> $trait_assign<&'a F> for DeltaMeasure<Domain, F> { | |
| 258 | fn $fn_assign(&mut self, b : &'a F) { | |
| 259 | self.α.$fn_assign(*b) | |
| 260 | } | |
| 261 | } | |
| 262 | } | |
| 263 | } | |
| 264 | ||
| 265 | make_delta_scalarop_rhs!(Mul, mul, MulAssign, mul_assign); | |
| 266 | make_delta_scalarop_rhs!(Div, div, DivAssign, div_assign); | |
| 267 | ||
| 268 | macro_rules! make_delta_scalarop_lhs { | |
| 269 | ($trait:ident, $fn:ident; $($f:ident)+) => { $( | |
| 270 | impl<Domain> $trait<DeltaMeasure<Domain, $f>> for $f { | |
| 271 | type Output = DeltaMeasure<Domain, $f>; | |
| 272 | fn $fn(self, mut δ : DeltaMeasure<Domain, $f>) -> Self::Output { | |
| 273 | δ.α = self.$fn(δ.α); | |
| 274 | δ | |
| 275 | } | |
| 276 | } | |
| 277 | ||
| 278 | impl<'a, Domain : Clone> $trait<&'a DeltaMeasure<Domain, $f>> for $f { | |
| 279 | type Output = DeltaMeasure<Domain, $f>; | |
| 280 | fn $fn(self, δ : &'a DeltaMeasure<Domain, $f>) -> Self::Output { | |
| 281 | DeltaMeasure{ x : δ.x.clone(), α : self.$fn(δ.α) } | |
| 282 | } | |
| 283 | } | |
| 284 | ||
| 285 | impl<'b, Domain> $trait<DeltaMeasure<Domain, $f>> for &'b $f { | |
| 286 | type Output = DeltaMeasure<Domain, $f>; | |
| 287 | fn $fn(self, mut δ : DeltaMeasure<Domain, $f>) -> Self::Output { | |
| 288 | δ.α = self.$fn(δ.α); | |
| 289 | δ | |
| 290 | } | |
| 291 | } | |
| 292 | ||
| 293 | impl<'a, 'b, Domain : Clone> $trait<&'a DeltaMeasure<Domain, $f>> for &'b $f { | |
| 294 | type Output = DeltaMeasure<Domain, $f>; | |
| 295 | fn $fn(self, δ : &'a DeltaMeasure<Domain, $f>) -> Self::Output { | |
| 296 | DeltaMeasure{ x : δ.x.clone(), α : self.$fn(δ.α) } | |
| 297 | } | |
| 298 | } | |
| 299 | )+ } | |
| 300 | } | |
| 301 | ||
| 302 | make_delta_scalarop_lhs!(Mul, mul; f32 f64 i8 i16 i32 i64 isize u8 u16 u32 u64 usize); | |
| 303 | make_delta_scalarop_lhs!(Div, div; f32 f64 i8 i16 i32 i64 isize u8 u16 u32 u64 usize); | |
| 304 | ||
| 305 | macro_rules! make_delta_unary { | |
| 306 | ($trait:ident, $fn:ident, $type:ty) => { | |
| 307 | impl<'a, F : Num + Neg<Output=F>, Domain : Clone> Neg for $type { | |
| 308 | type Output = DeltaMeasure<Domain, F>; | |
| 309 | fn $fn(self) -> Self::Output { | |
| 310 | let mut tmp = self.clone(); | |
| 311 | tmp.α = tmp.α.$fn(); | |
| 312 | tmp | |
| 313 | } | |
| 314 | } | |
| 315 | } | |
| 316 | } | |
| 317 | ||
| 318 | make_delta_unary!(Neg, neg, DeltaMeasure<Domain, F>); | |
| 319 | make_delta_unary!(Neg, neg, &'a DeltaMeasure<Domain, F>); | |
| 320 |