prime_formula/
lib.rs

1//! A high-performance prime number generator implementing a novel prime formula.
2//!
3//! This library enables efficient finding of prime numbers and prime constellations
4//! (twin primes, triplets, etc.) using The Periodic Table of Primes which is a novel
5//! theory that claims that all primes are descendants of just 48 Prime Roots, and that
6//! these descendants are in the form root + k×210.
7//!
8//! The implementation leverages:
9//! - Bitwise storage for compact representation
10//! - Rayon-based parallelism for multi-core scaling
11//! - Three distinct search modes optimized for different number ranges
12//!
13//! The core algorithm operates by eliminating composite candidates using precomputed
14//! prime root relationships rather than checking every potential divisor. The library
15//! implements theory proposed by Han-Lin Li, Shu-Cherng Fang & Way Kuo.
16//!
17//! For more info, see <https://ssrn.com/abstract=4742238>
18//
19// Copyright: Adam Cottrell (cottrela@gmail.com)
20
21// use bitvec::prelude::*;
22use rayon::prelude::*;
23use rayon::slice::ParallelSliceMut;
24
25use crate::common::{ConfigMode, NUM_ROOTS, get_small_primes};
26use crate::prime::{PrimalityTest, PrimeFormula};
27use crate::sieve::{Sieve, SieveMode};
28
29pub mod common;
30
31// Adds support for quickly finding many smaller primes
32pub mod sieve;
33
34// Adds support for quickly finding constellations of primes
35#[cfg(feature = "constellations")]
36pub mod constellations;
37
38// Adds support for quickly finding large primes
39pub mod prime;
40
41// Adds support for quickly finding one or more huge primes
42#[cfg(feature = "big-primes")]
43pub mod big_prime;
44
45/// Parallel prime number generator for a range
46///
47/// Uses all available CPU cores to process different prime roots simultaneously
48///
49/// # Arguments
50/// - start: Inclusive lower bound
51/// - end: Exclusive upper bound
52/// - mode: Sieve strategy selection
53pub fn get_primes(start: u128, end: u128, mode: &ConfigMode) -> Vec<u128> {
54    let mut primes: Vec<u128>;
55    if *mode == ConfigMode::MillerRabinDeterministic {
56        let inst = PrimeFormula::new(PrimalityTest::MillerRabinDeterministic, 8);
57        primes = inst.get_unsorted_primes(start, end);
58    } else if *mode == ConfigMode::MillerRabinProbabilistic {
59        let inst = PrimeFormula::new(PrimalityTest::MillerRabinProbabilistic, 8);
60        primes = inst.get_unsorted_primes(start, end);
61    } else {
62        primes = (0..NUM_ROOTS)
63            .into_par_iter()
64            .flat_map(
65                |root_idx| match Sieve::new(root_idx as u8, start, end, SieveMode::Sieve) {
66                    Ok(mut sieve) => sieve.get_primes(),
67                    Err(_e) => vec![0; 0],
68                },
69            )
70            .collect();
71    }
72
73    // Add small primes, if necessary
74    primes.extend(get_small_primes(start, end));
75
76    // Primes arrive interleaved, and so must be resorted
77    primes.par_sort_unstable();
78
79    primes
80}
81
82/// Parallel prime counter for a range
83///
84/// More memory-efficient than get_primes() as it doesn't store results
85pub fn count_primes(start: u128, end: u128, mode: &ConfigMode) -> usize {
86    let mut count: usize = get_small_primes(start, end).len();
87    count += if *mode == ConfigMode::MillerRabinDeterministic {
88        let inst = PrimeFormula::new(PrimalityTest::MillerRabinDeterministic, 8);
89        let primes = inst.get_unsorted_primes(start, end);
90        primes.len()
91    } else if *mode == ConfigMode::MillerRabinProbabilistic {
92        let inst = PrimeFormula::new(PrimalityTest::MillerRabinProbabilistic, 8);
93        let primes = inst.get_unsorted_primes(start, end);
94        primes.len()
95    } else {
96        (0..NUM_ROOTS)
97            .into_par_iter()
98            .map(
99                |root_idx| match Sieve::new(root_idx as u8, start, end, SieveMode::Sieve) {
100                    Ok(mut sieve) => sieve.count_primes(),
101                    Err(_e) => 0,
102                },
103            )
104            .sum()
105    };
106
107    count
108}