src/measures/discrete.rs

changeset 0
eb3c7813b67a
child 4
5aa5c279e341
equal deleted inserted replaced
-1:000000000000 0:eb3c7813b67a
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);

mercurial