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;