primal_sieve/streaming/
primes.rs1use crate::wheel;
2use crate::streaming::{self, StreamingSieve};
3
4#[cfg(target_pointer_width = "32")]
5const SQRT: usize = 1 << 16;
6#[cfg(target_pointer_width = "64")]
7const SQRT: usize = 1 << 32;
8
9enum Early {
10 Two,
11 Three,
12 Five,
13 Done,
14}
15
16pub struct Primes {
33 early: Early,
34 base: usize,
35 ones: primal_bit::IntoOnes,
36 streaming: StreamingSieve,
37 sieving_primes: Option<Box<Primes>>,
38 left_over: Option<usize>,
39}
40
41impl Primes {
42 pub fn all() -> Primes {
53 Primes::sqrt(SQRT)
54 }
55
56 fn sqrt(sqrt: usize) -> Primes {
57 let (sieving, limit) = if sqrt < streaming::isqrt(streaming::SEG_LEN) {
58 (None, sqrt * sqrt)
59 } else {
60 (Some(Box::new(Primes::sqrt(streaming::isqrt(sqrt)))),
61 streaming::SEG_LEN)
62 };
63 let mut streaming = StreamingSieve::new(limit);
64
65 let ones = {
66 let (_, bits) = streaming.next().unwrap();
67 bits.clone().into_ones()
68 };
69
70 streaming.small = None;
72 streaming.limit = !0;
74
75 Primes {
76 early: Early::Two,
77 base: 0,
78 ones,
79 streaming,
80 sieving_primes: sieving,
81 left_over: None,
82 }
83 }
84
85 #[inline]
86 fn from_bit_index(&self, i: usize) -> Option<usize> {
87 let w = wheel::from_bit_index(i);
88 self.base.checked_add(w)
89 }
90
91 fn advance_ones(&mut self) -> bool {
92 let low = self.streaming.low;
93 let high = low.saturating_add(streaming::SEG_LEN);
94
95 for q in self.left_over.into_iter().chain(self.sieving_primes.as_mut().unwrap()) {
96 if q.saturating_mul(q) >= high {
97 self.left_over = Some(q);
98 break
99 }
100 if q > streaming::isqrt(streaming::SEG_LEN) {
101 self.streaming.add_sieving_prime(q, low);
102 }
103 }
104
105 match self.streaming.next() {
106 Some((_, bits)) => {
107 self.base = low;
108 self.ones = bits.clone().into_ones();
109 true
110 },
111 None => false,
112 }
113 }
114}
115
116impl Iterator for Primes {
118 type Item = usize;
119
120 #[inline]
121 fn next(&mut self) -> Option<usize> {
122 match self.early {
123 Early::Done => {}
124 Early::Two => {
125 self.early = Early::Three;
126 return Some(2)
127 }
128 Early::Three => {
129 self.early = Early::Five;
130 return Some(3)
131 }
132 Early::Five => {
133 self.early = Early::Done;
134 return Some(5)
135 }
136 }
137
138 loop {
139 if let Some(i) = self.ones.next() {
140 return self.from_bit_index(i);
141 }
142 if !self.advance_ones() {
143 return None;
144 }
145 }
146 }
147
148 fn fold<Acc, F>(mut self, mut acc: Acc, mut f: F) -> Acc
149 where
150 F: FnMut(Acc, Self::Item) -> Acc
151 {
152 match self.early {
153 Early::Done => {}
154 Early::Two => {
155 acc = f(acc, 2);
156 acc = f(acc, 3);
157 acc = f(acc, 5);
158 }
159 Early::Three => {
160 acc = f(acc, 3);
161 acc = f(acc, 5);
162 }
163 Early::Five => {
164 acc = f(acc, 5);
165 }
166 }
167 loop {
168 while let Some(i) = self.ones.next() {
169 match self.from_bit_index(i) {
170 Some(p) => acc = f(acc, p),
171 None => return acc,
172 }
173 }
174 if !self.advance_ones() {
175 return acc;
176 }
177 }
178 }
179}
180
181#[cfg(test)]
182mod tests {
183 use crate::Sieve;
184 use super::Primes;
185
186 fn check_equality(limit: usize) {
187 let sieve = Sieve::new(limit);
188
189 let real = sieve.primes_from(0).take_while(|x| *x < limit);
190 let computed = Primes::all().take_while(|x| *x < limit);
191
192 let mut i = 0;
193 for (r, c) in real.zip(computed) {
194 assert_eq!(c, r);
195 i += 1;
196 }
197 assert_eq!(sieve.prime_pi(limit), i);
198 }
199
200 #[test]
201 fn equality() {
202 check_equality(20_000_000);
203 }
204
205 #[test]
206 fn equality_huge() {
207 let limit = if cfg!(feature = "slow_tests") {
208 ::std::u32::MAX as usize
210 } else {
211 100_000_000
212 };
213 check_equality(limit);
214 }
215
216 #[test]
217 #[should_panic = "123456791"]
218 fn fold() {
219 Primes::all().fold((), |(), p| {
222 if p > 123456789 {
223 panic!("{}", p);
224 }
225 })
226 }
227}