From a8967d7d399b2324d5a9380d933d038e9159bb6b Mon Sep 17 00:00:00 2001 From: Aria Shrimpton Date: Tue, 23 Jan 2024 11:54:47 +0000 Subject: add prime sieve test --- src/tests/Cargo.toml | 1 + src/tests/prime_sieve/Cargo.toml | 16 ++++++++++ src/tests/prime_sieve/benches/main.rs | 13 +++++++++ src/tests/prime_sieve/src/lib.rs | 55 +++++++++++++++++++++++++++++++++++ src/tests/prime_sieve/src/types.pr.rs | 13 +++++++++ 5 files changed, 98 insertions(+) create mode 100644 src/tests/prime_sieve/Cargo.toml create mode 100644 src/tests/prime_sieve/benches/main.rs create mode 100644 src/tests/prime_sieve/src/lib.rs create mode 100644 src/tests/prime_sieve/src/types.pr.rs (limited to 'src/tests') diff --git a/src/tests/Cargo.toml b/src/tests/Cargo.toml index b40694f..120e0cd 100644 --- a/src/tests/Cargo.toml +++ b/src/tests/Cargo.toml @@ -2,6 +2,7 @@ resolver = "2" members = [ "example_stack", + "prime_sieve" ] [workspace.dependencies] diff --git a/src/tests/prime_sieve/Cargo.toml b/src/tests/prime_sieve/Cargo.toml new file mode 100644 index 0000000..294a977 --- /dev/null +++ b/src/tests/prime_sieve/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "prime_sieve" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +primrose-library = { path = "../../crates/library" } + +[dev-dependencies] +criterion = { workspace = true } + +[[bench]] +name = "main" +harness = false diff --git a/src/tests/prime_sieve/benches/main.rs b/src/tests/prime_sieve/benches/main.rs new file mode 100644 index 0000000..fd04578 --- /dev/null +++ b/src/tests/prime_sieve/benches/main.rs @@ -0,0 +1,13 @@ +use criterion::BenchmarkId; +use criterion::Criterion; +use criterion::{criterion_group, criterion_main}; + +fn bench_sieve(c: &mut Criterion) { + let size: usize = 10; + c.bench_with_input(BenchmarkId::new("prime_sieve", size), &size, |b, &n| { + b.iter(|| prime_sieve::prime_sieve(n)); + }); +} + +criterion_group!(benches, bench_sieve); +criterion_main!(benches); diff --git a/src/tests/prime_sieve/src/lib.rs b/src/tests/prime_sieve/src/lib.rs new file mode 100644 index 0000000..8d53e30 --- /dev/null +++ b/src/tests/prime_sieve/src/lib.rs @@ -0,0 +1,55 @@ +#![feature(type_alias_impl_trait)] + +mod types; +use types::*; + +/// Find all primes < `n` using the sieve of eratosthenes +pub fn prime_sieve(n: usize) -> Primes { + // Add numbers to sieve through + let mut sieve = Sieve::default(); + (2..n).rev().for_each(|x| sieve.push(x)); + + let mut primes = Primes::default(); + while let Some(x) = sieve.pop() { + primes.insert(x); + + // remove all multiples of x from sieve + let mut sieved = 2 * x; + while sieved < n { + sieve.remove(sieved); + sieved += x; + } + } + + primes +} + +#[cfg(test)] +mod tests { + use crate::prime_sieve; + use primrose_library::traits::*; + use std::fmt::Display; + + fn assert_coneq>(mut left: T, right: Vec) { + assert_eq!(left.len(), right.len(), "length must be equal"); + for i in right.into_iter() { + assert!(left.contains(&i), "must container element {}", i); + } + } + + #[test] + fn test10() { + assert_coneq(prime_sieve(10), vec![2, 3, 5, 7]); + } + + #[test] + fn test100() { + assert_coneq( + prime_sieve(100), + vec![ + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, + 83, 89, 97, + ], + ); + } +} diff --git a/src/tests/prime_sieve/src/types.pr.rs b/src/tests/prime_sieve/src/types.pr.rs new file mode 100644 index 0000000..2006302 --- /dev/null +++ b/src/tests/prime_sieve/src/types.pr.rs @@ -0,0 +1,13 @@ +/*SPEC* +property lifo { + \c <: (Stack) -> (forall \x -> ((equal? (pop ((push c) x))) x)) +} + +property ascending { + \c -> ((for-all-consecutive-pairs c) leq?) +} + + +type Sieve = {c impl (Container, Stack) | (lifo c)} +type Primes = {c impl (Container, Stack) | (ascending c)} +*ENDSPEC*/ -- cgit v1.2.3