#![doc(html_root_url = "https://wackywendell.github.io/primes/")]
use std::cmp::Ordering::{Equal, Greater, Less};
use std::cmp::Reverse;
use std::collections::BinaryHeap;
use std::ops::Index;
use std::slice;
pub trait PrimeSetBasics {
fn expand(&mut self);
fn list(&self) -> &[u64];
}
#[derive(Clone)]
pub struct TrialDivision {
lst: Vec<u64>,
}
const WHEEL30: [u64; 8] = [1, 7, 11, 13, 17, 19, 23, 29];
#[derive(Copy, Clone)]
struct Wheel30 {
base: u64,
ix: usize,
}
impl Wheel30 {
pub fn next(&mut self) -> u64 {
let value = self.base + WHEEL30[self.ix];
self.ix += 1;
if self.ix >= WHEEL30.len() {
self.ix = 0;
self.base += 30;
}
value
}
}
impl Default for Wheel30 {
fn default() -> Self {
Wheel30 { base: 0, ix: 1 }
}
}
#[derive(Clone)]
pub struct Sieve {
primes: Vec<u64>,
wheel: Wheel30,
sieve: BinaryHeap<Reverse<(u64, u64)>>,
}
pub struct PrimeSetIter<'a, P: PrimeSet> {
p: &'a mut P,
n: usize,
expand: bool,
}
impl TrialDivision {
pub fn new() -> TrialDivision {
TrialDivision { lst: vec![2, 3] }
}
}
impl Default for TrialDivision {
fn default() -> Self {
Self::new()
}
}
impl PrimeSetBasics for TrialDivision {
fn expand(&mut self) {
let mut l: u64 = self.lst.last().unwrap() + 2;
let mut remainder = 0;
loop {
for &n in &self.lst {
remainder = l % n;
if remainder == 0 || n * n > l {
break;
}
}
if remainder != 0 {
self.lst.push(l);
break;
};
l += 2;
}
}
fn list(&self) -> &[u64] {
&self.lst[..]
}
}
impl Default for Sieve {
fn default() -> Self {
Self::new()
}
}
impl Sieve {
pub fn new() -> Sieve {
Sieve {
primes: vec![2, 3, 5],
sieve: BinaryHeap::new(),
wheel: Wheel30 { base: 0, ix: 1 },
}
}
fn insert(&mut self, prime: u64, composite: u64) {
self.sieve.push(Reverse((composite, prime)));
}
}
impl PrimeSetBasics for Sieve {
fn expand(&mut self) {
let mut nextp = self.wheel.next();
loop {
let (composite, factor) = match self.sieve.peek() {
None => {
self.insert(nextp, nextp * nextp);
self.primes.push(nextp);
return;
}
Some(&Reverse(v)) => v,
};
match composite.cmp(&nextp) {
Less => {
let _ = self.sieve.pop();
self.insert(factor, composite + 2 * factor);
}
Equal => {
let _ = self.sieve.pop();
self.insert(factor, composite + 2 * factor);
nextp = self.wheel.next();
}
Greater => {
self.insert(nextp, nextp * nextp);
self.primes.push(nextp);
return;
}
}
}
}
fn list(&self) -> &[u64] {
&self.primes[..]
}
}
pub trait PrimeSet: PrimeSetBasics + Sized {
fn len(&self) -> usize {
self.list().len()
}
fn is_empty(&self) -> bool {
self.list().is_empty()
}
fn generator(&mut self) -> PrimeSetIter<Self> {
let myn = self.len();
PrimeSetIter {
p: self,
n: myn,
expand: true,
}
}
fn iter(&mut self) -> PrimeSetIter<Self> {
PrimeSetIter {
p: self,
n: 0,
expand: true,
}
}
fn iter_vec(&self) -> slice::Iter<u64> {
self.list().iter()
}
fn find(&mut self, n: u64) -> (usize, u64) {
while n > *(self.list().last().unwrap_or(&0)) {
self.expand();
}
self.find_vec(n).unwrap()
}
fn is_prime(&mut self, n: u64) -> bool {
if n <= 1 {
return false;
}
if n == 2 {
return true;
} for m in self.iter() {
if n % m == 0 {
return false;
};
if m * m > n {
return true;
};
}
unreachable!("This iterator should not be empty.");
}
fn find_vec(&self, n: u64) -> Option<(usize, u64)> {
if n > *(self.list().last().unwrap_or(&0)) {
return None;
}
let mut base: usize = 0;
let mut lim: usize = self.len();
while lim != 0 {
let ix = base + (lim >> 1);
match self.list()[ix].cmp(&n) {
Equal => return Some((ix, self.list()[ix])),
Less => {
base = ix + 1;
lim -= 1;
}
Greater => (),
}
lim >>= 1;
}
Some((base, self.list()[base]))
}
fn get(&mut self, index: usize) -> u64 {
for _ in 0..(index as isize) + 1 - (self.list().len() as isize) {
self.expand();
}
self.list()[index]
}
fn prime_factors(&mut self, n: u64) -> Vec<u64> {
if n == 1 {
return Vec::new();
}
let mut curn = n;
let mut lst: Vec<u64> = Vec::new();
for p in self.iter() {
while curn % p == 0 {
lst.push(p);
curn /= p;
if curn == 1 {
return lst;
}
}
if p * p > curn {
lst.push(curn);
return lst;
}
}
unreachable!("This should be unreachable.");
}
}
impl<P: PrimeSetBasics> PrimeSet for P {}
impl Index<usize> for TrialDivision {
type Output = u64;
fn index(&self, index: usize) -> &u64 {
&self.list()[index]
}
}
impl<'a, P: PrimeSet> Iterator for PrimeSetIter<'a, P> {
type Item = u64;
fn next(&mut self) -> Option<u64> {
while self.n >= self.p.list().len() {
if self.expand {
self.p.expand()
} else {
return None;
}
}
self.n += 1;
let m = self.p.list()[self.n - 1];
Some(m)
}
}
fn firstfac(x: u64) -> u64 {
if x % 2 == 0 {
return 2;
};
for n in (1..).map(|m| 2 * m + 1).take_while(|m| m * m <= x) {
if x % n == 0 {
return n;
};
}
x
}
pub fn factors(x: u64) -> Vec<u64> {
if x <= 1 {
return vec![];
};
let mut lst: Vec<u64> = Vec::new();
let mut curn = x;
loop {
let m = firstfac(curn);
lst.push(m);
if m == curn {
break;
} else {
curn /= m
};
}
lst
}
pub fn factors_uniq(x: u64) -> Vec<u64> {
if x <= 1 {
return vec![];
};
let mut lst: Vec<u64> = Vec::new();
let mut curn = x;
loop {
let m = firstfac(curn);
lst.push(m);
if curn == m {
break;
}
while curn % m == 0 {
curn /= m;
}
if curn == 1 {
break;
}
}
lst
}
pub fn is_prime(n: u64) -> bool {
if n <= 1 {
return false;
}
firstfac(n) == n
}