diff options
-rw-r--r-- | src/tests/Cargo.toml | 1 | ||||
-rw-r--r-- | src/tests/prime_sieve/Cargo.toml | 16 | ||||
-rw-r--r-- | src/tests/prime_sieve/benches/main.rs | 13 | ||||
-rw-r--r-- | src/tests/prime_sieve/src/lib.rs | 55 | ||||
-rw-r--r-- | src/tests/prime_sieve/src/types.pr.rs | 13 |
5 files changed, 98 insertions, 0 deletions
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<usize> { + // 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<E: Display, T: Container<E>>(mut left: T, right: Vec<E>) { + 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<T> { + \c <: (Stack) -> (forall \x -> ((equal? (pop ((push c) x))) x)) +} + +property ascending<T> { + \c -> ((for-all-consecutive-pairs c) leq?) +} + + +type Sieve<S> = {c impl (Container, Stack) | (lifo c)} +type Primes<S> = {c impl (Container, Stack) | (ascending c)} +*ENDSPEC*/ |