| 1 |
|
| 2 use std::iter::Chain; |
1 use std::iter::Chain; |
| 3 use std::sync::Arc; |
2 use std::sync::Arc; |
| 4 |
3 |
| |
4 use crate::iter::{MapF, MapZ, Mappable}; |
| |
5 use crate::loc::Loc; |
| |
6 use crate::mapping::{DifferentiableImpl, DifferentiableMapping, Instance, Mapping, Space}; |
| |
7 use crate::sets::Cube; |
| 5 use crate::types::*; |
8 use crate::types::*; |
| 6 use crate::mapping::{ |
9 |
| 7 Instance, |
10 use super::aggregator::*; |
| 8 Mapping, |
|
| 9 DifferentiableImpl, |
|
| 10 DifferentiableMapping, |
|
| 11 Space, |
|
| 12 }; |
|
| 13 use crate::iter::{Mappable, MapF, MapZ}; |
|
| 14 use crate::sets::Cube; |
|
| 15 use crate::loc::Loc; |
|
| 16 |
|
| 17 use super::support::*; |
11 use super::support::*; |
| 18 use super::aggregator::*; |
|
| 19 |
12 |
| 20 /// A structure for storing two [`SupportGenerator`]s summed/chain together. |
13 /// A structure for storing two [`SupportGenerator`]s summed/chain together. |
| 21 /// |
14 /// |
| 22 /// This is needed to work with sums of different types of [`Support`]s. |
15 /// This is needed to work with sums of different types of [`Support`]s. |
| 23 #[derive(Debug,Clone)] |
16 #[derive(Debug, Clone)] |
| 24 pub struct BothGenerators<A, B>( |
17 pub struct BothGenerators<A, B>(pub(super) Arc<A>, pub(super) Arc<B>); |
| 25 pub(super) Arc<A>, |
|
| 26 pub(super) Arc<B>, |
|
| 27 ); |
|
| 28 |
18 |
| 29 /// A structure for a [`Support`] that can be either `A` or `B`. |
19 /// A structure for a [`Support`] that can be either `A` or `B`. |
| 30 /// |
20 /// |
| 31 /// This is needed to work with sums of different types of [`Support`]s. |
21 /// This is needed to work with sums of different types of [`Support`]s. |
| 32 #[derive(Debug,Clone)] |
22 #[derive(Debug, Clone)] |
| 33 pub enum EitherSupport<A, B> { |
23 pub enum EitherSupport<B, A> { |
| 34 Left(A), |
24 Left(A), |
| 35 Right(B), |
25 Right(B), |
| 36 } |
26 } |
| 37 |
27 |
| 38 // We need type alias bounds to access associate types. |
28 // We need type alias bounds to access associate types. |
| 39 #[allow(type_alias_bounds)] |
29 #[allow(type_alias_bounds)] |
| 40 type BothAllDataIter< |
30 type BothAllDataIter< |
| 41 'a, F, |
31 'a, |
| 42 G1 : SupportGenerator<F, N>, |
32 F, |
| 43 G2 : SupportGenerator<F, N>, |
33 G1: SupportGenerator<N, F>, |
| 44 const N : usize |
34 G2: SupportGenerator<N, F>, |
| |
35 const N: usize, |
| 45 > = Chain< |
36 > = Chain< |
| 46 MapF<G1::AllDataIter<'a>, (usize, EitherSupport<G1::SupportType, G2::SupportType>)>, |
37 MapF<G1::AllDataIter<'a>, (usize, EitherSupport<G2::SupportType, G1::SupportType>)>, |
| 47 MapZ<G2::AllDataIter<'a>, usize, (usize, EitherSupport<G1::SupportType, G2::SupportType>)>, |
38 MapZ<G2::AllDataIter<'a>, usize, (usize, EitherSupport<G2::SupportType, G1::SupportType>)>, |
| 48 >; |
39 >; |
| 49 |
40 |
| 50 impl<G1, G2> BothGenerators<G1, G2> { |
41 impl<G1, G2> BothGenerators<G1, G2> { |
| 51 /// Helper for [`all_left_data`]. |
42 /// Helper for [`all_left_data`]. |
| 52 #[inline] |
43 #[inline] |
| 53 fn map_left<F : Float, const N : usize>((d, support) : (G1::Id, G1::SupportType)) |
44 fn map_left<F: Float, const N: usize>( |
| 54 -> (usize, EitherSupport<G1::SupportType, G2::SupportType>) |
45 (d, support): (G1::Id, G1::SupportType), |
| 55 where G1 : SupportGenerator<F, N, Id=usize>, |
46 ) -> (usize, EitherSupport<G2::SupportType, G1::SupportType>) |
| 56 G2 : SupportGenerator<F, N, Id=usize> { |
47 where |
| 57 |
48 G1: SupportGenerator<N, F, Id = usize>, |
| 58 let id : usize = d.into(); |
49 G2: SupportGenerator<N, F, Id = usize>, |
| |
50 { |
| |
51 let id: usize = d.into(); |
| 59 (id.into(), EitherSupport::Left(support)) |
52 (id.into(), EitherSupport::Left(support)) |
| 60 } |
53 } |
| 61 |
54 |
| 62 /// Helper for [`all_right_data`]. |
55 /// Helper for [`all_right_data`]. |
| 63 #[inline] |
56 #[inline] |
| 64 fn map_right<F : Float, const N : usize>(n0 : &usize, (d, support) : (G2::Id, G2::SupportType)) |
57 fn map_right<F: Float, const N: usize>( |
| 65 -> (usize, EitherSupport<G1::SupportType, G2::SupportType>) |
58 n0: &usize, |
| 66 where G1 : SupportGenerator<F, N, Id=usize>, |
59 (d, support): (G2::Id, G2::SupportType), |
| 67 G2 : SupportGenerator<F, N, Id=usize> { |
60 ) -> (usize, EitherSupport<G2::SupportType, G1::SupportType>) |
| 68 |
61 where |
| 69 let id : usize = d.into(); |
62 G1: SupportGenerator<N, F, Id = usize>, |
| 70 ((n0+id).into(), EitherSupport::Right(support)) |
63 G2: SupportGenerator<N, F, Id = usize>, |
| |
64 { |
| |
65 let id: usize = d.into(); |
| |
66 ((n0 + id).into(), EitherSupport::Right(support)) |
| 71 } |
67 } |
| 72 |
68 |
| 73 /// Calls [`SupportGenerator::all_data`] on the “left” support generator. |
69 /// Calls [`SupportGenerator::all_data`] on the “left” support generator. |
| 74 /// |
70 /// |
| 75 /// Converts both the id and the [`Support`] into a form that corresponds to `BothGenerators`. |
71 /// Converts both the id and the [`Support`] into a form that corresponds to `BothGenerators`. |
| 76 #[inline] |
72 #[inline] |
| 77 pub(super) fn all_left_data<F : Float, const N : usize>(&self) |
73 pub(super) fn all_left_data<F: Float, const N: usize>( |
| 78 -> MapF<G1::AllDataIter<'_>, (usize, EitherSupport<G1::SupportType, G2::SupportType>)> |
74 &self, |
| 79 where G1 : SupportGenerator<F, N, Id=usize>, |
75 ) -> MapF<G1::AllDataIter<'_>, (usize, EitherSupport<G2::SupportType, G1::SupportType>)> |
| 80 G2 : SupportGenerator<F, N, Id=usize> { |
76 where |
| |
77 G1: SupportGenerator<N, F, Id = usize>, |
| |
78 G2: SupportGenerator<N, F, Id = usize>, |
| |
79 { |
| 81 self.0.all_data().mapF(Self::map_left) |
80 self.0.all_data().mapF(Self::map_left) |
| 82 } |
81 } |
| 83 |
82 |
| 84 /// Calls [`SupportGenerator::all_data`] on the “right” support generator. |
83 /// Calls [`SupportGenerator::all_data`] on the “right” support generator. |
| 85 /// |
84 /// |
| 86 /// Converts both the id and the [`Support`] into a form that corresponds to `BothGenerators`. |
85 /// Converts both the id and the [`Support`] into a form that corresponds to `BothGenerators`. |
| 87 #[inline] |
86 #[inline] |
| 88 pub(super) fn all_right_data<F : Float, const N : usize>(&self) |
87 pub(super) fn all_right_data<F: Float, const N: usize>( |
| 89 -> MapZ<G2::AllDataIter<'_>, usize, (usize, EitherSupport<G1::SupportType, G2::SupportType>)> |
88 &self, |
| 90 where G1 : SupportGenerator<F, N, Id=usize>, |
89 ) -> MapZ<G2::AllDataIter<'_>, usize, (usize, EitherSupport<G2::SupportType, G1::SupportType>)> |
| 91 G2 : SupportGenerator<F, N, Id=usize> { |
90 where |
| |
91 G1: SupportGenerator<N, F, Id = usize>, |
| |
92 G2: SupportGenerator<N, F, Id = usize>, |
| |
93 { |
| 92 let n0 = self.0.support_count(); |
94 let n0 = self.0.support_count(); |
| 93 self.1.all_data().mapZ(n0, Self::map_right) |
95 self.1.all_data().mapZ(n0, Self::map_right) |
| 94 } |
96 } |
| 95 } |
97 } |
| 96 |
98 |
| 97 impl<F : Float, G1, G2, const N : usize> |
99 impl<F: Float, G1, G2, const N: usize> SupportGenerator<N, F> for BothGenerators<G1, G2> |
| 98 SupportGenerator<F, N> |
100 where |
| 99 for BothGenerators<G1, G2> |
101 G1: SupportGenerator<N, F, Id = usize>, |
| 100 where G1 : SupportGenerator<F, N, Id=usize>, |
102 G2: SupportGenerator<N, F, Id = usize>, |
| 101 G2 : SupportGenerator<F, N, Id=usize> { |
103 { |
| 102 |
|
| 103 type Id = usize; |
104 type Id = usize; |
| 104 type SupportType = EitherSupport<G1::SupportType, G2::SupportType>; |
105 type SupportType = EitherSupport<G2::SupportType, G1::SupportType>; |
| 105 type AllDataIter<'a> = BothAllDataIter<'a, F, G1, G2, N> where G1 : 'a, G2 : 'a; |
106 type AllDataIter<'a> |
| 106 |
107 = BothAllDataIter<'a, F, G1, G2, N> |
| 107 #[inline] |
108 where |
| 108 fn support_for(&self, id : Self::Id) |
109 G1: 'a, |
| 109 -> Self::SupportType { |
110 G2: 'a; |
| |
111 |
| |
112 #[inline] |
| |
113 fn support_for(&self, id: Self::Id) -> Self::SupportType { |
| 110 let n0 = self.0.support_count(); |
114 let n0 = self.0.support_count(); |
| 111 if id < n0 { |
115 if id < n0 { |
| 112 EitherSupport::Left(self.0.support_for(id.into())) |
116 EitherSupport::Left(self.0.support_for(id.into())) |
| 113 } else { |
117 } else { |
| 114 EitherSupport::Right(self.1.support_for((id-n0).into())) |
118 EitherSupport::Right(self.1.support_for((id - n0).into())) |
| 115 } |
119 } |
| 116 } |
120 } |
| 117 |
121 |
| 118 #[inline] |
122 #[inline] |
| 119 fn support_count(&self) -> usize { |
123 fn support_count(&self) -> usize { |
| 124 fn all_data(&self) -> Self::AllDataIter<'_> { |
128 fn all_data(&self) -> Self::AllDataIter<'_> { |
| 125 self.all_left_data().chain(self.all_right_data()) |
129 self.all_left_data().chain(self.all_right_data()) |
| 126 } |
130 } |
| 127 } |
131 } |
| 128 |
132 |
| 129 impl<F: Float, S1, S2, const N : usize> Support<F, N> for EitherSupport<S1, S2> |
133 impl<F: Float, S1, S2, const N: usize> Support<N, F> for EitherSupport<S2, S1> |
| 130 where S1 : Support<F, N>, |
134 where |
| 131 S2 : Support<F, N> { |
135 S1: Support<N, F>, |
| 132 |
136 S2: Support<N, F>, |
| 133 #[inline] |
137 { |
| 134 fn support_hint(&self) -> Cube<F,N> { |
138 #[inline] |
| |
139 fn support_hint(&self) -> Cube<N, F> { |
| 135 match self { |
140 match self { |
| 136 EitherSupport::Left(ref a) => a.support_hint(), |
141 EitherSupport::Left(ref a) => a.support_hint(), |
| 137 EitherSupport::Right(ref b) => b.support_hint(), |
142 EitherSupport::Right(ref b) => b.support_hint(), |
| 138 } |
143 } |
| 139 } |
144 } |
| 140 |
145 |
| 141 #[inline] |
146 #[inline] |
| 142 fn in_support(&self, x : &Loc<F,N>) -> bool { |
147 fn in_support(&self, x: &Loc<N, F>) -> bool { |
| 143 match self { |
148 match self { |
| 144 EitherSupport::Left(ref a) => a.in_support(x), |
149 EitherSupport::Left(ref a) => a.in_support(x), |
| 145 EitherSupport::Right(ref b) => b.in_support(x), |
150 EitherSupport::Right(ref b) => b.in_support(x), |
| 146 } |
151 } |
| 147 } |
152 } |
| 148 |
153 |
| 149 #[inline] |
154 #[inline] |
| 150 fn bisection_hint(&self, cube : &Cube<F, N>) -> [Option<F>; N] { |
155 fn bisection_hint(&self, cube: &Cube<N, F>) -> [Option<F>; N] { |
| 151 match self { |
156 match self { |
| 152 EitherSupport::Left(ref a) => a.bisection_hint(cube), |
157 EitherSupport::Left(ref a) => a.bisection_hint(cube), |
| 153 EitherSupport::Right(ref b) => b.bisection_hint(cube), |
158 EitherSupport::Right(ref b) => b.bisection_hint(cube), |
| 154 } |
159 } |
| 155 } |
160 } |
| 156 } |
161 } |
| 157 |
162 |
| 158 impl<F : Float, A, S1, S2, const N : usize> LocalAnalysis<F, A, N> for EitherSupport<S1, S2> |
163 impl<F: Float, A, S1, S2, const N: usize> LocalAnalysis<F, A, N> for EitherSupport<S2, S1> |
| 159 where A : Aggregator, |
164 where |
| 160 S1 : LocalAnalysis<F, A, N>, |
165 A: Aggregator, |
| 161 S2 : LocalAnalysis<F, A, N>, { |
166 S1: LocalAnalysis<F, A, N>, |
| 162 |
167 S2: LocalAnalysis<F, A, N>, |
| 163 #[inline] |
168 { |
| 164 fn local_analysis(&self, cube : &Cube<F, N>) -> A { |
169 #[inline] |
| |
170 fn local_analysis(&self, cube: &Cube<N, F>) -> A { |
| 165 match self { |
171 match self { |
| 166 EitherSupport::Left(ref a) => a.local_analysis(cube), |
172 EitherSupport::Left(ref a) => a.local_analysis(cube), |
| 167 EitherSupport::Right(ref b) => b.local_analysis(cube), |
173 EitherSupport::Right(ref b) => b.local_analysis(cube), |
| 168 } |
174 } |
| 169 } |
175 } |
| 170 } |
176 } |
| 171 |
177 |
| 172 impl<F : Float, A, S1, S2> GlobalAnalysis<F, A> for EitherSupport<S1, S2> |
178 impl<F: Float, A, S1, S2> GlobalAnalysis<F, A> for EitherSupport<S2, S1> |
| 173 where A : Aggregator, |
179 where |
| 174 S1 : GlobalAnalysis<F, A>, |
180 A: Aggregator, |
| 175 S2 : GlobalAnalysis<F, A>, { |
181 S1: GlobalAnalysis<F, A>, |
| 176 |
182 S2: GlobalAnalysis<F, A>, |
| |
183 { |
| 177 #[inline] |
184 #[inline] |
| 178 fn global_analysis(&self) -> A { |
185 fn global_analysis(&self) -> A { |
| 179 match self { |
186 match self { |
| 180 EitherSupport::Left(ref a) => a.global_analysis(), |
187 EitherSupport::Left(ref a) => a.global_analysis(), |
| 181 EitherSupport::Right(ref b) => b.global_analysis(), |
188 EitherSupport::Right(ref b) => b.global_analysis(), |
| 182 } |
189 } |
| 183 } |
190 } |
| 184 } |
191 } |
| 185 |
192 |
| 186 impl<F, S1, S2, X> Mapping<X> for EitherSupport<S1, S2> |
193 impl<F, S1, S2, X> Mapping<X> for EitherSupport<S2, S1> |
| 187 where |
194 where |
| 188 F : Space, |
195 F: Space, |
| 189 X : Space, |
196 X: Space, |
| 190 S1 : Mapping<X, Codomain=F>, |
197 S1: Mapping<X, Codomain = F>, |
| 191 S2 : Mapping<X, Codomain=F>, |
198 S2: Mapping<X, Codomain = F>, |
| 192 { |
199 { |
| 193 type Codomain = F; |
200 type Codomain = F; |
| 194 |
201 |
| 195 #[inline] |
202 #[inline] |
| 196 fn apply<I : Instance<X>>(&self, x : I) -> F { |
203 fn apply<I: Instance<X>>(&self, x: I) -> F { |
| 197 match self { |
204 match self { |
| 198 EitherSupport::Left(ref a) => a.apply(x), |
205 EitherSupport::Left(ref a) => a.apply(x), |
| 199 EitherSupport::Right(ref b) => b.apply(x), |
206 EitherSupport::Right(ref b) => b.apply(x), |
| 200 } |
207 } |
| 201 } |
208 } |
| 202 } |
209 } |
| 203 |
210 |
| 204 impl<X, S1, S2, O> DifferentiableImpl<X> for EitherSupport<S1, S2> |
211 impl<X, S1, S2, O> DifferentiableImpl<X> for EitherSupport<S2, S1> |
| 205 where |
212 where |
| 206 O : Space, |
213 O: Space, |
| 207 X : Space, |
214 X: Space, |
| 208 S1 : DifferentiableMapping<X, DerivativeDomain=O>, |
215 S1: DifferentiableMapping<X, DerivativeDomain = O>, |
| 209 S2 : DifferentiableMapping<X, DerivativeDomain=O>, |
216 S2: DifferentiableMapping<X, DerivativeDomain = O>, |
| 210 { |
217 { |
| 211 type Derivative = O; |
218 type Derivative = O; |
| 212 |
219 |
| 213 #[inline] |
220 #[inline] |
| 214 fn differential_impl<I : Instance<X>>(&self, x : I) -> O { |
221 fn differential_impl<I: Instance<X>>(&self, x: I) -> O { |
| 215 match self { |
222 match self { |
| 216 EitherSupport::Left(ref a) => a.differential(x), |
223 EitherSupport::Left(ref a) => a.differential(x), |
| 217 EitherSupport::Right(ref b) => b.differential(x), |
224 EitherSupport::Right(ref b) => b.differential(x), |
| 218 } |
225 } |
| 219 } |
226 } |
| 220 } |
227 } |
| 221 |
228 |
| 222 macro_rules! make_either_scalarop_rhs { |
229 macro_rules! make_either_scalarop_rhs { |
| 223 ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { |
230 ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { |
| 224 impl<F : Float, G1, G2> |
231 impl<F: Float, G1, G2> std::ops::$trait_assign<F> for BothGenerators<G1, G2> |
| 225 std::ops::$trait_assign<F> |
232 where |
| 226 for BothGenerators<G1, G2> |
233 G1: std::ops::$trait_assign<F> + Clone, |
| 227 where G1 : std::ops::$trait_assign<F> + Clone, |
234 G2: std::ops::$trait_assign<F> + Clone, |
| 228 G2 : std::ops::$trait_assign<F> + Clone, { |
235 { |
| 229 #[inline] |
236 #[inline] |
| 230 fn $fn_assign(&mut self, t : F) { |
237 fn $fn_assign(&mut self, t: F) { |
| 231 Arc::make_mut(&mut self.0).$fn_assign(t); |
238 Arc::make_mut(&mut self.0).$fn_assign(t); |
| 232 Arc::make_mut(&mut self.1).$fn_assign(t); |
239 Arc::make_mut(&mut self.1).$fn_assign(t); |
| 233 } |
240 } |
| 234 } |
241 } |
| 235 |
242 |
| 236 impl<'a, F : Float, G1, G2> |
243 impl<'a, F: Float, G1, G2> std::ops::$trait<F> for &'a BothGenerators<G1, G2> |
| 237 std::ops::$trait<F> |
244 where |
| 238 for &'a BothGenerators<G1, G2> |
245 &'a G1: std::ops::$trait<F, Output = G1>, |
| 239 where &'a G1 : std::ops::$trait<F,Output=G1>, |
246 &'a G2: std::ops::$trait<F, Output = G2>, |
| 240 &'a G2 : std::ops::$trait<F,Output=G2> { |
247 { |
| 241 type Output = BothGenerators<G1, G2>; |
248 type Output = BothGenerators<G1, G2>; |
| 242 #[inline] |
249 #[inline] |
| 243 fn $fn(self, t : F) -> BothGenerators<G1, G2> { |
250 fn $fn(self, t: F) -> BothGenerators<G1, G2> { |
| 244 BothGenerators(Arc::new(self.0.$fn(t)), |
251 BothGenerators(Arc::new(self.0.$fn(t)), Arc::new(self.1.$fn(t))) |
| 245 Arc::new(self.1.$fn(t))) |
|
| 246 } |
252 } |
| 247 } |
253 } |
| 248 } |
254 }; |
| 249 } |
255 } |
| 250 |
256 |
| 251 make_either_scalarop_rhs!(Mul, mul, MulAssign, mul_assign); |
257 make_either_scalarop_rhs!(Mul, mul, MulAssign, mul_assign); |
| 252 make_either_scalarop_rhs!(Div, div, DivAssign, div_assign); |
258 make_either_scalarop_rhs!(Div, div, DivAssign, div_assign); |
| 253 |
259 |
| 254 impl<G1, G2> std::ops::Neg for BothGenerators<G1, G2> |
260 impl<G1, G2> std::ops::Neg for BothGenerators<G1, G2> |
| 255 where G1 : std::ops::Neg + Clone, |
261 where |
| 256 G2 : std::ops::Neg + Clone, { |
262 G1: std::ops::Neg + Clone, |
| |
263 G2: std::ops::Neg + Clone, |
| |
264 { |
| 257 type Output = BothGenerators<G1::Output, G2::Output>; |
265 type Output = BothGenerators<G1::Output, G2::Output>; |
| 258 #[inline] |
266 #[inline] |
| 259 fn neg(self) -> Self::Output { |
267 fn neg(self) -> Self::Output { |
| 260 BothGenerators(Arc::new(Arc::unwrap_or_clone(self.0).neg()), |
268 BothGenerators( |
| 261 Arc::new(Arc::unwrap_or_clone(self.1).neg())) |
269 Arc::new(Arc::unwrap_or_clone(self.0).neg()), |
| |
270 Arc::new(Arc::unwrap_or_clone(self.1).neg()), |
| |
271 ) |
| 262 } |
272 } |
| 263 } |
273 } |
| 264 /* |
274 /* |
| 265 impl<'a, G1, G2> std::ops::Neg for &'a BothGenerators<G1, G2> |
275 impl<'a, G1, G2> std::ops::Neg for &'a BothGenerators<G1, G2> |
| 266 where &'a G1 : std::ops::Neg, &'a G2 : std::ops::Neg, { |
276 where &'a G1 : std::ops::Neg, &'a G2 : std::ops::Neg, { |