prime_data/data/iterators/
coprime.rs

1use std::ops::RangeInclusive;
2use crate::{K_VALUES, data::utils};
3
4/// Struct that iterates over numbers that are coprime with 2, 3, and 5 (a.k.a 30)
5/// 
6/// To learn more, read the [guide](crate::guide::iterators::_1_coprime).
7/// 
8/// # Examples
9/// 
10/// ```
11/// use prime_data::CoprimeIter;
12/// 
13/// let mut iter = CoprimeIter::new(8..=22);
14/// assert_eq!(iter.next(), Some(11));
15/// assert_eq!(iter.next(), Some(13));
16/// assert_eq!(iter.next(), Some(17));
17/// assert_eq!(iter.next(), Some(19));
18/// assert_eq!(iter.next(), None);
19/// ```
20pub struct CoprimeIter {
21    current: (u64, usize),
22    stop_after: u64,
23}
24
25impl CoprimeIter {
26    /// Creates a new iterator over numbers coprime with 30
27    pub fn new(range: RangeInclusive<u64>) -> Self {
28
29        let (start, end) = range.into_inner();
30
31        let offset = start / 30;
32        let value = (start % 30) as u8;
33        let index = utils::unwrap_any(K_VALUES.binary_search(&value));
34
35        Self { current: (offset, index), stop_after: end }
36    }
37}
38
39impl Iterator for CoprimeIter {
40    type Item = u64;
41
42    fn next(&mut self) -> Option<Self::Item> {
43        let (offset, index) = self.current;
44        let current_value = 30 * offset + (K_VALUES[index] as u64);
45
46        if current_value > self.stop_after { return None }
47
48        if index < 7 {
49            self.current = (offset, index + 1);
50        } else {
51            self.current = (offset + 1, 0);
52        }
53
54        Some(current_value)
55    }
56}