| 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}; |
|
| 10 use alg_tools::norms::Norm; |
|
| 11 use alg_tools::linops::{Mapping, Linear}; |
|
| 12 use alg_tools::instance::{Instance, Space}; |
|
| 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 |
|
| 54 impl<Domain, F : Float> Measure<F> for DeltaMeasure<Domain, F> { |
|
| 55 type Domain = Domain; |
|
| 56 } |
|
| 57 |
|
| 58 impl<Domain, F : Float> Norm<F, Radon> for DeltaMeasure<Domain, F> { |
|
| 59 #[inline] |
|
| 60 fn norm(&self, _ : Radon) -> F { |
|
| 61 self.α.abs() |
|
| 62 } |
|
| 63 } |
|
| 64 |
|
| 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 |
|
| 85 #[inline] |
|
| 86 fn apply<I : Instance<G>>(&self, g : I) -> Self::Codomain { |
|
| 87 g.eval(|g̃| g̃.apply(&self.x) * self.α) |
|
| 88 } |
|
| 89 } |
|
| 90 |
|
| 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 { } |
|
| 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 |
|
| 152 impl<'a, Domain : Clone, F : Num> From<&'a DeltaMeasure<Domain, F>> for DeltaMeasure<Domain, F> { |
|
| 153 #[inline] |
|
| 154 fn from(d : &'a DeltaMeasure<Domain, F>) -> Self { |
|
| 155 d.clone() |
|
| 156 } |
|
| 157 } |
|
| 158 |
|
| 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 |
|
| 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 |
|
| 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 |
|