Sun, 26 Jan 2025 11:58:02 -0500
Fixes to Radon norm prox term inner algorithm
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; | |
35 | 14 | use alg_tools::linops::{Mapping, Linear}; |
0 | 15 | use alg_tools::iter::{MapF,Mappable}; |
16 | use alg_tools::nalgebra_support::ToNalgebraRealField; | |
35 | 17 | use alg_tools::collection::Collection; |
18 | use alg_tools::instance::{Instance, Decomposition, MyCow, EitherDecomp, Space}; | |
0 | 19 | |
20 | use crate::types::*; | |
21 | use super::base::*; | |
22 | use super::delta::*; | |
23 | ||
24 | /// Representation of a discrete measure. | |
25 | /// | |
26 | /// This is the measure $μ = ∑_{k=1}^n α_k δ_{x_k}$, consisting of several | |
27 | /// [`DeltaMeasure`], i.e., “spikes” $α_k δ_{x_k}$ with weights $\alpha_k$ in `F` at locations | |
28 | /// $x_k$ in `Domain`. | |
29 | #[derive(Clone,Debug)] | |
30 | pub struct DiscreteMeasure<Domain, F : Num> { | |
31 | pub(super) spikes : Vec<DeltaMeasure<Domain, F>>, | |
32 | } | |
33 | ||
35 | 34 | pub type RNDM<F, const N : usize> = DiscreteMeasure<Loc<F, N>, F>; |
35 | ||
0 | 36 | /// Iterator over the [`DeltaMeasure`] spikes of a [`DiscreteMeasure`]. |
37 | pub type SpikeIter<'a, Domain, F> = std::slice::Iter<'a, DeltaMeasure<Domain, F>>; | |
38 | ||
39 | /// Iterator over mutable [`DeltaMeasure`] spikes of a [`DiscreteMeasure`]. | |
40 | pub type SpikeIterMut<'a, Domain, F> = std::slice::IterMut<'a, DeltaMeasure<Domain, F>>; | |
41 | ||
42 | /// Iterator over the locations of the spikes of a [`DiscreteMeasure`]. | |
43 | pub type LocationIter<'a, Domain, F> | |
44 | = std::iter::Map<SpikeIter<'a, Domain, F>, fn(&'a DeltaMeasure<Domain, F>) -> &'a Domain>; | |
45 | ||
46 | /// Iterator over the masses of the spikes of a [`DiscreteMeasure`]. | |
47 | pub type MassIter<'a, Domain, F> | |
48 | = std::iter::Map<SpikeIter<'a, Domain, F>, fn(&'a DeltaMeasure<Domain, F>) -> F>; | |
49 | ||
50 | /// Iterator over the mutable locations of the spikes of a [`DiscreteMeasure`]. | |
51 | pub type MassIterMut<'a, Domain, F> | |
52 | = std::iter::Map<SpikeIterMut<'a, Domain, F>, for<'r> fn(&'r mut DeltaMeasure<Domain, F>) -> &'r mut F>; | |
53 | ||
54 | impl<Domain, F : Num> DiscreteMeasure<Domain, F> { | |
55 | /// Create a new zero measure (empty spike set). | |
56 | pub fn new() -> Self { | |
57 | DiscreteMeasure{ spikes : Vec::new() } | |
58 | } | |
59 | ||
60 | /// Number of [`DeltaMeasure`] spikes in the measure | |
61 | #[inline] | |
62 | pub fn len(&self) -> usize { | |
63 | self.spikes.len() | |
64 | } | |
65 | ||
32 | 66 | /// Replace with the zero measure. |
67 | #[inline] | |
68 | pub fn clear(&mut self) { | |
69 | self.spikes.clear() | |
70 | } | |
71 | ||
72 | /// Remove `i`:th spike, not maintaining order. | |
73 | /// | |
74 | /// Panics if indiex is out of bounds. | |
75 | #[inline] | |
76 | pub fn swap_remove(&mut self, i : usize) -> DeltaMeasure<Domain, F>{ | |
77 | self.spikes.swap_remove(i) | |
78 | } | |
79 | ||
0 | 80 | /// Iterate over (references to) the [`DeltaMeasure`] spikes in this measure |
81 | #[inline] | |
82 | pub fn iter_spikes(&self) -> SpikeIter<'_, Domain, F> { | |
83 | self.spikes.iter() | |
84 | } | |
85 | ||
86 | /// Iterate over mutable references to the [`DeltaMeasure`] spikes in this measure | |
87 | #[inline] | |
88 | pub fn iter_spikes_mut(&mut self) -> SpikeIterMut<'_, Domain, F> { | |
89 | self.spikes.iter_mut() | |
90 | } | |
91 | ||
92 | /// Iterate over the location of the spikes in this measure | |
93 | #[inline] | |
94 | pub fn iter_locations(&self) -> LocationIter<'_, Domain, F> { | |
95 | self.iter_spikes().map(DeltaMeasure::get_location) | |
96 | } | |
97 | ||
98 | /// Iterate over the masses of the spikes in this measure | |
99 | #[inline] | |
100 | pub fn iter_masses(&self) -> MassIter<'_, Domain, F> { | |
101 | self.iter_spikes().map(DeltaMeasure::get_mass) | |
102 | } | |
103 | ||
104 | /// Iterate over the masses of the spikes in this measure | |
105 | #[inline] | |
106 | pub fn iter_masses_mut(&mut self) -> MassIterMut<'_, Domain, F> { | |
107 | self.iter_spikes_mut().map(DeltaMeasure::get_mass_mut) | |
108 | } | |
109 | ||
110 | /// Update the masses of all the spikes to those produced by an iterator. | |
111 | #[inline] | |
112 | pub fn set_masses<I : Iterator<Item=F>>(&mut self, iter : I) { | |
113 | self.spikes.iter_mut().zip(iter).for_each(|(δ, α)| δ.set_mass(α)); | |
114 | } | |
115 | ||
35 | 116 | /// Update the locations of all the spikes to those produced by an iterator. |
117 | #[inline] | |
118 | pub fn set_locations<'a, I : Iterator<Item=&'a Domain>>(&mut self, iter : I) | |
119 | where Domain : 'static + Clone { | |
120 | self.spikes.iter_mut().zip(iter.cloned()).for_each(|(δ, α)| δ.set_location(α)); | |
121 | } | |
122 | ||
0 | 123 | // /// Map the masses of all the spikes using a function and an iterator |
124 | // #[inline] | |
125 | // pub fn zipmap_masses< | |
126 | // I : Iterator<Item=F>, | |
127 | // G : Fn(F, I::Item) -> F | |
128 | // > (&mut self, iter : I, g : G) { | |
129 | // self.spikes.iter_mut().zip(iter).for_each(|(δ, v)| δ.set_mass(g(δ.get_mass(), v))); | |
130 | // } | |
131 | ||
132 | /// Prune all spikes with zero mass. | |
133 | #[inline] | |
134 | pub fn prune(&mut self) { | |
34
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
135 | self.prune_by(|δ| δ.α != F::ZERO); |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
136 | } |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
137 | |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
138 | /// Prune spikes by the predicate `g`. |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
139 | #[inline] |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
140 | 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
|
141 | self.spikes.retain(g); |
0 | 142 | } |
32 | 143 | |
144 | /// Add the spikes produced by `iter` to this measure. | |
145 | #[inline] | |
146 | pub fn extend<I : Iterator<Item=DeltaMeasure<Domain, F>>>( | |
147 | &mut self, | |
148 | iter : I | |
149 | ) { | |
150 | self.spikes.extend(iter); | |
151 | } | |
152 | ||
153 | /// Add a spike to the measure | |
154 | #[inline] | |
155 | pub fn push(&mut self, δ : DeltaMeasure<Domain, F>) { | |
156 | self.spikes.push(δ); | |
157 | } | |
34
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
158 | |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
159 | /// 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
|
160 | /// to have equal locations of same spike indices. |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
161 | 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
|
162 | impl Iterator<Item=(F, F, &'a Domain)> { |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
163 | let m = self.len().max(other.len()); |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
164 | self.iter_spikes().map(Some).chain(std::iter::repeat(None)) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
165 | .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
|
166 | .take(m) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
167 | .map(|(oδ, orδ)| { |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
168 | match (oδ, orδ) { |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
169 | (Some(δ), Some(rδ)) => (δ.α, rδ.α, &δ.x), // Assumed δ.x=rδ.x |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
170 | (Some(δ), None) => (δ.α, F::ZERO, &δ.x), |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
171 | (None, Some(rδ)) => (F::ZERO, rδ.α, &rδ.x), |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
172 | (None, None) => panic!("This cannot happen!"), |
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 | }) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
175 | } |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
176 | |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
177 | /// 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
|
178 | 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
|
179 | where Domain : Clone { |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
180 | self.both_matching(other) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
181 | .map(|(α, β, x)| (x.clone(), α - β)) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
182 | .collect() |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
183 | } |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
184 | |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
185 | /// 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
|
186 | 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
|
187 | where Domain : Clone { |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
188 | self.both_matching(other) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
189 | .map(|(α, β, x)| (x.clone(), α + β)) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
190 | .collect() |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
191 | } |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
192 | |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
193 | /// Calculate the Radon-norm distance of `self` to `other`, |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
194 | /// assuming equal locations of same spike indices. |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
195 | 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
|
196 | self.both_matching(other) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
197 | .map(|(α, β, _)| (α-β).abs()) |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
198 | .sum() |
efa60bc4f743
Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
32
diff
changeset
|
199 | } |
32 | 200 | } |
201 | ||
202 | impl<Domain, F : Num> IntoIterator for DiscreteMeasure<Domain, F> { | |
203 | type Item = DeltaMeasure<Domain, F>; | |
35 | 204 | type IntoIter = std::vec::IntoIter<DeltaMeasure<Domain, F>>; |
32 | 205 | |
206 | #[inline] | |
207 | fn into_iter(self) -> Self::IntoIter { | |
208 | self.spikes.into_iter() | |
209 | } | |
0 | 210 | } |
211 | ||
35 | 212 | impl<'a, Domain, F : Num> IntoIterator for &'a DiscreteMeasure<Domain, F> { |
213 | type Item = &'a DeltaMeasure<Domain, F>; | |
214 | type IntoIter = SpikeIter<'a, Domain, F>; | |
215 | ||
216 | #[inline] | |
217 | fn into_iter(self) -> Self::IntoIter { | |
218 | self.spikes.iter() | |
219 | } | |
220 | } | |
221 | ||
222 | impl<Domain, F : Num> Sum<DeltaMeasure<Domain, F>> for DiscreteMeasure<Domain, F> { | |
223 | // Required method | |
224 | fn sum<I>(iter: I) -> Self | |
225 | where | |
226 | I : Iterator<Item = DeltaMeasure<Domain, F>> | |
227 | { | |
228 | Self::from_iter(iter) | |
229 | } | |
230 | } | |
231 | ||
232 | impl<'a, Domain : Clone, F : Num> Sum<&'a DeltaMeasure<Domain, F>> | |
233 | for DiscreteMeasure<Domain, F> | |
234 | { | |
235 | // Required method | |
236 | fn sum<I>(iter: I) -> Self | |
237 | where | |
238 | I : Iterator<Item = &'a DeltaMeasure<Domain, F>> | |
239 | { | |
240 | Self::from_iter(iter.cloned()) | |
241 | } | |
242 | } | |
243 | ||
244 | impl<Domain, F : Num> Sum<DiscreteMeasure<Domain, F>> for DiscreteMeasure<Domain, F> { | |
245 | // Required method | |
246 | fn sum<I>(iter: I) -> Self | |
247 | where | |
248 | I : Iterator<Item = DiscreteMeasure<Domain, F>> | |
249 | { | |
250 | Self::from_iter(iter.map(|μ| μ.into_iter()).flatten()) | |
251 | } | |
252 | } | |
253 | ||
254 | impl<'a, Domain : Clone, F : Num> Sum<&'a DiscreteMeasure<Domain, F>> | |
255 | for DiscreteMeasure<Domain, F> | |
256 | { | |
257 | // Required method | |
258 | fn sum<I>(iter: I) -> Self | |
259 | where | |
260 | I : Iterator<Item = &'a DiscreteMeasure<Domain, F>> | |
261 | { | |
262 | Self::from_iter(iter.map(|μ| μ.iter_spikes()).flatten().cloned()) | |
263 | } | |
264 | } | |
265 | ||
0 | 266 | impl<Domain : Clone, F : Float> DiscreteMeasure<Domain, F> { |
267 | /// Computes `μ1 ← θ * μ1 - ζ * μ2`, pruning entries where both `μ1` (`self`) and `μ2` have | |
39
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
268 | // zero weight. `μ2` will contain a pruned copy of pruned original `μ1` without arithmetic |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
269 | /// performed. **This expects `self` and `μ2` to have matching coordinates in each index**. |
0 | 270 | // `μ2` can be than `self`, but not longer. |
271 | pub fn pruning_sub(&mut self, θ : F, ζ : F, μ2 : &mut Self) { | |
39
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
272 | for δ in &self[μ2.len()..] { |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
273 | μ2.push(DeltaMeasure{ x : δ.x.clone(), α : F::ZERO}); |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
274 | } |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
275 | debug_assert_eq!(self.len(), μ2.len()); |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
276 | let mut dest = 0; |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
277 | for i in 0..self.len() { |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
278 | let α = self[i].α; |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
279 | let α_new = θ * α - ζ * μ2[i].α; |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
280 | if dest < i { |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
281 | μ2[dest] = DeltaMeasure{ x : self[i].x.clone(), α }; |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
282 | self[dest] = DeltaMeasure{ x : self[i].x.clone(), α : α_new }; |
0 | 283 | } else { |
39
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
284 | μ2[i].α = α; |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
285 | self[i].α = α_new; |
0 | 286 | } |
39
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
287 | dest += 1; |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
288 | } |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
289 | self.spikes.truncate(dest); |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
290 | μ2.spikes.truncate(dest); |
0 | 291 | } |
292 | } | |
293 | ||
294 | impl<Domain, F : Float> DiscreteMeasure<Domain, F> { | |
295 | /// Prune all spikes with mass absolute value less than the given `tolerance`. | |
296 | #[inline] | |
297 | pub fn prune_approx(&mut self, tolerance : F) { | |
298 | self.spikes.retain(|δ| δ.α.abs() > tolerance); | |
299 | } | |
300 | } | |
301 | ||
302 | impl<Domain, F : Float + ToNalgebraRealField> DiscreteMeasure<Domain, F> { | |
303 | /// Extracts the masses of the spikes as a [`DVector`]. | |
304 | pub fn masses_dvector(&self) -> DVector<F::MixedType> { | |
305 | DVector::from_iterator(self.len(), | |
306 | self.iter_masses() | |
307 | .map(|α| α.to_nalgebra_mixed())) | |
308 | } | |
309 | ||
310 | /// Sets the masses of the spikes from the values of a [`DVector`]. | |
311 | pub fn set_masses_dvector(&mut self, x : &DVector<F::MixedType>) { | |
312 | self.set_masses(x.iter().map(|&α| F::from_nalgebra_mixed(α))); | |
313 | } | |
37
c5d8bd1a7728
Generic proximal penalty support
Tuomo Valkonen <tuomov@iki.fi>
parents:
35
diff
changeset
|
314 | |
39
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
315 | // /// Extracts the masses of the spikes as a [`Vec`]. |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
316 | // pub fn masses_vec(&self) -> Vec<F::MixedType> { |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
317 | // self.iter_masses() |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
318 | // .map(|α| α.to_nalgebra_mixed()) |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
319 | // .collect() |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
320 | // } |
37
c5d8bd1a7728
Generic proximal penalty support
Tuomo Valkonen <tuomov@iki.fi>
parents:
35
diff
changeset
|
321 | |
39
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
322 | // /// Sets the masses of the spikes from the values of a [`Vec`]. |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
323 | // pub fn set_masses_vec(&mut self, x : &Vec<F::MixedType>) { |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
324 | // self.set_masses(x.iter().map(|&α| F::from_nalgebra_mixed(α))); |
6316d68b58af
Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
37
diff
changeset
|
325 | // } |
0 | 326 | } |
327 | ||
32 | 328 | // impl<Domain, F :Num> Index<usize> for DiscreteMeasure<Domain, F> { |
329 | // type Output = DeltaMeasure<Domain, F>; | |
330 | // #[inline] | |
331 | // fn index(&self, i : usize) -> &Self::Output { | |
332 | // self.spikes.index(i) | |
333 | // } | |
334 | // } | |
335 | ||
336 | // impl<Domain, F :Num> IndexMut<usize> for DiscreteMeasure<Domain, F> { | |
337 | // #[inline] | |
338 | // fn index_mut(&mut self, i : usize) -> &mut Self::Output { | |
339 | // self.spikes.index_mut(i) | |
340 | // } | |
341 | // } | |
342 | ||
343 | impl< | |
344 | Domain, | |
345 | F : Num, | |
346 | I : std::slice::SliceIndex<[DeltaMeasure<Domain, F>]> | |
347 | > Index<I> | |
348 | for DiscreteMeasure<Domain, F> { | |
349 | type Output = <I as std::slice::SliceIndex<[DeltaMeasure<Domain, F>]>>::Output; | |
0 | 350 | #[inline] |
32 | 351 | fn index(&self, i : I) -> &Self::Output { |
0 | 352 | self.spikes.index(i) |
353 | } | |
354 | } | |
355 | ||
32 | 356 | impl< |
357 | Domain, | |
358 | F : Num, | |
359 | I : std::slice::SliceIndex<[DeltaMeasure<Domain, F>]> | |
360 | > IndexMut<I> | |
361 | for DiscreteMeasure<Domain, F> { | |
0 | 362 | #[inline] |
32 | 363 | fn index_mut(&mut self, i : I) -> &mut Self::Output { |
0 | 364 | self.spikes.index_mut(i) |
365 | } | |
366 | } | |
367 | ||
32 | 368 | |
0 | 369 | impl<Domain, F : Num, D : Into<DeltaMeasure<Domain, F>>, const K : usize> From<[D; K]> |
370 | for DiscreteMeasure<Domain, F> { | |
371 | #[inline] | |
372 | fn from(list : [D; K]) -> Self { | |
373 | list.into_iter().collect() | |
374 | } | |
375 | } | |
376 | ||
35 | 377 | impl<Domain, F : Num> From<Vec<DeltaMeasure<Domain, F>>> |
378 | for DiscreteMeasure<Domain, F> { | |
379 | #[inline] | |
380 | fn from(spikes : Vec<DeltaMeasure<Domain, F>>) -> Self { | |
381 | DiscreteMeasure{ spikes } | |
382 | } | |
383 | } | |
384 | ||
385 | impl<'a, Domain, F : Num, D> From<&'a [D]> | |
386 | for DiscreteMeasure<Domain, F> | |
387 | where &'a D : Into<DeltaMeasure<Domain, F>> { | |
388 | #[inline] | |
389 | fn from(list : &'a [D]) -> Self { | |
390 | list.into_iter().map(|d| d.into()).collect() | |
391 | } | |
392 | } | |
393 | ||
394 | ||
395 | impl<Domain, F : Num> From<DeltaMeasure<Domain, F>> | |
396 | for DiscreteMeasure<Domain, F> { | |
397 | #[inline] | |
398 | fn from(δ : DeltaMeasure<Domain, F>) -> Self { | |
399 | DiscreteMeasure{ | |
400 | spikes : vec!(δ) | |
401 | } | |
402 | } | |
403 | } | |
404 | ||
405 | impl<'a, Domain : Clone, F : Num> From<&'a DeltaMeasure<Domain, F>> | |
406 | for DiscreteMeasure<Domain, F> { | |
407 | #[inline] | |
408 | fn from(δ : &'a DeltaMeasure<Domain, F>) -> Self { | |
409 | DiscreteMeasure{ | |
410 | spikes : vec!(δ.clone()) | |
411 | } | |
412 | } | |
413 | } | |
414 | ||
415 | ||
0 | 416 | impl<Domain, F : Num, D : Into<DeltaMeasure<Domain, F>>> FromIterator<D> |
417 | for DiscreteMeasure<Domain, F> { | |
418 | #[inline] | |
419 | fn from_iter<T>(iter : T) -> Self | |
420 | where T : IntoIterator<Item=D> { | |
421 | DiscreteMeasure{ | |
422 | spikes : iter.into_iter().map(|m| m.into()).collect() | |
423 | } | |
424 | } | |
425 | } | |
426 | ||
427 | impl<'a, F : Num, const N : usize> TableDump<'a> | |
428 | for DiscreteMeasure<Loc<F, N>,F> | |
429 | where DeltaMeasure<Loc<F, N>, F> : Serialize + 'a { | |
430 | type Iter = std::slice::Iter<'a, DeltaMeasure<Loc<F, N>, F>>; | |
431 | ||
432 | // fn tabledump_headers(&'a self) -> Vec<String> { | |
433 | // let mut v : Vec<String> = (0..N).map(|i| format!("x{}", i)).collect(); | |
434 | // v.push("weight".into()); | |
435 | // v | |
436 | // } | |
437 | ||
438 | fn tabledump_entries(&'a self) -> Self::Iter { | |
439 | // Ensure order matching the headers above | |
440 | self.spikes.iter() | |
441 | } | |
442 | } | |
443 | ||
444 | // Need to manually implement serialisation for DeltaMeasure<Loc<F, N>, F> [`csv`] writer fails on | |
445 | // structs with nested arrays as well as with #[serde(flatten)]. | |
446 | // Then derive no longer works for DiscreteMeasure | |
447 | impl<F : Num, const N : usize> Serialize for DiscreteMeasure<Loc<F, N>, F> | |
448 | where | |
449 | F: Serialize, | |
450 | { | |
451 | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | |
452 | where | |
453 | S: Serializer, | |
454 | { | |
455 | let mut s = serializer.serialize_seq(Some(self.spikes.len()))?; | |
456 | for δ in self.spikes.iter() { | |
457 | s.serialize_element(δ)?; | |
458 | } | |
459 | s.end() | |
460 | } | |
461 | } | |
462 | ||
463 | impl<Domain : PartialEq, F : Float> Measure<F> for DiscreteMeasure<Domain, F> { | |
464 | type Domain = Domain; | |
465 | } | |
466 | ||
467 | impl<Domain : PartialEq, F : Float> Norm<F, Radon> for DiscreteMeasure<Domain, F> | |
468 | where DeltaMeasure<Domain, F> : Norm<F, Radon> { | |
469 | #[inline] | |
470 | fn norm(&self, _ : Radon) -> F { | |
471 | self.spikes.iter().map(|m| m.norm(Radon)).sum() | |
472 | } | |
473 | } | |
474 | ||
35 | 475 | impl<Domain, G, F : Num> Mapping<G> for DiscreteMeasure<Domain, F> |
476 | where | |
477 | Domain : Space, | |
478 | G::Codomain : Sum + Mul<F, Output=G::Codomain>, | |
479 | G : Mapping<Domain, Codomain=F> + Clone + Space, | |
480 | for<'b> &'b Domain : Instance<Domain>, | |
481 | { | |
482 | type Codomain = G::Codomain; | |
483 | ||
0 | 484 | #[inline] |
35 | 485 | fn apply<I : Instance<G>>(&self, g : I) -> Self::Codomain { |
486 | g.eval(|g| self.spikes.iter().map(|m| g.apply(&m.x) * m.α).sum()) | |
0 | 487 | } |
488 | } | |
489 | ||
35 | 490 | impl<Domain, G, F : Num> Linear<G> for DiscreteMeasure<Domain, F> |
491 | where | |
492 | Domain : Space, | |
493 | G::Codomain : Sum + Mul<F, Output=G::Codomain>, | |
494 | G : Mapping<Domain, Codomain=F> + Clone + Space, | |
495 | for<'b> &'b Domain : Instance<Domain>, | |
496 | { } | |
0 | 497 | |
498 | ||
499 | /// Helper trait for constructing arithmetic operations for combinations | |
500 | /// of [`DiscreteMeasure`] and [`DeltaMeasure`], and their references. | |
501 | trait Lift<F : Num, Domain> { | |
502 | type Producer : Iterator<Item=DeltaMeasure<Domain, F>>; | |
503 | ||
35 | 504 | #[allow(dead_code)] |
0 | 505 | /// Lifts `self` into a [`DiscreteMeasure`]. |
506 | fn lift(self) -> DiscreteMeasure<Domain, F>; | |
507 | ||
508 | /// Lifts `self` into a [`DiscreteMeasure`], apply either `f` or `f_mut` whether the type | |
509 | /// this method is implemented for is a reference or or not. | |
510 | fn lift_with(self, | |
511 | f : impl Fn(&DeltaMeasure<Domain, F>) -> DeltaMeasure<Domain, F>, | |
512 | f_mut : impl FnMut(&mut DeltaMeasure<Domain, F>)) | |
513 | -> DiscreteMeasure<Domain, F>; | |
514 | ||
515 | /// Extend `self` into a [`DiscreteMeasure`] with the spikes produced by `iter`. | |
516 | fn lift_extend<I : Iterator<Item=DeltaMeasure<Domain, F>>>( | |
517 | self, | |
518 | iter : I | |
519 | ) -> DiscreteMeasure<Domain, F>; | |
520 | ||
521 | /// Returns an iterator for producing copies of the spikes of `self`. | |
522 | fn produce(self) -> Self::Producer; | |
523 | } | |
524 | ||
525 | impl<F : Num, Domain> Lift<F, Domain> for DiscreteMeasure<Domain, F> { | |
526 | type Producer = std::vec::IntoIter<DeltaMeasure<Domain, F>>; | |
527 | ||
528 | #[inline] | |
529 | fn lift(self) -> DiscreteMeasure<Domain, F> { self } | |
530 | ||
531 | fn lift_with(mut self, | |
532 | _f : impl Fn(&DeltaMeasure<Domain, F>) -> DeltaMeasure<Domain, F>, | |
533 | f_mut : impl FnMut(&mut DeltaMeasure<Domain, F>)) | |
534 | -> DiscreteMeasure<Domain, F> { | |
535 | self.spikes.iter_mut().for_each(f_mut); | |
536 | self | |
537 | } | |
538 | ||
539 | #[inline] | |
540 | fn lift_extend<I : Iterator<Item=DeltaMeasure<Domain, F>>>( | |
541 | mut self, | |
542 | iter : I | |
543 | ) -> DiscreteMeasure<Domain, F> { | |
544 | self.spikes.extend(iter); | |
545 | self | |
546 | } | |
547 | ||
548 | #[inline] | |
549 | fn produce(self) -> Self::Producer { | |
550 | self.spikes.into_iter() | |
551 | } | |
552 | } | |
553 | ||
554 | impl<'a, F : Num, Domain : Clone> Lift<F, Domain> for &'a DiscreteMeasure<Domain, F> { | |
555 | type Producer = MapF<std::slice::Iter<'a, DeltaMeasure<Domain, F>>, DeltaMeasure<Domain, F>>; | |
556 | ||
557 | #[inline] | |
558 | fn lift(self) -> DiscreteMeasure<Domain, F> { self.clone() } | |
559 | ||
560 | fn lift_with(self, | |
561 | f : impl Fn(&DeltaMeasure<Domain, F>) -> DeltaMeasure<Domain, F>, | |
562 | _f_mut : impl FnMut(&mut DeltaMeasure<Domain, F>)) | |
563 | -> DiscreteMeasure<Domain, F> { | |
564 | DiscreteMeasure{ spikes : self.spikes.iter().map(f).collect() } | |
565 | } | |
566 | ||
567 | #[inline] | |
568 | fn lift_extend<I : Iterator<Item=DeltaMeasure<Domain, F>>>( | |
569 | self, | |
570 | iter : I | |
571 | ) -> DiscreteMeasure<Domain, F> { | |
572 | let mut res = self.clone(); | |
573 | res.spikes.extend(iter); | |
574 | res | |
575 | } | |
576 | ||
577 | #[inline] | |
578 | fn produce(self) -> Self::Producer { | |
579 | // TODO: maybe not optimal to clone here and would benefit from | |
580 | // a reference version of lift_extend. | |
581 | self.spikes.iter().mapF(Clone::clone) | |
582 | } | |
583 | } | |
584 | ||
585 | impl<F : Num, Domain> Lift<F, Domain> for DeltaMeasure<Domain, F> { | |
586 | type Producer = std::iter::Once<DeltaMeasure<Domain, F>>; | |
587 | ||
588 | #[inline] | |
589 | fn lift(self) -> DiscreteMeasure<Domain, F> { DiscreteMeasure { spikes : vec![self] } } | |
590 | ||
591 | #[inline] | |
592 | fn lift_with(mut self, | |
593 | _f : impl Fn(&DeltaMeasure<Domain, F>) -> DeltaMeasure<Domain, F>, | |
594 | mut f_mut : impl FnMut(&mut DeltaMeasure<Domain, F>)) | |
595 | -> DiscreteMeasure<Domain, F> { | |
596 | f_mut(&mut self); | |
597 | DiscreteMeasure{ spikes : vec![self] } | |
598 | } | |
599 | ||
600 | #[inline] | |
601 | fn lift_extend<I : Iterator<Item=DeltaMeasure<Domain, F>>>( | |
602 | self, | |
603 | iter : I | |
604 | ) -> DiscreteMeasure<Domain, F> { | |
605 | let mut spikes = vec![self]; | |
606 | spikes.extend(iter); | |
607 | DiscreteMeasure{ spikes : spikes } | |
608 | } | |
609 | ||
610 | #[inline] | |
611 | fn produce(self) -> Self::Producer { | |
612 | std::iter::once(self) | |
613 | } | |
614 | } | |
615 | ||
616 | impl<'a, F : Num, Domain : Clone> Lift<F, Domain> for &'a DeltaMeasure<Domain, F> { | |
617 | type Producer = std::iter::Once<DeltaMeasure<Domain, F>>; | |
618 | ||
619 | #[inline] | |
620 | fn lift(self) -> DiscreteMeasure<Domain, F> { DiscreteMeasure { spikes : vec![self.clone()] } } | |
621 | ||
622 | #[inline] | |
623 | fn lift_with(self, | |
624 | f : impl Fn(&DeltaMeasure<Domain, F>) -> DeltaMeasure<Domain, F>, | |
625 | _f_mut : impl FnMut(&mut DeltaMeasure<Domain, F>)) | |
626 | -> DiscreteMeasure<Domain, F> { | |
627 | DiscreteMeasure{ spikes : vec![f(self)] } | |
628 | } | |
629 | ||
630 | #[inline] | |
631 | fn lift_extend<I : Iterator<Item=DeltaMeasure<Domain, F>>>( | |
632 | self, | |
633 | iter : I | |
634 | ) -> DiscreteMeasure<Domain, F> { | |
635 | let mut spikes = vec![self.clone()]; | |
636 | spikes.extend(iter); | |
637 | DiscreteMeasure{ spikes : spikes } | |
638 | } | |
639 | ||
640 | #[inline] | |
641 | fn produce(self) -> Self::Producer { | |
642 | std::iter::once(self.clone()) | |
643 | } | |
644 | } | |
645 | ||
646 | macro_rules! make_discrete_addsub_assign { | |
647 | ($rhs:ty) => { | |
648 | // Discrete += (&)Discrete | |
649 | impl<'a, F : Num, Domain : Clone> AddAssign<$rhs> | |
650 | for DiscreteMeasure<Domain, F> { | |
651 | fn add_assign(&mut self, other : $rhs) { | |
652 | self.spikes.extend(other.produce()); | |
653 | } | |
654 | } | |
655 | ||
656 | impl<'a, F : Num + Neg<Output=F>, Domain : Clone> SubAssign<$rhs> | |
657 | for DiscreteMeasure<Domain, F> { | |
658 | fn sub_assign(&mut self, other : $rhs) { | |
659 | self.spikes.extend(other.produce().map(|δ| -δ)); | |
660 | } | |
661 | } | |
662 | } | |
663 | } | |
664 | ||
665 | make_discrete_addsub_assign!(DiscreteMeasure<Domain, F>); | |
666 | make_discrete_addsub_assign!(&'a DiscreteMeasure<Domain, F>); | |
667 | make_discrete_addsub_assign!(DeltaMeasure<Domain, F>); | |
668 | make_discrete_addsub_assign!(&'a DeltaMeasure<Domain, F>); | |
669 | ||
670 | macro_rules! make_discrete_addsub { | |
671 | ($lhs:ty, $rhs:ty, $alt_order:expr) => { | |
672 | impl<'a, 'b, F : Num, Domain : Clone> Add<$rhs> for $lhs { | |
673 | type Output = DiscreteMeasure<Domain, F>; | |
674 | fn add(self, other : $rhs) -> DiscreteMeasure<Domain, F> { | |
675 | if !$alt_order { | |
676 | self.lift_extend(other.produce()) | |
677 | } else { | |
678 | other.lift_extend(self.produce()) | |
679 | } | |
680 | } | |
681 | } | |
682 | ||
683 | impl<'a, 'b, F : Num + Neg<Output=F>, Domain : Clone> Sub<$rhs> for $lhs { | |
684 | type Output = DiscreteMeasure<Domain, F>; | |
685 | fn sub(self, other : $rhs) -> DiscreteMeasure<Domain, F> { | |
686 | self.lift_extend(other.produce().map(|δ| -δ)) | |
687 | } | |
688 | } | |
689 | }; | |
690 | } | |
691 | ||
692 | make_discrete_addsub!(DiscreteMeasure<Domain, F>, DiscreteMeasure<Domain, F>, false); | |
693 | make_discrete_addsub!(DiscreteMeasure<Domain, F>, &'b DiscreteMeasure<Domain, F>, false); | |
694 | make_discrete_addsub!(&'a DiscreteMeasure<Domain, F>, DiscreteMeasure<Domain, F>, true); | |
695 | make_discrete_addsub!(&'a DiscreteMeasure<Domain, F>, &'b DiscreteMeasure<Domain, F>, false); | |
696 | make_discrete_addsub!(DeltaMeasure<Domain, F>, DiscreteMeasure<Domain, F>, false); | |
697 | make_discrete_addsub!(DeltaMeasure<Domain, F>, &'b DiscreteMeasure<Domain, F>, false); | |
698 | make_discrete_addsub!(&'a DeltaMeasure<Domain, F>, DiscreteMeasure<Domain, F>, true); | |
699 | make_discrete_addsub!(&'a DeltaMeasure<Domain, F>, &'b DiscreteMeasure<Domain, F>, false); | |
700 | make_discrete_addsub!(DiscreteMeasure<Domain, F>, DeltaMeasure<Domain, F>, false); | |
701 | make_discrete_addsub!(DiscreteMeasure<Domain, F>, &'b DeltaMeasure<Domain, F>, false); | |
702 | make_discrete_addsub!(&'a DiscreteMeasure<Domain, F>, DeltaMeasure<Domain, F>, false); | |
703 | make_discrete_addsub!(&'a DiscreteMeasure<Domain, F>, &'b DeltaMeasure<Domain, F>, false); | |
704 | make_discrete_addsub!(DeltaMeasure<Domain, F>, DeltaMeasure<Domain, F>, false); | |
705 | make_discrete_addsub!(DeltaMeasure<Domain, F>, &'b DeltaMeasure<Domain, F>, false); | |
706 | make_discrete_addsub!(&'a DeltaMeasure<Domain, F>, DeltaMeasure<Domain, F>, false); | |
707 | make_discrete_addsub!(&'a DeltaMeasure<Domain, F>, &'b DeltaMeasure<Domain, F>, false); | |
708 | ||
709 | macro_rules! make_discrete_scalarop_rhs { | |
710 | ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { | |
711 | make_discrete_scalarop_rhs!(@assign DiscreteMeasure<Domain, F>, F, $trait_assign, $fn_assign); | |
712 | make_discrete_scalarop_rhs!(@assign DiscreteMeasure<Domain, F>, &'a F, $trait_assign, $fn_assign); | |
713 | make_discrete_scalarop_rhs!(@new DiscreteMeasure<Domain, F>, F, $trait, $fn, $fn_assign); | |
714 | make_discrete_scalarop_rhs!(@new DiscreteMeasure<Domain, F>, &'a F, $trait, $fn, $fn_assign); | |
715 | make_discrete_scalarop_rhs!(@new &'b DiscreteMeasure<Domain, F>, F, $trait, $fn, $fn_assign); | |
716 | make_discrete_scalarop_rhs!(@new &'b DiscreteMeasure<Domain, F>, &'a F, $trait, $fn, $fn_assign); | |
717 | }; | |
718 | ||
719 | (@assign $lhs:ty, $rhs:ty, $trait_assign:ident, $fn_assign:ident) => { | |
720 | impl<'a, 'b, F : Num, Domain> $trait_assign<$rhs> for $lhs { | |
721 | fn $fn_assign(&mut self, b : $rhs) { | |
722 | self.spikes.iter_mut().for_each(|δ| δ.$fn_assign(b)); | |
723 | } | |
724 | } | |
725 | }; | |
726 | (@new $lhs:ty, $rhs:ty, $trait:ident, $fn:ident, $fn_assign:ident) => { | |
727 | impl<'a, 'b, F : Num, Domain : Clone> $trait<$rhs> for $lhs { | |
728 | type Output = DiscreteMeasure<Domain, F>; | |
729 | fn $fn(self, b : $rhs) -> Self::Output { | |
730 | self.lift_with(|δ| δ.$fn(b), |δ| δ.$fn_assign(b)) | |
731 | } | |
732 | } | |
733 | }; | |
734 | } | |
735 | ||
736 | make_discrete_scalarop_rhs!(Mul, mul, MulAssign, mul_assign); | |
737 | make_discrete_scalarop_rhs!(Div, div, DivAssign, div_assign); | |
738 | ||
739 | macro_rules! make_discrete_unary { | |
740 | ($trait:ident, $fn:ident, $type:ty) => { | |
741 | impl<'a, F : Num + Neg<Output=F>, Domain : Clone> Neg for $type { | |
742 | type Output = DiscreteMeasure<Domain, F>; | |
743 | fn $fn(self) -> Self::Output { | |
744 | self.lift_with(|δ| δ.$fn(), |δ| δ.α = δ.α.$fn()) | |
745 | } | |
746 | } | |
747 | } | |
748 | } | |
749 | ||
750 | make_discrete_unary!(Neg, neg, DiscreteMeasure<Domain, F>); | |
751 | make_discrete_unary!(Neg, neg, &'a DiscreteMeasure<Domain, F>); | |
752 | ||
753 | // impl<F : Num, Domain> Neg for DiscreteMeasure<Domain, F> { | |
754 | // type Output = Self; | |
755 | // fn $fn(mut self, b : F) -> Self { | |
756 | // self.lift().spikes.iter_mut().for_each(|δ| δ.neg(b)); | |
757 | // self | |
758 | // } | |
759 | // } | |
760 | ||
761 | macro_rules! make_discrete_scalarop_lhs { | |
762 | ($trait:ident, $fn:ident; $($f:ident)+) => { $( | |
763 | impl<Domain> $trait<DiscreteMeasure<Domain, $f>> for $f { | |
764 | type Output = DiscreteMeasure<Domain, $f>; | |
765 | fn $fn(self, mut v : DiscreteMeasure<Domain, $f>) -> Self::Output { | |
766 | v.spikes.iter_mut().for_each(|δ| δ.α = self.$fn(δ.α)); | |
767 | v | |
768 | } | |
769 | } | |
770 | ||
771 | impl<'a, Domain : Copy> $trait<&'a DiscreteMeasure<Domain, $f>> for $f { | |
772 | type Output = DiscreteMeasure<Domain, $f>; | |
773 | fn $fn(self, v : &'a DiscreteMeasure<Domain, $f>) -> Self::Output { | |
774 | DiscreteMeasure{ | |
775 | spikes : v.spikes.iter().map(|δ| self.$fn(δ)).collect() | |
776 | } | |
777 | } | |
778 | } | |
779 | ||
780 | impl<'b, Domain> $trait<DiscreteMeasure<Domain, $f>> for &'b $f { | |
781 | type Output = DiscreteMeasure<Domain, $f>; | |
782 | fn $fn(self, mut v : DiscreteMeasure<Domain, $f>) -> Self::Output { | |
783 | v.spikes.iter_mut().for_each(|δ| δ.α = self.$fn(δ.α)); | |
784 | v | |
785 | } | |
786 | } | |
787 | ||
788 | impl<'a, 'b, Domain : Copy> $trait<&'a DiscreteMeasure<Domain, $f>> for &'b $f { | |
789 | type Output = DiscreteMeasure<Domain, $f>; | |
790 | fn $fn(self, v : &'a DiscreteMeasure<Domain, $f>) -> Self::Output { | |
791 | DiscreteMeasure{ | |
792 | spikes : v.spikes.iter().map(|δ| self.$fn(δ)).collect() | |
793 | } | |
794 | } | |
795 | } | |
796 | )+ } | |
797 | } | |
798 | ||
799 | make_discrete_scalarop_lhs!(Mul, mul; f32 f64 i8 i16 i32 i64 isize u8 u16 u32 u64 usize); | |
800 | make_discrete_scalarop_lhs!(Div, div; f32 f64 i8 i16 i32 i64 isize u8 u16 u32 u64 usize); | |
35 | 801 | |
802 | impl<F : Num, Domain> Collection for DiscreteMeasure<Domain, F> { | |
803 | type Element = DeltaMeasure<Domain, F>; | |
804 | type RefsIter<'a> = std::slice::Iter<'a, Self::Element> where Self : 'a; | |
805 | ||
806 | #[inline] | |
807 | fn iter_refs(&self) -> Self::RefsIter<'_> { | |
808 | self.iter_spikes() | |
809 | } | |
810 | } | |
811 | ||
812 | impl<Domain : Clone, F : Num> Space for DiscreteMeasure<Domain, F> { | |
813 | type Decomp = MeasureDecomp; | |
814 | } | |
815 | ||
816 | pub type SpikeSlice<'b, Domain, F> = &'b [DeltaMeasure<Domain, F>]; | |
817 | ||
818 | pub type EitherSlice<'b, Domain, F> = EitherDecomp< | |
819 | Vec<DeltaMeasure<Domain, F>>, | |
820 | SpikeSlice<'b, Domain, F> | |
821 | >; | |
822 | ||
823 | impl<F : Num, Domain : Clone> Decomposition<DiscreteMeasure<Domain, F>> for MeasureDecomp { | |
824 | type Decomposition<'b> = EitherSlice<'b, Domain, F> where DiscreteMeasure<Domain, F> : 'b; | |
825 | type Reference<'b> = SpikeSlice<'b, Domain, F> where DiscreteMeasure<Domain, F> : 'b; | |
826 | ||
827 | /// Left the lightweight reference type into a full decomposition type. | |
828 | fn lift<'b>(r : Self::Reference<'b>) -> Self::Decomposition<'b> { | |
829 | EitherDecomp::Borrowed(r) | |
830 | } | |
831 | } | |
832 | ||
833 | impl<F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp> | |
834 | for DiscreteMeasure<Domain, F> | |
835 | { | |
836 | fn decompose<'b>(self) | |
837 | -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b> | |
838 | where Self : 'b, DiscreteMeasure<Domain, F> : 'b { | |
839 | EitherDecomp::Owned(self.spikes) | |
840 | } | |
841 | ||
842 | fn ref_instance(&self) | |
843 | -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_> | |
844 | { | |
845 | self.spikes.as_slice() | |
846 | } | |
847 | ||
848 | fn cow<'b>(self) -> MyCow<'b, DiscreteMeasure<Domain, F>> where Self : 'b { | |
849 | MyCow::Owned(self) | |
850 | } | |
851 | ||
852 | fn own(self) -> DiscreteMeasure<Domain, F> { | |
853 | self | |
854 | } | |
855 | } | |
856 | ||
857 | impl<'a, F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp> | |
858 | for &'a DiscreteMeasure<Domain, F> | |
859 | { | |
860 | fn decompose<'b>(self) | |
861 | -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b> | |
862 | where Self : 'b, DiscreteMeasure<Domain, F> : 'b { | |
863 | EitherDecomp::Borrowed(self.spikes.as_slice()) | |
864 | } | |
865 | ||
866 | fn ref_instance(&self) | |
867 | -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_> | |
868 | { | |
869 | self.spikes.as_slice() | |
870 | } | |
871 | ||
872 | fn cow<'b>(self) -> MyCow<'b, DiscreteMeasure<Domain, F>> where Self : 'b { | |
873 | MyCow::Borrowed(self) | |
874 | } | |
875 | ||
876 | fn own(self) -> DiscreteMeasure<Domain, F> { | |
877 | self.clone() | |
878 | } | |
879 | } | |
880 | ||
881 | impl<'a, F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp> | |
882 | for EitherSlice<'a, Domain, F> | |
883 | { | |
884 | fn decompose<'b>(self) | |
885 | -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b> | |
886 | where Self : 'b, DiscreteMeasure<Domain, F> : 'b { | |
887 | self | |
888 | } | |
889 | ||
890 | fn ref_instance(&self) | |
891 | -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_> | |
892 | { | |
893 | match self { | |
894 | EitherDecomp::Owned(v) => v.as_slice(), | |
895 | EitherDecomp::Borrowed(s) => s, | |
896 | } | |
897 | } | |
898 | ||
899 | fn own(self) -> DiscreteMeasure<Domain, F> { | |
900 | match self { | |
901 | EitherDecomp::Owned(v) => v.into(), | |
902 | EitherDecomp::Borrowed(s) => s.into(), | |
903 | } | |
904 | } | |
905 | } | |
906 | ||
907 | impl<'a, F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp> | |
908 | for &'a EitherSlice<'a, Domain, F> | |
909 | { | |
910 | fn decompose<'b>(self) | |
911 | -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b> | |
912 | where Self : 'b, DiscreteMeasure<Domain, F> : 'b { | |
913 | match self { | |
914 | EitherDecomp::Owned(v) => EitherDecomp::Borrowed(v.as_slice()), | |
915 | EitherDecomp::Borrowed(s) => EitherDecomp::Borrowed(s), | |
916 | } | |
917 | } | |
918 | ||
919 | fn ref_instance(&self) | |
920 | -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_> | |
921 | { | |
922 | match self { | |
923 | EitherDecomp::Owned(v) => v.as_slice(), | |
924 | EitherDecomp::Borrowed(s) => s, | |
925 | } | |
926 | } | |
927 | ||
928 | fn own(self) -> DiscreteMeasure<Domain, F> { | |
929 | match self { | |
930 | EitherDecomp::Owned(v) => v.as_slice(), | |
931 | EitherDecomp::Borrowed(s) => s | |
932 | }.into() | |
933 | } | |
934 | } | |
935 | ||
936 | impl<'a, F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp> | |
937 | for SpikeSlice<'a, Domain, F> | |
938 | { | |
939 | fn decompose<'b>(self) | |
940 | -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b> | |
941 | where Self : 'b, DiscreteMeasure<Domain, F> : 'b { | |
942 | EitherDecomp::Borrowed(self) | |
943 | } | |
944 | ||
945 | fn ref_instance(&self) | |
946 | -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_> | |
947 | { | |
948 | self | |
949 | } | |
950 | ||
951 | fn own(self) -> DiscreteMeasure<Domain, F> { | |
952 | self.into() | |
953 | } | |
954 | } | |
955 | ||
956 | impl<'a, F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp> | |
957 | for &'a SpikeSlice<'a, Domain, F> | |
958 | { | |
959 | fn decompose<'b>(self) | |
960 | -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b> | |
961 | where Self : 'b, DiscreteMeasure<Domain, F> : 'b { | |
962 | EitherDecomp::Borrowed(*self) | |
963 | } | |
964 | ||
965 | fn ref_instance(&self) | |
966 | -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_> | |
967 | { | |
968 | *self | |
969 | } | |
970 | ||
971 | fn own(self) -> DiscreteMeasure<Domain, F> { | |
972 | (*self).into() | |
973 | } | |
974 | } | |
975 | ||
976 | impl<F : Num, Domain : Clone > Instance<DiscreteMeasure<Domain, F>, MeasureDecomp> | |
977 | for DeltaMeasure<Domain, F> | |
978 | { | |
979 | fn decompose<'b>(self) | |
980 | -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b> | |
981 | where Self : 'b, DiscreteMeasure<Domain, F> : 'b { | |
982 | EitherDecomp::Owned(vec![self]) | |
983 | } | |
984 | ||
985 | fn ref_instance(&self) | |
986 | -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_> | |
987 | { | |
988 | std::slice::from_ref(self) | |
989 | } | |
990 | ||
991 | fn own(self) -> DiscreteMeasure<Domain, F> { | |
992 | self.into() | |
993 | } | |
994 | } | |
995 | ||
996 | impl<'a, F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp> | |
997 | for &'a DeltaMeasure<Domain, F> | |
998 | { | |
999 | fn decompose<'b>(self) | |
1000 | -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b> | |
1001 | where Self : 'b, DiscreteMeasure<Domain, F> : 'b { | |
1002 | EitherDecomp::Borrowed(std::slice::from_ref(self)) | |
1003 | } | |
1004 | ||
1005 | fn ref_instance(&self) | |
1006 | -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_> | |
1007 | { | |
1008 | std::slice::from_ref(*self) | |
1009 | } | |
1010 | ||
1011 | fn own(self) -> DiscreteMeasure<Domain, F> { | |
1012 | self.into() | |
1013 | } | |
1014 | } |