diff --git a/Cargo.toml b/Cargo.toml index 3ca684f..756e5b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ repository = "https://git.sr.ht/~swaits/vivaldi-nc" [dev-dependencies] assert_approx_eq = "1.1.0" +proptest = "1.0.0" serde_json = "1.0.91" [dependencies] diff --git a/proptest-regressions/vector.txt b/proptest-regressions/vector.txt new file mode 100644 index 0000000..525328f --- /dev/null +++ b/proptest-regressions/vector.txt @@ -0,0 +1,9 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc 9746321b74151b1897633df1bb1acba31bd29b780939385d9bece281322379fb # shrinks to x = 0.0, y = 0.0, z = 0.0 +cc 92f14e65f9256a1213cabcecf6f45152c96f39193a1bdedb7a5cdfcaf74b8550 # shrinks to x = 1.345588e30, y = 0.0, z = 0.0, m = 8.635428e-39 +cc 6bd8ea879a7c332aea9f429cf4d6d9bd61c96661edfe8875c733aea750e0c5d8 # shrinks to x = 0.0, y = 0.0, z = 9.319843e-7, d = 0.0 diff --git a/src/vector.rs b/src/vector.rs index b89e7bd..777a0f8 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -118,7 +118,10 @@ where fn mul(self, rhs: T) -> Self::Output { let mut ret = Self::Output::new(); for i in 0..N { - ret.inner[i] = self.inner[i] * rhs + ret.inner[i] = self.inner[i] * rhs; + if !ret.inner[i].is_normal() { + ret.inner[i] = T::zero(); + } } ret } @@ -134,7 +137,10 @@ where fn div(self, rhs: T) -> Self::Output { let mut ret = Self::Output::new(); for i in 0..N { - ret.inner[i] = self.inner[i] / rhs + ret.inner[i] = self.inner[i] / rhs; + if !ret.inner[i].is_normal() { + ret.inner[i] = T::zero(); + } } ret } @@ -161,6 +167,54 @@ mod tests { use super::*; use assert_approx_eq::assert_approx_eq; + use num_traits::Zero; + use proptest::prelude::*; + + proptest! { + #[test] + fn proptest_new(x: f32, y: f32, z: f32){ + let v = Vector::::from([x,y,z]); + assert_eq!(v[0], x); + assert_eq!(v[1], y); + assert_eq!(v[2], z); + assert!(v[0].is_finite()); + assert!(v[1].is_finite()); + assert!(v[1].is_finite()); + } + + #[test] + fn proptest_mul(x: f32, y: f32, z: f32, m: f32) { + let v = Vector::::from([x,y,z]); + let w = v * m; + if m.is_zero() { + assert_eq!(w[0], 0.0); + assert_eq!(w[1], 0.0); + assert_eq!(w[2], 0.0); + } + assert!(v[0].is_finite()); + assert!(v[1].is_finite()); + assert!(v[1].is_finite()); + assert!(w[0].is_finite()); + assert!(w[1].is_finite()); + assert!(w[1].is_finite()); + } + #[test] + fn proptest_div(x: f32, y: f32, z: f32, d: f32) { + let v = Vector::::from([x,y,z]); + let w = v / d; + if d.is_zero() { + assert_eq!(w[0], 0.0); + assert_eq!(w[1], 0.0); + assert_eq!(w[2], 0.0); + } + assert!(v[0].is_finite()); + assert!(v[1].is_finite()); + assert!(v[1].is_finite()); + assert!(w[0].is_finite()); + assert!(w[1].is_finite()); + assert!(w[1].is_finite()); + } + } #[test] fn test_default_new() {