1use std::{cell::RefCell, mem};
2
3use super::UNDER_100000;
4
5fn is_prime_known(n: u32, known: &[u32]) -> bool {
9 !known.iter().take_while(|&&p| p < n).any(|p| n % p == 0)
10}
11
12pub struct Primes<'a> {
13 cache: &'a Cache,
14 next: u32,
15}
16
17impl Iterator for Primes<'_> {
18 type Item = u32;
19
20 fn next(&mut self) -> Option<Self::Item> {
21 let next = if self.next == 2 {
22 3
23 } else {
24 let mut next = self.next;
25 while !self.cache.is_prime(next) {
26 next += 2;
27 }
28 next
29 };
30 Some(mem::replace(&mut self.next, next))
31 }
32}
33
34#[derive(Default)]
35pub struct Cache {
36 known: RefCell<Vec<u32>>,
37}
38
39impl Cache {
40 fn extend_past(&self, n: u32) {
41 let mut known = self.known.borrow_mut();
42 if known.is_empty() {
43 known.extend_from_slice(&UNDER_100000);
44 }
45 let last = known[known.len() - 1];
46 if last < n {
47 let limit = n * 2; for candidate in (last..limit).step_by(2) {
49 if is_prime_known(candidate, &known) {
50 known.push(candidate);
51 }
52 }
53 }
54 }
55
56 pub fn is_prime(&self, n: u32) -> bool {
57 self.extend_past(n);
58 self.known.borrow().binary_search(&n).is_ok()
59 }
60
61 #[must_use]
62 pub fn new(known: &[u32]) -> Cache {
63 Cache {
64 known: RefCell::new(known.to_vec()),
65 }
66 }
67
68 pub fn primes(&self) -> Primes {
69 Primes {
70 cache: self,
71 next: 2,
72 }
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use crate::UNDER_1000;
79
80 use super::*;
81
82 #[ignore = "slow"]
83 #[test]
84 fn test_cache_is_prime() {
85 let cache = Cache::new(&UNDER_1000);
86 for n in 0..100_000 {
87 assert_eq!(cache.is_prime(n), UNDER_100000.contains(&n));
88 }
89 }
90}