Thu, 29 Aug 2024 00:00:00 -0500
Radon FB + sliding improvements
0 | 1 | //! This module implementes discrete measures. |
2 | ||
3 | use std::ops::{ | |
4 | Div,Mul,DivAssign,MulAssign,Neg, | |
5 | Add,Sub,AddAssign,SubAssign, | |
6 | Index,IndexMut, | |
7 | }; | |
8 | use std::iter::Sum; | |
9 | use serde::ser::{Serializer, Serialize, SerializeSeq}; | |
10 | use nalgebra::DVector; | |
11 | ||
12 | use alg_tools::norms::Norm; | |
13 | use alg_tools::tabledump::TableDump; | |
14 | use alg_tools::linops::{Apply, Linear}; | |
15 | use alg_tools::iter::{MapF,Mappable}; | |
16 | use alg_tools::nalgebra_support::ToNalgebraRealField; | |
17 | ||
18 | use crate::types::*; | |
19 | use super::base::*; | |
20 | use super::delta::*; | |
21 | ||
22 | /// Representation of a discrete measure. | |
23 | /// | |
24 | /// This is the measure $μ = ∑_{k=1}^n α_k δ_{x_k}$, consisting of several | |
25 | /// [`DeltaMeasure`], i.e., “spikes” $α_k δ_{x_k}$ with weights $\alpha_k$ in `F` at locations | |
26 | /// $x_k$ in `Domain`. | |
27 | #[derive(Clone,Debug)] | |
28 | pub struct DiscreteMeasure<Domain, F : Num> { | |
29 | pub(super) spikes : Vec<DeltaMeasure<Domain, F>>, | |
30 | } | |
31 | ||
32 | /// Iterator over the [`DeltaMeasure`] spikes of a [`DiscreteMeasure`]. | |
33 | pub type SpikeIter<'a, Domain, F> = std::slice::Iter<'a, DeltaMeasure<Domain, F>>; | |
34 | ||
35 | /// Iterator over mutable [`DeltaMeasure`] spikes of a [`DiscreteMeasure`]. | |
36 | pub type SpikeIterMut<'a, Domain, F> = std::slice::IterMut<'a, DeltaMeasure<Domain, F>>; | |
37 | ||
38 | /// Iterator over the locations of the spikes of a [`DiscreteMeasure`]. | |
39 | pub type LocationIter<'a, Domain, F> | |
40 | = std::iter::Map<SpikeIter<'a, Domain, F>, fn(&'a DeltaMeasure<Domain, F>) -> &'a Domain>; | |
41 | ||
42 | /// Iterator over the masses of the spikes of a [`DiscreteMeasure`]. | |
43 | pub type MassIter<'a, Domain, F> | |
44 | = std::iter::Map<SpikeIter<'a, Domain, F>, fn(&'a DeltaMeasure<Domain, F>) -> F>; | |
45 | ||
46 | /// Iterator over the mutable locations of the spikes of a [`DiscreteMeasure`]. | |
47 | pub type MassIterMut<'a, Domain, F> | |
48 | = std::iter::Map<SpikeIterMut<'a, Domain, F>, for<'r> fn(&'r mut DeltaMeasure<Domain, F>) -> &'r mut F>; | |
49 | ||
50 | impl<Domain, F : Num> DiscreteMeasure<Domain, F> { | |
51 | /// Create a new zero measure (empty spike set). | |
52 | pub fn new() -> Self { | |
53 | DiscreteMeasure{ spikes : Vec::new() } | |
54 | } | |
55 | ||
56 | /// Number of [`DeltaMeasure`] spikes in the measure | |
57 | #[inline] | |
58 | pub fn len(&self) -> usize { | |
59 | self.spikes.len() | |
60 | } | |
61 | ||
32 | 62 | /// Replace with the zero measure. |
63 | #[inline] | |
64 | pub fn clear(&mut self) { | |
65 | self.spikes.clear() | |
66 | } | |
67 | ||
68 | /// Remove `i`:th spike, not maintaining order. | |
69 | /// | |
70 | /// Panics if indiex is out of bounds. | |
71 | #[inline] | |
72 | pub fn swap_remove(&mut self, i : usize) -> DeltaMeasure<Domain, F>{ | |
73 | self.spikes.swap_remove(i) | |
74 | } | |
75 | ||
0 | 76 | /// Iterate over (references to) the [`DeltaMeasure`] spikes in this measure |
77 | #[inline] | |
78 | pub fn iter_spikes(&self) -> SpikeIter<'_, Domain, F> { | |
79 | self.spikes.iter() | |
80 | } | |
81 | ||
82 | /// Iterate over mutable references to the [`DeltaMeasure`] spikes in this measure | |
83 | #[inline] | |
84 | pub fn iter_spikes_mut(&mut self) -> SpikeIterMut<'_, Domain, F> { | |
85 | self.spikes.iter_mut() | |
86 | } | |
87 | ||
88 | /// Iterate over the location of the spikes in this measure | |
89 | #[inline] | |
90 | pub fn iter_locations(&self) -> LocationIter<'_, Domain, F> { | |
91 | self.iter_spikes().map(DeltaMeasure::get_location) | |
92 | } | |
93 | ||
94 | /// Iterate over the masses of the spikes in this measure | |
95 | #[inline] | |
96 | pub fn iter_masses(&self) -> MassIter<'_, Domain, F> { | |
97 | self.iter_spikes().map(DeltaMeasure::get_mass) | |
98 | } | |
99 | ||
100 | /// Iterate over the masses of the spikes in this measure | |
101 | #[inline] | |
102 | pub fn iter_masses_mut(&mut self) -> MassIterMut<'_, Domain, F> { | |
103 | self.iter_spikes_mut().map(DeltaMeasure::get_mass_mut) | |
104 | } | |
105 | ||
106 | /// Update the masses of all the spikes to those produced by an iterator. | |
107 | #[inline] | |
108 | pub fn set_masses<I : Iterator<Item=F>>(&mut self, iter : I) { | |
109 | self.spikes.iter_mut().zip(iter).for_each(|(δ, α)| δ.set_mass(α)); | |
110 | } | |
111 | ||
112 | // /// Map the masses of all the spikes using a function and an iterator | |
113 | // #[inline] | |
114 | // pub fn zipmap_masses< | |
115 | // I : Iterator<Item=F>, | |
116 | // G : Fn(F, I::Item) -> F | |
117 | // > (&mut self, iter : I, g : G) { | |
118 | // self.spikes.iter_mut().zip(iter).for_each(|(δ, v)| δ.set_mass(g(δ.get_mass(), v))); | |
119 | // } | |
120 | ||
121 | /// Prune all spikes with zero mass. | |
122 | #[inline] | |
123 | pub fn prune(&mut self) { | |
34
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
124 | self.prune_by(|δ| δ.α != F::ZERO); |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
125 | } |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
126 | |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
127 | /// Prune spikes by the predicate `g`. |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
128 | #[inline] |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
129 | pub fn prune_by<G : FnMut(&DeltaMeasure<Domain, F>) -> bool>(&mut self, g : G) { |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
130 | self.spikes.retain(g); |
0 | 131 | } |
32 | 132 | |
133 | /// Add the spikes produced by `iter` to this measure. | |
134 | #[inline] | |
135 | pub fn extend<I : Iterator<Item=DeltaMeasure<Domain, F>>>( | |
136 | &mut self, | |
137 | iter : I | |
138 | ) { | |
139 | self.spikes.extend(iter); | |
140 | } | |
141 | ||
142 | /// Add a spike to the measure | |
143 | #[inline] | |
144 | pub fn push(&mut self, δ : DeltaMeasure<Domain, F>) { | |
145 | self.spikes.push(δ); | |
146 | } | |
34
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
147 | |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
148 | /// Iterate over triples of masses and locations of two discrete measures, which are assumed |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
149 | /// to have equal locations of same spike indices. |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
150 | pub fn both_matching<'a>(&'a self, other : &'a DiscreteMeasure<Domain, F>) -> |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
151 | impl Iterator<Item=(F, F, &'a Domain)> { |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
152 | let m = self.len().max(other.len()); |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
153 | self.iter_spikes().map(Some).chain(std::iter::repeat(None)) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
154 | .zip(other.iter_spikes().map(Some).chain(std::iter::repeat(None))) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
155 | .take(m) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
156 | .map(|(oδ, orδ)| { |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
157 | match (oδ, orδ) { |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
158 | (Some(δ), Some(rδ)) => (δ.α, rδ.α, &δ.x), // Assumed δ.x=rδ.x |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
159 | (Some(δ), None) => (δ.α, F::ZERO, &δ.x), |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
160 | (None, Some(rδ)) => (F::ZERO, rδ.α, &rδ.x), |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
161 | (None, None) => panic!("This cannot happen!"), |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
162 | } |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
163 | }) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
164 | } |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
165 | |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
166 | /// Subtract `other` from `self`, assuming equal locations of same spike indices |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
167 | pub fn sub_matching(&self, other : &DiscreteMeasure<Domain, F>) -> DiscreteMeasure<Domain, F> |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
168 | where Domain : Clone { |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
169 | self.both_matching(other) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
170 | .map(|(α, β, x)| (x.clone(), α - β)) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
171 | .collect() |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
172 | } |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
173 | |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
174 | /// Add `other` to `self`, assuming equal locations of same spike indices |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
175 | pub fn add_matching(&self, other : &DiscreteMeasure<Domain, F>) -> DiscreteMeasure<Domain, F> |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
176 | where Domain : Clone { |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
177 | self.both_matching(other) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
178 | .map(|(α, β, x)| (x.clone(), α + β)) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
179 | .collect() |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
180 | } |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
181 | |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
182 | /// Calculate the Radon-norm distance of `self` to `other`, |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
183 | /// assuming equal locations of same spike indices. |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
184 | pub fn dist_matching(&self, other : &DiscreteMeasure<Domain, F>) -> F where F : Float { |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
185 | self.both_matching(other) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
186 | .map(|(α, β, _)| (α-β).abs()) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
187 | .sum() |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
188 | } |
32 | 189 | } |
190 | ||
191 | impl<Domain, F : Num> IntoIterator for DiscreteMeasure<Domain, F> { | |
192 | type Item = DeltaMeasure<Domain, F>; | |
193 | type IntoIter = <Vec<DeltaMeasure<Domain, F>> as IntoIterator>::IntoIter; | |
194 | ||
195 | #[inline] | |
196 | fn into_iter(self) -> Self::IntoIter { | |
197 | self.spikes.into_iter() | |
198 | } | |
0 | 199 | } |
200 | ||
201 | impl<Domain : Clone, F : Float> DiscreteMeasure<Domain, F> { | |
202 | /// Computes `μ1 ← θ * μ1 - ζ * μ2`, pruning entries where both `μ1` (`self`) and `μ2` have | |
203 | // zero weight. `μ2` will contain copy of pruned original `μ1` without arithmetic performed. | |
204 | /// **This expects `self` and `μ2` to have matching coordinates in each index**. | |
205 | // `μ2` can be than `self`, but not longer. | |
206 | pub fn pruning_sub(&mut self, θ : F, ζ : F, μ2 : &mut Self) { | |
207 | let mut μ2_get = 0; | |
208 | let mut μ2_insert = 0; | |
32 | 209 | self.spikes.retain_mut(|&mut DeltaMeasure{ α : ref mut α_ref, ref x }| { |
0 | 210 | // Get weight of spike in μ2, zero if out of bounds. |
211 | let β = μ2.spikes.get(μ2_get).map_or(F::ZERO, DeltaMeasure::get_mass); | |
212 | μ2_get += 1; | |
213 | ||
214 | if *α_ref == F::ZERO && β == F::ZERO { | |
215 | // Prune | |
216 | true | |
217 | } else { | |
218 | // Save self weight | |
219 | let α = *α_ref; | |
220 | // Modify self | |
221 | *α_ref = θ * α - ζ * β; | |
222 | // Make copy of old self weight in μ2 | |
223 | let δ = DeltaMeasure{ α, x : x.clone() }; | |
224 | match μ2.spikes.get_mut(μ2_insert) { | |
225 | Some(replace) => { | |
226 | *replace = δ; | |
227 | }, | |
228 | None => { | |
229 | debug_assert_eq!(μ2.len(), μ2_insert); | |
230 | μ2.spikes.push(δ); | |
231 | }, | |
232 | } | |
233 | μ2_insert += 1; | |
234 | // Keep | |
235 | false | |
236 | } | |
237 | }); | |
238 | // Truncate μ2 to same length as self. | |
239 | μ2.spikes.truncate(μ2_insert); | |
240 | debug_assert_eq!(μ2.len(), self.len()); | |
241 | } | |
242 | } | |
243 | ||
244 | impl<Domain, F : Float> DiscreteMeasure<Domain, F> { | |
245 | /// Prune all spikes with mass absolute value less than the given `tolerance`. | |
246 | #[inline] | |
247 | pub fn prune_approx(&mut self, tolerance : F) { | |
248 | self.spikes.retain(|δ| δ.α.abs() > tolerance); | |
249 | } | |
250 | } | |
251 | ||
252 | impl<Domain, F : Float + ToNalgebraRealField> DiscreteMeasure<Domain, F> { | |
253 | /// Extracts the masses of the spikes as a [`DVector`]. | |
254 | pub fn masses_dvector(&self) -> DVector<F::MixedType> { | |
255 | DVector::from_iterator(self.len(), | |
256 | self.iter_masses() | |
257 | .map(|α| α.to_nalgebra_mixed())) | |
258 | } | |
259 | ||
260 | /// Sets the masses of the spikes from the values of a [`DVector`]. | |
261 | pub fn set_masses_dvector(&mut self, x : &DVector<F::MixedType>) { | |
262 | self.set_masses(x.iter().map(|&α| F::from_nalgebra_mixed(α))); | |
263 | } | |
264 | } | |
265 | ||
32 | 266 | // impl<Domain, F :Num> Index<usize> for DiscreteMeasure<Domain, F> { |
267 | // type Output = DeltaMeasure<Domain, F>; | |
268 | // #[inline] | |
269 | // fn index(&self, i : usize) -> &Self::Output { | |
270 | // self.spikes.index(i) | |
271 | // } | |
272 | // } | |
273 | ||
274 | // impl<Domain, F :Num> IndexMut<usize> for DiscreteMeasure<Domain, F> { | |
275 | // #[inline] | |
276 | // fn index_mut(&mut self, i : usize) -> &mut Self::Output { | |
277 | // self.spikes.index_mut(i) | |
278 | // } | |
279 | // } | |
280 | ||
281 | impl< | |
282 | Domain, | |
283 | F : Num, | |
284 | I : std::slice::SliceIndex<[DeltaMeasure<Domain, F>]> | |
285 | > Index<I> | |
286 | for DiscreteMeasure<Domain, F> { | |
287 | type Output = <I as std::slice::SliceIndex<[DeltaMeasure<Domain, F>]>>::Output; | |
0 | 288 | #[inline] |
32 | 289 | fn index(&self, i : I) -> &Self::Output { |
0 | 290 | self.spikes.index(i) |
291 | } | |
292 | } | |
293 | ||
32 | 294 | impl< |
295 | Domain, | |
296 | F : Num, | |
297 | I : std::slice::SliceIndex<[DeltaMeasure<Domain, F>]> | |
298 | > IndexMut<I> | |
299 | for DiscreteMeasure<Domain, F> { | |
0 | 300 | #[inline] |
32 | 301 | fn index_mut(&mut self, i : I) -> &mut Self::Output { |
0 | 302 | self.spikes.index_mut(i) |
303 | } | |
304 | } | |
305 | ||
32 | 306 | |
0 | 307 | impl<Domain, F : Num, D : Into<DeltaMeasure<Domain, F>>, const K : usize> From<[D; K]> |
308 | for DiscreteMeasure<Domain, F> { | |
309 | #[inline] | |
310 | fn from(list : [D; K]) -> Self { | |
311 | list.into_iter().collect() | |
312 | } | |
313 | } | |
314 | ||
315 | impl<Domain, F : Num, D : Into<DeltaMeasure<Domain, F>>> FromIterator<D> | |
316 | for DiscreteMeasure<Domain, F> { | |
317 | #[inline] | |
318 | fn from_iter<T>(iter : T) -> Self | |
319 | where T : IntoIterator<Item=D> { | |
320 | DiscreteMeasure{ | |
321 | spikes : iter.into_iter().map(|m| m.into()).collect() | |
322 | } | |
323 | } | |
324 | } | |
325 | ||
326 | impl<'a, F : Num, const N : usize> TableDump<'a> | |
327 | for DiscreteMeasure<Loc<F, N>,F> | |
328 | where DeltaMeasure<Loc<F, N>, F> : Serialize + 'a { | |
329 | type Iter = std::slice::Iter<'a, DeltaMeasure<Loc<F, N>, F>>; | |
330 | ||
331 | // fn tabledump_headers(&'a self) -> Vec<String> { | |
332 | // let mut v : Vec<String> = (0..N).map(|i| format!("x{}", i)).collect(); | |
333 | // v.push("weight".into()); | |
334 | // v | |
335 | // } | |
336 | ||
337 | fn tabledump_entries(&'a self) -> Self::Iter { | |
338 | // Ensure order matching the headers above | |
339 | self.spikes.iter() | |
340 | } | |
341 | } | |
342 | ||
343 | // Need to manually implement serialisation for DeltaMeasure<Loc<F, N>, F> [`csv`] writer fails on | |
344 | // structs with nested arrays as well as with #[serde(flatten)]. | |
345 | // Then derive no longer works for DiscreteMeasure | |
346 | impl<F : Num, const N : usize> Serialize for DiscreteMeasure<Loc<F, N>, F> | |
347 | where | |
348 | F: Serialize, | |
349 | { | |
350 | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | |
351 | where | |
352 | S: Serializer, | |
353 | { | |
354 | let mut s = serializer.serialize_seq(Some(self.spikes.len()))?; | |
355 | for δ in self.spikes.iter() { | |
356 | s.serialize_element(δ)?; | |
357 | } | |
358 | s.end() | |
359 | } | |
360 | } | |
361 | ||
362 | impl<Domain : PartialEq, F : Float> Measure<F> for DiscreteMeasure<Domain, F> { | |
363 | type Domain = Domain; | |
364 | } | |
365 | ||
366 | impl<Domain : PartialEq, F : Float> Norm<F, Radon> for DiscreteMeasure<Domain, F> | |
367 | where DeltaMeasure<Domain, F> : Norm<F, Radon> { | |
368 | #[inline] | |
369 | fn norm(&self, _ : Radon) -> F { | |
370 | self.spikes.iter().map(|m| m.norm(Radon)).sum() | |
371 | } | |
372 | } | |
373 | ||
374 | impl<Domain, G, F : Num, Y : Sum + Mul<F, Output=Y>> Apply<G> for DiscreteMeasure<Domain, F> | |
375 | where G: for<'a> Apply<&'a Domain, Output = Y> { | |
376 | type Output = Y; | |
377 | #[inline] | |
378 | fn apply(&self, g : G) -> Y { | |
379 | self.spikes.iter().map(|m| g.apply(&m.x) * m.α).sum() | |
380 | } | |
381 | } | |
382 | ||
383 | impl<Domain, G, F : Num, Y : Sum + Mul<F, Output=Y>> Linear<G> for DiscreteMeasure<Domain, F> | |
384 | where G : for<'a> Apply<&'a Domain, Output = Y> { | |
385 | type Codomain = Y; | |
386 | } | |
387 | ||
388 | ||
389 | /// Helper trait for constructing arithmetic operations for combinations | |
390 | /// of [`DiscreteMeasure`] and [`DeltaMeasure`], and their references. | |
391 | trait Lift<F : Num, Domain> { | |
392 | type Producer : Iterator<Item=DeltaMeasure<Domain, F>>; | |
393 | ||
394 | /// Lifts `self` into a [`DiscreteMeasure`]. | |
395 | fn lift(self) -> DiscreteMeasure<Domain, F>; | |
396 | ||
397 | /// Lifts `self` into a [`DiscreteMeasure`], apply either `f` or `f_mut` whether the type | |
398 | /// this method is implemented for is a reference or or not. | |
399 | fn lift_with(self, | |
400 | f : impl Fn(&DeltaMeasure<Domain, F>) -> DeltaMeasure<Domain, F>, | |
401 | f_mut : impl FnMut(&mut DeltaMeasure<Domain, F>)) | |
402 | -> DiscreteMeasure<Domain, F>; | |
403 | ||
404 | /// Extend `self` into a [`DiscreteMeasure`] with the spikes produced by `iter`. | |
405 | fn lift_extend<I : Iterator<Item=DeltaMeasure<Domain, F>>>( | |
406 | self, | |
407 | iter : I | |
408 | ) -> DiscreteMeasure<Domain, F>; | |
409 | ||
410 | /// Returns an iterator for producing copies of the spikes of `self`. | |
411 | fn produce(self) -> Self::Producer; | |
412 | } | |
413 | ||
414 | impl<F : Num, Domain> Lift<F, Domain> for DiscreteMeasure<Domain, F> { | |
415 | type Producer = std::vec::IntoIter<DeltaMeasure<Domain, F>>; | |
416 | ||
417 | #[inline] | |
418 | fn lift(self) -> DiscreteMeasure<Domain, F> { self } | |
419 | ||
420 | fn lift_with(mut self, | |
421 | _f : impl Fn(&DeltaMeasure<Domain, F>) -> DeltaMeasure<Domain, F>, | |
422 | f_mut : impl FnMut(&mut DeltaMeasure<Domain, F>)) | |
423 | -> DiscreteMeasure<Domain, F> { | |
424 | self.spikes.iter_mut().for_each(f_mut); | |
425 | self | |
426 | } | |
427 | ||
428 | #[inline] | |
429 | fn lift_extend<I : Iterator<Item=DeltaMeasure<Domain, F>>>( | |
430 | mut self, | |
431 | iter : I | |
432 | ) -> DiscreteMeasure<Domain, F> { | |
433 | self.spikes.extend(iter); | |
434 | self | |
435 | } | |
436 | ||
437 | #[inline] | |
438 | fn produce(self) -> Self::Producer { | |
439 | self.spikes.into_iter() | |
440 | } | |
441 | } | |
442 | ||
443 | impl<'a, F : Num, Domain : Clone> Lift<F, Domain> for &'a DiscreteMeasure<Domain, F> { | |
444 | type Producer = MapF<std::slice::Iter<'a, DeltaMeasure<Domain, F>>, DeltaMeasure<Domain, F>>; | |
445 | ||
446 | #[inline] | |
447 | fn lift(self) -> DiscreteMeasure<Domain, F> { self.clone() } | |
448 | ||
449 | fn lift_with(self, | |
450 | f : impl Fn(&DeltaMeasure<Domain, F>) -> DeltaMeasure<Domain, F>, | |
451 | _f_mut : impl FnMut(&mut DeltaMeasure<Domain, F>)) | |
452 | -> DiscreteMeasure<Domain, F> { | |
453 | DiscreteMeasure{ spikes : self.spikes.iter().map(f).collect() } | |
454 | } | |
455 | ||
456 | #[inline] | |
457 | fn lift_extend<I : Iterator<Item=DeltaMeasure<Domain, F>>>( | |
458 | self, | |
459 | iter : I | |
460 | ) -> DiscreteMeasure<Domain, F> { | |
461 | let mut res = self.clone(); | |
462 | res.spikes.extend(iter); | |
463 | res | |
464 | } | |
465 | ||
466 | #[inline] | |
467 | fn produce(self) -> Self::Producer { | |
468 | // TODO: maybe not optimal to clone here and would benefit from | |
469 | // a reference version of lift_extend. | |
470 | self.spikes.iter().mapF(Clone::clone) | |
471 | } | |
472 | } | |
473 | ||
474 | impl<F : Num, Domain> Lift<F, Domain> for DeltaMeasure<Domain, F> { | |
475 | type Producer = std::iter::Once<DeltaMeasure<Domain, F>>; | |
476 | ||
477 | #[inline] | |
478 | fn lift(self) -> DiscreteMeasure<Domain, F> { DiscreteMeasure { spikes : vec![self] } } | |
479 | ||
480 | #[inline] | |
481 | fn lift_with(mut self, | |
482 | _f : impl Fn(&DeltaMeasure<Domain, F>) -> DeltaMeasure<Domain, F>, | |
483 | mut f_mut : impl FnMut(&mut DeltaMeasure<Domain, F>)) | |
484 | -> DiscreteMeasure<Domain, F> { | |
485 | f_mut(&mut self); | |
486 | DiscreteMeasure{ spikes : vec![self] } | |
487 | } | |
488 | ||
489 | #[inline] | |
490 | fn lift_extend<I : Iterator<Item=DeltaMeasure<Domain, F>>>( | |
491 | self, | |
492 | iter : I | |
493 | ) -> DiscreteMeasure<Domain, F> { | |
494 | let mut spikes = vec![self]; | |
495 | spikes.extend(iter); | |
496 | DiscreteMeasure{ spikes : spikes } | |
497 | } | |
498 | ||
499 | #[inline] | |
500 | fn produce(self) -> Self::Producer { | |
501 | std::iter::once(self) | |
502 | } | |
503 | } | |
504 | ||
505 | impl<'a, F : Num, Domain : Clone> Lift<F, Domain> for &'a DeltaMeasure<Domain, F> { | |
506 | type Producer = std::iter::Once<DeltaMeasure<Domain, F>>; | |
507 | ||
508 | #[inline] | |
509 | fn lift(self) -> DiscreteMeasure<Domain, F> { DiscreteMeasure { spikes : vec![self.clone()] } } | |
510 | ||
511 | #[inline] | |
512 | fn lift_with(self, | |
513 | f : impl Fn(&DeltaMeasure<Domain, F>) -> DeltaMeasure<Domain, F>, | |
514 | _f_mut : impl FnMut(&mut DeltaMeasure<Domain, F>)) | |
515 | -> DiscreteMeasure<Domain, F> { | |
516 | DiscreteMeasure{ spikes : vec![f(self)] } | |
517 | } | |
518 | ||
519 | #[inline] | |
520 | fn lift_extend<I : Iterator<Item=DeltaMeasure<Domain, F>>>( | |
521 | self, | |
522 | iter : I | |
523 | ) -> DiscreteMeasure<Domain, F> { | |
524 | let mut spikes = vec![self.clone()]; | |
525 | spikes.extend(iter); | |
526 | DiscreteMeasure{ spikes : spikes } | |
527 | } | |
528 | ||
529 | #[inline] | |
530 | fn produce(self) -> Self::Producer { | |
531 | std::iter::once(self.clone()) | |
532 | } | |
533 | } | |
534 | ||
535 | macro_rules! make_discrete_addsub_assign { | |
536 | ($rhs:ty) => { | |
537 | // Discrete += (&)Discrete | |
538 | impl<'a, F : Num, Domain : Clone> AddAssign<$rhs> | |
539 | for DiscreteMeasure<Domain, F> { | |
540 | fn add_assign(&mut self, other : $rhs) { | |
541 | self.spikes.extend(other.produce()); | |
542 | } | |
543 | } | |
544 | ||
545 | impl<'a, F : Num + Neg<Output=F>, Domain : Clone> SubAssign<$rhs> | |
546 | for DiscreteMeasure<Domain, F> { | |
547 | fn sub_assign(&mut self, other : $rhs) { | |
548 | self.spikes.extend(other.produce().map(|δ| -δ)); | |
549 | } | |
550 | } | |
551 | } | |
552 | } | |
553 | ||
554 | make_discrete_addsub_assign!(DiscreteMeasure<Domain, F>); | |
555 | make_discrete_addsub_assign!(&'a DiscreteMeasure<Domain, F>); | |
556 | make_discrete_addsub_assign!(DeltaMeasure<Domain, F>); | |
557 | make_discrete_addsub_assign!(&'a DeltaMeasure<Domain, F>); | |
558 | ||
559 | macro_rules! make_discrete_addsub { | |
560 | ($lhs:ty, $rhs:ty, $alt_order:expr) => { | |
561 | impl<'a, 'b, F : Num, Domain : Clone> Add<$rhs> for $lhs { | |
562 | type Output = DiscreteMeasure<Domain, F>; | |
563 | fn add(self, other : $rhs) -> DiscreteMeasure<Domain, F> { | |
564 | if !$alt_order { | |
565 | self.lift_extend(other.produce()) | |
566 | } else { | |
567 | other.lift_extend(self.produce()) | |
568 | } | |
569 | } | |
570 | } | |
571 | ||
572 | impl<'a, 'b, F : Num + Neg<Output=F>, Domain : Clone> Sub<$rhs> for $lhs { | |
573 | type Output = DiscreteMeasure<Domain, F>; | |
574 | fn sub(self, other : $rhs) -> DiscreteMeasure<Domain, F> { | |
575 | self.lift_extend(other.produce().map(|δ| -δ)) | |
576 | } | |
577 | } | |
578 | }; | |
579 | } | |
580 | ||
581 | make_discrete_addsub!(DiscreteMeasure<Domain, F>, DiscreteMeasure<Domain, F>, false); | |
582 | make_discrete_addsub!(DiscreteMeasure<Domain, F>, &'b DiscreteMeasure<Domain, F>, false); | |
583 | make_discrete_addsub!(&'a DiscreteMeasure<Domain, F>, DiscreteMeasure<Domain, F>, true); | |
584 | make_discrete_addsub!(&'a DiscreteMeasure<Domain, F>, &'b DiscreteMeasure<Domain, F>, false); | |
585 | make_discrete_addsub!(DeltaMeasure<Domain, F>, DiscreteMeasure<Domain, F>, false); | |
586 | make_discrete_addsub!(DeltaMeasure<Domain, F>, &'b DiscreteMeasure<Domain, F>, false); | |
587 | make_discrete_addsub!(&'a DeltaMeasure<Domain, F>, DiscreteMeasure<Domain, F>, true); | |
588 | make_discrete_addsub!(&'a DeltaMeasure<Domain, F>, &'b DiscreteMeasure<Domain, F>, false); | |
589 | make_discrete_addsub!(DiscreteMeasure<Domain, F>, DeltaMeasure<Domain, F>, false); | |
590 | make_discrete_addsub!(DiscreteMeasure<Domain, F>, &'b DeltaMeasure<Domain, F>, false); | |
591 | make_discrete_addsub!(&'a DiscreteMeasure<Domain, F>, DeltaMeasure<Domain, F>, false); | |
592 | make_discrete_addsub!(&'a DiscreteMeasure<Domain, F>, &'b DeltaMeasure<Domain, F>, false); | |
593 | make_discrete_addsub!(DeltaMeasure<Domain, F>, DeltaMeasure<Domain, F>, false); | |
594 | make_discrete_addsub!(DeltaMeasure<Domain, F>, &'b DeltaMeasure<Domain, F>, false); | |
595 | make_discrete_addsub!(&'a DeltaMeasure<Domain, F>, DeltaMeasure<Domain, F>, false); | |
596 | make_discrete_addsub!(&'a DeltaMeasure<Domain, F>, &'b DeltaMeasure<Domain, F>, false); | |
597 | ||
598 | macro_rules! make_discrete_scalarop_rhs { | |
599 | ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { | |
600 | make_discrete_scalarop_rhs!(@assign DiscreteMeasure<Domain, F>, F, $trait_assign, $fn_assign); | |
601 | make_discrete_scalarop_rhs!(@assign DiscreteMeasure<Domain, F>, &'a F, $trait_assign, $fn_assign); | |
602 | make_discrete_scalarop_rhs!(@new DiscreteMeasure<Domain, F>, F, $trait, $fn, $fn_assign); | |
603 | make_discrete_scalarop_rhs!(@new DiscreteMeasure<Domain, F>, &'a F, $trait, $fn, $fn_assign); | |
604 | make_discrete_scalarop_rhs!(@new &'b DiscreteMeasure<Domain, F>, F, $trait, $fn, $fn_assign); | |
605 | make_discrete_scalarop_rhs!(@new &'b DiscreteMeasure<Domain, F>, &'a F, $trait, $fn, $fn_assign); | |
606 | }; | |
607 | ||
608 | (@assign $lhs:ty, $rhs:ty, $trait_assign:ident, $fn_assign:ident) => { | |
609 | impl<'a, 'b, F : Num, Domain> $trait_assign<$rhs> for $lhs { | |
610 | fn $fn_assign(&mut self, b : $rhs) { | |
611 | self.spikes.iter_mut().for_each(|δ| δ.$fn_assign(b)); | |
612 | } | |
613 | } | |
614 | }; | |
615 | (@new $lhs:ty, $rhs:ty, $trait:ident, $fn:ident, $fn_assign:ident) => { | |
616 | impl<'a, 'b, F : Num, Domain : Clone> $trait<$rhs> for $lhs { | |
617 | type Output = DiscreteMeasure<Domain, F>; | |
618 | fn $fn(self, b : $rhs) -> Self::Output { | |
619 | self.lift_with(|δ| δ.$fn(b), |δ| δ.$fn_assign(b)) | |
620 | } | |
621 | } | |
622 | }; | |
623 | } | |
624 | ||
625 | make_discrete_scalarop_rhs!(Mul, mul, MulAssign, mul_assign); | |
626 | make_discrete_scalarop_rhs!(Div, div, DivAssign, div_assign); | |
627 | ||
628 | macro_rules! make_discrete_unary { | |
629 | ($trait:ident, $fn:ident, $type:ty) => { | |
630 | impl<'a, F : Num + Neg<Output=F>, Domain : Clone> Neg for $type { | |
631 | type Output = DiscreteMeasure<Domain, F>; | |
632 | fn $fn(self) -> Self::Output { | |
633 | self.lift_with(|δ| δ.$fn(), |δ| δ.α = δ.α.$fn()) | |
634 | } | |
635 | } | |
636 | } | |
637 | } | |
638 | ||
639 | make_discrete_unary!(Neg, neg, DiscreteMeasure<Domain, F>); | |
640 | make_discrete_unary!(Neg, neg, &'a DiscreteMeasure<Domain, F>); | |
641 | ||
642 | // impl<F : Num, Domain> Neg for DiscreteMeasure<Domain, F> { | |
643 | // type Output = Self; | |
644 | // fn $fn(mut self, b : F) -> Self { | |
645 | // self.lift().spikes.iter_mut().for_each(|δ| δ.neg(b)); | |
646 | // self | |
647 | // } | |
648 | // } | |
649 | ||
650 | macro_rules! make_discrete_scalarop_lhs { | |
651 | ($trait:ident, $fn:ident; $($f:ident)+) => { $( | |
652 | impl<Domain> $trait<DiscreteMeasure<Domain, $f>> for $f { | |
653 | type Output = DiscreteMeasure<Domain, $f>; | |
654 | fn $fn(self, mut v : DiscreteMeasure<Domain, $f>) -> Self::Output { | |
655 | v.spikes.iter_mut().for_each(|δ| δ.α = self.$fn(δ.α)); | |
656 | v | |
657 | } | |
658 | } | |
659 | ||
660 | impl<'a, Domain : Copy> $trait<&'a DiscreteMeasure<Domain, $f>> for $f { | |
661 | type Output = DiscreteMeasure<Domain, $f>; | |
662 | fn $fn(self, v : &'a DiscreteMeasure<Domain, $f>) -> Self::Output { | |
663 | DiscreteMeasure{ | |
664 | spikes : v.spikes.iter().map(|δ| self.$fn(δ)).collect() | |
665 | } | |
666 | } | |
667 | } | |
668 | ||
669 | impl<'b, Domain> $trait<DiscreteMeasure<Domain, $f>> for &'b $f { | |
670 | type Output = DiscreteMeasure<Domain, $f>; | |
671 | fn $fn(self, mut v : DiscreteMeasure<Domain, $f>) -> Self::Output { | |
672 | v.spikes.iter_mut().for_each(|δ| δ.α = self.$fn(δ.α)); | |
673 | v | |
674 | } | |
675 | } | |
676 | ||
677 | impl<'a, 'b, Domain : Copy> $trait<&'a DiscreteMeasure<Domain, $f>> for &'b $f { | |
678 | type Output = DiscreteMeasure<Domain, $f>; | |
679 | fn $fn(self, v : &'a DiscreteMeasure<Domain, $f>) -> Self::Output { | |
680 | DiscreteMeasure{ | |
681 | spikes : v.spikes.iter().map(|δ| self.$fn(δ)).collect() | |
682 | } | |
683 | } | |
684 | } | |
685 | )+ } | |
686 | } | |
687 | ||
688 | make_discrete_scalarop_lhs!(Mul, mul; f32 f64 i8 i16 i32 i64 isize u8 u16 u32 u64 usize); | |
689 | make_discrete_scalarop_lhs!(Div, div; f32 f64 i8 i16 i32 i64 isize u8 u16 u32 u64 usize); |