Mon, 24 Oct 2022 09:41:43 +0300
Allow step closure of AlgIterators to indicate succesfull termination or failure.
0 | 1 | |
2 | use crate::types::*; | |
3 | use super::support::*; | |
4 | use crate::mapping::Mapping; | |
5 | use std::iter::Chain; | |
6 | use crate::iter::{Mappable,MapF,MapZ}; | |
7 | use super::aggregator::*; | |
8 | ||
9 | // TODO: try to remove F and N | |
10 | #[derive(Debug,Clone)] | |
11 | pub struct BothGenerators<A, B>( | |
12 | pub(super) A, | |
13 | pub(super) B, | |
14 | ); | |
15 | ||
16 | #[derive(Debug,Clone)] | |
17 | pub enum EitherSupport<A, B> { | |
18 | Left(A), | |
19 | Right(B), | |
20 | } | |
21 | ||
22 | // We need type alias bounds to access associate types. | |
23 | #[allow(type_alias_bounds)] | |
24 | type BothAllDataIter< | |
25 | 'a, F, | |
26 | G1 : SupportGenerator<F, N>, | |
27 | G2 : SupportGenerator<F, N>, | |
28 | const N : usize | |
29 | > = Chain< | |
30 | MapF<G1::AllDataIter<'a>, (usize, EitherSupport<G1::SupportType, G2::SupportType>)>, | |
31 | MapZ<G2::AllDataIter<'a>, usize, (usize, EitherSupport<G1::SupportType, G2::SupportType>)>, | |
32 | >; | |
33 | ||
34 | impl<G1, G2> BothGenerators<G1, G2> { | |
35 | /// Helper for [`all_data`]. | |
36 | #[inline] | |
37 | fn map_left<F : Float, const N : usize>((d, support) : (G1::Id, G1::SupportType)) | |
38 | -> (usize, EitherSupport<G1::SupportType, G2::SupportType>) | |
39 | where G1 : SupportGenerator<F, N, Id=usize>, | |
40 | G2 : SupportGenerator<F, N, Id=usize> { | |
41 | ||
42 | let id : usize = d.into(); | |
43 | (id.into(), EitherSupport::Left(support)) | |
44 | } | |
45 | ||
46 | /// Helper for [`all_data`]. | |
47 | #[inline] | |
48 | fn map_right<F : Float, const N : usize>(n0 : &usize, (d, support) : (G2::Id, G2::SupportType)) | |
49 | -> (usize, EitherSupport<G1::SupportType, G2::SupportType>) | |
50 | where G1 : SupportGenerator<F, N, Id=usize>, | |
51 | G2 : SupportGenerator<F, N, Id=usize> { | |
52 | ||
53 | let id : usize = d.into(); | |
54 | ((n0+id).into(), EitherSupport::Right(support)) | |
55 | } | |
56 | ||
57 | #[inline] | |
58 | pub(super) fn all_left_data<F : Float, const N : usize>(&self) | |
59 | -> MapF<G1::AllDataIter<'_>, (usize, EitherSupport<G1::SupportType, G2::SupportType>)> | |
60 | where G1 : SupportGenerator<F, N, Id=usize>, | |
61 | G2 : SupportGenerator<F, N, Id=usize> { | |
62 | self.0.all_data().mapF(Self::map_left) | |
63 | } | |
64 | ||
65 | #[inline] | |
66 | pub(super) fn all_right_data<F : Float, const N : usize>(&self) | |
67 | -> MapZ<G2::AllDataIter<'_>, usize, (usize, EitherSupport<G1::SupportType, G2::SupportType>)> | |
68 | where G1 : SupportGenerator<F, N, Id=usize>, | |
69 | G2 : SupportGenerator<F, N, Id=usize> { | |
70 | let n0 = self.0.support_count(); | |
71 | self.1.all_data().mapZ(n0, Self::map_right) | |
72 | } | |
73 | } | |
74 | ||
75 | impl<F : Float, G1, G2, const N : usize> | |
76 | SupportGenerator<F, N> | |
77 | for BothGenerators<G1, G2> | |
78 | where G1 : SupportGenerator<F, N, Id=usize>, | |
79 | G2 : SupportGenerator<F, N, Id=usize> { | |
80 | ||
81 | type Id = usize; | |
82 | type SupportType = EitherSupport<G1::SupportType, G2::SupportType>; | |
83 | type AllDataIter<'a> = BothAllDataIter<'a, F, G1, G2, N> where G1 : 'a, G2 : 'a; | |
84 | ||
85 | #[inline] | |
86 | fn support_for(&self, id : Self::Id) | |
87 | -> Self::SupportType { | |
88 | let n0 = self.0.support_count(); | |
89 | if id < n0 { | |
90 | EitherSupport::Left(self.0.support_for(id.into())) | |
91 | } else { | |
92 | EitherSupport::Right(self.1.support_for((id-n0).into())) | |
93 | } | |
94 | } | |
95 | ||
96 | #[inline] | |
97 | fn support_count(&self) -> usize { | |
98 | self.0.support_count() + self.1.support_count() | |
99 | } | |
100 | ||
101 | #[inline] | |
102 | fn all_data(&self) -> Self::AllDataIter<'_> { | |
103 | self.all_left_data().chain(self.all_right_data()) | |
104 | } | |
105 | } | |
106 | ||
107 | impl<F: Float, S1, S2, const N : usize> Support<F, N> for EitherSupport<S1, S2> | |
108 | where S1 : Support<F, N>, | |
109 | S2 : Support<F, N> { | |
110 | ||
111 | #[inline] | |
112 | fn support_hint(&self) -> Cube<F,N> { | |
113 | match self { | |
114 | EitherSupport::Left(ref a) => a.support_hint(), | |
115 | EitherSupport::Right(ref b) => b.support_hint(), | |
116 | } | |
117 | } | |
118 | ||
119 | #[inline] | |
120 | fn in_support(&self, x : &Loc<F,N>) -> bool { | |
121 | match self { | |
122 | EitherSupport::Left(ref a) => a.in_support(x), | |
123 | EitherSupport::Right(ref b) => b.in_support(x), | |
124 | } | |
125 | } | |
126 | ||
127 | #[inline] | |
128 | fn bisection_hint(&self, cube : &Cube<F, N>) -> [Option<F>; N] { | |
129 | match self { | |
130 | EitherSupport::Left(ref a) => a.bisection_hint(cube), | |
131 | EitherSupport::Right(ref b) => b.bisection_hint(cube), | |
132 | } | |
133 | } | |
134 | } | |
135 | ||
136 | impl<F : Float, A, S1, S2, const N : usize> LocalAnalysis<F, A, N> for EitherSupport<S1, S2> | |
137 | where A : Aggregator, | |
138 | S1 : LocalAnalysis<F, A, N>, | |
139 | S2 : LocalAnalysis<F, A, N>, { | |
140 | ||
141 | #[inline] | |
142 | fn local_analysis(&self, cube : &Cube<F, N>) -> A { | |
143 | match self { | |
144 | EitherSupport::Left(ref a) => a.local_analysis(cube), | |
145 | EitherSupport::Right(ref b) => b.local_analysis(cube), | |
146 | } | |
147 | } | |
148 | } | |
149 | ||
150 | impl<F : Float, A, S1, S2> GlobalAnalysis<F, A> for EitherSupport<S1, S2> | |
151 | where A : Aggregator, | |
152 | S1 : GlobalAnalysis<F, A>, | |
153 | S2 : GlobalAnalysis<F, A>, { | |
154 | ||
155 | #[inline] | |
156 | fn global_analysis(&self) -> A { | |
157 | match self { | |
158 | EitherSupport::Left(ref a) => a.global_analysis(), | |
159 | EitherSupport::Right(ref b) => b.global_analysis(), | |
160 | } | |
161 | } | |
162 | } | |
163 | ||
164 | impl<F, S1, S2, X> Mapping<X> for EitherSupport<S1, S2> | |
165 | where S1 : Mapping<X, Codomain=F>, | |
166 | S2 : Mapping<X, Codomain=F> { | |
167 | type Codomain = F; | |
168 | #[inline] | |
169 | fn value(&self, x : X) -> F { | |
170 | match self { | |
171 | EitherSupport::Left(ref a) => a.value(x), | |
172 | EitherSupport::Right(ref b) => b.value(x), | |
173 | } | |
174 | } | |
175 | } | |
176 | ||
177 | macro_rules! make_either_scalarop_rhs { | |
178 | ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { | |
179 | impl<F : Float, G1, G2> | |
180 | std::ops::$trait_assign<F> | |
181 | for BothGenerators<G1, G2> | |
182 | where G1 : std::ops::$trait_assign<F>, | |
183 | G2 : std::ops::$trait_assign<F>, { | |
184 | #[inline] | |
185 | fn $fn_assign(&mut self, t : F) { | |
186 | self.0.$fn_assign(t); | |
187 | self.1.$fn_assign(t); | |
188 | } | |
189 | } | |
190 | ||
191 | impl<'a, F : Float, G1, G2> | |
192 | std::ops::$trait<F> | |
193 | for &'a BothGenerators<G1, G2> | |
194 | where &'a G1 : std::ops::$trait<F,Output=G1>, | |
195 | &'a G2 : std::ops::$trait<F,Output=G2> { | |
196 | type Output = BothGenerators<G1, G2>; | |
197 | #[inline] | |
198 | fn $fn(self, t : F) -> BothGenerators<G1, G2> { | |
199 | BothGenerators(self.0.$fn(t), self.1.$fn(t)) | |
200 | } | |
201 | } | |
202 | } | |
203 | } | |
204 | ||
205 | make_either_scalarop_rhs!(Mul, mul, MulAssign, mul_assign); | |
206 | make_either_scalarop_rhs!(Div, div, DivAssign, div_assign); | |
207 | ||
208 | impl<G1, G2> std::ops::Neg for BothGenerators<G1, G2> | |
209 | where G1 : std::ops::Neg, G2 : std::ops::Neg, { | |
210 | type Output = BothGenerators<G1::Output, G2::Output>; | |
211 | #[inline] | |
212 | fn neg(self) -> Self::Output { | |
213 | BothGenerators(self.0.neg(), self.1.neg()) | |
214 | } | |
215 | } | |
216 | /* | |
217 | impl<'a, G1, G2> std::ops::Neg for &'a BothGenerators<G1, G2> | |
218 | where &'a G1 : std::ops::Neg, &'a G2 : std::ops::Neg, { | |
219 | type Output = BothGenerators<<&'a G1 as std::ops::Neg>::Output, | |
220 | <&'a G2 as std::ops::Neg>::Output>; | |
221 | fn neg(self) -> Self::Output { | |
222 | BothGenerators(self.0.neg(), self.1.neg()) | |
223 | } | |
224 | } | |
225 | */ |