Skip to content

Instantly share code, notes, and snippets.

@reckenrode
Created April 28, 2019 19:08
Show Gist options
  • Save reckenrode/e06a221ac9bb8e6138aadee3880d0db4 to your computer and use it in GitHub Desktop.
Save reckenrode/e06a221ac9bb8e6138aadee3880d0db4 to your computer and use it in GitHub Desktop.
Rust Sieve of Eratosthenes
use num::Unsigned;
use structopt::StructOpt;
#[derive(Debug)]
enum NumberType {
Unit(usize), Prime(usize), Composite(usize)
}
impl NumberType {
fn value(&self) -> &usize {
match self {
NumberType::Unit(n) => n,
NumberType::Prime(n) => n,
NumberType::Composite(n) => n
}
}
fn is_prime(&self) -> bool {
match self {
NumberType::Prime(_) => true,
_ => false
}
}
}
trait TwoFour {
fn two() -> Self;
fn four() -> Self;
}
macro_rules! def_two_four {
($type:ty) => {
impl TwoFour for $type {
fn two() -> Self {
2
}
fn four() -> Self {
4
}
}
};
}
def_two_four!(u8);
def_two_four!(u16);
def_two_four!(u32);
def_two_four!(u64);
def_two_four!(u128);
def_two_four!(usize);
trait Isqrt<N: Unsigned + Ord + Clone + TwoFour> {
fn isqrt(&self) -> Self;
}
impl<N: Unsigned + Ord + Clone + TwoFour> Isqrt<N> for N {
fn isqrt(&self) -> N {
if *self < N::two() {
self.clone()
} else {
let small_candidate = (self.clone() / N::four()).isqrt() * N::two();
let large_candidate = small_candidate.clone() + N::one();
if large_candidate.clone() > self.clone() / large_candidate.clone() {
small_candidate
} else {
large_candidate
}
}
}
}
fn sieve(upper_limit: usize) -> Vec<NumberType> {
let mut result: Vec<NumberType> = std::iter::successors(Some(1), |n| Some(n + 1))
.map(|n| if n == 1 { NumberType::Unit(1) } else { NumberType::Prime(n) })
.take(upper_limit)
.collect();
let limit = upper_limit.isqrt();
for idx in 1..=limit {
if let NumberType::Prime(n) = result[idx] {
for idx in ((idx + n)..upper_limit).step_by(n) {
result[idx] = NumberType::Composite(result[idx].value().clone());
}
}
}
result
}
#[derive(StructOpt)]
struct Options {
limit: usize
}
fn main() {
let n = Options::from_args().limit;
let primes: Vec<usize> = sieve(n).into_iter()
.filter(NumberType::is_prime)
.map(|n| n.value().clone())
.collect();
println!("primes: {:?}", primes);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment