diff --git a/src/generation.rs b/src/generation.rs index 7bb9746..de84694 100644 --- a/src/generation.rs +++ b/src/generation.rs @@ -16,15 +16,18 @@ use crate::{sieve, sieving::sieve_segment, Underlying}; /// const PRIMES: [u32; 10] = primes(); /// assert_eq!(PRIMES, [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]); /// ``` -/// Fails to compile if `N = 0`: +/// +/// # Panics +/// +/// Panics if `N = 0`. In const contexts, this is a compile error: /// ```compile_fail /// # use const_primes::primes; -/// let primes: [u32; 0] = primes(); +/// const PRIMES: [u32; 0] = primes(); /// ``` /// #[must_use = "the function only returns a new value"] pub const fn primes() -> [Underlying; N] { - const { assert!(N > 0, "`N` must be at least 1") } + assert!(N > 0, "`N` must be at least 1"); if N == 1 { return [2; N]; @@ -166,11 +169,10 @@ pub const fn primes() -> [Underlying; N] { pub const fn primes_lt( mut upper_limit: u64, ) -> Result<[u64; N], GenerationError> { - const { - assert!(N > 0, "`N` must be at least 1"); - assert!(MEM >= N, "`MEM` must be at least as large as `N`"); - } - let mem_sqr = const { + assert!(N > 0, "`N` must be at least 1"); + assert!(MEM >= N, "`MEM` must be at least as large as `N`"); + + let mem_sqr = { let mem64 = MEM as u64; match mem64.checked_mul(mem64) { Some(prod) => prod, @@ -321,11 +323,10 @@ macro_rules! primes_segment { pub const fn primes_geq( lower_limit: u64, ) -> Result<[u64; N], GenerationError> { - const { - assert!(N > 0, "`N` must be at least 1"); - assert!(MEM >= N, "`MEM` must be at least as large as `N`"); - } - let (mem64, mem_sqr) = const { + assert!(N > 0, "`N` must be at least 1"); + assert!(MEM >= N, "`MEM` must be at least as large as `N`"); + + let (mem64, mem_sqr) = { let mem64 = MEM as u64; let Some(mem_sqr) = mem64.checked_mul(mem64) else { panic!("`MEM`^2 must fit in a `u64`") diff --git a/src/lib.rs b/src/lib.rs index c4fa0a1..e66d050 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -123,20 +123,24 @@ pub use sieving::{sieve, sieve_geq, sieve_lt, SieveError}; pub use wrapper::Primes; /// Returns an array of size `N` where the value at a given index is how many primes are less than or equal to the index. -/// Fails to compile if `N` is 0. /// /// Sieves primes with [`sieve`] and then counts them. /// /// # Example +/// /// Basic usage /// ``` /// # use const_primes::prime_counts; /// const COUNTS: [usize; 10] = prime_counts(); /// assert_eq!(COUNTS, [0, 0, 1, 2, 2, 3, 3, 4, 4, 4]); /// ``` +/// +/// # Panics +/// +/// Panics if `N` is 0. In const contexts this is a compile error. #[must_use = "the function only returns a new value"] pub const fn prime_counts() -> [usize; N] { - const { assert!(N > 0, "`N` must be at least 1") } + assert!(N > 0, "`N` must be at least 1"); let mut counts = [0; N]; if N <= 2 { return counts; diff --git a/src/sieving.rs b/src/sieving.rs index f10c7ba..c11cdbc 100644 --- a/src/sieving.rs +++ b/src/sieving.rs @@ -3,12 +3,16 @@ use crate::isqrt; /// Uses the primalities of the first `N` integers in `base_sieve` to sieve the numbers in the range `[upper_limit - N, upper_limit)`. /// Assumes that the base sieve contains the prime status of the `N` fist integers. The output is only meaningful /// for the numbers below `N^2`. Fails to compile if `N` is 0. +/// +/// # Panics +/// +/// Panics if `N` is 0. #[must_use = "the function only returns a new value and does not modify its inputs"] pub(crate) const fn sieve_segment( base_sieve: &[bool; N], upper_limit: u64, ) -> [bool; N] { - const { assert!(N > 0, "`N` must be at least 1") } + assert!(N > 0, "`N` must be at least 1"); let mut segment_sieve = [true; N]; @@ -55,8 +59,6 @@ pub(crate) const fn sieve_segment( /// `MEM` must be large enough for the sieve to be able to determine the prime status of all numbers in the requested range, /// that is: `MEM`^2 must be at least as large as `upper_limit`. /// -/// Fails to compile if `N` is 0, or if `MEM` is smaller than `N`. -/// /// If you just want the prime status of the first `N` integers, see [`sieve`], and if you want the prime status of /// the integers above some number, see [`sieve_geq`]. /// @@ -110,16 +112,19 @@ pub(crate) const fn sieve_segment( /// const PS: Result<[bool; 5], SieveError> = sieve_lt::<5, 5>(4); /// assert_eq!(PS, Err(SieveError::TooSmallLimit)); /// ``` +/// +/// # Panics +/// +/// Panics if `N` is 0, if `MEM` is smaller than `N`, or if `MEM`^2 does not fit in a `u64`. +/// In const contexts this is a compile error. #[must_use = "the function only returns a new value and does not modify its input"] pub const fn sieve_lt( upper_limit: u64, ) -> Result<[bool; N], SieveError> { - const { - assert!(N > 0, "`N` must be at least 1"); - assert!(MEM >= N, "`MEM` must be at least as large as `N`"); - } + assert!(N > 0, "`N` must be at least 1"); + assert!(MEM >= N, "`MEM` must be at least as large as `N`"); - let mem_sqr = const { + let mem_sqr = { let mem64 = MEM as u64; match mem64.checked_mul(mem64) { Some(prod) => prod, @@ -158,7 +163,6 @@ pub const fn sieve_lt( } /// Returns an array of size `N` where the value at a given index indicates whether the index is prime. -/// Fails to compile if `N` is 0. /// /// # Example /// @@ -168,9 +172,13 @@ pub const fn sieve_lt( /// // 0 1 2 3 4 5 6 7 8 9 /// assert_eq!(PRIMALITY, [false, false, true, true, false, true, false, true, false, false]); /// ``` +/// +/// # Panics +/// +/// Panics if `N` is 0. In const contexts this is a compile error. #[must_use = "the function only returns a new value"] pub const fn sieve() -> [bool; N] { - const { assert!(N > 0, "`N` must be at least 1") } + assert!(N > 0, "`N` must be at least 1"); let mut sieve = [true; N]; if N > 0 { @@ -236,8 +244,6 @@ impl std::error::Error for SieveError {} /// `MEM` must be large enough for the sieve to be able to determine the prime status of all numbers in the requested range, /// that is `MEM`^2 must be larger than `lower_limit + N`. /// -/// Fails to compile if `N` is 0, or if `MEM` is smaller than `N`. -/// /// If you just want the prime status of the first N integers, see [`sieve`], and if you want the /// prime status of the integers below some number, see [`sieve_lt`]. /// @@ -280,15 +286,19 @@ impl std::error::Error for SieveError {} /// assert_eq!(P1, Err(SieveError::TooLargeTotal)); /// assert_eq!(P2, Err(SieveError::TotalDoesntFitU64)); /// ``` +/// +/// # Panics +/// +/// Panics if `N` is 0, if `MEM` is smaller than `N`, or if `MEM`^2 does not fit in a `u64`. +/// In const contexts this is a compile error. #[must_use = "the function only returns a new value and does not modify its input"] pub const fn sieve_geq( lower_limit: u64, ) -> Result<[bool; N], SieveError> { - const { - assert!(N > 0, "`N` must be at least 1"); - assert!(MEM >= N, "`MEM` must be at least as large as `N`"); - } - let (mem64, mem_sqr) = const { + assert!(N > 0, "`N` must be at least 1"); + assert!(MEM >= N, "`MEM` must be at least as large as `N`"); + + let (mem64, mem_sqr) = { let mem64 = MEM as u64; match mem64.checked_mul(mem64) { Some(prod) => (mem64, prod), diff --git a/src/wrapper.rs b/src/wrapper.rs index 8781115..3d648c1 100644 --- a/src/wrapper.rs +++ b/src/wrapper.rs @@ -56,18 +56,18 @@ impl Primes { /// assert_eq!(primes, [2, 3, 5, 7, 11]); /// ``` /// - /// Fails to compile if `N` is zero. + /// # Panics + /// + /// Panics if `N` is zero. In const contexts this is a compile error. /// ```compile_fail /// # use const_primes::Primes; /// const NO_PRIMES: Primes<0> = Primes::new(); /// ``` /// - /// # Panics - /// /// If any of the primes overflow a `u32` it will panic in const contexts or debug mode. #[must_use = "the associated method only returns a new value"] pub const fn new() -> Self { - const { assert!(N > 0, "`N` must be at least 1") } + assert!(N > 0, "`N` must be at least 1"); Self { primes: primes() } } @@ -310,11 +310,11 @@ impl Primes { } } -/// This statically asserts that N > 0. +/// Panics if `N` is 0. impl Default for Primes { fn default() -> Self { - const { assert!(N > 0, "`N` must be at least 1") } - Self::new() + assert!(N > 0, "`N` must be at least 1"); + Self { primes: primes() } } }