27 pub enum EitherSupport<A, B> { |
27 pub enum EitherSupport<A, B> { |
28 Left(A), |
28 Left(A), |
29 Right(B), |
29 Right(B), |
30 } |
30 } |
31 |
31 |
|
32 impl<A, B, F : Num> HasScalarField for EitherSupport<A, B> |
|
33 where A : HasScalarField<Field = F>, |
|
34 B : HasScalarField<Field = F> { |
|
35 type Field = F; |
|
36 } |
|
37 |
32 // We need type alias bounds to access associate types. |
38 // We need type alias bounds to access associate types. |
33 #[allow(type_alias_bounds)] |
39 #[allow(type_alias_bounds)] |
34 type BothAllDataIter< |
40 type BothAllDataIter< |
35 'a, F, |
41 'a, |
36 G1 : SupportGenerator<F, N>, |
42 G1 : SupportGenerator<N>, |
37 G2 : SupportGenerator<F, N>, |
43 G2 : SupportGenerator<N, RealField = G1::RealField>, |
38 const N : usize |
44 const N : usize |
39 > = Chain< |
45 > = Chain< |
40 MapF<G1::AllDataIter<'a>, (usize, EitherSupport<G1::SupportType, G2::SupportType>)>, |
46 MapF<G1::AllDataIter<'a>, (usize, EitherSupport<G1::SupportType, G2::SupportType>)>, |
41 MapZ<G2::AllDataIter<'a>, usize, (usize, EitherSupport<G1::SupportType, G2::SupportType>)>, |
47 MapZ<G2::AllDataIter<'a>, usize, (usize, EitherSupport<G1::SupportType, G2::SupportType>)>, |
42 >; |
48 >; |
44 impl<G1, G2> BothGenerators<G1, G2> { |
50 impl<G1, G2> BothGenerators<G1, G2> { |
45 /// Helper for [`all_left_data`]. |
51 /// Helper for [`all_left_data`]. |
46 #[inline] |
52 #[inline] |
47 fn map_left<F : Float, const N : usize>((d, support) : (G1::Id, G1::SupportType)) |
53 fn map_left<F : Float, const N : usize>((d, support) : (G1::Id, G1::SupportType)) |
48 -> (usize, EitherSupport<G1::SupportType, G2::SupportType>) |
54 -> (usize, EitherSupport<G1::SupportType, G2::SupportType>) |
49 where G1 : SupportGenerator<F, N, Id=usize>, |
55 where G1 : SupportGenerator<N, Id=usize, RealField =F>, |
50 G2 : SupportGenerator<F, N, Id=usize> { |
56 G2 : SupportGenerator<N, Id=usize, RealField = F> { |
51 |
57 |
52 let id : usize = d.into(); |
58 let id : usize = d.into(); |
53 (id.into(), EitherSupport::Left(support)) |
59 (id.into(), EitherSupport::Left(support)) |
54 } |
60 } |
55 |
61 |
56 /// Helper for [`all_right_data`]. |
62 /// Helper for [`all_right_data`]. |
57 #[inline] |
63 #[inline] |
58 fn map_right<F : Float, const N : usize>(n0 : &usize, (d, support) : (G2::Id, G2::SupportType)) |
64 fn map_right<F : Float, const N : usize>(n0 : &usize, (d, support) : (G2::Id, G2::SupportType)) |
59 -> (usize, EitherSupport<G1::SupportType, G2::SupportType>) |
65 -> (usize, EitherSupport<G1::SupportType, G2::SupportType>) |
60 where G1 : SupportGenerator<F, N, Id=usize>, |
66 where G1 : SupportGenerator<N, Id=usize, RealField = F>, |
61 G2 : SupportGenerator<F, N, Id=usize> { |
67 G2 : SupportGenerator<N, Id=usize, RealField = F> { |
62 |
68 |
63 let id : usize = d.into(); |
69 let id : usize = d.into(); |
64 ((n0+id).into(), EitherSupport::Right(support)) |
70 ((n0+id).into(), EitherSupport::Right(support)) |
65 } |
71 } |
66 |
72 |
68 /// |
74 /// |
69 /// Converts both the id and the [`Support`] into a form that corresponds to `BothGenerators`. |
75 /// Converts both the id and the [`Support`] into a form that corresponds to `BothGenerators`. |
70 #[inline] |
76 #[inline] |
71 pub(super) fn all_left_data<F : Float, const N : usize>(&self) |
77 pub(super) fn all_left_data<F : Float, const N : usize>(&self) |
72 -> MapF<G1::AllDataIter<'_>, (usize, EitherSupport<G1::SupportType, G2::SupportType>)> |
78 -> MapF<G1::AllDataIter<'_>, (usize, EitherSupport<G1::SupportType, G2::SupportType>)> |
73 where G1 : SupportGenerator<F, N, Id=usize>, |
79 where G1 : SupportGenerator<N, Id=usize, RealField = F>, |
74 G2 : SupportGenerator<F, N, Id=usize> { |
80 G2 : SupportGenerator<N, Id=usize, RealField = F> { |
75 self.0.all_data().mapF(Self::map_left) |
81 self.0.all_data().mapF(Self::map_left) |
76 } |
82 } |
77 |
83 |
78 /// Calls [`SupportGenerator::all_data`] on the “right” support generator. |
84 /// Calls [`SupportGenerator::all_data`] on the “right” support generator. |
79 /// |
85 /// |
80 /// Converts both the id and the [`Support`] into a form that corresponds to `BothGenerators`. |
86 /// Converts both the id and the [`Support`] into a form that corresponds to `BothGenerators`. |
81 #[inline] |
87 #[inline] |
82 pub(super) fn all_right_data<F : Float, const N : usize>(&self) |
88 pub(super) fn all_right_data<F : Float, const N : usize>(&self) |
83 -> MapZ<G2::AllDataIter<'_>, usize, (usize, EitherSupport<G1::SupportType, G2::SupportType>)> |
89 -> MapZ<G2::AllDataIter<'_>, usize, (usize, EitherSupport<G1::SupportType, G2::SupportType>)> |
84 where G1 : SupportGenerator<F, N, Id=usize>, |
90 where G1 : SupportGenerator<N, Id=usize, RealField=F>, |
85 G2 : SupportGenerator<F, N, Id=usize> { |
91 G2 : SupportGenerator<N, Id=usize, RealField=F> { |
86 let n0 = self.0.support_count(); |
92 let n0 = self.0.support_count(); |
87 self.1.all_data().mapZ(n0, Self::map_right) |
93 self.1.all_data().mapZ(n0, Self::map_right) |
88 } |
94 } |
89 } |
95 } |
90 |
96 |
|
97 impl<F : Float, G1, G2> HasScalarField for BothGenerators<G1, G2> |
|
98 where G1 : HasScalarField<Field=F>, |
|
99 G2 : HasScalarField<Field=F> { |
|
100 type Field = F; |
|
101 } |
|
102 |
91 impl<F : Float, G1, G2, const N : usize> |
103 impl<F : Float, G1, G2, const N : usize> |
92 SupportGenerator<F, N> |
104 SupportGenerator<N> |
93 for BothGenerators<G1, G2> |
105 for BothGenerators<G1, G2> |
94 where G1 : SupportGenerator<F, N, Id=usize>, |
106 where G1 : SupportGenerator<N, Id=usize> + HasRealField<RealField=F>, |
95 G2 : SupportGenerator<F, N, Id=usize> { |
107 G2 : SupportGenerator<N, Id=usize> + HasRealField<RealField=F>, |
|
108 Self : HasRealField<RealField = F> { |
96 |
109 |
97 type Id = usize; |
110 type Id = usize; |
98 type SupportType = EitherSupport<G1::SupportType, G2::SupportType>; |
111 type SupportType = EitherSupport<G1::SupportType, G2::SupportType>; |
99 type AllDataIter<'a> = BothAllDataIter<'a, F, G1, G2, N> where G1 : 'a, G2 : 'a; |
112 type AllDataIter<'a> = BothAllDataIter<'a, G1, G2, N> where G1 : 'a, G2 : 'a; |
100 |
113 |
101 #[inline] |
114 #[inline] |
102 fn support_for(&self, id : Self::Id) |
115 fn support_for(&self, id : Self::Id) |
103 -> Self::SupportType { |
116 -> Self::SupportType { |
104 let n0 = self.0.support_count(); |
117 let n0 = self.0.support_count(); |
118 fn all_data(&self) -> Self::AllDataIter<'_> { |
131 fn all_data(&self) -> Self::AllDataIter<'_> { |
119 self.all_left_data().chain(self.all_right_data()) |
132 self.all_left_data().chain(self.all_right_data()) |
120 } |
133 } |
121 } |
134 } |
122 |
135 |
123 impl<F: Float, S1, S2, const N : usize> Support<F, N> for EitherSupport<S1, S2> |
136 impl<F: Float, S1, S2, const N : usize> Support<N> for EitherSupport<S1, S2> |
124 where S1 : Support<F, N>, |
137 where S1 : Support<N, RealField = F>, |
125 S2 : Support<F, N> { |
138 S2 : Support<N, RealField = F> { |
126 |
139 |
127 #[inline] |
140 #[inline] |
128 fn support_hint(&self) -> Cube<F,N> { |
141 fn support_hint(&self) -> Cube<F,N> { |
129 match self { |
142 match self { |
130 EitherSupport::Left(ref a) => a.support_hint(), |
143 EitherSupport::Left(ref a) => a.support_hint(), |
147 EitherSupport::Right(ref b) => b.bisection_hint(cube), |
160 EitherSupport::Right(ref b) => b.bisection_hint(cube), |
148 } |
161 } |
149 } |
162 } |
150 } |
163 } |
151 |
164 |
152 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<A, Cube<F, N>> |
|
166 for EitherSupport<S1, S2> |
153 where A : Aggregator, |
167 where A : Aggregator, |
154 S1 : LocalAnalysis<F, A, N>, |
168 S1 : LocalAnalysis<A, Cube<F, N>>, |
155 S2 : LocalAnalysis<F, A, N>, { |
169 S2 : LocalAnalysis<A, Cube<F, N>> { |
156 |
170 |
157 #[inline] |
171 #[inline] |
158 fn local_analysis(&self, cube : &Cube<F, N>) -> A { |
172 fn local_analysis(&self, cube : &Cube<F, N>) -> A { |
159 match self { |
173 match self { |
160 EitherSupport::Left(ref a) => a.local_analysis(cube), |
174 EitherSupport::Left(ref a) => a.local_analysis(cube), |
161 EitherSupport::Right(ref b) => b.local_analysis(cube), |
175 EitherSupport::Right(ref b) => b.local_analysis(cube), |
162 } |
176 } |
163 } |
177 } |
164 } |
178 } |
165 |
179 |
166 impl<F : Float, A, S1, S2> GlobalAnalysis<F, A> for EitherSupport<S1, S2> |
180 impl<A, S1, S2> GlobalAnalysis<A> for EitherSupport<S1, S2> |
167 where A : Aggregator, |
181 where A : Aggregator, |
168 S1 : GlobalAnalysis<F, A>, |
182 S1 : GlobalAnalysis<A>, |
169 S2 : GlobalAnalysis<F, A>, { |
183 S2 : GlobalAnalysis<A>, { |
170 |
184 |
171 #[inline] |
185 #[inline] |
172 fn global_analysis(&self) -> A { |
186 fn global_analysis(&self) -> A { |
173 match self { |
187 match self { |
174 EitherSupport::Left(ref a) => a.global_analysis(), |
188 EitherSupport::Left(ref a) => a.global_analysis(), |
188 EitherSupport::Right(ref b) => b.apply(x), |
202 EitherSupport::Right(ref b) => b.apply(x), |
189 } |
203 } |
190 } |
204 } |
191 } |
205 } |
192 |
206 |
193 impl<F, S1, S2, X> Differentiable<X> for EitherSupport<S1, S2> |
207 impl<F : Float, S1, S2, X> Differentiable<X> for EitherSupport<S1, S2> |
194 where S1 : Differentiable<X, Derivative=F>, |
208 where S1 : Differentiable<X, Derivative=F, RealField=F>, |
195 S2 : Differentiable<X, Derivative=F> { |
209 S2 : Differentiable<X, Derivative=F, RealField=F> { |
196 type Derivative = F; |
210 type Derivative = F; |
197 #[inline] |
211 #[inline] |
198 fn differential(&self, x : X) -> F { |
212 fn differential(&self, x : X) -> F { |
199 match self { |
213 match self { |
200 EitherSupport::Left(ref a) => a.differential(x), |
214 EitherSupport::Left(ref a) => a.differential(x), |