Skip to content

Commit

Permalink
Documented SieveOfAtkin
Browse files Browse the repository at this point in the history
  • Loading branch information
tfpf committed Aug 2, 2024
1 parent 327561f commit 00d8b69
Showing 1 changed file with 65 additions and 0 deletions.
65 changes: 65 additions & 0 deletions src/utils/objects/sieve_of_atkin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub struct SieveOfAtkin {
limit_rounded_isqrt: usize,
sieve: Vec<u16>,
}

impl SieveOfAtkin {
// Consecutive differences between coprime residues modulo 60: 1, 7, 11,
// 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 49, 53 and 59.
Expand All @@ -25,7 +26,9 @@ impl SieveOfAtkin {
16, 16, 15,
];
}

impl SieveOfAtkin {

/// Construct the sieve of Atkin up to and including the given number.
///
/// * `limit` Non-strict upper bound.
Expand All @@ -43,6 +46,8 @@ impl SieveOfAtkin {
sieve_of_atkin.init();
sieve_of_atkin
}

/// Initialise the sieve of Atkin.
fn init(&mut self) {
for (delta, shift) in [1, 13, 17, 29, 37, 41, 49, 53]
.into_iter()
Expand Down Expand Up @@ -78,6 +83,12 @@ impl SieveOfAtkin {
}
}
}

/// Of the prime numbers congruent to 1 modulo 4, find those congruent to
/// `delta` modulo 60.
///
/// * `delta` Residue.
/// * `shift` Position of `delta` in a list of coprime residues modulo 60.
fn algorithm_3_1(&mut self, delta: i32, shift: u8) {
for f in 1..=15 {
for g in (1..=30).step_by(2) {
Expand All @@ -88,6 +99,12 @@ impl SieveOfAtkin {
}
}
}

/// Of the prime numbers congruent to 1 modulo 6, find those congruent to
/// `delta` modulo 60.
///
/// * `delta` Residue.
/// * `shift` Position of `delta` in a list of coprime residues modulo 60.
fn algorithm_3_2(&mut self, delta: i32, shift: u8) {
for f in (1..=10).step_by(2) {
for g in [2, 4, 8, 10, 14, 16, 20, 22, 26, 28] {
Expand All @@ -98,6 +115,12 @@ impl SieveOfAtkin {
}
}
}

/// Of the prime numbers congruent to 11 modulo 12, find those congruent to
/// `delta` modulo 60.
///
/// * `delta` Residue.
/// * `shift` Position of `delta` in a list of coprime residues modulo 60.
fn algorithm_3_3(&mut self, delta: i32, shift: u8) {
for (f, gstart) in (1..=10).zip([2, 1].into_iter().cycle()) {
for g in (gstart..=30).step_by(2) {
Expand All @@ -109,6 +132,18 @@ impl SieveOfAtkin {
}
}
}

/// Starting from a point which generates a prime number congruent to 1
/// modulo 4 and `delta` modulo 60, find all such prime numbers by tracing
/// the generating curve:
///
/// 4<i>f</i><sup>2</sup> + <i>g</i><sup>2</sup> = 60<i>h</i> + δ
/// (equivalently: `4f^2 + g^2 = 60h + δ`).
///
/// * `shift` Position of δ in a list of coprime residues modulo 60.
/// * `f` Starting abscissa.
/// * `g` Starting ordinate.
/// * `h` Multiplier of 60 in the generating curve.
fn algorithm_4_1(&mut self, shift: u8, f: i32, g: i32, h: i32) {
let (mut x, mut y0, mut k0) = (f as i64, g as i64, h as i64);
while k0 < self.sieve.len() as i64 {
Expand All @@ -129,6 +164,18 @@ impl SieveOfAtkin {
}
}
}

/// Starting from a point which generates a prime number congruent to 1
/// modulo 6 and `delta` modulo 60, find all such prime numbers by tracing
/// the generating curve:
///
/// 3<i>f</i><sup>2</sup> + <i>g</i><sup>2</sup> = 60<i>h</i> + δ
/// (equivalently: `3f^2 + g^2 = 60h + δ`).
///
/// * `shift` Position of δ in a list of coprime residues modulo 60.
/// * `f` Starting abscissa.
/// * `g` Starting ordinate.
/// * `h` Multiplier of 60 in the generating curve.
fn algorithm_4_2(&mut self, shift: u8, f: i32, g: i32, h: i32) {
let (mut x, mut y0, mut k0) = (f as i64, g as i64, h as i64);
while k0 < self.sieve.len() as i64 {
Expand All @@ -149,6 +196,18 @@ impl SieveOfAtkin {
}
}
}

/// Starting from a point which generates a prime number congruent to 11
/// modulo 12 and `delta` modulo 60, find all such prime numbers by tracing
/// the generating curve:
///
/// 3<i>f</i><sup>2</sup> − <i>g</i><sup>2</sup> = 60<i>h</i> + δ
/// (equivalently: `3f^2 - g^2 = 60h + δ`).
///
/// * `shift` Position of δ in a list of coprime residues modulo 60.
/// * `f` Starting abscissa.
/// * `g` Starting ordinate.
/// * `h` Multiplier of 60 in the generating curve.
fn algorithm_4_3(&mut self, shift: u8, f: i32, g: i32, h: i32) {
let (mut x, mut y0, mut k0) = (f as i64, g as i64, h as i64);
loop {
Expand All @@ -166,6 +225,10 @@ impl SieveOfAtkin {
(k0, x) = (k0 + x + 5, x + 10);
}
}

/// Check whether the given number is prime.
///
/// * `num`
pub fn is_prime(&self, num: usize) -> bool {
if num < 2 {
return false;
Expand All @@ -179,6 +242,8 @@ impl SieveOfAtkin {
}
self.sieve[num_div_60] & (1u32 << SieveOfAtkin::SHIFTS[num_mod_60]) as u16 != 0
}

/// Yield the found prime numbers in order.
pub fn iter(&self) -> impl Iterator<Item = i64> + '_ {
let mut num: usize = 1;
let mut offset = SieveOfAtkin::OFFSETS.iter().cycle();
Expand Down

0 comments on commit 00d8b69

Please sign in to comment.