malachite_base/iterators/mod.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9#[cfg(feature = "random")]
10use crate::bools::random::{WeightedRandomBools, weighted_random_bools};
11use crate::num::arithmetic::traits::Parity;
12use crate::num::basic::traits::Zero;
13#[cfg(feature = "random")]
14use crate::random::Seed;
15#[cfg(feature = "random")]
16use crate::vecs::{RandomValuesFromVec, random_values_from_vec};
17use alloc::collections::VecDeque;
18use alloc::string::{String, ToString};
19use alloc::vec::Vec;
20use core::fmt::Display;
21use core::hash::Hash;
22use hashbrown::HashSet;
23use itertools::Itertools;
24
25/// Generates all the nonzero values of a provided iterator.
26///
27/// This `struct` is created by [`nonzero_values`]; see its documentation for more.
28#[derive(Clone, Debug)]
29pub struct NonzeroValues<I: Iterator>(I)
30where
31 I::Item: PartialEq<I::Item> + Zero;
32
33impl<I: Iterator> Iterator for NonzeroValues<I>
34where
35 I::Item: PartialEq<I::Item> + Zero,
36{
37 type Item = I::Item;
38
39 #[inline]
40 fn next(&mut self) -> Option<I::Item> {
41 loop {
42 let x = self.0.next();
43 if x != Some(I::Item::ZERO) {
44 return x;
45 }
46 }
47 }
48}
49
50impl<I: DoubleEndedIterator> DoubleEndedIterator for NonzeroValues<I>
51where
52 I::Item: PartialEq<I::Item> + Zero,
53{
54 #[inline]
55 fn next_back(&mut self) -> Option<I::Item> {
56 loop {
57 let x = self.0.next_back();
58 if x != Some(I::Item::ZERO) {
59 return x;
60 }
61 }
62 }
63}
64
65/// Returns an iterator that generates all the nonzero values of a provided iterator.
66///
67/// `nonzero_values(xs)` generates the same values as `xs.filter(|x| x != I::Item::ZERO)`, but its
68/// type is easier to work with.
69///
70/// This iterator will hang if given an iterator that produces an infinite suffix of zeros.
71///
72/// The output length is the number of nonzero values produced by `xs`.
73///
74/// # Examples
75/// ```
76/// use itertools::Itertools;
77/// use malachite_base::iterators::nonzero_values;
78///
79/// assert_eq!(
80/// nonzero_values([-3i8, -2, -1, 0, 1, 2, 3].iter().cloned()).collect_vec(),
81/// &[-3, -2, -1, 1, 2, 3]
82/// )
83/// ```
84#[inline]
85pub const fn nonzero_values<I: Iterator>(xs: I) -> NonzeroValues<I>
86where
87 I::Item: PartialEq<I::Item> + Zero,
88{
89 NonzeroValues(xs)
90}
91
92/// Returns whether all of the values generated by an iterator are equal.
93///
94/// `is_constant(xs)` is equivalent to `xs.unique().count() == 1` for finite nonempty iterators, but
95/// is more efficient, doesn't require [`Clone`] or [`Hash`] implementations, and doesn't hang if
96/// provided an infinite non-constant iterator.
97///
98/// This function will hang if given an infinite constant iterator.
99///
100/// # Examples
101/// ```
102/// use malachite_base::iterators::is_constant;
103///
104/// assert_eq!(is_constant([1; 4].iter()), true);
105/// assert_eq!(is_constant([1, 2, 3, 4].iter()), false);
106/// assert_eq!(is_constant(0..), false);
107/// ```
108pub fn is_constant<I: Iterator>(xs: I) -> bool
109where
110 I::Item: Eq,
111{
112 let mut first = None;
113 for x in xs {
114 if let Some(ref first) = first {
115 if x != *first {
116 return false;
117 }
118 } else {
119 first = Some(x);
120 }
121 }
122 true
123}
124
125/// Returns whether an iterator returns at least some number of values.
126///
127/// `count_is_at_least(xs, n)` is equivalent to `xs.count() >= n` for finite iterators, but doesn't
128/// hang if provided an infinite iterator.
129///
130/// # Examples
131/// ```
132/// use malachite_base::iterators::count_is_at_least;
133///
134/// assert_eq!(count_is_at_least([1, 2, 3, 4].iter(), 3), true);
135/// assert_eq!(count_is_at_least([1, 2, 3, 4].iter(), 4), true);
136/// assert_eq!(count_is_at_least([1, 2, 3, 4].iter(), 5), false);
137/// assert_eq!(count_is_at_least(0.., 5), true);
138/// ```
139#[inline]
140pub fn count_is_at_least<I: Iterator>(xs: I, n: usize) -> bool {
141 xs.take(n).count() == n
142}
143
144/// Returns whether an iterator returns at most some number of values.
145///
146/// `count_is_at_most(xs, n)` is equivalent to `xs.count() <= n` for finite iterators, but doesn't
147/// hang if provided an infinite iterator.
148///
149/// # Examples
150/// ```
151/// use malachite_base::iterators::count_is_at_most;
152///
153/// assert_eq!(count_is_at_most([1, 2, 3, 4].iter(), 3), false);
154/// assert_eq!(count_is_at_most([1, 2, 3, 4].iter(), 4), true);
155/// assert_eq!(count_is_at_most([1, 2, 3, 4].iter(), 5), true);
156/// assert_eq!(count_is_at_most(0.., 5), false);
157/// ```
158#[inline]
159pub fn count_is_at_most<I: Iterator>(xs: I, n: usize) -> bool {
160 xs.take(n + 1).count() <= n
161}
162
163/// Returns whether an iterator never returns the same value twice.
164///
165/// `is_unique(xs)` is equivalent to `xs.unique().count() <= 1` for finite iterators, but is more
166/// efficient and doesn't hang if provided a non-unique infinite iterator.
167///
168/// This iterator will hang if given an infinite unique iterator.
169///
170/// # Examples
171/// ```
172/// use malachite_base::iterators::is_unique;
173///
174/// let empty: [u32; 0] = [];
175/// assert_eq!(is_unique(empty.iter()), true);
176/// assert_eq!(is_unique([1, 2, 3, 4].iter()), true);
177/// assert_eq!(is_unique([1, 2, 3, 1].iter()), false);
178/// assert_eq!(is_unique((0..).map(|i| i / 2)), false);
179/// ```
180#[inline]
181pub fn is_unique<I: Iterator>(xs: I) -> bool
182where
183 I::Item: Eq + Hash,
184{
185 let mut set = HashSet::new();
186 for x in xs {
187 if !set.insert(x) {
188 return false;
189 }
190 }
191 true
192}
193
194/// Returns the first and last elements of an iterator, or `None` if it is empty.
195///
196/// The iterator's elements must be cloneable, since if the iterator consists of a single element
197/// `x`, the result will be `(x, x)`.
198///
199/// This iterator will hang if given an infinite iterator.
200///
201/// # Examples
202/// ```
203/// use malachite_base::iterators::first_and_last;
204///
205/// let empty: [u32; 0] = [];
206/// assert_eq!(first_and_last(&mut empty.iter()), None);
207/// assert_eq!(first_and_last(&mut [1].iter().cloned()), Some((1, 1)));
208/// assert_eq!(first_and_last(&mut [1, 2, 3].iter().cloned()), Some((1, 3)));
209/// ```
210#[inline]
211pub fn first_and_last<I: Iterator>(xs: &mut I) -> Option<(I::Item, I::Item)>
212where
213 I::Item: Clone,
214{
215 xs.next().map(|first| {
216 if let Some(last) = xs.last() {
217 (first, last)
218 } else {
219 (first.clone(), first)
220 }
221 })
222}
223
224/// Groups elements of an iterator into intervals of adjacent elements that match a predicate. The
225/// endpoints of each interval are returned.
226///
227/// The intervals are inclusive.
228///
229/// This iterator will hang if given an infinite iterator.
230///
231/// # Examples
232/// ```
233/// use malachite_base::iterators::matching_intervals_in_iterator;
234///
235/// let xs = &[1, 2, 10, 11, 12, 7, 8, 16, 5];
236/// assert_eq!(
237/// matching_intervals_in_iterator(xs.iter().cloned(), |&x| x >= 10).as_slice(),
238/// &[(10, 12), (16, 16)]
239/// );
240/// assert_eq!(
241/// matching_intervals_in_iterator(xs.iter().cloned(), |&x| x < 10).as_slice(),
242/// &[(1, 2), (7, 8), (5, 5)]
243/// );
244/// ```
245#[inline]
246pub fn matching_intervals_in_iterator<I: Iterator, F: Fn(&I::Item) -> bool>(
247 xs: I,
248 predicate: F,
249) -> Vec<(I::Item, I::Item)>
250where
251 I::Item: Clone,
252{
253 xs.chunk_by(predicate)
254 .into_iter()
255 .filter_map(|(b, mut group)| if b { first_and_last(&mut group) } else { None })
256 .collect()
257}
258
259#[cfg(feature = "random")]
260/// An iterator that randomly produces another iterator's values, or produces a special value.
261///
262/// This `struct` is created by [`with_special_value`]; see its documentation for more.
263#[derive(Clone, Debug)]
264pub struct WithSpecialValue<I: Iterator>
265where
266 I::Item: Clone,
267{
268 bs: WeightedRandomBools,
269 special_value: I::Item,
270 xs: I,
271}
272
273#[cfg(feature = "random")]
274impl<I: Iterator> Iterator for WithSpecialValue<I>
275where
276 I::Item: Clone,
277{
278 type Item = I::Item;
279
280 fn next(&mut self) -> Option<I::Item> {
281 if self.bs.next().unwrap() {
282 Some(self.special_value.clone())
283 } else {
284 self.xs.next()
285 }
286 }
287}
288
289#[cfg(feature = "random")]
290/// An iterator that randomly produces another iterator's values, or produces a special value.
291///
292/// Let $n_p$ be `p_numerator`, $d_p$ be `p_denominator`, and let $p=n_p/d_p$.
293///
294/// Every time a value is to be generated, the iterator returns the special value with probability
295/// $p$, or else returns a value from the inner iterator.
296///
297/// If $p > 0$, the output length is infinite. Otherwise, it is the same as the length of `xs`.
298///
299/// # Panics
300/// Panics if `p_denominator` is 0 or `p_numerator` is greater than `p_denominator`.
301///
302/// # Examples
303/// ```
304/// use malachite_base::iterators::{prefix_to_string, with_special_value};
305/// use malachite_base::num::random::random_primitive_ints;
306/// use malachite_base::random::EXAMPLE_SEED;
307///
308/// assert_eq!(
309/// prefix_to_string(
310/// with_special_value(EXAMPLE_SEED, -1i16, 1, 2, &random_primitive_ints::<i16>),
311/// 20
312/// ),
313/// "[-1, -1, -1, 2901, -1, -14200, -1, -1, -1, -30997, -8245, -5338, -1, -1, -20007, -1, -1, \
314/// -1, -1, -1, ...]"
315/// );
316/// ```
317pub fn with_special_value<I: Iterator>(
318 seed: Seed,
319 special_value: I::Item,
320 p_numerator: u64,
321 p_denominator: u64,
322 xs_gen: &dyn Fn(Seed) -> I,
323) -> WithSpecialValue<I>
324where
325 I::Item: Clone,
326{
327 WithSpecialValue {
328 bs: weighted_random_bools(seed.fork("bs"), p_numerator, p_denominator),
329 special_value,
330 xs: xs_gen(seed.fork("xs")),
331 }
332}
333
334#[cfg(feature = "random")]
335/// An iterator that randomly produces another iterator's values, or samples from a [`Vec`] of
336/// special values.
337///
338/// This `struct` is created by [`with_special_values`]; see its documentation for more.
339#[derive(Clone, Debug)]
340pub struct WithSpecialValues<I: Iterator>
341where
342 I::Item: Clone,
343{
344 bs: WeightedRandomBools,
345 special_values: RandomValuesFromVec<I::Item>,
346 xs: I,
347}
348
349#[cfg(feature = "random")]
350impl<I: Iterator> Iterator for WithSpecialValues<I>
351where
352 I::Item: Clone,
353{
354 type Item = I::Item;
355
356 fn next(&mut self) -> Option<I::Item> {
357 if self.bs.next().unwrap() {
358 self.special_values.next()
359 } else {
360 self.xs.next()
361 }
362 }
363}
364
365#[cfg(feature = "random")]
366/// An iterator that randomly produces another iterator's values, or produces a random special value
367/// from a [`Vec`].
368///
369/// Let $n_p$ be `p_numerator`, $d_p$ be `p_denominator`, and let $p=n_p/d_p$.
370///
371/// Every time a value is to be generated, the iterator uniformly samples the special values [`Vec`]
372/// with probability $p$, or else returns a value from the inner iterator.
373///
374/// If $p > 0$, the output length is infinite. Otherwise, it is the same as the length of `xs`.
375///
376/// # Worst-case complexity per iteration
377/// Constant time and additional memory.
378///
379/// # Panics
380/// Panics if `special_values` is empty, `p_denominator` is 0, or if `p_numerator` is greater than
381/// `p_denominator`.
382///
383/// # Examples
384/// ```
385/// use malachite_base::iterators::{prefix_to_string, with_special_values};
386/// use malachite_base::num::random::random_primitive_ints;
387/// use malachite_base::random::EXAMPLE_SEED;
388///
389/// assert_eq!(
390/// prefix_to_string(
391/// with_special_values(
392/// EXAMPLE_SEED,
393/// vec![1, 2, 3],
394/// 1,
395/// 2,
396/// &random_primitive_ints::<i16>
397/// ),
398/// 20,
399/// ),
400/// "[3, 1, 3, 2901, 1, -14200, 2, 3, 1, -30997, -8245, -5338, 1, 1, -20007, 3, 1, 1, 1, 1, \
401/// ...]"
402/// );
403/// ```
404pub fn with_special_values<I: Iterator>(
405 seed: Seed,
406 special_values: Vec<I::Item>,
407 p_numerator: u64,
408 p_denominator: u64,
409 xs_gen: &dyn Fn(Seed) -> I,
410) -> WithSpecialValues<I>
411where
412 I::Item: Clone,
413{
414 WithSpecialValues {
415 bs: weighted_random_bools(seed.fork("bs"), p_numerator, p_denominator),
416 special_values: random_values_from_vec(seed.fork("special_values"), special_values),
417 xs: xs_gen(seed.fork("xs")),
418 }
419}
420
421/// Generates sliding windows of elements from an iterator.
422///
423/// This `struct` is created by [`iter_windows`]; see its documentation for more.
424#[derive(Clone, Debug)]
425pub struct IterWindows<I: Iterator>
426where
427 I::Item: Clone,
428{
429 xs: I,
430 window: VecDeque<I::Item>,
431 window_size: usize,
432}
433
434impl<I: Iterator> Iterator for IterWindows<I>
435where
436 I::Item: Clone,
437{
438 type Item = VecDeque<I::Item>;
439
440 fn next(&mut self) -> Option<VecDeque<I::Item>> {
441 if self.window.len() < self.window_size {
442 self.window = (&mut self.xs).take(self.window_size).collect();
443 if self.window.len() < self.window_size {
444 None
445 } else {
446 Some(self.window.clone())
447 }
448 } else {
449 let x = self.xs.next()?;
450 self.window.pop_front();
451 self.window.push_back(x);
452 Some(self.window.clone())
453 }
454 }
455}
456
457/// Returns windows of $n$ adjacent elements of an iterator, advancing the window by 1 in each
458/// iteration. The values are cloned each time a new window is generated.
459///
460/// The output length is $n - k + 1$, where $n$ is `xs.count()` and $k$ is `window_size`.
461///
462/// # Panics
463/// Panics if `window_size` is 0.
464///
465/// # Examples
466/// ```
467/// use itertools::Itertools;
468/// use malachite_base::iterators::iter_windows;
469///
470/// let xs = 0..=5;
471/// let windows = iter_windows(3, xs)
472/// .map(|ws| ws.iter().cloned().collect_vec())
473/// .collect_vec();
474/// assert_eq!(
475/// windows.iter().map(Vec::as_slice).collect_vec().as_slice(),
476/// &[&[0, 1, 2], &[1, 2, 3], &[2, 3, 4], &[3, 4, 5]]
477/// );
478/// ```
479pub fn iter_windows<I: Iterator>(window_size: usize, xs: I) -> IterWindows<I>
480where
481 I::Item: Clone,
482{
483 assert_ne!(window_size, 0);
484 IterWindows {
485 xs,
486 window: VecDeque::with_capacity(window_size),
487 window_size,
488 }
489}
490
491/// Converts a prefix of an iterator to a string.
492///
493/// Suppose the iterator generates $(a, b, c, d)$. If `max_len` is 3, this function will return the
494/// string `"[a, b, c, ...]"`. If `max_len` is 4 or more, this function will return `[a, b, c, d]`.
495///
496/// This function will attempt to advance the iterator `max_len + 1` times. The extra time is used
497/// determine whether the output string should contain an ellipsis.
498///
499/// # Panics
500/// Panics if `max_len` is 0.
501///
502/// # Examples
503/// ```
504/// use malachite_base::iterators::prefix_to_string;
505///
506/// assert_eq!(prefix_to_string(0..10, 3), "[0, 1, 2, ...]");
507/// assert_eq!(prefix_to_string(0..4, 5), "[0, 1, 2, 3]");
508/// ```
509pub fn prefix_to_string<I: Iterator>(mut xs: I, max_len: usize) -> String
510where
511 I::Item: Display,
512{
513 assert_ne!(max_len, 0);
514 let mut s = String::new();
515 s.push('[');
516 let mut first = true;
517 let mut done = false;
518 for _ in 0..max_len {
519 if let Some(x) = xs.next() {
520 if first {
521 first = false;
522 } else {
523 s.push_str(", ");
524 }
525 s.push_str(&x.to_string());
526 } else {
527 done = true;
528 break;
529 }
530 }
531 if !done && xs.next().is_some() {
532 s.push_str(", ...");
533 }
534 s.push(']');
535 s
536}
537
538/// An iterator that generates the Thue-Morse sequence. See [`thue_morse_sequence`] for more
539/// information.
540#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
541pub struct ThueMorseSequence(u64);
542
543impl Iterator for ThueMorseSequence {
544 type Item = bool;
545
546 fn next(&mut self) -> Option<bool> {
547 let b = self.0.count_ones().odd();
548 self.0 += 1;
549 Some(b)
550 }
551}
552
553/// Returns an iterator that generates the Thue-Morse sequence.
554///
555/// The output length is infinite.
556///
557/// # Worst-case complexity per iteration
558/// Constant time and additional memory.
559///
560/// # Examples
561/// ```
562/// use malachite_base::iterators::thue_morse_sequence;
563///
564/// let s: String = thue_morse_sequence()
565/// .take(100)
566/// .map(|b| if b { '1' } else { '0' })
567/// .collect();
568/// assert_eq!(
569/// s,
570/// "01101001100101101001011001101001100101100110100101101001100101101001011001101001011010011\
571/// 00101100110"
572/// )
573/// ```
574#[inline]
575pub const fn thue_morse_sequence() -> ThueMorseSequence {
576 ThueMorseSequence(0)
577}
578
579/// Contains [`BitDistributor`](bit_distributor::BitDistributor), which helps generate tuples
580/// exhaustively.
581pub mod bit_distributor;
582/// Functions that compare adjacent iterator elements.
583pub mod comparison;
584/// Contains [`IteratorCache`](iterator_cache::IteratorCache), which remembers values produced by an
585/// iterator.
586pub mod iterator_cache;