From 4fede94df5fb025e7cefa29c2890f393af465665 Mon Sep 17 00:00:00 2001 From: Richard Dodd Date: Sat, 28 Apr 2018 11:34:45 +0100 Subject: [PATCH 1/4] Add is_finite method to vectors and matrices. This method is useful in debug to error early when some kind of singularity is encountered. --- src/matrix.rs | 15 +++++++++++++++ src/vector.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/matrix.rs b/src/matrix.rs index c960064..c5606d1 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -106,6 +106,11 @@ impl Matrix2 { Matrix2::new(c, s, -s, c) } + + /// Are all entries in the matrix finite. + pub fn is_finite(&self) -> bool { + self.x.is_finite() && self.y.is_finite() + } } impl Matrix3 { @@ -205,6 +210,11 @@ impl Matrix3 { _1subc * axis.z * axis.z + c, ) } + + /// Are all entries in the matrix finite. + pub fn is_finite(&self) -> bool { + self.x.is_finite() && self.y.is_finite() && self.z.is_finite() + } } impl Matrix4 { @@ -357,6 +367,11 @@ impl Matrix4 { S::zero(), S::zero(), S::zero(), S::one(), ) } + + /// Are all entries in the matrix finite. + pub fn is_finite(&self) -> bool { + self.w.is_finite() && self.x.is_finite() && self.y.is_finite() && self.z.is_finite() + } } impl Zero for Matrix2 { diff --git a/src/vector.rs b/src/vector.rs index 108792a..9cc18a6 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -118,6 +118,13 @@ macro_rules! impl_vector { $VectorN::new($($field),+) } + impl $VectorN { + /// True if all entries in the vector are finite + pub fn is_finite(&self) -> bool { + $(self.$field.is_finite())&&+ + } + } + impl $VectorN { /// Component-wise casting to another type. #[inline] @@ -1323,6 +1330,14 @@ mod tests { assert_eq!(v, &VECTOR2); } } + + #[test] + fn test_is_finite() { + use num_traits::Float; + assert!(!Vector2::from([Float::nan(), 1.0]).is_finite()); + assert!(!Vector2::from([1.0, Float::infinity()]).is_finite()); + assert!(Vector2::from([-1.0, 1.0]).is_finite()); + } } mod vector3 { @@ -1428,6 +1443,14 @@ mod tests { assert_eq!(v, &VECTOR3); } } + + #[test] + fn test_is_finite() { + use num_traits::Float; + assert!(!Vector3::from([Float::nan(), 1.0, 1.0]).is_finite()); + assert!(!Vector3::from([1.0, 1.0, Float::infinity()]).is_finite()); + assert!(Vector3::from([-1.0, 1.0, 1.0]).is_finite()); + } } mod vector4 { @@ -1539,5 +1562,13 @@ mod tests { assert_eq!(v, &VECTOR4); } } + + #[test] + fn test_is_finite() { + use num_traits::Float; + assert!(!Vector4::from([0.0, Float::nan(), 1.0, 1.0]).is_finite()); + assert!(!Vector4::from([1.0, 1.0, Float::neg_infinity(), 0.0]).is_finite()); + assert!(Vector4::from([-1.0, 0.0, 1.0, 1.0]).is_finite()); + } } } From f82e421e2caf0a86a2da0d73f946777951eaf09a Mon Sep 17 00:00:00 2001 From: Richard Dodd Date: Sat, 28 Apr 2018 15:09:45 +0100 Subject: [PATCH 2/4] Fix for simd --- src/vector.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/vector.rs b/src/vector.rs index 9cc18a6..05d1ae7 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -360,6 +360,13 @@ macro_rules! impl_vector_default { $VectorN::new($($field),+) } + impl $VectorN { + /// True if all entries in the vector are finite + pub fn is_finite(&self) -> bool { + $(self.$field.is_finite())&&+ + } + } + impl $VectorN { /// Component-wise casting to another type. #[inline] From f8e92ed327bb65a78d2eb2c63baa6dbc990f429d Mon Sep 17 00:00:00 2001 From: Richard Dodd Date: Sun, 29 Apr 2018 14:21:42 +0100 Subject: [PATCH 3/4] Add is_finite to array and quaternion --- src/point.rs | 4 ++++ src/quaternion.rs | 4 ++++ src/structure.rs | 5 +++++ src/vector.rs | 11 ++++------- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/point.rs b/src/point.rs index df5a299..980d496 100644 --- a/src/point.rs +++ b/src/point.rs @@ -118,6 +118,10 @@ macro_rules! impl_point { fn product(self) -> S where S: Mul { fold_array!(mul, { $(self.$field),+ }) } + + fn is_finite(&self) -> bool where S: BaseFloat { + $(self.$field.is_finite())&&+ + } } impl $PointN { diff --git a/src/quaternion.rs b/src/quaternion.rs index fb07ae4..8723785 100644 --- a/src/quaternion.rs +++ b/src/quaternion.rs @@ -173,6 +173,10 @@ impl Quaternion { (self * scale1 + other * scale2) * Rad::sin(theta).recip() } } + + pub fn is_finite(&self) -> bool { + self.s.is_finite() && self.v.is_finite() + } } impl Zero for Quaternion { diff --git a/src/structure.rs b/src/structure.rs index d165fa1..75eadeb 100644 --- a/src/structure.rs +++ b/src/structure.rs @@ -87,6 +87,11 @@ where fn product(self) -> Self::Element where Self::Element: Mul::Element>; + + /// Whether all elements of the array are finite + fn is_finite(&self) -> bool + where + Self::Element: BaseFloat; } /// Element-wise arithmetic operations. These are supplied for pragmatic diff --git a/src/vector.rs b/src/vector.rs index 05d1ae7..b71c65e 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -118,13 +118,6 @@ macro_rules! impl_vector { $VectorN::new($($field),+) } - impl $VectorN { - /// True if all entries in the vector are finite - pub fn is_finite(&self) -> bool { - $(self.$field.is_finite())&&+ - } - } - impl $VectorN { /// Component-wise casting to another type. #[inline] @@ -170,6 +163,10 @@ macro_rules! impl_vector { fn product(self) -> S where S: Mul { fold_array!(mul, { $(self.$field),+ }) } + + fn is_finite(&self) -> bool where S: BaseFloat { + $(self.$field.is_finite())&&+ + } } impl Zero for $VectorN { From 2a7e2ebda390c3da257256414e2de312341d646d Mon Sep 17 00:00:00 2001 From: Richard Dodd Date: Sun, 29 Apr 2018 17:04:49 +0100 Subject: [PATCH 4/4] Fix simd --- src/vector.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vector.rs b/src/vector.rs index b71c65e..055c7e0 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -409,6 +409,10 @@ macro_rules! impl_vector_default { fn product(self) -> S where S: Mul { fold_array!(mul, { $(self.$field),+ }) } + + fn is_finite(&self) -> bool where S: BaseFloat { + $(self.$field.is_finite())&&+ + } } impl Zero for $VectorN {