test_case_core/test_matrix/
matrix_product.rs
1#[derive(Clone)]
11#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
19pub struct MultiProduct<I>(Vec<MultiProductIter<I>>)
20where
21 I: Iterator + Clone,
22 I::Item: Clone;
23
24pub fn multi_cartesian_product<H>(iters: H) -> MultiProduct<<H::Item as IntoIterator>::IntoIter>
32where
33 H: Iterator,
34 H::Item: IntoIterator,
35 <H::Item as IntoIterator>::IntoIter: Clone,
36 <H::Item as IntoIterator>::Item: Clone,
37{
38 MultiProduct(
39 iters
40 .map(|i| MultiProductIter::new(i.into_iter()))
41 .collect(),
42 )
43}
44
45#[derive(Clone, Debug)]
46struct MultiProductIter<I>
48where
49 I: Iterator + Clone,
50 I::Item: Clone,
51{
52 cur: Option<I::Item>,
53 iter: I,
54 iter_orig: I,
55}
56
57#[derive(Debug)]
59enum MultiProductIterState {
60 StartOfIter,
61 MidIter { on_first_iter: bool },
62}
63
64impl<I> MultiProduct<I>
65where
66 I: Iterator + Clone,
67 I::Item: Clone,
68{
69 fn iterate_last(
74 multi_iters: &mut [MultiProductIter<I>],
75 mut state: MultiProductIterState,
76 ) -> bool {
77 use self::MultiProductIterState::*;
78
79 if let Some((last, rest)) = multi_iters.split_last_mut() {
80 let on_first_iter = match state {
81 StartOfIter => {
82 let on_first_iter = !last.in_progress();
83 state = MidIter { on_first_iter };
84 on_first_iter
85 }
86 MidIter { on_first_iter } => on_first_iter,
87 };
88
89 if !on_first_iter {
90 last.iterate();
91 }
92
93 if last.in_progress() {
94 true
95 } else if MultiProduct::iterate_last(rest, state) {
96 last.reset();
97 last.iterate();
98 last.in_progress()
101 } else {
102 false
103 }
104 } else {
105 match state {
108 StartOfIter => false,
109 MidIter { on_first_iter } => on_first_iter,
110 }
111 }
112 }
113
114 fn curr_iterator(&self) -> Vec<I::Item> {
116 self.0
117 .iter()
118 .map(|multi_iter| multi_iter.cur.clone().unwrap())
119 .collect()
120 }
121
122 fn in_progress(&self) -> bool {
125 if let Some(last) = self.0.last() {
126 last.in_progress()
127 } else {
128 false
129 }
130 }
131}
132
133impl<I> MultiProductIter<I>
134where
135 I: Iterator + Clone,
136 I::Item: Clone,
137{
138 fn new(iter: I) -> Self {
139 MultiProductIter {
140 cur: None,
141 iter: iter.clone(),
142 iter_orig: iter,
143 }
144 }
145
146 fn iterate(&mut self) {
148 self.cur = self.iter.next();
149 }
150
151 fn reset(&mut self) {
153 self.iter = self.iter_orig.clone();
154 }
155
156 fn in_progress(&self) -> bool {
159 self.cur.is_some()
160 }
161}
162
163impl<I> Iterator for MultiProduct<I>
164where
165 I: Iterator + Clone,
166 I::Item: Clone,
167{
168 type Item = Vec<I::Item>;
169
170 fn next(&mut self) -> Option<Self::Item> {
171 if MultiProduct::iterate_last(&mut self.0, MultiProductIterState::StartOfIter) {
172 Some(self.curr_iterator())
173 } else {
174 None
175 }
176 }
177
178 fn count(self) -> usize {
179 if self.0.is_empty() {
180 return 0;
181 }
182
183 if !self.in_progress() {
184 return self
185 .0
186 .into_iter()
187 .fold(1, |acc, multi_iter| acc * multi_iter.iter.count());
188 }
189
190 self.0.into_iter().fold(
191 0,
192 |acc,
193 MultiProductIter {
194 iter,
195 iter_orig,
196 cur: _,
197 }| {
198 let total_count = iter_orig.count();
199 let cur_count = iter.count();
200 acc * total_count + cur_count
201 },
202 )
203 }
204
205 fn size_hint(&self) -> (usize, Option<usize>) {
206 if self.0.is_empty() {
208 return (0, Some(0));
209 }
210
211 if !self.in_progress() {
212 return self.0.iter().fold((1, Some(1)), |acc, multi_iter| {
213 size_hint::mul(acc, multi_iter.iter.size_hint())
214 });
215 }
216
217 self.0.iter().fold(
220 (0, Some(0)),
221 |acc,
222 MultiProductIter {
223 iter,
224 iter_orig,
225 cur: _,
226 }| {
227 let cur_size = iter.size_hint();
228 let total_size = iter_orig.size_hint();
229 size_hint::add(size_hint::mul(acc, total_size), cur_size)
230 },
231 )
232 }
233
234 fn last(self) -> Option<Self::Item> {
235 let iter_count = self.0.len();
236
237 let lasts: Self::Item = self
241 .0
242 .into_iter()
243 .filter_map(|multi_iter| multi_iter.iter.last())
244 .collect();
245
246 if lasts.len() == iter_count {
247 Some(lasts)
248 } else {
249 None
250 }
251 }
252}
253
254mod size_hint {
257 pub type SizeHint = (usize, Option<usize>);
259
260 #[inline]
262 pub fn add(a: SizeHint, b: SizeHint) -> SizeHint {
263 let min = a.0.saturating_add(b.0);
264 let max = match (a.1, b.1) {
265 (Some(x), Some(y)) => x.checked_add(y),
266 _ => None,
267 };
268
269 (min, max)
270 }
271
272 #[inline]
274 pub fn mul(a: SizeHint, b: SizeHint) -> SizeHint {
275 let low = a.0.saturating_mul(b.0);
276 let hi = match (a.1, b.1) {
277 (Some(x), Some(y)) => x.checked_mul(y),
278 (Some(0), None) | (None, Some(0)) => Some(0),
279 _ => None,
280 };
281 (low, hi)
282 }
283}