From 213cc41f7d34c58c28fec7db157f31846b470c53 Mon Sep 17 00:00:00 2001 From: Dimitri Sabadie Date: Fri, 29 Jul 2016 15:56:04 +0200 Subject: [PATCH 1/4] Added exp(), log() and powf() for Quaternion / UnitQuaternion. --- src/structs/quaternion.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/structs/quaternion.rs b/src/structs/quaternion.rs index d785321a..52c7b26d 100644 --- a/src/structs/quaternion.rs +++ b/src/structs/quaternion.rs @@ -568,6 +568,33 @@ impl Arbitrary for UnitQuaternion { } } +impl Quaternion { + /// Compute the exponential of a quaternion. + /// + /// This function yields a `UnitQuaternion`. + pub fn exp(&self) -> UnitQuaternion { + let v = Vector3::new(self.i, self.j, self.k); + let n = v.norm(); + let z = v / n * n.sin(); + + UnitQuaternion::new_with_quaternion(Quaternion::new(n.cos(), z[0], z[1], z[2])) + } +} + +impl UnitQuaternion { + /// Compute the natural logarithm (a.k.a ln()) of a unit quaternion. + /// + /// Becareful, this function yields a `Quaternion`, losing the unit property. + pub fn log(&self) -> Quaternion { + let q = self.quaternion(); + (Quaternion { w: 0., .. *q }).normalize() * q.w.acos() + } + + /// Raise the quaternion to a given floating power. + pub fn powf(&self, n: f32) -> Self { + (self.log() * n).exp() + } +} pord_impl!(Quaternion, w, i, j, k); vec_axis_impl!(Quaternion, w, i, j, k); From 988d9272d2e108e86a43ecaf6bb4e04bcf94aa00 Mon Sep 17 00:00:00 2001 From: Dimitri Sabadie Date: Fri, 29 Jul 2016 17:51:35 +0200 Subject: [PATCH 2/4] =?UTF-8?q?Cleaned=20up=20exp(),=20log()=20and=20powf(?= =?UTF-8?q?)=20for=20Quaternion.=20Also,=20they=E2=80=99re=20for=20Quatern?= =?UTF-8?q?ion=20only=20as=20we=20cannot=20define=20them=20on=20UnitQuater?= =?UTF-8?q?nion.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/structs/quaternion.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/structs/quaternion.rs b/src/structs/quaternion.rs index 52c7b26d..504066b6 100644 --- a/src/structs/quaternion.rs +++ b/src/structs/quaternion.rs @@ -570,24 +570,24 @@ impl Arbitrary for UnitQuaternion { impl Quaternion { /// Compute the exponential of a quaternion. - /// - /// This function yields a `UnitQuaternion`. - pub fn exp(&self) -> UnitQuaternion { - let v = Vector3::new(self.i, self.j, self.k); - let n = v.norm(); - let z = v / n * n.sin(); - - UnitQuaternion::new_with_quaternion(Quaternion::new(n.cos(), z[0], z[1], z[2])) + pub fn exp(&self) -> Self { + let v = *self.vector(); + let nn = v.norm_squared(); + + if nn.is_zero() { + ::one() + } else { + let n = nn.sqrt(); + let nv = v / n * n.sin(); + Quaternion::new(n.cos(), nv.x, nv.y, nv.z) + } } -} -impl UnitQuaternion { - /// Compute the natural logarithm (a.k.a ln()) of a unit quaternion. + /// Compute the natural logarithm (a.k.a ln()) of a quaternion. /// /// Becareful, this function yields a `Quaternion`, losing the unit property. - pub fn log(&self) -> Quaternion { - let q = self.quaternion(); - (Quaternion { w: 0., .. *q }).normalize() * q.w.acos() + pub fn log(&self) -> Self { + (Quaternion { w: 0., .. *self }).normalize() * self.w.acos() } /// Raise the quaternion to a given floating power. From f9c1a2fd9896852b065c017303569076636ad7c7 Mon Sep 17 00:00:00 2001 From: Dimitri Sabadie Date: Fri, 29 Jul 2016 18:02:37 +0200 Subject: [PATCH 3/4] Added a test for Quaternion::exp(). --- tests/quat.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/quat.rs b/tests/quat.rs index 251fabfc..cfe2557a 100644 --- a/tests/quat.rs +++ b/tests/quat.rs @@ -1,7 +1,7 @@ extern crate nalgebra as na; extern crate rand; -use na::{Point3, Vector3, Rotation3, UnitQuaternion, Rotation}; +use na::{Point3, Quaternion, Vector3, Rotation3, UnitQuaternion, Rotation, one}; use rand::random; #[test] @@ -90,3 +90,9 @@ fn test_quaternion_angle_between() { assert!(na::approx_eq(&na::norm(&na::rotation(&delta)), &delta_angle)) } + +#[test] +fn test_quaternion_exp_zero_is_one() { + let q = Quaternion::new(0., 0., 0., 0.); + assert!(na::approx_eq(&q.exp(), &one())) +} From 1fdd8979afa464d1a13d0bfe926e0d9aaab0ee1a Mon Sep 17 00:00:00 2001 From: Dimitri 'phaazon' Sabadie Date: Sat, 30 Jul 2016 14:08:55 +0200 Subject: [PATCH 4/4] Fixed Zero and One for Quaternion. --- src/structs/quaternion.rs | 17 ++++++++++++++++- tests/quat.rs | 12 ++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/structs/quaternion.rs b/src/structs/quaternion.rs index 504066b6..aa127402 100644 --- a/src/structs/quaternion.rs +++ b/src/structs/quaternion.rs @@ -596,6 +596,22 @@ impl Quaternion { } } +impl Zero for Quaternion where T: Zero { + fn zero() -> Self { + Quaternion::new(::zero(), ::zero(), ::zero(), ::zero()) + } + + fn is_zero(&self) -> bool { + self.w.is_zero() && self.i.is_zero() && self.j.is_zero() && self.k.is_zero() + } +} + +impl One for Quaternion where T: Copy + One + Zero + Sub + Add { + fn one() -> Self { + Quaternion::new(T::one(), T::zero(), T::zero(), T::zero()) + } +} + pord_impl!(Quaternion, w, i, j, k); vec_axis_impl!(Quaternion, w, i, j, k); vec_cast_impl!(Quaternion, w, i, j, k); @@ -613,7 +629,6 @@ scalar_sub_impl!(Quaternion, w, i, j, k); scalar_mul_impl!(Quaternion, w, i, j, k); scalar_div_impl!(Quaternion, w, i, j, k); neg_impl!(Quaternion, w, i, j, k); -zero_one_impl!(Quaternion, w, i, j, k); approx_eq_impl!(Quaternion, w, i, j, k); from_iterator_impl!(Quaternion, iterator, iterator, iterator, iterator); bounded_impl!(Quaternion, w, i, j, k); diff --git a/tests/quat.rs b/tests/quat.rs index cfe2557a..1b0185eb 100644 --- a/tests/quat.rs +++ b/tests/quat.rs @@ -96,3 +96,15 @@ fn test_quaternion_exp_zero_is_one() { let q = Quaternion::new(0., 0., 0., 0.); assert!(na::approx_eq(&q.exp(), &one())) } + +#[test] +fn test_quaternion_neutral() { + for _ in 0 .. 10000 { + let q1: Quaternion = random(); + let qi: Quaternion = one(); + let q2 = q1 * qi; + let q3 = qi * q1; + + assert!(na::approx_eq(&q1, &q2) && na::approx_eq(&q2, &q3)) + } +}