From 101a37b6bcabae56e79f3c103723f90cec9da094 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Thu, 5 Mar 2020 16:24:33 -0500 Subject: [PATCH] Tests and fixes --- Dockerfile | 3 --- Jenkinsfile | 1 + src/bigint.rs | 25 +++++++++++++++++-------- src/lib.rs | 30 ++++++++++++++++++++++++++---- 4 files changed, 44 insertions(+), 15 deletions(-) delete mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 46f9341..0000000 --- a/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM rust:latest - -RUN cargo install cargo-tarpaulin \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile index d394fdd..28d0739 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -18,6 +18,7 @@ pipeline { } stage('Coverage') { steps { + sh "cargo clean" sh "cargo install cargo-tarpaulin" sh "make generate-coverage" } diff --git a/src/bigint.rs b/src/bigint.rs index cbf9839..6ac5767 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -95,6 +95,7 @@ impl Add for BigInt { type Output = Self; fn add(self, rhs: Self) -> Self::Output { + // @TODO: handle signs let mut out = BigInt::default(); let u_digits = self.inner.len(); @@ -112,14 +113,13 @@ impl Add for BigInt { let b = *rhs.inner.get(i).unwrap_or(&0usize); let (res, overflowed) = a.overflowing_add(b); - // assert!(!overflowed, "Expected to overflow: {:#?}", (res, overflowed)); if overflowed { if i == 0 { - out.inner[i] = res; + out.inner[i] = res + carry; } else { - out.inner.push(res); + out.inner.push(res + carry); } - carry = core::usize::MAX - res; + carry = 1; } else { if res < core::usize::MAX { out.inner.push(res + carry); @@ -216,8 +216,9 @@ impl Not for BigInt { fn not(self) -> Self::Output { let mut flipped: Vec = Vec::with_capacity(self.inner.len()); - for (i, val) in self.inner.iter().enumerate() { - flipped[i] = val.reverse_bits(); + for val in self.inner.iter() { + let rev = !*val; + flipped.push(rev); } BigInt { @@ -255,11 +256,19 @@ mod tests { ); assert_eq!(sum.inner[1], 1usize, "most significant place should be 1"); - /* let a = BigInt::from(core::usize::MAX); + let a = BigInt::from(core::usize::MAX); let b = BigInt::from(1usize); let sum = a + b; assert_eq!(sum.inner[0], 0usize); - assert_eq!(sum.inner[1], 1usize); */ + assert_eq!(sum.inner[1], 1usize); + } + + #[test] + fn test_not() { + let a = BigInt::from(0u8); + let b = !a; + + assert_eq!(b.inner[0], core::usize::MAX); } #[test] diff --git a/src/lib.rs b/src/lib.rs index d2f0dc8..9ec36ad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,8 +3,7 @@ //! Playin' with Numerics in Rust #![forbid(unsafe_code)] -use std::f64::consts::PI; -use std::f64::consts::E; +use std::f64::consts::{E, PI}; pub mod bigint; pub mod num; @@ -175,11 +174,34 @@ pub fn factorial(n: usize) -> Option { } } -pub fn approx_factorial(n: f64) -> f64 { +/// Approximates a factorial using Stirling's approximation +/// +/// Based on https://en.wikipedia.org/wiki/Stirling's_approximation +/// +/// Can approximate up to ~ 170.624! +/// +/// Example: +/// ```rust +/// use rusty_numbers::approx_factorial; +/// +/// let valid = approx_factorial(170.6); // Some(..) +/// # assert!(valid.is_some()); +/// +/// let invalid = approx_factorial(171.0); // None +/// # assert!(invalid.is_none()); +/// ``` +#[inline] +pub fn approx_factorial(n: f64) -> Option { let power = (n / E).powf(n); let root = (PI * 2.0 * n).sqrt(); - power * root + let res = power * root; + + if res >= core::f64::MIN && res <= core::f64::MAX { + Some(res) + } else { + None + } } #[cfg(test)]