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