Skip to main content

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/// # Worst-case complexity per iteration
75/// $T(i) = O(z T^\prime(i))$
76///
77/// $M(i) = O(M^\prime(i))$
78///
79/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
80/// $M^\prime$ are the time and memory functions of `xs`, and $z$ is the number of consecutive zeros
81/// that must be skipped to reach the next nonzero value.
82///
83/// # Examples
84/// ```
85/// use itertools::Itertools;
86/// use malachite_base::iterators::nonzero_values;
87///
88/// assert_eq!(
89///     nonzero_values([-3i8, -2, -1, 0, 1, 2, 3].iter().cloned()).collect_vec(),
90///     &[-3, -2, -1, 1, 2, 3]
91/// )
92/// ```
93#[inline]
94pub const fn nonzero_values<I: Iterator>(xs: I) -> NonzeroValues<I>
95where
96    I::Item: PartialEq<I::Item> + Zero,
97{
98    NonzeroValues(xs)
99}
100
101/// Returns whether all of the values generated by an iterator are equal.
102///
103/// `is_constant(xs)` is equivalent to `xs.unique().count() == 1` for finite nonempty iterators, but
104/// is more efficient, doesn't require [`Clone`] or [`Hash`] implementations, and doesn't hang if
105/// provided an infinite non-constant iterator.
106///
107/// This function will hang if given an infinite constant iterator.
108///
109/// # Examples
110/// ```
111/// use malachite_base::iterators::is_constant;
112///
113/// assert_eq!(is_constant([1; 4].iter()), true);
114/// assert_eq!(is_constant([1, 2, 3, 4].iter()), false);
115/// assert_eq!(is_constant(0..), false);
116/// ```
117pub fn is_constant<I: Iterator>(xs: I) -> bool
118where
119    I::Item: Eq,
120{
121    let mut first = None;
122    for x in xs {
123        if let Some(ref first) = first {
124            if x != *first {
125                return false;
126            }
127        } else {
128            first = Some(x);
129        }
130    }
131    true
132}
133
134/// Returns whether an iterator returns at least some number of values.
135///
136/// `count_is_at_least(xs, n)` is equivalent to `xs.count() >= n` for finite iterators, but doesn't
137/// hang if provided an infinite iterator.
138///
139/// # Examples
140/// ```
141/// use malachite_base::iterators::count_is_at_least;
142///
143/// assert_eq!(count_is_at_least([1, 2, 3, 4].iter(), 3), true);
144/// assert_eq!(count_is_at_least([1, 2, 3, 4].iter(), 4), true);
145/// assert_eq!(count_is_at_least([1, 2, 3, 4].iter(), 5), false);
146/// assert_eq!(count_is_at_least(0.., 5), true);
147/// ```
148#[inline]
149pub fn count_is_at_least<I: Iterator>(xs: I, n: usize) -> bool {
150    xs.take(n).count() == n
151}
152
153/// Returns whether an iterator returns at most some number of values.
154///
155/// `count_is_at_most(xs, n)` is equivalent to `xs.count() <= n` for finite iterators, but doesn't
156/// hang if provided an infinite iterator.
157///
158/// # Examples
159/// ```
160/// use malachite_base::iterators::count_is_at_most;
161///
162/// assert_eq!(count_is_at_most([1, 2, 3, 4].iter(), 3), false);
163/// assert_eq!(count_is_at_most([1, 2, 3, 4].iter(), 4), true);
164/// assert_eq!(count_is_at_most([1, 2, 3, 4].iter(), 5), true);
165/// assert_eq!(count_is_at_most(0.., 5), false);
166/// ```
167#[inline]
168pub fn count_is_at_most<I: Iterator>(xs: I, n: usize) -> bool {
169    xs.take(n + 1).count() <= n
170}
171
172/// Returns whether an iterator never returns the same value twice.
173///
174/// `is_unique(xs)` is equivalent to `xs.unique().count() <= 1` for finite iterators, but is more
175/// efficient and doesn't hang if provided a non-unique infinite iterator.
176///
177/// This iterator will hang if given an infinite unique iterator.
178///
179/// # Examples
180/// ```
181/// use malachite_base::iterators::is_unique;
182///
183/// let empty: [u32; 0] = [];
184/// assert_eq!(is_unique(empty.iter()), true);
185/// assert_eq!(is_unique([1, 2, 3, 4].iter()), true);
186/// assert_eq!(is_unique([1, 2, 3, 1].iter()), false);
187/// assert_eq!(is_unique((0..).map(|i| i / 2)), false);
188/// ```
189#[inline]
190pub fn is_unique<I: Iterator>(xs: I) -> bool
191where
192    I::Item: Eq + Hash,
193{
194    let mut set = HashSet::new();
195    for x in xs {
196        if !set.insert(x) {
197            return false;
198        }
199    }
200    true
201}
202
203/// Returns the first and last elements of an iterator, or `None` if it is empty.
204///
205/// The iterator's elements must be cloneable, since if the iterator consists of a single element
206/// `x`, the result will be `(x, x)`.
207///
208/// This iterator will hang if given an infinite iterator.
209///
210/// # Examples
211/// ```
212/// use malachite_base::iterators::first_and_last;
213///
214/// let empty: [u32; 0] = [];
215/// assert_eq!(first_and_last(&mut empty.iter()), None);
216/// assert_eq!(first_and_last(&mut [1].iter().cloned()), Some((1, 1)));
217/// assert_eq!(first_and_last(&mut [1, 2, 3].iter().cloned()), Some((1, 3)));
218/// ```
219#[inline]
220pub fn first_and_last<I: Iterator>(xs: &mut I) -> Option<(I::Item, I::Item)>
221where
222    I::Item: Clone,
223{
224    xs.next().map(|first| {
225        if let Some(last) = xs.last() {
226            (first, last)
227        } else {
228            (first.clone(), first)
229        }
230    })
231}
232
233/// Folds an iterator by merging its elements in a balanced binary tree rather than linearly.
234///
235/// A linear fold combines an ever-growing accumulator with each new element, which is wasteful when
236/// the cost of `merge` grows more than linearly in the sizes of its arguments, as it does for
237/// bignum multiplication. This function instead maintains a stack of intermediate results, where
238/// the $k$th entry from the top is the merge of about $2^k$ consecutive elements, so merges tend to
239/// combine values of comparable size. The stack never holds more than $\lceil \log_2 n \rceil + 1$
240/// entries.
241///
242/// The `merge` function must be associative, but need not be commutative: `merge(a, b)` always
243/// receives a block of consecutive elements `a` immediately followed by the block `b`, and must
244/// store the combination of the two in `a`. `None` is returned if the iterator is empty.
245///
246/// If an element for which `is_absorbing` returns true is encountered, it is returned immediately,
247/// and the rest of the iterator is not consumed. This short-circuits, for example, a product that
248/// encounters a zero.
249///
250/// The pairing is oblivious to the actual sizes of the values, which is optimal when the elements
251/// have comparable sizes and within a factor of $O(\log n)$ of optimal in general. When one element
252/// dominates all the others combined (say, one million-bit factor among thousands of word-sized
253/// ones), a size-aware merge order can win that factor back; measured against a smallest-first
254/// heap, this function loses at most about $2.5\times$ on such distributions while winning on
255/// uniform ones. Callers with known-pathological size distributions can sort by size before
256/// folding.
257///
258/// # Worst-case complexity
259/// $T(n) = O(n\mu)$
260///
261/// $M(n) = O(m\log n)$
262///
263/// where $T$ is time, $M$ is additional memory, $n$ is `xs.count()`, $\mu$ is the worst-case time
264/// of `merge`, and $m$ is the largest size of any intermediate value.
265///
266/// # Examples
267/// ```
268/// use malachite_base::iterators::balanced_fold;
269///
270/// // The merges form a balanced tree, preserving the order of the elements.
271/// assert_eq!(
272///     balanced_fold(
273///         ["a", "b", "c", "d", "e"].into_iter().map(String::from),
274///         |_| false,
275///         |a, b| *a = format!("({a}{b})"),
276///     )
277///     .unwrap(),
278///     "(((ab)(cd))e)"
279/// );
280///
281/// // An absorbing element short-circuits.
282/// assert_eq!(
283///     balanced_fold([5u32, 6, 0, 7].into_iter(), |&x| x == 0, |a, b| *a *= b),
284///     Some(0)
285/// );
286///
287/// assert_eq!(
288///     balanced_fold([5u32, 6, 7].into_iter(), |_| false, |a, b| *a *= b),
289///     Some(210)
290/// );
291/// assert_eq!(
292///     balanced_fold(std::iter::empty::<u32>(), |_| false, |a, b| *a *= b),
293///     None
294/// );
295/// ```
296pub fn balanced_fold<T, I: Iterator<Item = T>>(
297    xs: I,
298    mut is_absorbing: impl FnMut(&T) -> bool,
299    mut merge: impl FnMut(&mut T, T),
300) -> Option<T> {
301    let mut stack: Vec<T> = Vec::new();
302    for (i, x) in xs.enumerate() {
303        if is_absorbing(&x) {
304            return Some(x);
305        }
306        let mut p = x;
307        // The stack behaves like a binary counter: after the (i + 1)th element, the entries
308        // correspond to the 1-bits of i + 1, and incrementing the counter merges once per trailing
309        // zero.
310        for _ in 0..(i + 1).trailing_zeros() {
311            let mut top = stack.pop().unwrap();
312            merge(&mut top, p);
313            p = top;
314        }
315        stack.push(p);
316    }
317    let mut result = stack.pop()?;
318    while let Some(mut top) = stack.pop() {
319        merge(&mut top, result);
320        result = top;
321    }
322    Some(result)
323}
324
325/// Groups elements of an iterator into intervals of adjacent elements that match a predicate. The
326/// endpoints of each interval are returned.
327///
328/// The intervals are inclusive.
329///
330/// This iterator will hang if given an infinite iterator.
331///
332/// # Examples
333/// ```
334/// use malachite_base::iterators::matching_intervals_in_iterator;
335///
336/// let xs = &[1, 2, 10, 11, 12, 7, 8, 16, 5];
337/// assert_eq!(
338///     matching_intervals_in_iterator(xs.iter().cloned(), |&x| x >= 10).as_slice(),
339///     &[(10, 12), (16, 16)]
340/// );
341/// assert_eq!(
342///     matching_intervals_in_iterator(xs.iter().cloned(), |&x| x < 10).as_slice(),
343///     &[(1, 2), (7, 8), (5, 5)]
344/// );
345/// ```
346#[inline]
347pub fn matching_intervals_in_iterator<I: Iterator, F: Fn(&I::Item) -> bool>(
348    xs: I,
349    predicate: F,
350) -> Vec<(I::Item, I::Item)>
351where
352    I::Item: Clone,
353{
354    xs.chunk_by(predicate)
355        .into_iter()
356        .filter_map(|(b, mut group)| if b { first_and_last(&mut group) } else { None })
357        .collect()
358}
359
360#[cfg(feature = "random")]
361/// An iterator that randomly produces another iterator's values, or produces a special value.
362///
363/// This `struct` is created by [`with_special_value`]; see its documentation for more.
364#[derive(Clone, Debug)]
365pub struct WithSpecialValue<I: Iterator>
366where
367    I::Item: Clone,
368{
369    bs: WeightedRandomBools,
370    special_value: I::Item,
371    xs: I,
372}
373
374#[cfg(feature = "random")]
375impl<I: Iterator> Iterator for WithSpecialValue<I>
376where
377    I::Item: Clone,
378{
379    type Item = I::Item;
380
381    fn next(&mut self) -> Option<I::Item> {
382        if self.bs.next().unwrap() {
383            Some(self.special_value.clone())
384        } else {
385            self.xs.next()
386        }
387    }
388}
389
390#[cfg(feature = "random")]
391/// An iterator that randomly produces another iterator's values, or produces a special value.
392///
393/// Let $n_p$ be `p_numerator`, $d_p$ be `p_denominator`, and let $p=n_p/d_p$.
394///
395/// Every time a value is to be generated, the iterator returns the special value with probability
396/// $p$, or else returns a value from the inner iterator.
397///
398/// If $p > 0$, the output length is infinite. Otherwise, it is the same as the length of `xs`.
399///
400/// # Panics
401/// Panics if `p_denominator` is 0 or `p_numerator` is greater than `p_denominator`.
402///
403/// # Examples
404/// ```
405/// use malachite_base::iterators::{prefix_to_string, with_special_value};
406/// use malachite_base::num::random::random_primitive_ints;
407/// use malachite_base::random::EXAMPLE_SEED;
408///
409/// assert_eq!(
410///     prefix_to_string(
411///         with_special_value(EXAMPLE_SEED, -1i16, 1, 2, &random_primitive_ints::<i16>),
412///         20
413///     ),
414///     "[-1, -1, -1, 2901, -1, -14200, -1, -1, -1, -30997, -8245, -5338, -1, -1, -20007, -1, -1, \
415///     -1, -1, -1, ...]"
416/// );
417/// ```
418pub fn with_special_value<I: Iterator>(
419    seed: Seed,
420    special_value: I::Item,
421    p_numerator: u64,
422    p_denominator: u64,
423    xs_gen: &dyn Fn(Seed) -> I,
424) -> WithSpecialValue<I>
425where
426    I::Item: Clone,
427{
428    WithSpecialValue {
429        bs: weighted_random_bools(seed.fork("bs"), p_numerator, p_denominator),
430        special_value,
431        xs: xs_gen(seed.fork("xs")),
432    }
433}
434
435#[cfg(feature = "random")]
436/// An iterator that randomly produces another iterator's values, or samples from a [`Vec`] of
437/// special values.
438///
439/// This `struct` is created by [`with_special_values`]; see its documentation for more.
440#[derive(Clone, Debug)]
441pub struct WithSpecialValues<I: Iterator>
442where
443    I::Item: Clone,
444{
445    bs: WeightedRandomBools,
446    special_values: RandomValuesFromVec<I::Item>,
447    xs: I,
448}
449
450#[cfg(feature = "random")]
451impl<I: Iterator> Iterator for WithSpecialValues<I>
452where
453    I::Item: Clone,
454{
455    type Item = I::Item;
456
457    fn next(&mut self) -> Option<I::Item> {
458        if self.bs.next().unwrap() {
459            self.special_values.next()
460        } else {
461            self.xs.next()
462        }
463    }
464}
465
466#[cfg(feature = "random")]
467/// An iterator that randomly produces another iterator's values, or produces a random special value
468/// from a [`Vec`].
469///
470/// Let $n_p$ be `p_numerator`, $d_p$ be `p_denominator`, and let $p=n_p/d_p$.
471///
472/// Every time a value is to be generated, the iterator uniformly samples the special values [`Vec`]
473/// with probability $p$, or else returns a value from the inner iterator.
474///
475/// If $p > 0$, the output length is infinite. Otherwise, it is the same as the length of `xs`.
476///
477/// # Worst-case complexity per iteration
478/// Constant time and additional memory.
479///
480/// # Panics
481/// Panics if `special_values` is empty, `p_denominator` is 0, or if `p_numerator` is greater than
482/// `p_denominator`.
483///
484/// # Examples
485/// ```
486/// use malachite_base::iterators::{prefix_to_string, with_special_values};
487/// use malachite_base::num::random::random_primitive_ints;
488/// use malachite_base::random::EXAMPLE_SEED;
489///
490/// assert_eq!(
491///     prefix_to_string(
492///         with_special_values(
493///             EXAMPLE_SEED,
494///             vec![1, 2, 3],
495///             1,
496///             2,
497///             &random_primitive_ints::<i16>
498///         ),
499///         20,
500///     ),
501///     "[3, 1, 3, 2901, 1, -14200, 2, 3, 1, -30997, -8245, -5338, 1, 1, -20007, 3, 1, 1, 1, 1, \
502///     ...]"
503/// );
504/// ```
505pub fn with_special_values<I: Iterator>(
506    seed: Seed,
507    special_values: Vec<I::Item>,
508    p_numerator: u64,
509    p_denominator: u64,
510    xs_gen: &dyn Fn(Seed) -> I,
511) -> WithSpecialValues<I>
512where
513    I::Item: Clone,
514{
515    WithSpecialValues {
516        bs: weighted_random_bools(seed.fork("bs"), p_numerator, p_denominator),
517        special_values: random_values_from_vec(seed.fork("special_values"), special_values),
518        xs: xs_gen(seed.fork("xs")),
519    }
520}
521
522/// Generates sliding windows of elements from an iterator.
523///
524/// This `struct` is created by [`iter_windows`]; see its documentation for more.
525#[derive(Clone, Debug)]
526pub struct IterWindows<I: Iterator>
527where
528    I::Item: Clone,
529{
530    xs: I,
531    window: VecDeque<I::Item>,
532    window_size: usize,
533}
534
535impl<I: Iterator> Iterator for IterWindows<I>
536where
537    I::Item: Clone,
538{
539    type Item = VecDeque<I::Item>;
540
541    fn next(&mut self) -> Option<VecDeque<I::Item>> {
542        if self.window.len() < self.window_size {
543            self.window = (&mut self.xs).take(self.window_size).collect();
544            if self.window.len() < self.window_size {
545                None
546            } else {
547                Some(self.window.clone())
548            }
549        } else {
550            let x = self.xs.next()?;
551            self.window.pop_front();
552            self.window.push_back(x);
553            Some(self.window.clone())
554        }
555    }
556}
557
558/// Returns windows of $n$ adjacent elements of an iterator, advancing the window by 1 in each
559/// iteration. The values are cloned each time a new window is generated.
560///
561/// The output length is $n - k + 1$, where $n$ is `xs.count()` and $k$ is `window_size`.
562///
563/// # Worst-case complexity per iteration
564/// $T(i) = O(\ell + T^\prime(i))$
565///
566/// $M(i) = O(\ell + M^\prime(i))$
567///
568/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
569/// $M^\prime$ are the time and memory functions of `xs`, and $\ell$ is `window_size`.
570///
571/// # Panics
572/// Panics if `window_size` is 0.
573///
574/// # Examples
575/// ```
576/// use itertools::Itertools;
577/// use malachite_base::iterators::iter_windows;
578///
579/// let xs = 0..=5;
580/// let windows = iter_windows(3, xs)
581///     .map(|ws| ws.iter().cloned().collect_vec())
582///     .collect_vec();
583/// assert_eq!(
584///     windows.iter().map(Vec::as_slice).collect_vec().as_slice(),
585///     &[&[0, 1, 2], &[1, 2, 3], &[2, 3, 4], &[3, 4, 5]]
586/// );
587/// ```
588pub fn iter_windows<I: Iterator>(window_size: usize, xs: I) -> IterWindows<I>
589where
590    I::Item: Clone,
591{
592    assert_ne!(window_size, 0);
593    IterWindows {
594        xs,
595        window: VecDeque::with_capacity(window_size),
596        window_size,
597    }
598}
599
600/// Converts a prefix of an iterator to a string.
601///
602/// Suppose the iterator generates $(a, b, c, d)$. If `max_len` is 3, this function will return the
603/// string `"[a, b, c, ...]"`. If `max_len` is 4 or more, this function will return `[a, b, c, d]`.
604///
605/// This function will attempt to advance the iterator `max_len + 1` times. The extra time is used
606/// determine whether the output string should contain an ellipsis.
607///
608/// # Panics
609/// Panics if `max_len` is 0.
610///
611/// # Examples
612/// ```
613/// use malachite_base::iterators::prefix_to_string;
614///
615/// assert_eq!(prefix_to_string(0..10, 3), "[0, 1, 2, ...]");
616/// assert_eq!(prefix_to_string(0..4, 5), "[0, 1, 2, 3]");
617/// ```
618pub fn prefix_to_string<I: Iterator>(mut xs: I, max_len: usize) -> String
619where
620    I::Item: Display,
621{
622    assert_ne!(max_len, 0);
623    let mut s = String::new();
624    s.push('[');
625    let mut first = true;
626    let mut done = false;
627    for _ in 0..max_len {
628        if let Some(x) = xs.next() {
629            if first {
630                first = false;
631            } else {
632                s.push_str(", ");
633            }
634            s.push_str(&x.to_string());
635        } else {
636            done = true;
637            break;
638        }
639    }
640    if !done && xs.next().is_some() {
641        s.push_str(", ...");
642    }
643    s.push(']');
644    s
645}
646
647/// An iterator that generates the Thue-Morse sequence. See [`thue_morse_sequence`] for more
648/// information.
649#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
650pub struct ThueMorseSequence(u64);
651
652impl Iterator for ThueMorseSequence {
653    type Item = bool;
654
655    fn next(&mut self) -> Option<bool> {
656        let b = self.0.count_ones().odd();
657        self.0 += 1;
658        Some(b)
659    }
660}
661
662/// Returns an iterator that generates the Thue-Morse sequence.
663///
664/// The output length is infinite.
665///
666/// # Worst-case complexity per iteration
667/// Constant time and additional memory.
668///
669/// # Examples
670/// ```
671/// use malachite_base::iterators::thue_morse_sequence;
672///
673/// let s: String = thue_morse_sequence()
674///     .take(100)
675///     .map(|b| if b { '1' } else { '0' })
676///     .collect();
677/// assert_eq!(
678///     s,
679///     "01101001100101101001011001101001100101100110100101101001100101101001011001101001011010011\
680///     00101100110"
681/// )
682/// ```
683#[inline]
684pub const fn thue_morse_sequence() -> ThueMorseSequence {
685    ThueMorseSequence(0)
686}
687
688/// Contains [`BitDistributor`](bit_distributor::BitDistributor), which helps generate tuples
689/// exhaustively.
690pub mod bit_distributor;
691/// Functions that compare adjacent iterator elements.
692pub mod comparison;
693/// Contains [`IteratorCache`](iterator_cache::IteratorCache), which remembers values produced by an
694/// iterator.
695pub mod iterator_cache;