| 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), |