From 94d428d23ea10fc38ea9c88ffbe7fe6fcdca249b Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Sat, 4 Apr 2015 20:15:00 -0400 Subject: [PATCH 1/4] Fixed the Neg disaster --- Cargo.toml | 2 +- src/matrix.rs | 73 ++++++++++++++++++++++++++++----------------------- src/num.rs | 2 +- src/vector.rs | 21 ++++++++------- 4 files changed, 54 insertions(+), 44 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a396ec5..0aa8c88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "cgmath" -version = "0.1.2" +version = "0.1.3" authors = ["Brendan Zabarauskas ", "Brian Heylin", "Colin Sherratt", diff --git a/src/matrix.rs b/src/matrix.rs index 2d7f9e6..8720071 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -44,7 +44,7 @@ pub struct Matrix3 { pub x: Vector3, pub y: Vector3, pub z: Vector3 pub struct Matrix4 { pub x: Vector4, pub y: Vector4, pub z: Vector4, pub w: Vector4 } -impl Matrix2 { +impl Matrix2 { /// Create a new matrix, providing values for each index. #[inline] pub fn new(c0r0: S, c0r1: S, @@ -58,7 +58,9 @@ impl Matrix2 { pub fn from_cols(c0: Vector2, c1: Vector2) -> Matrix2 { Matrix2 { x: c0, y: c1 } } +} +impl Matrix2 { /// Create a new diagonal matrix, providing a single value to use for each /// non-zero index. #[inline] @@ -98,6 +100,15 @@ impl Matrix2 { } } +impl> Matrix2 { + /// Negate this `Matrix2` in-place. + #[inline] + pub fn neg_self(&mut self) { + (&mut self[0]).neg_self(); + (&mut self[1]).neg_self(); + } +} + impl Matrix3 { /// Create a new matrix, providing values for each index. #[inline] @@ -137,8 +148,7 @@ impl Matrix3 { } } -impl -Matrix3 { +impl Matrix3 { /// Create a transformation matrix that will cause a vector to point at /// `dir`, using `up` for orientation. pub fn look_at(dir: &Vector3, up: &Vector3) -> Matrix3 { @@ -220,6 +230,16 @@ Matrix3 { } } +impl> Matrix3 { + /// Negate this `Matrix3` in-place. + #[inline] + pub fn neg_self(&mut self) { + (&mut self[0]).neg_self(); + (&mut self[1]).neg_self(); + (&mut self[2]).neg_self(); + } +} + impl Matrix4 { /// Create a new matrix, providing values for each index. #[inline] @@ -271,8 +291,7 @@ impl Matrix4 { } } -impl -Matrix4 { +impl Matrix4 { /// Create a transformation matrix that will cause a vector to point at /// `dir`, using `up` for orientation. pub fn look_at(eye: &Point3, center: &Point3, up: &Vector3) -> Matrix4 { @@ -287,8 +306,18 @@ Matrix4 { } } +impl> Matrix4 { + /// Negate this `Matrix4` in-place. + #[inline] + pub fn neg_self(&mut self) { + (&mut self[0]).neg_self(); + (&mut self[1]).neg_self(); + (&mut self[2]).neg_self(); + (&mut self[3]).neg_self(); + } +} + pub trait Matrix>: Array2 - + Neg + Zero + One + ApproxEq + Sized { @@ -317,9 +346,6 @@ pub trait Matrix>: Array2 #[must_use] fn mul_m(&self, m: &Self) -> Self; - /// Negate this matrix in-place (multiply by scalar -1). - fn neg_self(&mut self); - /// Multiply this matrix by a scalar, in-place. fn mul_self_s(&mut self, s: S); /// Divide this matrix by a scalar, in-place. @@ -423,11 +449,13 @@ impl Sub for Matrix4 { fn sub(self, other: Matrix4) -> Matrix4 { self.sub_m(&other) } } -impl Neg for Matrix2 { - type Output = Matrix2; +impl Neg for Matrix2 { + type Output = Matrix2; #[inline] - fn neg(self) -> Matrix2 { Matrix2::from_cols(self[0].neg(), self[1].neg()) } + fn neg(self) -> Matrix2 { + Matrix2::from_cols(self.x.neg(), self.y.neg()) + } } impl Neg for Matrix3 { @@ -795,12 +823,6 @@ impl Matrix> for Matrix2 { self.row(0).dot(&other[1]), self.row(1).dot(&other[1])) } - #[inline] - fn neg_self(&mut self) { - (&mut self[0]).neg_self(); - (&mut self[1]).neg_self(); - } - #[inline] fn mul_self_s(&mut self, s: S) { (&mut self[0]).mul_self_s(s); @@ -926,13 +948,6 @@ impl Matrix> for Matrix3 { self.row(0).dot(&other[2]),self.row(1).dot(&other[2]),self.row(2).dot(&other[2])) } - #[inline] - fn neg_self(&mut self) { - (&mut self[0]).neg_self(); - (&mut self[1]).neg_self(); - (&mut self[2]).neg_self(); - } - #[inline] fn mul_self_s(&mut self, s: S) { (&mut self[0]).mul_self_s(s); @@ -1094,14 +1109,6 @@ impl Matrix> for Matrix4 { dot_matrix4!(self, other, 0, 3), dot_matrix4!(self, other, 1, 3), dot_matrix4!(self, other, 2, 3), dot_matrix4!(self, other, 3, 3)) } - #[inline] - fn neg_self(&mut self) { - (&mut self[0]).neg_self(); - (&mut self[1]).neg_self(); - (&mut self[2]).neg_self(); - (&mut self[3]).neg_self(); - } - #[inline] fn mul_self_s(&mut self, s: S) { (&mut self[0]).mul_self_s(s); diff --git a/src/num.rs b/src/num.rs index 7de7ebf..cbd5744 100644 --- a/src/num.rs +++ b/src/num.rs @@ -72,7 +72,7 @@ pub trait One { /// Base numeric types with partial ordering pub trait BaseNum: Copy + NumCast + Clone + Add + Sub + - Mul + Div + Rem + Neg + PartialEq + Mul + Div + Rem + PartialEq + PartialOrd + cmp::PartialOrd + fmt::Debug + Zero + One {} diff --git a/src/vector.rs b/src/vector.rs index 7f32b8e..4cc8581 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -111,7 +111,7 @@ use num::{BaseNum, BaseFloat, Zero, One, zero, one}; /// A trait that specifies a range of numeric operations for vectors. Not all /// of these make sense from a linear algebra point of view, but are included /// for pragmatic reasons. -pub trait Vector: Array1 + Zero + One + Neg { +pub trait Vector: Array1 + Zero + One { /// Construct a vector from a single value, replicating it. fn from_value(s: S) -> Self; /// Add a scalar to this vector, returning a new vector. @@ -146,9 +146,6 @@ pub trait Vector: Array1 + Zero + One + Neg { #[must_use] fn rem_v(&self, v: &Self) -> Self; - /// Negate this vector in-place. - fn neg_self(&mut self); - /// Add a scalar to this vector in-place. fn add_self_s(&mut self, s: S); /// Subtract a scalar from this vector, in-place. @@ -203,6 +200,14 @@ macro_rules! vec( } } + impl<$S: Copy + Neg> $Self_<$S> { + /// Negate this vector in-place (multiply by -1). + #[inline] + pub fn neg_self(&mut self) { + $(self.$field = -self.$field);+ + } + } + /// The short constructor. #[inline] pub fn $constructor($($field: S),+) -> $Self_ { @@ -300,8 +305,6 @@ macro_rules! vec( #[inline] fn div_v(&self, v: &$Self_) -> $Self_ { $Self_::new($(self.$field / v.$field),+) } #[inline] fn rem_v(&self, v: &$Self_) -> $Self_ { $Self_::new($(self.$field % v.$field),+) } - #[inline] fn neg_self(&mut self) { $(self.$field = -self.$field;)+ } - #[inline] fn add_self_s(&mut self, s: S) { $(self.$field = self.$field + s;)+ } #[inline] fn sub_self_s(&mut self, s: S) { $(self.$field = self.$field - s;)+ } #[inline] fn mul_self_s(&mut self, s: S) { $(self.$field = self.$field * s;)+ } @@ -334,11 +337,11 @@ macro_rules! vec( fn sub(self, v: $Self_) -> $Self_ { self.sub_v(&v) } } - impl Neg for $Self_ { - type Output = $Self_; + impl Neg for $Self_ { + type Output = $Self_; #[inline] - fn neg(self) -> $Self_ { $Self_::new($(-self.$field),+) } + fn neg(self) -> $Self_ { $Self_::new($(-self.$field),+) } } impl Mul for $Self_ { From 8db429acae12a78c8b8dc38d1959ce50920f4464 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Sat, 4 Apr 2015 21:19:11 -0400 Subject: [PATCH 2/4] Using rust-lang/num --- Cargo.toml | 1 + src/aabb.rs | 9 +++++--- src/angle.rs | 6 +++-- src/approx.rs | 6 ++--- src/lib.rs | 1 + src/line.rs | 5 +++- src/matrix.rs | 58 +++++++++++++++++++++++++++------------------- src/num.rs | 59 +++++------------------------------------------ src/plane.rs | 4 +++- src/point.rs | 4 +++- src/projection.rs | 4 +++- src/quaternion.rs | 7 +++--- src/sphere.rs | 4 +++- src/transform.rs | 7 +++--- src/vector.rs | 9 ++++---- 15 files changed, 84 insertions(+), 100 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0aa8c88..f904e74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,4 +24,5 @@ name = "cgmath" rustc_serialize = "*" [dependencies] +num = "*" rand = "*" diff --git a/src/aabb.rs b/src/aabb.rs index 5b28ad8..ebdeb35 100644 --- a/src/aabb.rs +++ b/src/aabb.rs @@ -20,15 +20,18 @@ //! dimension) where the slope of every line is either 0 or undefined. These //! are useful for very cheap collision detection. +use std::fmt; + +use rust_num::{Float, zero, one}; + use bound::*; use point::{Point, Point2, Point3}; use vector::{Vector, Vector2, Vector3}; use ray::{Ray2}; use intersect::Intersect; -use num::{zero, one, BaseNum, BaseFloat}; +use num::{BaseNum, BaseFloat}; use plane::Plane; -use std::fmt; -use std::num::Float; + pub trait Aabb, P: Point>: Sized { /// Create a new AABB using two points as opposing corners. diff --git a/src/angle.rs b/src/angle.rs index d5df99f..da928f0 100644 --- a/src/angle.rs +++ b/src/angle.rs @@ -17,14 +17,16 @@ use std::fmt; use std::f64; -use std::num::{cast, Float}; +use std::num::cast; use std::ops::*; use rand::{Rand, Rng}; use rand::distributions::range::SampleRange; +use rust_num::{One, Zero, one, zero}; + use approx::ApproxEq; -use num::{BaseFloat, One, one, Zero, zero}; +use num::BaseFloat; /// An angle, in radians #[derive(Copy, Clone, PartialEq, PartialOrd, Hash, RustcEncodable, RustcDecodable)] diff --git a/src/approx.rs b/src/approx.rs index 1531850..f391c7e 100644 --- a/src/approx.rs +++ b/src/approx.rs @@ -13,12 +13,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::num; -use std::num::Float; +use std::num::cast; +use rust_num::Float; pub trait ApproxEq: Sized { fn approx_epsilon(_hack: Option) -> T { - num::cast(1.0e-5f64).unwrap() + cast(1.0e-5f64).unwrap() } fn approx_eq(&self, other: &Self) -> bool { diff --git a/src/lib.rs b/src/lib.rs index 1880634..c44f878 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,6 +31,7 @@ //! `look_at`, `from_angle`, `from_euler`, and `from_axis_angle` methods. //! These are provided for convenience. +extern crate num as rust_num; extern crate rustc_serialize; extern crate rand; diff --git a/src/line.rs b/src/line.rs index 3156cbb..3d20e45 100644 --- a/src/line.rs +++ b/src/line.rs @@ -16,7 +16,10 @@ //! Line segments use std::marker::PhantomData; -use num::{BaseNum, BaseFloat, Zero, zero, One, one}; + +use rust_num::{Zero, zero, One, one}; + +use num::{BaseNum, BaseFloat}; use point::{Point, Point2, Point3}; use vector::{Vector, Vector2, Vector3}; use ray::{Ray2}; diff --git a/src/matrix.rs b/src/matrix.rs index 8720071..9c6572c 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -22,10 +22,12 @@ use std::ops::*; use rand::{Rand, Rng}; +use rust_num::{Zero, zero, One, one}; + use angle::{Rad, sin, cos, sin_cos}; use approx::ApproxEq; use array::{Array1, Array2, FixedArray}; -use num::{BaseFloat, BaseNum, Zero, zero, One, one}; +use num::{BaseFloat, BaseNum}; use point::{Point, Point3}; use quaternion::{Quaternion, ToQuaternion}; use vector::{Vector, EuclideanVector}; @@ -82,7 +84,7 @@ impl Matrix2 { } } -impl Matrix2 { +impl Matrix2 { /// Create a transformation matrix that will cause a vector to point at /// `dir`, using `up` for orientation. pub fn look_at(dir: &Vector2, up: &Vector2) -> Matrix2 { @@ -109,7 +111,7 @@ impl> Matrix2 { } } -impl Matrix3 { +impl Matrix3 { /// Create a new matrix, providing values for each index. #[inline] pub fn new(c0r0:S, c0r1:S, c0r2:S, @@ -125,7 +127,9 @@ impl Matrix3 { pub fn from_cols(c0: Vector3, c1: Vector3, c2: Vector3) -> Matrix3 { Matrix3 { x: c0, y: c1, z: c2 } } +} +impl Matrix3 { /// Create a new diagonal matrix, providing a single value to use for each /// non-zero index. #[inline] @@ -148,7 +152,7 @@ impl Matrix3 { } } -impl Matrix3 { +impl Matrix3 { /// Create a transformation matrix that will cause a vector to point at /// `dir`, using `up` for orientation. pub fn look_at(dir: &Vector3, up: &Vector3) -> Matrix3 { @@ -240,7 +244,7 @@ impl> Matrix3 { } } -impl Matrix4 { +impl Matrix4 { /// Create a new matrix, providing values for each index. #[inline] pub fn new(c0r0: S, c0r1: S, c0r2: S, c0r3: S, @@ -258,7 +262,9 @@ impl Matrix4 { pub fn from_cols(c0: Vector4, c1: Vector4, c2: Vector4, c3: Vector4) -> Matrix4 { Matrix4 { x: c0, y: c1, z: c2, w: c3 } } +} +impl Matrix4 { /// Create a new diagonal matrix, providing a single value to use for each /// non-zero index. #[inline] @@ -407,42 +413,42 @@ pub trait Matrix>: Array2 fn is_symmetric(&self) -> bool; } -impl Add for Matrix2 { +impl Add for Matrix2 { type Output = Matrix2; #[inline] fn add(self, other: Matrix2) -> Matrix2 { self.add_m(&other) } } -impl Add for Matrix3 { +impl Add for Matrix3 { type Output = Matrix3; #[inline] fn add(self, other: Matrix3) -> Matrix3 { self.add_m(&other) } } -impl Add for Matrix4 { +impl Add for Matrix4 { type Output = Matrix4; #[inline] fn add(self, other: Matrix4) -> Matrix4 { self.add_m(&other) } } -impl Sub for Matrix2 { +impl Sub for Matrix2 { type Output = Matrix2; #[inline] fn sub(self, other: Matrix2) -> Matrix2 { self.sub_m(&other) } } -impl Sub for Matrix3 { +impl Sub for Matrix3 { type Output = Matrix3; #[inline] fn sub(self, other: Matrix3) -> Matrix3 { self.sub_m(&other) } } -impl Sub for Matrix4 { +impl Sub for Matrix4 { type Output = Matrix4; #[inline] @@ -458,18 +464,22 @@ impl Neg for Matrix2 { } } -impl Neg for Matrix3 { - type Output = Matrix3; +impl Neg for Matrix3 { + type Output = Matrix3; #[inline] - fn neg(self) -> Matrix3 { Matrix3::from_cols(self[0].neg(), self[1].neg(), self[2].neg()) } + fn neg(self) -> Matrix3 { + Matrix3::from_cols(self.x.neg(), self.y.neg(), self.z.neg()) + } } -impl Neg for Matrix4 { - type Output = Matrix4; +impl Neg for Matrix4 { + type Output = Matrix4; #[inline] - fn neg(self) -> Matrix4 { Matrix4::from_cols(self[0].neg(), self[1].neg(), self[2].neg(), self[3].neg()) } + fn neg(self) -> Matrix4 { + Matrix4::from_cols(self.x.neg(), self.y.neg(), self.z.neg(), self.w.neg()) + } } impl Zero for Matrix2 { @@ -493,21 +503,21 @@ impl Zero for Matrix4 { fn is_zero(&self) -> bool{ *self == zero() } } -impl Mul for Matrix2 { +impl Mul for Matrix2 { type Output = Matrix2; #[inline] fn mul(self, other: Matrix2) -> Matrix2 { self.mul_m(&other) } } -impl Mul for Matrix3 { +impl Mul for Matrix3 { type Output = Matrix3; #[inline] fn mul(self, other: Matrix3) -> Matrix3 { self.mul_m(&other) } } -impl Mul for Matrix4 { +impl Mul for Matrix4 { type Output = Matrix4; #[inline] @@ -781,7 +791,7 @@ impl Array2, Vector4, S> for Matrix4 { } } -impl Matrix> for Matrix2 { +impl Matrix> for Matrix2 { #[inline] fn mul_s(&self, s: S) -> Matrix2 { Matrix2::from_cols(self[0].mul_s(s), @@ -899,7 +909,7 @@ impl Matrix> for Matrix2 { } } -impl Matrix> for Matrix3 { +impl Matrix> for Matrix3 { #[inline] fn mul_s(&self, s: S) -> Matrix3 { Matrix3::from_cols(self[0].mul_s(s), @@ -1053,7 +1063,7 @@ macro_rules! dot_matrix4( ($A[3][$I]) * ($B[$J][3]) )); -impl Matrix> for Matrix4 { +impl Matrix> for Matrix4 { #[inline] fn mul_s(&self, s: S) -> Matrix4 { Matrix4::from_cols(self[0].mul_s(s), @@ -1345,7 +1355,7 @@ impl ToMatrix4 for Matrix3 { } } -impl ToQuaternion for Matrix3 { +impl ToQuaternion for Matrix3 { /// Convert the matrix to a quaternion fn to_quaternion(&self) -> Quaternion { // http://www.cs.ucr.edu/~vbz/resources/quatut.pdf diff --git a/src/num.rs b/src/num.rs index cbd5744..e2e4a32 100644 --- a/src/num.rs +++ b/src/num.rs @@ -17,9 +17,10 @@ use approx::ApproxEq; use std::cmp; use std::fmt; -use std::num::{Float, Int, NumCast}; use std::ops::*; +use rust_num::{Float, Num, NumCast}; + /// A trait providing a [partial ordering](http://mathworld.wolfram.com/PartialOrder.html). pub trait PartialOrd { fn partial_min(self, other: Self) -> Self; @@ -58,43 +59,18 @@ macro_rules! partial_ord_float ( partial_ord_float!(f32); partial_ord_float!(f64); -/// Additive neutral element -pub trait Zero { - fn zero() -> Self; - fn is_zero(&self) -> bool; -} - -/// Multiplicative neutral element -pub trait One { - fn one() -> Self; -} /// Base numeric types with partial ordering pub trait BaseNum: - Copy + NumCast + Clone + Add + Sub + - Mul + Div + Rem + PartialEq - + PartialOrd + cmp::PartialOrd + fmt::Debug + Zero + One + Copy + NumCast + Clone + Num + + PartialOrd + cmp::PartialOrd + fmt::Debug + + 'static {} macro_rules! impl_basenum_int ( ($T: ident) => ( impl BaseNum for $T {} - impl Zero for $T { - fn zero() -> $T { - Int::zero() - } - - fn is_zero(&self) -> bool { - *self == Int::zero() - } - } - - impl One for $T { - fn one() -> $T { - Int::one() - } - } ) ); @@ -113,38 +89,15 @@ impl_basenum_int!(usize); macro_rules! impl_basenum_float ( ($T: ident) => ( impl BaseNum for $T {} - impl Zero for $T { - fn zero() -> $T { - Float::zero() - } - - fn is_zero(&self) -> bool { - *self == Float::zero() - } - } - - impl One for $T { - fn one() -> $T { - Float::one() - } - } ) ); impl_basenum_float!(f32); impl_basenum_float!(f64); -pub fn zero() -> T { - Zero::zero() -} - -pub fn one() -> T { - One::one() -} - /// Base integer types -pub trait BaseInt : BaseNum + Int {} +pub trait BaseInt : BaseNum {} impl BaseInt for i8 {} impl BaseInt for i16 {} diff --git a/src/plane.rs b/src/plane.rs index 72251ab..2c3c102 100644 --- a/src/plane.rs +++ b/src/plane.rs @@ -15,9 +15,11 @@ use std::fmt; +use rust_num::{one, Zero, zero}; + use approx::ApproxEq; use intersect::Intersect; -use num::{BaseFloat, one, Zero, zero}; +use num::{BaseFloat}; use point::{Point, Point3}; use ray::Ray3; use vector::{Vector3, Vector4}; diff --git a/src/point.rs b/src/point.rs index 03923ef..a19c15e 100644 --- a/src/point.rs +++ b/src/point.rs @@ -21,11 +21,13 @@ use std::fmt; use std::mem; use std::ops::*; +use rust_num::{one, zero}; + use approx::ApproxEq; use array::{Array1, FixedArray}; use bound::*; use matrix::{Matrix, Matrix4}; -use num::{BaseNum, BaseFloat, one, zero}; +use num::{BaseNum, BaseFloat}; use plane::Plane; use vector::*; diff --git a/src/projection.rs b/src/projection.rs index e1ed503..639ca0d 100644 --- a/src/projection.rs +++ b/src/projection.rs @@ -15,10 +15,12 @@ use std::num::cast; +use rust_num::{zero, one}; + use angle::{Angle, tan, cot}; use frustum::Frustum; use matrix::{Matrix4, ToMatrix4}; -use num::{BaseFloat, zero, one}; +use num::BaseFloat; use plane::Plane; /// Create a perspective projection matrix. diff --git a/src/quaternion.rs b/src/quaternion.rs index 7d48b1a..af6c822 100644 --- a/src/quaternion.rs +++ b/src/quaternion.rs @@ -13,19 +13,20 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::f64; use std::fmt; use std::mem; -use std::f64; -use std::num::{cast, Float}; +use std::num::cast; use std::ops::*; use rand::{Rand, Rng}; +use rust_num::{Float, one, zero}; use angle::{Angle, Rad, acos, sin, sin_cos, rad}; use approx::ApproxEq; use array::Array1; use matrix::{Matrix3, ToMatrix3, ToMatrix4, Matrix4}; -use num::{BaseFloat, one, zero}; +use num::BaseFloat; use point::Point3; use rotation::{Rotation, Rotation3, Basis3, ToBasis3}; use vector::{Vector3, Vector, EuclideanVector}; diff --git a/src/sphere.rs b/src/sphere.rs index b297aec..28deb77 100644 --- a/src/sphere.rs +++ b/src/sphere.rs @@ -15,9 +15,11 @@ //! Bounding sphere +use rust_num::zero; + use bound::*; use intersect::Intersect; -use num::{BaseFloat, zero}; +use num::BaseFloat; use point::{Point, Point3}; use plane::Plane; use ray::Ray3; diff --git a/src/transform.rs b/src/transform.rs index 0382839..0dabdf3 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -15,19 +15,20 @@ use std::fmt; +use rust_num::{zero, one}; + use approx::ApproxEq; use matrix::*; use num::*; use point::*; use ray::Ray; use rotation::*; -use std::marker::PhantomFn; use vector::*; /// A trait representing an [affine /// transformation](https://en.wikipedia.org/wiki/Affine_transformation) that /// can be applied to points or vectors. An affine transformation is one which -pub trait Transform, P: Point>: Sized + PhantomFn { +pub trait Transform, P: Point>: Sized { /// Create an identity transformation. That is, a transformation which /// does nothing. fn identity() -> Self; @@ -236,7 +237,7 @@ impl Transform3 for AffineMatrix3 {} /// A trait that allows extracting components (rotation, translation, scale) /// from an arbitrary transformations -pub trait ToComponents, P: Point, R: Rotation>: PhantomFn<(S, P)> { +pub trait ToComponents, P: Point, R: Rotation> { /// Extract the (scale, rotation, translation) triple fn decompose(&self) -> (V, R, V); } diff --git a/src/vector.rs b/src/vector.rs index 4cc8581..af2ee69 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -98,15 +98,16 @@ use std::fmt; use std::mem; -use std::num::NumCast; use std::ops::*; use rand::{Rand, Rng}; +use rust_num::{NumCast, Zero, One, zero, one}; + use angle::{Rad, atan2, acos}; use approx::ApproxEq; use array::{Array1, FixedArray}; -use num::{BaseNum, BaseFloat, Zero, One, zero, one}; +use num::{BaseNum, BaseFloat}; /// A trait that specifies a range of numeric operations for vectors. Not all /// of these make sense from a linear algebra point of view, but are included @@ -214,7 +215,7 @@ macro_rules! vec( $Self_::new($($field),+) } - impl<$S: Zero> Zero for $Self_<$S> { + impl<$S: Zero + BaseNum> Zero for $Self_<$S> { #[inline] fn zero() -> $Self_ { $Self_ { $($field: zero()),+ } } @@ -222,7 +223,7 @@ macro_rules! vec( fn is_zero(&self) -> bool { $((self.$field.is_zero()) )&&+ } } - impl<$S: One> One for $Self_<$S> { + impl<$S: One + BaseNum> One for $Self_<$S> { #[inline] fn one() -> $Self_<$S> { $Self_ { $($field: one()),+ } } } From b56ad542b3ac899a5d6a93a3aaf285e651a47280 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Sat, 4 Apr 2015 21:32:12 -0400 Subject: [PATCH 3/4] Fixed NumCast and angles --- src/angle.rs | 26 +++++++++++++++++++++----- src/approx.rs | 4 ++-- src/lib.rs | 2 +- src/num.rs | 4 ++-- src/vector.rs | 3 ++- 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/angle.rs b/src/angle.rs index da928f0..fa7191e 100644 --- a/src/angle.rs +++ b/src/angle.rs @@ -23,7 +23,7 @@ use std::ops::*; use rand::{Rand, Rng}; use rand::distributions::range::SampleRange; -use rust_num::{One, Zero, one, zero}; +use rust_num::{Float, One, Zero, one, zero}; use approx::ApproxEq; use num::BaseFloat; @@ -52,11 +52,27 @@ pub trait ToDeg { fn to_deg(&self) -> Deg; } -impl ToRad for Rad { #[inline] fn to_rad(&self) -> Rad { self.clone() } } -impl ToRad for Deg { #[inline] fn to_rad(&self) -> Rad { rad(self.s.to_radians()) } } +impl ToRad for Rad { + #[inline] + fn to_rad(&self) -> Rad { self.clone() } +} +impl ToRad for Deg { + #[inline] + fn to_rad(&self) -> Rad { + rad(self.s * cast(f64::consts::PI / 180.0).unwrap()) + } +} -impl ToDeg for Rad { #[inline] fn to_deg(&self) -> Deg { deg(self.s.to_degrees()) } } -impl ToDeg for Deg { #[inline] fn to_deg(&self) -> Deg { self.clone() } } +impl ToDeg for Rad { + #[inline] + fn to_deg(&self) -> Deg { + deg(self.s * cast(180.0 / f64::consts::PI).unwrap()) + } +} +impl ToDeg for Deg { + #[inline] + fn to_deg(&self) -> Deg { self.clone() } +} /// Private utility functions for converting to/from scalars trait ScalarConv { diff --git a/src/approx.rs b/src/approx.rs index f391c7e..5a12903 100644 --- a/src/approx.rs +++ b/src/approx.rs @@ -13,10 +13,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::num::cast; +use std::num::{NumCast, cast}; use rust_num::Float; -pub trait ApproxEq: Sized { +pub trait ApproxEq: Sized { fn approx_epsilon(_hack: Option) -> T { cast(1.0e-5f64).unwrap() } diff --git a/src/lib.rs b/src/lib.rs index c44f878..6d578ea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,7 +15,7 @@ #![crate_type = "rlib"] #![crate_type = "dylib"] -#![feature(plugin, core, std_misc, custom_derive)] +#![feature(plugin, core, custom_derive)] //! Computer graphics-centric math. //! diff --git a/src/num.rs b/src/num.rs index e2e4a32..9d68a2d 100644 --- a/src/num.rs +++ b/src/num.rs @@ -17,9 +17,9 @@ use approx::ApproxEq; use std::cmp; use std::fmt; -use std::ops::*; +use std::num::NumCast; -use rust_num::{Float, Num, NumCast}; +use rust_num::{Float, Num}; /// A trait providing a [partial ordering](http://mathworld.wolfram.com/PartialOrder.html). pub trait PartialOrd { diff --git a/src/vector.rs b/src/vector.rs index af2ee69..03a9da3 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -98,11 +98,12 @@ use std::fmt; use std::mem; +use std::num::NumCast; use std::ops::*; use rand::{Rand, Rng}; -use rust_num::{NumCast, Zero, One, zero, one}; +use rust_num::{Zero, One, zero, one}; use angle::{Rad, atan2, acos}; use approx::ApproxEq; From 498df017295bd42ded00523498894fc3124f8e6a Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Sat, 4 Apr 2015 22:14:03 -0400 Subject: [PATCH 4/4] Fixed all the warnings, compile issues, and tests --- src/lib.rs | 2 ++ src/matrix.rs | 18 +++++++++--------- src/transform.rs | 3 ++- src/vector.rs | 10 +++++----- tests/matrix.rs | 3 --- tests/quaternion.rs | 2 -- tests/sphere.rs | 1 - tests/transform.rs | 2 +- tests/vector.rs | 9 +++------ 9 files changed, 22 insertions(+), 28 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 6d578ea..4d2fcbd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,6 +63,8 @@ pub use sphere::Sphere; pub use approx::ApproxEq; pub use num::*; +pub use rust_num::{One, Zero, one, zero}; + // Modules mod array; diff --git a/src/matrix.rs b/src/matrix.rs index 9c6572c..ca6d3ea 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -455,29 +455,29 @@ impl Sub for Matrix4 { fn sub(self, other: Matrix4) -> Matrix4 { self.sub_m(&other) } } -impl Neg for Matrix2 { - type Output = Matrix2; +impl> Neg for Matrix2 { + type Output = Matrix2; #[inline] - fn neg(self) -> Matrix2 { + fn neg(self) -> Matrix2 { Matrix2::from_cols(self.x.neg(), self.y.neg()) } } -impl Neg for Matrix3 { - type Output = Matrix3; +impl> Neg for Matrix3 { + type Output = Matrix3; #[inline] - fn neg(self) -> Matrix3 { + fn neg(self) -> Matrix3 { Matrix3::from_cols(self.x.neg(), self.y.neg(), self.z.neg()) } } -impl Neg for Matrix4 { - type Output = Matrix4; +impl> Neg for Matrix4 { + type Output = Matrix4; #[inline] - fn neg(self) -> Matrix4 { + fn neg(self) -> Matrix4 { Matrix4::from_cols(self.x.neg(), self.y.neg(), self.z.neg(), self.w.neg()) } } diff --git a/src/transform.rs b/src/transform.rs index 0dabdf3..fc41c1e 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -261,7 +261,8 @@ impl< R: Rotation + Clone, > ToComponents for Decomposed { fn decompose(&self) -> (V, R, V) { - (Vector::from_value(self.scale), self.rot.clone(), self.disp.clone()) + let v: V = one(); + (v.mul_s(self.scale), self.rot.clone(), self.disp.clone()) } } diff --git a/src/vector.rs b/src/vector.rs index 03a9da3..4f72b93 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -26,7 +26,7 @@ //! //! assert_eq!(Vector2::new(1.0f64, 0.0f64), Vector2::unit_x()); //! assert_eq!(vec3(0.0f64, 0.0f64, 0.0f64), zero()); -//! assert_eq!(Vector::from_value(1.0f64), vec2(1.0, 1.0)); +//! assert_eq!(Vector2::from_value(1.0f64), vec2(1.0, 1.0)); //! ``` //! //! Vectors can be manipulated with typical mathematical operations (addition, @@ -76,7 +76,7 @@ //! //! // Scalar multiplication can return a new object, or be done in place //! // to avoid an allocation: -//! let mut c: Vector4 = Vector::from_value(3.0); +//! let mut c = Vector4::from_value(3f64); //! let d: Vector4 = c.mul_s(2.0); //! c.mul_self_s(2.0); //! assert_eq!(c, d); @@ -339,11 +339,11 @@ macro_rules! vec( fn sub(self, v: $Self_) -> $Self_ { self.sub_v(&v) } } - impl Neg for $Self_ { - type Output = $Self_; + impl> Neg for $Self_ { + type Output = $Self_; #[inline] - fn neg(self) -> $Self_ { $Self_::new($(-self.$field),+) } + fn neg(self) -> $Self_ { $Self_::new($(-self.$field),+) } } impl Mul for $Self_ { diff --git a/tests/matrix.rs b/tests/matrix.rs index 08d93cb..d087a02 100644 --- a/tests/matrix.rs +++ b/tests/matrix.rs @@ -13,9 +13,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![feature(core)] - - extern crate cgmath; use cgmath::*; diff --git a/tests/quaternion.rs b/tests/quaternion.rs index 6b0dcf2..3462365 100644 --- a/tests/quaternion.rs +++ b/tests/quaternion.rs @@ -13,8 +13,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![feature(core)] - extern crate cgmath; use cgmath::{ToMatrix4, ToMatrix3}; diff --git a/tests/sphere.rs b/tests/sphere.rs index 55d8415..29b9840 100644 --- a/tests/sphere.rs +++ b/tests/sphere.rs @@ -17,7 +17,6 @@ extern crate cgmath; use cgmath::*; -use std::num::Float; #[test] fn test_intersection() { diff --git a/tests/transform.rs b/tests/transform.rs index a46f6fb..e6654d8 100644 --- a/tests/transform.rs +++ b/tests/transform.rs @@ -50,7 +50,7 @@ fn test_components() { disp: Vector3::new(6.0f64,-7.0,8.0) }; let (scale, rot, disp) = t.decompose(); - assert_eq!(scale, Vector::from_value(t.scale)); + assert_eq!(scale, Vector3::from_value(t.scale)); assert_eq!(rot, t.rot); assert_eq!(disp, t.disp); } diff --git a/tests/vector.rs b/tests/vector.rs index 0be7926..65b0287 100644 --- a/tests/vector.rs +++ b/tests/vector.rs @@ -13,14 +13,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![feature(core)] - #[macro_use] extern crate cgmath; use cgmath::*; use std::f64; -use std::num::Float; #[test] fn test_constructor() { @@ -31,9 +28,9 @@ fn test_constructor() { #[test] fn test_from_value() { - assert_eq!(Vector::from_value(102isize), Vector2::new(102isize, 102isize)); - assert_eq!(Vector::from_value(22isize), Vector3::new(22isize, 22isize, 22isize)); - assert_eq!(Vector::from_value(76.5f64), Vector4::new(76.5f64, 76.5f64, 76.5f64, 76.5f64)); + assert_eq!(Vector2::from_value(102isize), Vector2::new(102isize, 102isize)); + assert_eq!(Vector3::from_value(22isize), Vector3::new(22isize, 22isize, 22isize)); + assert_eq!(Vector4::from_value(76.5f64), Vector4::new(76.5f64, 76.5f64, 76.5f64, 76.5f64)); } #[test]