| |
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 alg_tools::instance::{ClosedSpace, Instance, Space}; |
| |
8 use alg_tools::linops::{Linear, Mapping}; |
| |
9 use alg_tools::loc::Loc; |
| |
10 use alg_tools::norms::Norm; |
| |
11 use alg_tools::self_ownable; |
| |
12 use alg_tools::types::*; |
| |
13 use serde::ser::{Serialize, SerializeStruct, Serializer}; |
| |
14 use std::ops::{Div, DivAssign, Mul, MulAssign, Neg}; |
| |
15 |
| |
16 /// Representation of a delta measure. |
| |
17 /// |
| |
18 /// This is a single spike $\alpha \delta\_x$ for some location $x$ in `Domain` and |
| |
19 /// a mass $\alpha$ in `F`. |
| |
20 #[derive(Clone, Copy, Debug)] |
| |
21 pub struct DeltaMeasure<Domain, F: Num> { |
| |
22 // This causes [`csv`] to crash. |
| |
23 //#[serde(flatten)] |
| |
24 /// Location of the spike |
| |
25 pub x: Domain, |
| |
26 /// Mass of the spike |
| |
27 pub α: F, |
| |
28 } |
| |
29 |
| |
30 const COORDINATE_NAMES: &'static [&'static str] = &["x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7"]; |
| |
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<N, F>, 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 impl<Domain, F: Float> Measure<F> for DeltaMeasure<Domain, F> { |
| |
54 type Domain = Domain; |
| |
55 } |
| |
56 |
| |
57 impl<Domain, F: Float> Norm<Radon, F> 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<Radon, F> 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<Domain, G, F: Num> Mapping<G> for DeltaMeasure<Domain, F> |
| |
76 where |
| |
77 Domain: Space, |
| |
78 G::Codomain: Mul<F, Output = G::Codomain>, |
| |
79 G: Mapping<Domain> + Clone + ClosedSpace, |
| |
80 for<'b> &'b Domain: Instance<Domain>, |
| |
81 { |
| |
82 type Codomain = G::Codomain; |
| |
83 |
| |
84 #[inline] |
| |
85 fn apply<I: Instance<G>>(&self, g: I) -> Self::Codomain { |
| |
86 g.eval(|g̃| g̃.apply(&self.x) * self.α) |
| |
87 } |
| |
88 } |
| |
89 |
| |
90 impl<Domain, G, F: Num> Linear<G> for DeltaMeasure<Domain, F> |
| |
91 where |
| |
92 Domain: Space, |
| |
93 G::Codomain: Mul<F, Output = G::Codomain>, |
| |
94 G: Mapping<Domain> + Clone + ClosedSpace, |
| |
95 for<'b> &'b Domain: Instance<Domain>, |
| |
96 { |
| |
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<N, F>, F> |
| |
129 // where BT : BTImpl< N, F>, |
| |
130 // G : SupportGenerator< N, F, Id=BT::Data>, |
| |
131 // G::SupportType : LocalAnalysis<F, BT::Agg, N> + for<'a> Apply<&'a Loc<N, F>, 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 impl<D, Domain, F: Num> From<(D, F)> for DeltaMeasure<Domain, F> |
| |
144 where |
| |
145 D: Into<Domain>, |
| |
146 { |
| |
147 #[inline] |
| |
148 fn from((x, α): (D, F)) -> Self { |
| |
149 DeltaMeasure { x: x.into(), α: α } |
| |
150 } |
| |
151 } |
| |
152 |
| |
153 impl<'a, Domain: Clone, F: Num> From<&'a DeltaMeasure<Domain, F>> for DeltaMeasure<Domain, F> { |
| |
154 #[inline] |
| |
155 fn from(d: &'a DeltaMeasure<Domain, F>) -> Self { |
| |
156 d.clone() |
| |
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 macro_rules! make_delta_scalarop_rhs { |
| |
219 ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { |
| |
220 impl<F: Num, Domain> $trait<F> for DeltaMeasure<Domain, F> { |
| |
221 type Output = Self; |
| |
222 fn $fn(mut self, b: F) -> Self { |
| |
223 self.α.$fn_assign(b); |
| |
224 self |
| |
225 } |
| |
226 } |
| |
227 |
| |
228 impl<'a, F: Num, Domain> $trait<&'a F> for DeltaMeasure<Domain, F> { |
| |
229 type Output = Self; |
| |
230 fn $fn(mut self, b: &'a F) -> Self { |
| |
231 self.α.$fn_assign(*b); |
| |
232 self |
| |
233 } |
| |
234 } |
| |
235 |
| |
236 impl<'b, F: Num, Domain: Clone> $trait<F> for &'b DeltaMeasure<Domain, F> { |
| |
237 type Output = DeltaMeasure<Domain, F>; |
| |
238 fn $fn(self, b: F) -> Self::Output { |
| |
239 DeltaMeasure { α: self.α.$fn(b), x: self.x.clone() } |
| |
240 } |
| |
241 } |
| |
242 |
| |
243 impl<'a, 'b, F: Num, Domain: Clone> $trait<&'a F> for &'b DeltaMeasure<Domain, F> { |
| |
244 type Output = DeltaMeasure<Domain, F>; |
| |
245 fn $fn(self, b: &'a F) -> Self::Output { |
| |
246 DeltaMeasure { α: self.α.$fn(*b), x: self.x.clone() } |
| |
247 } |
| |
248 } |
| |
249 |
| |
250 impl<F: Num, Domain> $trait_assign<F> for DeltaMeasure<Domain, F> { |
| |
251 fn $fn_assign(&mut self, b: F) { |
| |
252 self.α.$fn_assign(b) |
| |
253 } |
| |
254 } |
| |
255 |
| |
256 impl<'a, F: Num, Domain> $trait_assign<&'a F> for DeltaMeasure<Domain, F> { |
| |
257 fn $fn_assign(&mut self, b: &'a F) { |
| |
258 self.α.$fn_assign(*b) |
| |
259 } |
| |
260 } |
| |
261 }; |
| |
262 } |
| |
263 |
| |
264 make_delta_scalarop_rhs!(Mul, mul, MulAssign, mul_assign); |
| |
265 make_delta_scalarop_rhs!(Div, div, DivAssign, div_assign); |
| |
266 |
| |
267 macro_rules! make_delta_scalarop_lhs { |
| |
268 ($trait:ident, $fn:ident; $($f:ident)+) => { $( |
| |
269 impl<Domain> $trait<DeltaMeasure<Domain, $f>> for $f { |
| |
270 type Output = DeltaMeasure<Domain, $f>; |
| |
271 fn $fn(self, mut δ : DeltaMeasure<Domain, $f>) -> Self::Output { |
| |
272 δ.α = self.$fn(δ.α); |
| |
273 δ |
| |
274 } |
| |
275 } |
| |
276 |
| |
277 impl<'a, Domain : Clone> $trait<&'a DeltaMeasure<Domain, $f>> for $f { |
| |
278 type Output = DeltaMeasure<Domain, $f>; |
| |
279 fn $fn(self, δ : &'a DeltaMeasure<Domain, $f>) -> Self::Output { |
| |
280 DeltaMeasure{ x : δ.x.clone(), α : self.$fn(δ.α) } |
| |
281 } |
| |
282 } |
| |
283 |
| |
284 impl<'b, Domain> $trait<DeltaMeasure<Domain, $f>> for &'b $f { |
| |
285 type Output = DeltaMeasure<Domain, $f>; |
| |
286 fn $fn(self, mut δ : DeltaMeasure<Domain, $f>) -> Self::Output { |
| |
287 δ.α = self.$fn(δ.α); |
| |
288 δ |
| |
289 } |
| |
290 } |
| |
291 |
| |
292 impl<'a, 'b, Domain : Clone> $trait<&'a DeltaMeasure<Domain, $f>> for &'b $f { |
| |
293 type Output = DeltaMeasure<Domain, $f>; |
| |
294 fn $fn(self, δ : &'a DeltaMeasure<Domain, $f>) -> Self::Output { |
| |
295 DeltaMeasure{ x : δ.x.clone(), α : self.$fn(δ.α) } |
| |
296 } |
| |
297 } |
| |
298 )+ } |
| |
299 } |
| |
300 |
| |
301 make_delta_scalarop_lhs!(Mul, mul; f32 f64 i8 i16 i32 i64 isize u8 u16 u32 u64 usize); |
| |
302 make_delta_scalarop_lhs!(Div, div; f32 f64 i8 i16 i32 i64 isize u8 u16 u32 u64 usize); |
| |
303 |
| |
304 macro_rules! make_delta_unary { |
| |
305 ($trait:ident, $fn:ident, $type:ty) => { |
| |
306 impl<'a, F: Num + Neg<Output = F>, Domain: Clone> Neg for $type { |
| |
307 type Output = DeltaMeasure<Domain, F>; |
| |
308 fn $fn(self) -> Self::Output { |
| |
309 let mut tmp = self.clone(); |
| |
310 tmp.α = tmp.α.$fn(); |
| |
311 tmp |
| |
312 } |
| |
313 } |
| |
314 }; |
| |
315 } |
| |
316 |
| |
317 make_delta_unary!(Neg, neg, DeltaMeasure<Domain, F>); |
| |
318 make_delta_unary!(Neg, neg, &'a DeltaMeasure<Domain, F>); |
| |
319 |
| |
320 self_ownable!(DeltaMeasure<Domain, F> where Domain: Clone, F: Num); |