| |
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 |
| |
62 /// Iterate over (references to) the [`DeltaMeasure`] spikes in this measure |
| |
63 #[inline] |
| |
64 pub fn iter_spikes(&self) -> SpikeIter<'_, Domain, F> { |
| |
65 self.spikes.iter() |
| |
66 } |
| |
67 |
| |
68 /// Iterate over mutable references to the [`DeltaMeasure`] spikes in this measure |
| |
69 #[inline] |
| |
70 pub fn iter_spikes_mut(&mut self) -> SpikeIterMut<'_, Domain, F> { |
| |
71 self.spikes.iter_mut() |
| |
72 } |
| |
73 |
| |
74 /// Iterate over the location of the spikes in this measure |
| |
75 #[inline] |
| |
76 pub fn iter_locations(&self) -> LocationIter<'_, Domain, F> { |
| |
77 self.iter_spikes().map(DeltaMeasure::get_location) |
| |
78 } |
| |
79 |
| |
80 /// Iterate over the masses of the spikes in this measure |
| |
81 #[inline] |
| |
82 pub fn iter_masses(&self) -> MassIter<'_, Domain, F> { |
| |
83 self.iter_spikes().map(DeltaMeasure::get_mass) |
| |
84 } |
| |
85 |
| |
86 /// Iterate over the masses of the spikes in this measure |
| |
87 #[inline] |
| |
88 pub fn iter_masses_mut(&mut self) -> MassIterMut<'_, Domain, F> { |
| |
89 self.iter_spikes_mut().map(DeltaMeasure::get_mass_mut) |
| |
90 } |
| |
91 |
| |
92 /// Update the masses of all the spikes to those produced by an iterator. |
| |
93 #[inline] |
| |
94 pub fn set_masses<I : Iterator<Item=F>>(&mut self, iter : I) { |
| |
95 self.spikes.iter_mut().zip(iter).for_each(|(δ, α)| δ.set_mass(α)); |
| |
96 } |
| |
97 |
| |
98 // /// Map the masses of all the spikes using a function and an iterator |
| |
99 // #[inline] |
| |
100 // pub fn zipmap_masses< |
| |
101 // I : Iterator<Item=F>, |
| |
102 // G : Fn(F, I::Item) -> F |
| |
103 // > (&mut self, iter : I, g : G) { |
| |
104 // self.spikes.iter_mut().zip(iter).for_each(|(δ, v)| δ.set_mass(g(δ.get_mass(), v))); |
| |
105 // } |
| |
106 |
| |
107 /// Prune all spikes with zero mass. |
| |
108 #[inline] |
| |
109 pub fn prune(&mut self) { |
| |
110 self.spikes.retain(|δ| δ.α != F::ZERO); |
| |
111 } |
| |
112 } |
| |
113 |
| |
114 impl<Domain : Clone, F : Float> DiscreteMeasure<Domain, F> { |
| |
115 /// Computes `μ1 ← θ * μ1 - ζ * μ2`, pruning entries where both `μ1` (`self`) and `μ2` have |
| |
116 // zero weight. `μ2` will contain copy of pruned original `μ1` without arithmetic performed. |
| |
117 /// **This expects `self` and `μ2` to have matching coordinates in each index**. |
| |
118 // `μ2` can be than `self`, but not longer. |
| |
119 pub fn pruning_sub(&mut self, θ : F, ζ : F, μ2 : &mut Self) { |
| |
120 let mut μ2_get = 0; |
| |
121 let mut μ2_insert = 0; |
| |
122 self.spikes.drain_filter(|&mut DeltaMeasure{ α : ref mut α_ref, ref x }| { |
| |
123 // Get weight of spike in μ2, zero if out of bounds. |
| |
124 let β = μ2.spikes.get(μ2_get).map_or(F::ZERO, DeltaMeasure::get_mass); |
| |
125 μ2_get += 1; |
| |
126 |
| |
127 if *α_ref == F::ZERO && β == F::ZERO { |
| |
128 // Prune |
| |
129 true |
| |
130 } else { |
| |
131 // Save self weight |
| |
132 let α = *α_ref; |
| |
133 // Modify self |
| |
134 *α_ref = θ * α - ζ * β; |
| |
135 // Make copy of old self weight in μ2 |
| |
136 let δ = DeltaMeasure{ α, x : x.clone() }; |
| |
137 match μ2.spikes.get_mut(μ2_insert) { |
| |
138 Some(replace) => { |
| |
139 *replace = δ; |
| |
140 }, |
| |
141 None => { |
| |
142 debug_assert_eq!(μ2.len(), μ2_insert); |
| |
143 μ2.spikes.push(δ); |
| |
144 }, |
| |
145 } |
| |
146 μ2_insert += 1; |
| |
147 // Keep |
| |
148 false |
| |
149 } |
| |
150 }); |
| |
151 // Truncate μ2 to same length as self. |
| |
152 μ2.spikes.truncate(μ2_insert); |
| |
153 debug_assert_eq!(μ2.len(), self.len()); |
| |
154 } |
| |
155 } |
| |
156 |
| |
157 impl<Domain, F : Float> DiscreteMeasure<Domain, F> { |
| |
158 /// Prune all spikes with mass absolute value less than the given `tolerance`. |
| |
159 #[inline] |
| |
160 pub fn prune_approx(&mut self, tolerance : F) { |
| |
161 self.spikes.retain(|δ| δ.α.abs() > tolerance); |
| |
162 } |
| |
163 } |
| |
164 |
| |
165 impl<Domain, F : Float + ToNalgebraRealField> DiscreteMeasure<Domain, F> { |
| |
166 /// Extracts the masses of the spikes as a [`DVector`]. |
| |
167 pub fn masses_dvector(&self) -> DVector<F::MixedType> { |
| |
168 DVector::from_iterator(self.len(), |
| |
169 self.iter_masses() |
| |
170 .map(|α| α.to_nalgebra_mixed())) |
| |
171 } |
| |
172 |
| |
173 /// Sets the masses of the spikes from the values of a [`DVector`]. |
| |
174 pub fn set_masses_dvector(&mut self, x : &DVector<F::MixedType>) { |
| |
175 self.set_masses(x.iter().map(|&α| F::from_nalgebra_mixed(α))); |
| |
176 } |
| |
177 } |
| |
178 |
| |
179 impl<Domain, F :Num> Index<usize> for DiscreteMeasure<Domain, F> { |
| |
180 type Output = DeltaMeasure<Domain, F>; |
| |
181 #[inline] |
| |
182 fn index(&self, i : usize) -> &Self::Output { |
| |
183 self.spikes.index(i) |
| |
184 } |
| |
185 } |
| |
186 |
| |
187 impl<Domain, F :Num> IndexMut<usize> for DiscreteMeasure<Domain, F> { |
| |
188 #[inline] |
| |
189 fn index_mut(&mut self, i : usize) -> &mut Self::Output { |
| |
190 self.spikes.index_mut(i) |
| |
191 } |
| |
192 } |
| |
193 |
| |
194 impl<Domain, F : Num, D : Into<DeltaMeasure<Domain, F>>, const K : usize> From<[D; K]> |
| |
195 for DiscreteMeasure<Domain, F> { |
| |
196 #[inline] |
| |
197 fn from(list : [D; K]) -> Self { |
| |
198 list.into_iter().collect() |
| |
199 } |
| |
200 } |
| |
201 |
| |
202 impl<Domain, F : Num, D : Into<DeltaMeasure<Domain, F>>> FromIterator<D> |
| |
203 for DiscreteMeasure<Domain, F> { |
| |
204 #[inline] |
| |
205 fn from_iter<T>(iter : T) -> Self |
| |
206 where T : IntoIterator<Item=D> { |
| |
207 DiscreteMeasure{ |
| |
208 spikes : iter.into_iter().map(|m| m.into()).collect() |
| |
209 } |
| |
210 } |
| |
211 } |
| |
212 |
| |
213 impl<'a, F : Num, const N : usize> TableDump<'a> |
| |
214 for DiscreteMeasure<Loc<F, N>,F> |
| |
215 where DeltaMeasure<Loc<F, N>, F> : Serialize + 'a { |
| |
216 type Iter = std::slice::Iter<'a, DeltaMeasure<Loc<F, N>, F>>; |
| |
217 |
| |
218 // fn tabledump_headers(&'a self) -> Vec<String> { |
| |
219 // let mut v : Vec<String> = (0..N).map(|i| format!("x{}", i)).collect(); |
| |
220 // v.push("weight".into()); |
| |
221 // v |
| |
222 // } |
| |
223 |
| |
224 fn tabledump_entries(&'a self) -> Self::Iter { |
| |
225 // Ensure order matching the headers above |
| |
226 self.spikes.iter() |
| |
227 } |
| |
228 } |
| |
229 |
| |
230 // Need to manually implement serialisation for DeltaMeasure<Loc<F, N>, F> [`csv`] writer fails on |
| |
231 // structs with nested arrays as well as with #[serde(flatten)]. |
| |
232 // Then derive no longer works for DiscreteMeasure |
| |
233 impl<F : Num, const N : usize> Serialize for DiscreteMeasure<Loc<F, N>, F> |
| |
234 where |
| |
235 F: Serialize, |
| |
236 { |
| |
237 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> |
| |
238 where |
| |
239 S: Serializer, |
| |
240 { |
| |
241 let mut s = serializer.serialize_seq(Some(self.spikes.len()))?; |
| |
242 for δ in self.spikes.iter() { |
| |
243 s.serialize_element(δ)?; |
| |
244 } |
| |
245 s.end() |
| |
246 } |
| |
247 } |
| |
248 |
| |
249 impl<Domain : PartialEq, F : Float> Measure<F> for DiscreteMeasure<Domain, F> { |
| |
250 type Domain = Domain; |
| |
251 } |
| |
252 |
| |
253 impl<Domain : PartialEq, F : Float> Norm<F, Radon> for DiscreteMeasure<Domain, F> |
| |
254 where DeltaMeasure<Domain, F> : Norm<F, Radon> { |
| |
255 #[inline] |
| |
256 fn norm(&self, _ : Radon) -> F { |
| |
257 self.spikes.iter().map(|m| m.norm(Radon)).sum() |
| |
258 } |
| |
259 } |
| |
260 |
| |
261 impl<Domain, G, F : Num, Y : Sum + Mul<F, Output=Y>> Apply<G> for DiscreteMeasure<Domain, F> |
| |
262 where G: for<'a> Apply<&'a Domain, Output = Y> { |
| |
263 type Output = Y; |
| |
264 #[inline] |
| |
265 fn apply(&self, g : G) -> Y { |
| |
266 self.spikes.iter().map(|m| g.apply(&m.x) * m.α).sum() |
| |
267 } |
| |
268 } |
| |
269 |
| |
270 impl<Domain, G, F : Num, Y : Sum + Mul<F, Output=Y>> Linear<G> for DiscreteMeasure<Domain, F> |
| |
271 where G : for<'a> Apply<&'a Domain, Output = Y> { |
| |
272 type Codomain = Y; |
| |
273 } |
| |
274 |
| |
275 |
| |
276 /// Helper trait for constructing arithmetic operations for combinations |
| |
277 /// of [`DiscreteMeasure`] and [`DeltaMeasure`], and their references. |
| |
278 trait Lift<F : Num, Domain> { |
| |
279 type Producer : Iterator<Item=DeltaMeasure<Domain, F>>; |
| |
280 |
| |
281 /// Lifts `self` into a [`DiscreteMeasure`]. |
| |
282 fn lift(self) -> DiscreteMeasure<Domain, F>; |
| |
283 |
| |
284 /// Lifts `self` into a [`DiscreteMeasure`], apply either `f` or `f_mut` whether the type |
| |
285 /// this method is implemented for is a reference or or not. |
| |
286 fn lift_with(self, |
| |
287 f : impl Fn(&DeltaMeasure<Domain, F>) -> DeltaMeasure<Domain, F>, |
| |
288 f_mut : impl FnMut(&mut DeltaMeasure<Domain, F>)) |
| |
289 -> DiscreteMeasure<Domain, F>; |
| |
290 |
| |
291 /// Extend `self` into a [`DiscreteMeasure`] with the spikes produced by `iter`. |
| |
292 fn lift_extend<I : Iterator<Item=DeltaMeasure<Domain, F>>>( |
| |
293 self, |
| |
294 iter : I |
| |
295 ) -> DiscreteMeasure<Domain, F>; |
| |
296 |
| |
297 /// Returns an iterator for producing copies of the spikes of `self`. |
| |
298 fn produce(self) -> Self::Producer; |
| |
299 } |
| |
300 |
| |
301 impl<F : Num, Domain> Lift<F, Domain> for DiscreteMeasure<Domain, F> { |
| |
302 type Producer = std::vec::IntoIter<DeltaMeasure<Domain, F>>; |
| |
303 |
| |
304 #[inline] |
| |
305 fn lift(self) -> DiscreteMeasure<Domain, F> { self } |
| |
306 |
| |
307 fn lift_with(mut self, |
| |
308 _f : impl Fn(&DeltaMeasure<Domain, F>) -> DeltaMeasure<Domain, F>, |
| |
309 f_mut : impl FnMut(&mut DeltaMeasure<Domain, F>)) |
| |
310 -> DiscreteMeasure<Domain, F> { |
| |
311 self.spikes.iter_mut().for_each(f_mut); |
| |
312 self |
| |
313 } |
| |
314 |
| |
315 #[inline] |
| |
316 fn lift_extend<I : Iterator<Item=DeltaMeasure<Domain, F>>>( |
| |
317 mut self, |
| |
318 iter : I |
| |
319 ) -> DiscreteMeasure<Domain, F> { |
| |
320 self.spikes.extend(iter); |
| |
321 self |
| |
322 } |
| |
323 |
| |
324 #[inline] |
| |
325 fn produce(self) -> Self::Producer { |
| |
326 self.spikes.into_iter() |
| |
327 } |
| |
328 } |
| |
329 |
| |
330 impl<'a, F : Num, Domain : Clone> Lift<F, Domain> for &'a DiscreteMeasure<Domain, F> { |
| |
331 type Producer = MapF<std::slice::Iter<'a, DeltaMeasure<Domain, F>>, DeltaMeasure<Domain, F>>; |
| |
332 |
| |
333 #[inline] |
| |
334 fn lift(self) -> DiscreteMeasure<Domain, F> { self.clone() } |
| |
335 |
| |
336 fn lift_with(self, |
| |
337 f : impl Fn(&DeltaMeasure<Domain, F>) -> DeltaMeasure<Domain, F>, |
| |
338 _f_mut : impl FnMut(&mut DeltaMeasure<Domain, F>)) |
| |
339 -> DiscreteMeasure<Domain, F> { |
| |
340 DiscreteMeasure{ spikes : self.spikes.iter().map(f).collect() } |
| |
341 } |
| |
342 |
| |
343 #[inline] |
| |
344 fn lift_extend<I : Iterator<Item=DeltaMeasure<Domain, F>>>( |
| |
345 self, |
| |
346 iter : I |
| |
347 ) -> DiscreteMeasure<Domain, F> { |
| |
348 let mut res = self.clone(); |
| |
349 res.spikes.extend(iter); |
| |
350 res |
| |
351 } |
| |
352 |
| |
353 #[inline] |
| |
354 fn produce(self) -> Self::Producer { |
| |
355 // TODO: maybe not optimal to clone here and would benefit from |
| |
356 // a reference version of lift_extend. |
| |
357 self.spikes.iter().mapF(Clone::clone) |
| |
358 } |
| |
359 } |
| |
360 |
| |
361 impl<F : Num, Domain> Lift<F, Domain> for DeltaMeasure<Domain, F> { |
| |
362 type Producer = std::iter::Once<DeltaMeasure<Domain, F>>; |
| |
363 |
| |
364 #[inline] |
| |
365 fn lift(self) -> DiscreteMeasure<Domain, F> { DiscreteMeasure { spikes : vec![self] } } |
| |
366 |
| |
367 #[inline] |
| |
368 fn lift_with(mut self, |
| |
369 _f : impl Fn(&DeltaMeasure<Domain, F>) -> DeltaMeasure<Domain, F>, |
| |
370 mut f_mut : impl FnMut(&mut DeltaMeasure<Domain, F>)) |
| |
371 -> DiscreteMeasure<Domain, F> { |
| |
372 f_mut(&mut self); |
| |
373 DiscreteMeasure{ spikes : vec![self] } |
| |
374 } |
| |
375 |
| |
376 #[inline] |
| |
377 fn lift_extend<I : Iterator<Item=DeltaMeasure<Domain, F>>>( |
| |
378 self, |
| |
379 iter : I |
| |
380 ) -> DiscreteMeasure<Domain, F> { |
| |
381 let mut spikes = vec![self]; |
| |
382 spikes.extend(iter); |
| |
383 DiscreteMeasure{ spikes : spikes } |
| |
384 } |
| |
385 |
| |
386 #[inline] |
| |
387 fn produce(self) -> Self::Producer { |
| |
388 std::iter::once(self) |
| |
389 } |
| |
390 } |
| |
391 |
| |
392 impl<'a, F : Num, Domain : Clone> Lift<F, Domain> for &'a DeltaMeasure<Domain, F> { |
| |
393 type Producer = std::iter::Once<DeltaMeasure<Domain, F>>; |
| |
394 |
| |
395 #[inline] |
| |
396 fn lift(self) -> DiscreteMeasure<Domain, F> { DiscreteMeasure { spikes : vec![self.clone()] } } |
| |
397 |
| |
398 #[inline] |
| |
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 DiscreteMeasure{ spikes : vec![f(self)] } |
| |
404 } |
| |
405 |
| |
406 #[inline] |
| |
407 fn lift_extend<I : Iterator<Item=DeltaMeasure<Domain, F>>>( |
| |
408 self, |
| |
409 iter : I |
| |
410 ) -> DiscreteMeasure<Domain, F> { |
| |
411 let mut spikes = vec![self.clone()]; |
| |
412 spikes.extend(iter); |
| |
413 DiscreteMeasure{ spikes : spikes } |
| |
414 } |
| |
415 |
| |
416 #[inline] |
| |
417 fn produce(self) -> Self::Producer { |
| |
418 std::iter::once(self.clone()) |
| |
419 } |
| |
420 } |
| |
421 |
| |
422 macro_rules! make_discrete_addsub_assign { |
| |
423 ($rhs:ty) => { |
| |
424 // Discrete += (&)Discrete |
| |
425 impl<'a, F : Num, Domain : Clone> AddAssign<$rhs> |
| |
426 for DiscreteMeasure<Domain, F> { |
| |
427 fn add_assign(&mut self, other : $rhs) { |
| |
428 self.spikes.extend(other.produce()); |
| |
429 } |
| |
430 } |
| |
431 |
| |
432 impl<'a, F : Num + Neg<Output=F>, Domain : Clone> SubAssign<$rhs> |
| |
433 for DiscreteMeasure<Domain, F> { |
| |
434 fn sub_assign(&mut self, other : $rhs) { |
| |
435 self.spikes.extend(other.produce().map(|δ| -δ)); |
| |
436 } |
| |
437 } |
| |
438 } |
| |
439 } |
| |
440 |
| |
441 make_discrete_addsub_assign!(DiscreteMeasure<Domain, F>); |
| |
442 make_discrete_addsub_assign!(&'a DiscreteMeasure<Domain, F>); |
| |
443 make_discrete_addsub_assign!(DeltaMeasure<Domain, F>); |
| |
444 make_discrete_addsub_assign!(&'a DeltaMeasure<Domain, F>); |
| |
445 |
| |
446 macro_rules! make_discrete_addsub { |
| |
447 ($lhs:ty, $rhs:ty, $alt_order:expr) => { |
| |
448 impl<'a, 'b, F : Num, Domain : Clone> Add<$rhs> for $lhs { |
| |
449 type Output = DiscreteMeasure<Domain, F>; |
| |
450 fn add(self, other : $rhs) -> DiscreteMeasure<Domain, F> { |
| |
451 if !$alt_order { |
| |
452 self.lift_extend(other.produce()) |
| |
453 } else { |
| |
454 other.lift_extend(self.produce()) |
| |
455 } |
| |
456 } |
| |
457 } |
| |
458 |
| |
459 impl<'a, 'b, F : Num + Neg<Output=F>, Domain : Clone> Sub<$rhs> for $lhs { |
| |
460 type Output = DiscreteMeasure<Domain, F>; |
| |
461 fn sub(self, other : $rhs) -> DiscreteMeasure<Domain, F> { |
| |
462 self.lift_extend(other.produce().map(|δ| -δ)) |
| |
463 } |
| |
464 } |
| |
465 }; |
| |
466 } |
| |
467 |
| |
468 make_discrete_addsub!(DiscreteMeasure<Domain, F>, DiscreteMeasure<Domain, F>, false); |
| |
469 make_discrete_addsub!(DiscreteMeasure<Domain, F>, &'b DiscreteMeasure<Domain, F>, false); |
| |
470 make_discrete_addsub!(&'a DiscreteMeasure<Domain, F>, DiscreteMeasure<Domain, F>, true); |
| |
471 make_discrete_addsub!(&'a DiscreteMeasure<Domain, F>, &'b DiscreteMeasure<Domain, F>, false); |
| |
472 make_discrete_addsub!(DeltaMeasure<Domain, F>, DiscreteMeasure<Domain, F>, false); |
| |
473 make_discrete_addsub!(DeltaMeasure<Domain, F>, &'b DiscreteMeasure<Domain, F>, false); |
| |
474 make_discrete_addsub!(&'a DeltaMeasure<Domain, F>, DiscreteMeasure<Domain, F>, true); |
| |
475 make_discrete_addsub!(&'a DeltaMeasure<Domain, F>, &'b DiscreteMeasure<Domain, F>, false); |
| |
476 make_discrete_addsub!(DiscreteMeasure<Domain, F>, DeltaMeasure<Domain, F>, false); |
| |
477 make_discrete_addsub!(DiscreteMeasure<Domain, F>, &'b DeltaMeasure<Domain, F>, false); |
| |
478 make_discrete_addsub!(&'a DiscreteMeasure<Domain, F>, DeltaMeasure<Domain, F>, false); |
| |
479 make_discrete_addsub!(&'a DiscreteMeasure<Domain, F>, &'b DeltaMeasure<Domain, F>, false); |
| |
480 make_discrete_addsub!(DeltaMeasure<Domain, F>, DeltaMeasure<Domain, F>, false); |
| |
481 make_discrete_addsub!(DeltaMeasure<Domain, F>, &'b DeltaMeasure<Domain, F>, false); |
| |
482 make_discrete_addsub!(&'a DeltaMeasure<Domain, F>, DeltaMeasure<Domain, F>, false); |
| |
483 make_discrete_addsub!(&'a DeltaMeasure<Domain, F>, &'b DeltaMeasure<Domain, F>, false); |
| |
484 |
| |
485 macro_rules! make_discrete_scalarop_rhs { |
| |
486 ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { |
| |
487 make_discrete_scalarop_rhs!(@assign DiscreteMeasure<Domain, F>, F, $trait_assign, $fn_assign); |
| |
488 make_discrete_scalarop_rhs!(@assign DiscreteMeasure<Domain, F>, &'a F, $trait_assign, $fn_assign); |
| |
489 make_discrete_scalarop_rhs!(@new DiscreteMeasure<Domain, F>, F, $trait, $fn, $fn_assign); |
| |
490 make_discrete_scalarop_rhs!(@new DiscreteMeasure<Domain, F>, &'a F, $trait, $fn, $fn_assign); |
| |
491 make_discrete_scalarop_rhs!(@new &'b DiscreteMeasure<Domain, F>, F, $trait, $fn, $fn_assign); |
| |
492 make_discrete_scalarop_rhs!(@new &'b DiscreteMeasure<Domain, F>, &'a F, $trait, $fn, $fn_assign); |
| |
493 }; |
| |
494 |
| |
495 (@assign $lhs:ty, $rhs:ty, $trait_assign:ident, $fn_assign:ident) => { |
| |
496 impl<'a, 'b, F : Num, Domain> $trait_assign<$rhs> for $lhs { |
| |
497 fn $fn_assign(&mut self, b : $rhs) { |
| |
498 self.spikes.iter_mut().for_each(|δ| δ.$fn_assign(b)); |
| |
499 } |
| |
500 } |
| |
501 }; |
| |
502 (@new $lhs:ty, $rhs:ty, $trait:ident, $fn:ident, $fn_assign:ident) => { |
| |
503 impl<'a, 'b, F : Num, Domain : Clone> $trait<$rhs> for $lhs { |
| |
504 type Output = DiscreteMeasure<Domain, F>; |
| |
505 fn $fn(self, b : $rhs) -> Self::Output { |
| |
506 self.lift_with(|δ| δ.$fn(b), |δ| δ.$fn_assign(b)) |
| |
507 } |
| |
508 } |
| |
509 }; |
| |
510 } |
| |
511 |
| |
512 make_discrete_scalarop_rhs!(Mul, mul, MulAssign, mul_assign); |
| |
513 make_discrete_scalarop_rhs!(Div, div, DivAssign, div_assign); |
| |
514 |
| |
515 macro_rules! make_discrete_unary { |
| |
516 ($trait:ident, $fn:ident, $type:ty) => { |
| |
517 impl<'a, F : Num + Neg<Output=F>, Domain : Clone> Neg for $type { |
| |
518 type Output = DiscreteMeasure<Domain, F>; |
| |
519 fn $fn(self) -> Self::Output { |
| |
520 self.lift_with(|δ| δ.$fn(), |δ| δ.α = δ.α.$fn()) |
| |
521 } |
| |
522 } |
| |
523 } |
| |
524 } |
| |
525 |
| |
526 make_discrete_unary!(Neg, neg, DiscreteMeasure<Domain, F>); |
| |
527 make_discrete_unary!(Neg, neg, &'a DiscreteMeasure<Domain, F>); |
| |
528 |
| |
529 // impl<F : Num, Domain> Neg for DiscreteMeasure<Domain, F> { |
| |
530 // type Output = Self; |
| |
531 // fn $fn(mut self, b : F) -> Self { |
| |
532 // self.lift().spikes.iter_mut().for_each(|δ| δ.neg(b)); |
| |
533 // self |
| |
534 // } |
| |
535 // } |
| |
536 |
| |
537 macro_rules! make_discrete_scalarop_lhs { |
| |
538 ($trait:ident, $fn:ident; $($f:ident)+) => { $( |
| |
539 impl<Domain> $trait<DiscreteMeasure<Domain, $f>> for $f { |
| |
540 type Output = DiscreteMeasure<Domain, $f>; |
| |
541 fn $fn(self, mut v : DiscreteMeasure<Domain, $f>) -> Self::Output { |
| |
542 v.spikes.iter_mut().for_each(|δ| δ.α = self.$fn(δ.α)); |
| |
543 v |
| |
544 } |
| |
545 } |
| |
546 |
| |
547 impl<'a, Domain : Copy> $trait<&'a DiscreteMeasure<Domain, $f>> for $f { |
| |
548 type Output = DiscreteMeasure<Domain, $f>; |
| |
549 fn $fn(self, v : &'a DiscreteMeasure<Domain, $f>) -> Self::Output { |
| |
550 DiscreteMeasure{ |
| |
551 spikes : v.spikes.iter().map(|δ| self.$fn(δ)).collect() |
| |
552 } |
| |
553 } |
| |
554 } |
| |
555 |
| |
556 impl<'b, Domain> $trait<DiscreteMeasure<Domain, $f>> for &'b $f { |
| |
557 type Output = DiscreteMeasure<Domain, $f>; |
| |
558 fn $fn(self, mut v : DiscreteMeasure<Domain, $f>) -> Self::Output { |
| |
559 v.spikes.iter_mut().for_each(|δ| δ.α = self.$fn(δ.α)); |
| |
560 v |
| |
561 } |
| |
562 } |
| |
563 |
| |
564 impl<'a, 'b, Domain : Copy> $trait<&'a DiscreteMeasure<Domain, $f>> for &'b $f { |
| |
565 type Output = DiscreteMeasure<Domain, $f>; |
| |
566 fn $fn(self, v : &'a DiscreteMeasure<Domain, $f>) -> Self::Output { |
| |
567 DiscreteMeasure{ |
| |
568 spikes : v.spikes.iter().map(|δ| self.$fn(δ)).collect() |
| |
569 } |
| |
570 } |
| |
571 } |
| |
572 )+ } |
| |
573 } |
| |
574 |
| |
575 make_discrete_scalarop_lhs!(Mul, mul; f32 f64 i8 i16 i32 i64 isize u8 u16 u32 u64 usize); |
| |
576 make_discrete_scalarop_lhs!(Div, div; f32 f64 i8 i16 i32 i64 isize u8 u16 u32 u64 usize); |