const_primes/cache/
mod.rs

1//! This module contains the implementation of the type [`Primes`] (and related iterators),
2//! which functions as a cache of prime numbers for related computations.
3
4mod prime_factors;
5mod primes_into_iter;
6mod primes_iter;
7
8pub use prime_factors::{PrimeFactorization, PrimeFactors};
9pub use primes_into_iter::PrimesIntoIter;
10pub use primes_iter::PrimesIter;
11
12use crate::{primes, Underlying};
13
14// region: Primes<N>
15
16/// A wrapper around an array that consists of the first `N` primes.
17/// Can use those primes for related computations.
18/// Ensures that `N` is non-zero at compile time.
19///
20/// # Examples
21///
22/// Basic usage:
23///
24/// ```
25/// # use const_primes::Primes;
26/// const PRIMES: Primes<3> = Primes::new();
27/// assert_eq!(PRIMES[2], 5);
28/// assert_eq!(PRIMES.as_array(), &[2, 3, 5]);
29/// ```
30///
31/// Reuse sieved primes for other computations:
32///
33/// ```
34/// # use const_primes::Primes;
35/// const CACHE: Primes<100> = Primes::new();
36/// const PRIME_CHECK: Option<bool> = CACHE.is_prime(541);
37/// const PRIME_COUNT: Option<usize> = CACHE.prime_pi(200);
38///
39/// assert_eq!(PRIME_CHECK, Some(true));
40/// assert_eq!(PRIME_COUNT, Some(46));
41///
42/// // If questions are asked about numbers outside the cache it returns None
43/// assert_eq!(CACHE.is_prime(1000), None);
44/// assert_eq!(CACHE.prime_pi(1000), None);
45/// ```
46#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
47#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
48#[cfg_attr(
49    feature = "zerocopy",
50    derive(zerocopy::IntoBytes, zerocopy::Immutable, zerocopy::KnownLayout)
51)]
52#[cfg_attr(
53    feature = "rkyv",
54    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
55)]
56#[cfg_attr(feature = "zerocopy", repr(transparent))]
57pub struct Primes<const N: usize>(
58    #[cfg_attr(feature = "serde", serde(with = "serde_arrays"))] [Underlying; N],
59);
60
61impl<const N: usize> Primes<N> {
62    /// Generates a new instance that contains the first `N` primes.
63    ///
64    /// Uses a [segmented sieve of Eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes#Segmented_sieve).
65    ///
66    /// # Examples
67    ///
68    /// Basic usage:
69    ///
70    /// ```
71    /// # use const_primes::Primes;
72    /// const PRIMES: Primes<3> = Primes::new();
73    /// assert_eq!(PRIMES.as_array(), &[2, 3, 5]);
74    /// ```
75    ///
76    /// Determine `N` through type inference
77    ///
78    /// ```
79    /// # use const_primes::Primes;
80    /// assert_eq!(Primes::new().as_array(), &[2, 3, 5, 7, 11]);
81    /// ```
82    ///
83    /// Specify `N` manually
84    ///
85    /// ```
86    /// # use const_primes::Primes;
87    /// let primes = Primes::<5>::new();
88    /// assert_eq!(primes.as_array(), &[2, 3, 5, 7, 11]);
89    /// ```
90    ///
91    /// # Errors
92    ///
93    /// It is a compile error to use an `N` of 0.
94    ///
95    /// ```compile_fail
96    /// # use const_primes::Primes;
97    /// const NO_PRIMES: Primes<0> = Primes::new();
98    /// ```
99    #[must_use = "the associated method only returns a new value"]
100    pub const fn new() -> Self {
101        const { assert!(N > 0, "`N` must be at least 1") }
102        Self(primes())
103    }
104
105    /// Returns whether `n` is prime, if it is smaller than or equal to the largest prime in `self`.
106    ///
107    /// Uses a binary search.
108    ///
109    /// # Example
110    ///
111    /// Basic usage:
112    ///
113    /// ```
114    /// # use const_primes::Primes;
115    /// const PRIMES: Primes<100> = Primes::new();
116    /// const TMOLTUAE: Option<bool> = PRIMES.is_prime(42);
117    ///
118    /// assert_eq!(PRIMES.is_prime(13), Some(true));
119    /// assert_eq!(TMOLTUAE, Some(false));
120    /// // 1000 is larger than 541, the largest prime in the cache,
121    /// // so we don't know whether it's prime.
122    /// assert_eq!(PRIMES.is_prime(1000), None);
123    /// ```
124    #[must_use = "the method only returns a new value and does not modify `self`"]
125    pub const fn is_prime(&self, n: u32) -> Option<bool> {
126        match self.binary_search(n) {
127            Ok(_) => Some(true),
128            Err(i) => {
129                if i < N {
130                    Some(false)
131                } else {
132                    None
133                }
134            }
135        }
136    }
137
138    /// Returns the number of primes smaller than or equal to `n`, if it's smaller than or equal to the largest prime in `self`.
139    ///
140    /// Uses a binary search to count the primes.
141    ///
142    /// # Example
143    ///
144    /// Basic usage:
145    ///
146    /// ```
147    /// # use const_primes::Primes;
148    /// const CACHE: Primes<100> = Primes::new();
149    /// const COUNT1: Option<usize> = CACHE.prime_pi(500);
150    /// const COUNT2: Option<usize> = CACHE.prime_pi(11);
151    /// const OUT_OF_BOUNDS: Option<usize> = CACHE.prime_pi(1_000);
152    ///
153    /// assert_eq!(COUNT1, Some(95));
154    /// assert_eq!(COUNT2, Some(5));
155    /// assert_eq!(OUT_OF_BOUNDS, None);
156    /// ```
157    #[must_use = "the method only returns a new value and does not modify `self`"]
158    pub const fn prime_pi(&self, n: Underlying) -> Option<usize> {
159        match self.binary_search(n) {
160            Ok(i) => Some(i + 1),
161            Err(maybe_i) => {
162                if maybe_i < N {
163                    Some(maybe_i)
164                } else {
165                    None
166                }
167            }
168        }
169    }
170
171    /// Returns an iterator over the prime factors of the given number in increasing order as well as their
172    /// multiplicities.
173    ///
174    /// If a number contains prime factors larger than the largest prime in `self`,
175    /// they will not be yielded by the iterator, but their product can be retrieved by calling
176    /// [`remainder`](PrimeFactorization::remainder) on the iterator.
177    ///
178    /// If you do not need to know the multiplicity of each prime factor,
179    /// it may be faster to use [`prime_factors`](Self::prime_factors).
180    ///
181    /// # Examples
182    ///
183    /// Basic usage:
184    ///
185    /// ```
186    /// # use const_primes::Primes;
187    /// // Contains the primes [2, 3, 5]
188    /// const CACHE: Primes<3> = Primes::new();
189    ///
190    /// assert_eq!(CACHE.prime_factorization(15).collect::<Vec<_>>(), &[(3, 1), (5, 1)]);
191    /// ```
192    ///
193    /// The second element of the returned tuples is the multiplicity of the prime in the number:
194    ///
195    /// ```
196    /// # use const_primes::Primes;
197    /// # const CACHE: Primes<3> = Primes::new();
198    /// // 1024 = 2^10
199    /// assert_eq!(CACHE.prime_factorization(1024).next(), Some((2, 10)));
200    /// ```
201    ///
202    /// 294 has 7 as a prime factor, but 7 is not in the cache:
203    ///
204    /// ```
205    /// # use const_primes::Primes;
206    /// # const CACHE: Primes<3> = Primes::new();
207    /// // 294 = 2*3*7*7
208    /// let mut factorization_of_294 = CACHE.prime_factorization(294);
209    ///
210    /// // only 2 and 3 are in the cache:
211    /// assert_eq!(factorization_of_294.by_ref().collect::<Vec<_>>(), &[(2, 1), (3, 1)]);
212    ///
213    /// // the factor of 7*7 can be found with the remainder function:
214    /// assert_eq!(factorization_of_294.remainder(), Some(49));
215    /// ```
216    #[inline]
217    pub fn prime_factorization(&self, number: Underlying) -> PrimeFactorization<'_> {
218        PrimeFactorization::new(&self.0, number)
219    }
220
221    /// Returns an iterator over all the prime factors of the given number in increasing order.
222    ///
223    /// If a number contains prime factors larger than the largest prime in `self`,
224    /// they will not be yielded by the iterator, but their product can be retrieved by calling
225    /// [`remainder`](PrimeFactors::remainder) on the iterator.
226    ///
227    /// If you also wish to know the multiplicity of each prime factor of the number,
228    /// take a look at [`prime_factorization`](Self::prime_factorization).
229    ///
230    /// # Examples
231    ///
232    /// ```
233    /// # use const_primes::Primes;
234    /// // Contains [2, 3, 5]
235    /// const CACHE: Primes<3> = Primes::new();
236    ///
237    /// assert_eq!(CACHE.prime_factors(3*5).collect::<Vec<_>>(), &[3, 5]);
238    /// assert_eq!(CACHE.prime_factors(2*2*2*2*3).collect::<Vec<_>>(), &[2, 3]);
239    /// ```
240    ///
241    /// 294 has 7 as a prime factor, but 7 is not in the cache:
242    ///
243    /// ```
244    /// # use const_primes::Primes;
245    /// # const CACHE: Primes<3> = Primes::new();
246    /// // 294 = 2*3*7*7
247    /// let mut factors_of_294 = CACHE.prime_factors(294);
248    ///
249    /// // only 2 and 3 are in the cache
250    /// assert_eq!(factors_of_294.by_ref().collect::<Vec<_>>(), &[2, 3]);
251    ///
252    /// // the factor of 7*7 can be found with the remainder function
253    /// assert_eq!(factors_of_294.remainder(), Some(49));
254    /// ```
255    #[inline]
256    pub fn prime_factors(&self, number: Underlying) -> PrimeFactors<'_> {
257        PrimeFactors::new(&self.0, number)
258    }
259
260    // region: Next prime
261
262    /// Returns the largest prime less than `n`.  
263    /// If `n` is 0, 1, 2, or larger than the largest prime in `self` this returns `None`.
264    ///
265    /// Uses a binary search.
266    ///
267    /// # Example
268    ///
269    /// ```
270    /// # use const_primes::Primes;
271    /// const CACHE: Primes<100> = Primes::new();
272    /// const PREV400: Option<u32> = CACHE.previous_prime(400);
273    /// assert_eq!(PREV400, Some(397));
274    /// ```
275    #[must_use = "the method only returns a new value and does not modify `self`"]
276    pub const fn previous_prime(&self, n: Underlying) -> Option<Underlying> {
277        if n <= 2 {
278            None
279        } else {
280            match self.binary_search(n) {
281                Ok(i) | Err(i) => {
282                    if i > 0 && i < N {
283                        Some(self.0[i - 1])
284                    } else {
285                        None
286                    }
287                }
288            }
289        }
290    }
291
292    /// Returns the smallest prime greater than `n`.  
293    /// If `n` is larger than or equal to the largest prime in `self` this returns `None`.
294    ///
295    /// Uses a binary search.
296    ///
297    /// # Example
298    ///
299    /// ```
300    /// # use const_primes::Primes;
301    /// const CACHE: Primes<100> = Primes::new();
302    /// const NEXT: Option<u32> = CACHE.next_prime(400);
303    /// assert_eq!(NEXT, Some(401));
304    /// ```
305    #[must_use = "the method only returns a new value and does not modify `self`"]
306    pub const fn next_prime(&self, n: Underlying) -> Option<Underlying> {
307        match self.binary_search(n) {
308            Ok(i) => {
309                if i + 1 < self.len() {
310                    Some(self.0[i + 1])
311                } else {
312                    None
313                }
314            }
315            Err(i) => {
316                if i < N {
317                    Some(self.0[i])
318                } else {
319                    None
320                }
321            }
322        }
323    }
324
325    // endregion: Next prime
326
327    /// Searches the underlying array of primes for the target integer.
328    ///
329    /// If the target is found it returns a [`Result::Ok`] that contains the index of the matching element.
330    /// If the target is not found in the array a [`Result::Err`] is returned that indicates where the
331    /// target could be inserted into the array while maintaining the sorted order.
332    ///
333    /// # Example
334    ///
335    /// Basic usage:
336    ///
337    /// ```
338    /// # use const_primes::Primes;
339    /// // [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
340    /// const PRIMES: Primes<10> = Primes::new();
341    ///
342    /// const WHERE_29: Result<usize, usize> = PRIMES.binary_search(29);
343    /// const WHERE_6: Result<usize, usize> = PRIMES.binary_search(6);
344    /// const WHERE_1000: Result<usize, usize> = PRIMES.binary_search(1_000);
345    ///
346    /// assert_eq!(WHERE_29, Ok(9));
347    /// assert_eq!(WHERE_6, Err(3));
348    /// assert_eq!(WHERE_1000, Err(10));
349    /// ```
350    #[must_use = "the method only returns a new value and does not modify `self`"]
351    pub const fn binary_search(&self, target: Underlying) -> Result<usize, usize> {
352        let mut size = N;
353        let mut left = 0;
354        let mut right = size;
355        while left < right {
356            let mid = left + size / 2;
357            let candidate = self.0[mid];
358            if candidate < target {
359                left = mid + 1;
360            } else if candidate > target {
361                right = mid;
362            } else {
363                return Ok(mid);
364            }
365            size = right - left;
366        }
367        Err(left)
368    }
369
370    // region: Conversions
371
372    /// Converts `self` into an array of size `N`.
373    ///
374    /// # Example
375    ///
376    /// Basic usage:
377    ///
378    /// ```
379    /// # use const_primes::Primes;
380    /// const PRIMES: [u32; 5] = Primes::new().into_array();
381    /// assert_eq!(PRIMES, [2, 3, 5, 7, 11]);
382    /// ```
383    #[inline]
384    #[must_use = "the method only returns a new value and does not modify `self`"]
385    pub const fn into_array(self) -> [Underlying; N] {
386        self.0
387    }
388
389    /// Returns a reference to the underlying array.
390    #[inline]
391    #[must_use = "the method only returns a new value and does not modify `self`"]
392    pub const fn as_array(&self) -> &[Underlying; N] {
393        &self.0
394    }
395
396    /// Returns a slice that contains the entire underlying array.
397    #[inline]
398    #[must_use = "the method only returns a new value and does not modify `self`"]
399    pub const fn as_slice(&self) -> &[Underlying] {
400        self.0.as_slice()
401    }
402
403    /// Returns a borrowing iterator over the primes.
404    ///
405    /// # Example
406    ///
407    /// Basic usage:
408    ///
409    /// ```
410    /// # use const_primes::Primes;
411    /// const PRIMES: Primes<10> = Primes::new();
412    ///
413    /// let mut primes = PRIMES.iter();
414    ///
415    /// assert_eq!(primes.nth(5), Some(&13));
416    /// assert_eq!(primes.next(), Some(&17));
417    /// assert_eq!(primes.as_slice(), &[19, 23, 29]);
418    /// ```
419    #[inline]
420    pub fn iter(&self) -> PrimesIter<'_> {
421        PrimesIter::new(IntoIterator::into_iter(&self.0))
422    }
423
424    // endregion: Conversions
425
426    /// Returns a reference to the element at the given index if it is within bounds.
427    ///
428    /// # Example
429    ///
430    /// Basic usage:
431    ///
432    /// ```
433    /// # use const_primes::Primes;
434    /// const PRIMES: Primes<5> = Primes::new();
435    /// const THIRD_PRIME: Option<&u32> = PRIMES.get(2);
436    /// assert_eq!(THIRD_PRIME, Some(&5));
437    /// ```
438    #[inline]
439    #[must_use = "the method only returns a new value and does not modify `self`"]
440    pub const fn get(&self, index: usize) -> Option<&Underlying> {
441        if index < N {
442            Some(&self.0[index])
443        } else {
444            None
445        }
446    }
447
448    /// Returns a reference to the last prime in `self`. This is also the largest prime in `self`.
449    ///
450    /// # Example
451    ///
452    /// Basic usage:
453    ///
454    /// ```
455    /// # use const_primes::Primes;
456    /// const PRIMES: Primes<5> = Primes::new();
457    /// assert_eq!(PRIMES.last(), &11);
458    /// ```
459    #[inline]
460    #[must_use = "the method only returns a new value and does not modify `self`"]
461    pub const fn last(&self) -> &Underlying {
462        match self.0.last() {
463            Some(l) => l,
464            None => panic!("unreachable: an empty `Primes<N>` can not be created"),
465        }
466    }
467
468    /// Returns the number of primes in `self`.
469    ///
470    /// # Example
471    ///
472    /// Basic usage:
473    ///
474    /// ```
475    /// # use const_primes::Primes;
476    /// const PRIMES: Primes<5> = Primes::new();
477    /// assert_eq!(PRIMES.len(), 5);
478    /// ```
479    #[inline]
480    #[must_use = "the method only returns a new value and does not modify `self`"]
481    // Can never be empty since we panic if the user tries to create an empty `Primes`.
482    #[allow(clippy::len_without_is_empty)]
483    pub const fn len(&self) -> usize {
484        N
485    }
486
487    /// Returns the value of the Euler totient function of `n`:
488    /// the number of positive integers up to `n` that are relatively prime to it.
489    ///
490    /// # Example
491    ///
492    /// ```
493    /// # use const_primes::{Primes, cache::PartialTotient};
494    /// const CACHE: Primes<3> = Primes::new();
495    /// const TOTIENT_OF_6: Result<u32, PartialTotient> = CACHE.totient(2*3);
496    ///
497    /// assert_eq!(TOTIENT_OF_6, Ok(2));
498    /// ```
499    ///
500    /// # Errors
501    ///
502    /// The totient function is computed here as the product over all factors of the form p^(k-1)*(p-1) where
503    /// p is the primes in the prime factorization of `n` and k is their multiplicity.
504    /// If `n` contains prime factors that are not part of `self`, a [`Result::Err`] is returned
505    /// that contains a [`PartialTotient`] struct that contains the result from using only the primes in `self`,
506    /// as well as the product of the prime factors that are not included in `self`.
507    ///
508    /// # Error example
509    ///
510    /// The number 2450 is equal to 2\*5\*5\*7\*7.
511    /// If the cache does not contain 7 the function runs out of primes after 5,
512    /// and can not finish the computation:
513    ///
514    /// ```
515    /// # use const_primes::{Primes, cache::PartialTotient};
516    /// // Contains the primes [2, 3, 5]
517    /// const CACHE: Primes<3> = Primes::new();
518    /// const TOTIENT_OF_2450: Result<u32, PartialTotient> = CACHE.totient(2*5*5*7*7);
519    ///
520    /// assert_eq!(
521    ///     TOTIENT_OF_2450,
522    ///     Err( PartialTotient {
523    /// //                 totient(2*5*5) = 20
524    ///         totient_using_known_primes: 20,
525    ///         product_of_unknown_prime_factors: 49
526    ///     })
527    /// );
528    /// ```
529    pub const fn totient(&self, mut n: Underlying) -> Result<Underlying, PartialTotient> {
530        if n == 0 {
531            return Ok(0);
532        }
533
534        let mut i = 0;
535        let mut ans = 1;
536        while let Some(&prime) = self.get(i) {
537            let mut count = 0;
538            while n % prime == 0 {
539                n /= prime;
540                count += 1;
541            }
542
543            if count > 0 {
544                ans *= prime.pow(count - 1) * (prime - 1);
545            }
546
547            if n == 1 {
548                break;
549            }
550            i += 1;
551        }
552
553        if n == 1 {
554            Ok(ans)
555        } else {
556            Err(PartialTotient {
557                totient_using_known_primes: ans,
558                product_of_unknown_prime_factors: n,
559            })
560        }
561    }
562}
563
564/// Contains the result of a partially successful evaluation of the [`totient`](Primes::totient) function.
565#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
566#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
567#[cfg_attr(
568    feature = "rkyv",
569    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
570)]
571pub struct PartialTotient {
572    /// The result of computing the totient function with only the primes in the related [`Primes`] struct.
573    pub totient_using_known_primes: Underlying,
574    /// The product of all remaining prime factors of the number.
575    pub product_of_unknown_prime_factors: Underlying,
576}
577
578impl<const N: usize> Default for Primes<N> {
579    /// It is a compile error if `N` is 0.
580    fn default() -> Self {
581        const { assert!(N > 0, "`N` must be at least 1") }
582        Self(primes())
583    }
584}
585
586impl<const N: usize, I> core::ops::Index<I> for Primes<N>
587where
588    I: core::slice::SliceIndex<[Underlying]>,
589{
590    type Output = I::Output;
591    #[inline]
592    fn index(&self, index: I) -> &Self::Output {
593        self.0.index(index)
594    }
595}
596
597impl<const N: usize> From<Primes<N>> for [Underlying; N] {
598    #[inline]
599    fn from(const_primes: Primes<N>) -> Self {
600        const_primes.0
601    }
602}
603
604// region: AsRef
605
606impl<const N: usize> AsRef<[Underlying]> for Primes<N> {
607    #[inline]
608    fn as_ref(&self) -> &[Underlying] {
609        &self.0
610    }
611}
612
613impl<const N: usize> AsRef<[Underlying; N]> for Primes<N> {
614    #[inline]
615    fn as_ref(&self) -> &[Underlying; N] {
616        &self.0
617    }
618}
619
620// endregion: AsRef
621
622// region: IntoIterator
623
624impl<const N: usize> IntoIterator for Primes<N> {
625    type Item = Underlying;
626    type IntoIter = PrimesIntoIter<N>;
627    #[inline]
628    fn into_iter(self) -> Self::IntoIter {
629        PrimesIntoIter::new(self.0.into_iter())
630    }
631}
632
633impl<'a, const N: usize> IntoIterator for &'a Primes<N> {
634    type IntoIter = PrimesIter<'a>;
635    type Item = &'a Underlying;
636    fn into_iter(self) -> Self::IntoIter {
637        PrimesIter::new(IntoIterator::into_iter(&self.0))
638    }
639}
640
641// endregion: IntoIterator
642
643// endregion: Primes<N>
644
645#[cfg(test)]
646mod test {
647    use crate::next_prime;
648
649    use super::*;
650
651    // region: TraitImpls
652
653    #[test]
654    fn verify_impl_from_primes_traits() {
655        const N: usize = 10;
656        const P: Primes<N> = Primes::new();
657        let p: [Underlying; N] = P.into();
658        assert_eq!(p, P.as_ref());
659        assert_eq!(
660            P.as_array(),
661            <Primes<N> as AsRef<[Underlying; N]>>::as_ref(&P)
662        );
663    }
664
665    #[test]
666    fn check_into_iter() {
667        const P: Primes<10> = Primes::new();
668        for (i, prime) in P.into_iter().enumerate() {
669            assert_eq!(prime, [2, 3, 5, 7, 11, 13, 17, 19, 23, 29][i]);
670        }
671    }
672
673    // endregion: TraitImpls
674
675    #[test]
676    fn check_binary_search() {
677        const CACHE: Primes<100> = Primes::new();
678        type BSResult = Result<usize, usize>;
679        const FOUND2: BSResult = CACHE.binary_search(2);
680        const INSERT0: BSResult = CACHE.binary_search(0);
681        const INSERT4: BSResult = CACHE.binary_search(4);
682        const FOUND541: BSResult = CACHE.binary_search(541);
683        const NOINFO542: BSResult = CACHE.binary_search(542);
684        const BIG: BSResult = CACHE.binary_search(1000000);
685        assert_eq!(FOUND2, Ok(0));
686        assert_eq!(INSERT0, Err(0));
687        assert_eq!(INSERT4, Err(2));
688        assert_eq!(FOUND541, Ok(99));
689        assert_eq!(NOINFO542, Err(100));
690        assert_eq!(BIG, Err(100));
691    }
692
693    #[test]
694    fn test_into_iter() {
695        const PRIMES: Primes<10> = Primes::new();
696
697        for (&prime, ans) in (&PRIMES)
698            .into_iter()
699            .zip([2, 3, 5, 7, 11, 13, 17, 19, 23, 29])
700        {
701            assert_eq!(prime, ans);
702        }
703    }
704
705    #[test]
706    fn check_previous_prime() {
707        const CACHE: Primes<100> = Primes::new();
708        const PREV0: Option<Underlying> = CACHE.previous_prime(0);
709        const PREV400: Option<Underlying> = CACHE.previous_prime(400);
710        const PREV541: Option<Underlying> = CACHE.previous_prime(541);
711        const PREV542: Option<Underlying> = CACHE.previous_prime(542);
712        const PREVS: [Underlying; 18] = [
713            2, 3, 3, 5, 5, 7, 7, 7, 7, 11, 11, 13, 13, 13, 13, 17, 17, 19,
714        ];
715        for (i, prev) in PREVS.into_iter().enumerate() {
716            assert_eq!(Some(prev), CACHE.previous_prime(i as u32 + 3));
717        }
718        assert_eq!(PREV0, None);
719        assert_eq!(PREV400, Some(397));
720        assert_eq!(PREV541, Some(523));
721        assert_eq!(PREV542, None);
722    }
723
724    #[test]
725    fn check_prime_factorization() {
726        const CACHE: Primes<3> = Primes::new();
727
728        let mut factorization_of_14 = CACHE.prime_factorization(14);
729
730        assert_eq!(factorization_of_14.next(), Some((2, 1)));
731        assert_eq!(factorization_of_14.next(), None);
732        assert_eq!(factorization_of_14.remainder(), Some(7));
733
734        let mut factorization_of_15 = CACHE.prime_factorization(15);
735
736        assert_eq!(factorization_of_15.next(), Some((3, 1)));
737        assert_eq!(factorization_of_15.next(), Some((5, 1)));
738        assert!(factorization_of_15.remainder().is_none());
739
740        let mut factorization_of_270 = CACHE.prime_factorization(2 * 3 * 3 * 3 * 5);
741        assert_eq!(factorization_of_270.next(), Some((2, 1)));
742        assert_eq!(factorization_of_270.next(), Some((3, 3)));
743        assert_eq!(factorization_of_270.next(), Some((5, 1)));
744    }
745
746    #[test]
747    fn check_prime_factors() {
748        const CACHE: Primes<3> = Primes::new();
749
750        let mut factors_of_14 = CACHE.prime_factors(14);
751
752        assert_eq!(factors_of_14.next(), Some(2));
753        assert_eq!(factors_of_14.next(), None);
754        assert_eq!(factors_of_14.remainder(), Some(7));
755
756        let mut factors_of_15 = CACHE.prime_factors(15);
757        assert_eq!(factors_of_15.next(), Some(3));
758        assert_eq!(factors_of_15.next(), Some(5));
759        assert!(factors_of_15.remainder().is_none());
760
761        let mut factors_of_270 = CACHE.prime_factors(2 * 3 * 3 * 3 * 5);
762        assert_eq!(factors_of_270.next(), Some(2));
763        assert_eq!(factors_of_270.next(), Some(3));
764        assert_eq!(factors_of_270.next(), Some(5));
765    }
766
767    #[test]
768    fn check_next_prime() {
769        const CACHE: Primes<100> = Primes::new();
770        const SPGEQ0: Option<Underlying> = CACHE.next_prime(0);
771        const SPGEQ400: Option<Underlying> = CACHE.next_prime(400);
772        const SPGEQ541: Option<Underlying> = CACHE.next_prime(540);
773        const SPGEQ542: Option<Underlying> = CACHE.next_prime(541);
774        assert_eq!(SPGEQ0, Some(2));
775        assert_eq!(SPGEQ400, Some(401));
776        assert_eq!(SPGEQ541, Some(541));
777        assert_eq!(SPGEQ542, None);
778
779        const N: usize = 31;
780        const NEXT_PRIME: [u32; N] = [
781            2, 2, 3, 5, 5, 7, 7, 11, 11, 11, 11, 13, 13, 17, 17, 17, 17, 19, 19, 23, 23, 23, 23,
782            29, 29, 29, 29, 29, 29, 31, 31,
783        ];
784        const P: Primes<N> = Primes::new();
785
786        for (n, next) in NEXT_PRIME.iter().enumerate().take(N) {
787            assert_eq!(P.next_prime(n as u32), Some(*next));
788        }
789    }
790
791    #[test]
792    fn verify_into_array() {
793        const N: usize = 10;
794        const P: Primes<N> = Primes::new();
795        const A: [Underlying; N] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29];
796        assert_eq!(P.into_array(), A);
797    }
798
799    #[test]
800    fn verify_as_slice() {
801        const N: usize = 10;
802        const P: Primes<N> = Primes::new();
803        const A: [Underlying; N] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29];
804        assert_eq!(P.as_slice(), &A);
805    }
806
807    #[test]
808    fn verify_as_array() {
809        const N: usize = 10;
810        const P: Primes<N> = Primes::new();
811        const A: [Underlying; N] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29];
812        assert_eq!(P.as_array(), &A);
813    }
814
815    #[test]
816    fn check_get() {
817        const N: usize = 10;
818        const P: Primes<N> = Primes::new();
819        const A: [Underlying; N] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29];
820        for (n, gotten) in A.iter().enumerate().take(N) {
821            assert_eq!(P.get(n), Some(gotten));
822        }
823        for n in N + 1..2 * N {
824            assert!(P.get(n).is_none());
825        }
826    }
827
828    #[test]
829    fn check_last_and_len() {
830        const PRIMES: [Underlying; 10] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29];
831        macro_rules! check_last_n {
832            ($($n:literal),+) => {
833                $(
834                    {
835                        let p: Primes<$n> = Primes::new();
836                        assert_eq!(*p.last(), PRIMES[$n - 1]);
837                        assert_eq!(p.len(), $n);
838                        assert_eq!(*p.last(), p[$n - 1]);
839                    }
840                )+
841            };
842        }
843        check_last_n!(1, 2, 3, 4, 5, 6, 7, 8, 9);
844    }
845
846    #[test]
847    fn check_count_primes_leq() {
848        const N: usize = 79;
849        const PRIME_COUNTS: [usize; N] = [
850            0, 0, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9,
851            10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15,
852            15, 15, 16, 16, 16, 16, 16, 16, 17, 17, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20,
853            21, 21, 21, 21, 21, 21,
854        ];
855        const P: Primes<N> = Primes::new();
856
857        for (n, count) in PRIME_COUNTS.iter().enumerate().take(N) {
858            assert_eq!(P.prime_pi(n as u32), Some(*count));
859        }
860
861        for n in *P.last() + 1..*P.last() * 2 {
862            assert!(P.prime_pi(n).is_none());
863        }
864    }
865
866    #[test]
867    fn check_iter() {
868        const P: Primes<10> = Primes::new();
869        for (p1, p2) in P.iter().zip([2, 3, 5, 7, 11, 13, 17, 19, 23, 29].iter()) {
870            assert_eq!(p1, p2);
871        }
872    }
873
874    #[test]
875    fn check_totient() {
876        const TOTIENTS: [Underlying; 101] = [
877            0, 1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6, 8, 8, 16, 6, 18, 8, 12, 10, 22, 8, 20,
878            12, 18, 12, 28, 8, 30, 16, 20, 16, 24, 12, 36, 18, 24, 16, 40, 12, 42, 20, 24, 22, 46,
879            16, 42, 20, 32, 24, 52, 18, 40, 24, 36, 28, 58, 16, 60, 30, 36, 32, 48, 20, 66, 32, 44,
880            24, 70, 24, 72, 36, 40, 36, 60, 24, 78, 32, 54, 40, 82, 24, 64, 42, 56, 40, 88, 24, 72,
881            44, 60, 46, 72, 32, 96, 42, 60, 40,
882        ];
883        const NEXT_OUTSIDE: Underlying = match next_prime(*BIG_CACHE.last() as u64) {
884            Some(np) => np as Underlying,
885            None => panic!(),
886        };
887
888        const SMALL_CACHE: Primes<3> = Primes::new();
889        const BIG_CACHE: Primes<100> = Primes::new();
890
891        assert_eq!(SMALL_CACHE.totient(6), Ok(2));
892        assert_eq!(
893            SMALL_CACHE.totient(2 * 5 * 5 * 7 * 7),
894            Err(PartialTotient {
895                totient_using_known_primes: 20,
896                product_of_unknown_prime_factors: 49
897            })
898        );
899
900        for (i, totient) in TOTIENTS.into_iter().enumerate() {
901            assert_eq!(BIG_CACHE.totient(i as Underlying), Ok(totient));
902            if i != 0 {
903                assert_eq!(
904                    BIG_CACHE.totient((i as Underlying) * NEXT_OUTSIDE),
905                    Err(PartialTotient {
906                        totient_using_known_primes: totient,
907                        product_of_unknown_prime_factors: NEXT_OUTSIDE
908                    })
909                );
910            }
911        }
912    }
913
914    #[cfg(feature = "zerocopy")]
915    #[test]
916    fn test_as_bytes() {
917        use zerocopy::IntoBytes;
918        const P: Primes<3> = Primes::new();
919        assert_eq!(P.as_bytes(), &[2, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0]);
920    }
921
922    #[cfg(feature = "serde")]
923    #[test]
924    fn test_serde() {
925        const P: Primes<3> = Primes::new();
926        const STRING_VERSION: &str = "[2,3,5]";
927        assert_eq!(serde_json::to_string(&P).unwrap(), STRING_VERSION);
928        assert_eq!(P, serde_json::from_str(STRING_VERSION).unwrap());
929    }
930}