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