From 25ca5670601485b6806001fd2b469c13cdac97c8 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 14 Nov 2015 12:03:12 +1100 Subject: [PATCH 1/6] Move element-wise operations into `Array1` trait --- src/array.rs | 14 ++++++++++++++ src/point.rs | 32 ++++++++++++++++++++++++++++++++ src/quaternion.rs | 5 ----- src/vector.rs | 27 +++++++++------------------ tests/vector.rs | 28 ++++++++++++++-------------- 5 files changed, 69 insertions(+), 37 deletions(-) diff --git a/src/array.rs b/src/array.rs index ba8fb55..128edf2 100644 --- a/src/array.rs +++ b/src/array.rs @@ -17,6 +17,8 @@ use std::mem; use std::ptr; use std::ops::*; +use num::PartialOrd; + /// An array containing elements of type `Element` pub trait Array1 where // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 @@ -47,6 +49,18 @@ pub trait Array1 where fn replace_elem(&mut self, i: usize, src: Self::Element) -> Self::Element { mem::replace(&mut self[i], src) } + + /// The sum of the elements of the array. + fn sum(self) -> Self::Element where Self::Element: Add::Element>; + + /// The product of the elements of the array. + fn product(self) -> Self::Element where Self::Element: Mul::Element>; + + /// The minimum element of the array. + fn min(self) -> Self::Element where Self::Element: PartialOrd; + + /// The maximum element of the array. + fn max(self) -> Self::Element where Self::Element: PartialOrd; } /// A column-major array diff --git a/src/point.rs b/src/point.rs index cbccab7..5cd3e9d 100644 --- a/src/point.rs +++ b/src/point.rs @@ -132,6 +132,22 @@ pub trait Point: Copy + Clone where impl Array1 for Point2 { type Element = S; + + fn sum(self) -> S { + self.x + self.y + } + + fn product(self) -> S { + self.x * self.y + } + + fn min(self) -> S { + self.x.partial_min(self.y) + } + + fn max(self) -> S { + self.x.partial_max(self.y) + } } impl Point for Point2 { @@ -212,6 +228,22 @@ impl ApproxEq for Point2 { impl Array1 for Point3 { type Element = S; + + fn sum(self) -> S { + self.x + self.y + self.z + } + + fn product(self) -> S { + self.x * self.y * self.z + } + + fn min(self) -> S { + self.x.partial_min(self.y).partial_min(self.z) + } + + fn max(self) -> S { + self.x.partial_max(self.y).partial_max(self.z) + } } impl Point for Point3 { diff --git a/src/quaternion.rs b/src/quaternion.rs index 616dc17..42f0dc9 100644 --- a/src/quaternion.rs +++ b/src/quaternion.rs @@ -24,7 +24,6 @@ use rust_num::traits::cast; use angle::{Angle, Rad, acos, sin, sin_cos, rad}; use approx::ApproxEq; -use array::Array1; use matrix::{Matrix3, Matrix4}; use num::BaseFloat; use point::Point3; @@ -40,10 +39,6 @@ pub struct Quaternion { pub v: Vector3, } -impl Array1 for Quaternion { - type Element = S; -} - impl Quaternion { /// Construct a new quaternion from one scalar component and three /// imaginary components diff --git a/src/vector.rs b/src/vector.rs index 64df9fe..5a817c6 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -106,7 +106,7 @@ use rust_num::{NumCast, Zero, One}; use angle::{Rad, atan2, acos}; use approx::ApproxEq; use array::Array1; -use num::{BaseNum, BaseFloat}; +use num::{BaseNum, BaseFloat, PartialOrd}; /// 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 @@ -196,19 +196,8 @@ pub trait Vector: Copy + Clone where /// Take the remainder of this vector by another, in-place. fn rem_self_v(&mut self, v: Self); - /// The sum of the components of the vector. - fn sum(self) -> Self::Scalar; - /// The product of the components of the vector. - fn product(self) -> Self::Scalar; - - /// Vector dot product. - #[inline] - fn dot(self, v: Self) -> Self::Scalar { self.mul_v(v).sum() } - - /// The minimum component of the vector. - fn comp_min(self) -> Self::Scalar; - /// The maximum component of the vector. - fn comp_max(self) -> Self::Scalar; + /// Vector dot product + fn dot(self, other: Self) -> Self::Scalar; } /// Dot product of two vectors. @@ -252,6 +241,11 @@ macro_rules! vec { impl Array1 for $VectorN { type Element = S; + + #[inline] fn sum(self) -> S where S: Add { fold!(add, { $(self.$field),+ }) } + #[inline] fn product(self) -> S where S: Mul { fold!(mul, { $(self.$field),+ }) } + #[inline] fn min(self) -> S where S: PartialOrd { fold!(partial_min, { $(self.$field),+ }) } + #[inline] fn max(self) -> S where S: PartialOrd { fold!(partial_max, { $(self.$field),+ }) } } impl Vector for $VectorN { @@ -283,10 +277,7 @@ macro_rules! vec { #[inline] fn div_self_v(&mut self, v: $VectorN) { *self = &*self / v; } #[inline] fn rem_self_v(&mut self, v: $VectorN) { *self = &*self % v; } - #[inline] fn sum(self) -> S { fold!(add, { $(self.$field),+ }) } - #[inline] fn product(self) -> S { fold!(mul, { $(self.$field),+ }) } - #[inline] fn comp_min(self) -> S { fold!(partial_min, { $(self.$field),+ }) } - #[inline] fn comp_max(self) -> S { fold!(partial_max, { $(self.$field),+ }) } + #[inline] fn dot(self, other: $VectorN) -> S { (self * other).sum() } } impl> Neg for $VectorN { diff --git a/tests/vector.rs b/tests/vector.rs index afe677c..241737c 100644 --- a/tests/vector.rs +++ b/tests/vector.rs @@ -63,25 +63,25 @@ fn test_product() { } #[test] -fn test_comp_min() { - assert_eq!(Vector2::new(1isize, 2isize).comp_min(), 1isize); - assert_eq!(Vector3::new(1isize, 2isize, 3isize).comp_min(), 1isize); - assert_eq!(Vector4::new(1isize, 2isize, 3isize, 4isize).comp_min(), 1isize); +fn test_min() { + assert_eq!(Vector2::new(1isize, 2isize).min(), 1isize); + assert_eq!(Vector3::new(1isize, 2isize, 3isize).min(), 1isize); + assert_eq!(Vector4::new(1isize, 2isize, 3isize, 4isize).min(), 1isize); - assert_eq!(Vector2::new(3.0f64, 4.0f64).comp_min(), 3.0f64); - assert_eq!(Vector3::new(4.0f64, 5.0f64, 6.0f64).comp_min(), 4.0f64); - assert_eq!(Vector4::new(5.0f64, 6.0f64, 7.0f64, 8.0f64).comp_min(), 5.0f64); + assert_eq!(Vector2::new(3.0f64, 4.0f64).min(), 3.0f64); + assert_eq!(Vector3::new(4.0f64, 5.0f64, 6.0f64).min(), 4.0f64); + assert_eq!(Vector4::new(5.0f64, 6.0f64, 7.0f64, 8.0f64).min(), 5.0f64); } #[test] -fn test_comp_max() { - assert_eq!(Vector2::new(1isize, 2isize).comp_max(), 2isize); - assert_eq!(Vector3::new(1isize, 2isize, 3isize).comp_max(), 3isize); - assert_eq!(Vector4::new(1isize, 2isize, 3isize, 4isize).comp_max(), 4isize); +fn test_max() { + assert_eq!(Vector2::new(1isize, 2isize).max(), 2isize); + assert_eq!(Vector3::new(1isize, 2isize, 3isize).max(), 3isize); + assert_eq!(Vector4::new(1isize, 2isize, 3isize, 4isize).max(), 4isize); - assert_eq!(Vector2::new(3.0f64, 4.0f64).comp_max(), 4.0f64); - assert_eq!(Vector3::new(4.0f64, 5.0f64, 6.0f64).comp_max(), 6.0f64); - assert_eq!(Vector4::new(5.0f64, 6.0f64, 7.0f64, 8.0f64).comp_max(), 8.0f64); + assert_eq!(Vector2::new(3.0f64, 4.0f64).max(), 4.0f64); + assert_eq!(Vector3::new(4.0f64, 5.0f64, 6.0f64).max(), 6.0f64); + assert_eq!(Vector4::new(5.0f64, 6.0f64, 7.0f64, 8.0f64).max(), 8.0f64); } #[test] From ac2bba01cf1083caaf4a6412a4291775e86221ae Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 14 Nov 2015 12:20:09 +1100 Subject: [PATCH 2/6] Make pointer access function names match those in std --- src/array.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/array.rs b/src/array.rs index 128edf2..cd0edc3 100644 --- a/src/array.rs +++ b/src/array.rs @@ -28,12 +28,14 @@ pub trait Array1 where type Element: Copy; /// Get the pointer to the first element of the array. - fn ptr<'a>(&'a self) -> &'a Self::Element { + #[inline] + fn as_ptr(&self) -> *const Self::Element { &self[0] } /// Get a mutable pointer to the first element of the array. - fn mut_ptr<'a>(&'a mut self) -> &'a mut Self::Element { + #[inline] + fn as_mut_ptr(&mut self) -> *mut Self::Element { &mut self[0] } @@ -74,12 +76,14 @@ pub trait Array2 where type Row: Array1; /// Get the pointer to the first element of the array. - fn ptr<'a>(&'a self) -> &'a Self::Element { + #[inline] + fn as_ptr(&self) -> *const Self::Element { &self[0][0] } /// Get a mutable pointer to the first element of the array. - fn mut_ptr<'a>(&'a mut self) -> &'a mut Self::Element { + #[inline] + fn as_mut_ptr(&mut self) -> *mut Self::Element { &mut self[0][0] } From ab24f3f8fe8c4e957c0af90fae9a52e0bd210f20 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 14 Nov 2015 15:30:03 +1100 Subject: [PATCH 3/6] Make Matrix trait work for matrices of arbritrary dimensions --- src/array.rs | 49 ----- src/matrix.rs | 507 ++++++++++++++++++++++++++++++------------------ src/rotation.rs | 5 +- 3 files changed, 320 insertions(+), 241 deletions(-) diff --git a/src/array.rs b/src/array.rs index cd0edc3..3940fba 100644 --- a/src/array.rs +++ b/src/array.rs @@ -64,52 +64,3 @@ pub trait Array1 where /// The maximum element of the array. fn max(self) -> Self::Element where Self::Element: PartialOrd; } - -/// A column-major array -pub trait Array2 where - // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 - Self: Index::Column>, - Self: IndexMut::Column>, -{ - type Element: Copy; - type Column: Array1; - type Row: Array1; - - /// Get the pointer to the first element of the array. - #[inline] - fn as_ptr(&self) -> *const Self::Element { - &self[0][0] - } - - /// Get a mutable pointer to the first element of the array. - #[inline] - fn as_mut_ptr(&mut self) -> *mut Self::Element { - &mut self[0][0] - } - - /// Swap two columns of this array. - #[inline] - fn swap_cols(&mut self, a: usize, b: usize) { - unsafe { ptr::swap(&mut self[a], &mut self[b]) }; - } - - /// Replace a column in the array. - #[inline] - fn replace_col(&mut self, c: usize, src: Self::Column) -> Self::Column { - mem::replace(&mut self[c], src) - } - - /// Get a row from this array by-value. - fn row(&self, r: usize) -> Self::Row; - - /// Swap two rows of this array. - fn swap_rows(&mut self, a: usize, b: usize); - - /// Swap the values at index `a` and `b` - #[inline] - fn swap_elems(&mut self, a: (usize, usize), b: (usize, usize)) { - let (ac, ar) = a; - let (bc, br) = b; - unsafe { ptr::swap(&mut self[ac][ar], &mut self[bc][br]) }; - } -} diff --git a/src/matrix.rs b/src/matrix.rs index add1c4d..8a8ef98 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -18,6 +18,7 @@ use std::fmt; use std::mem; use std::ops::*; +use std::ptr; use rand::{Rand, Rng}; @@ -26,7 +27,7 @@ use rust_num::traits::cast; use angle::{Rad, sin, cos, sin_cos}; use approx::ApproxEq; -use array::{Array1, Array2}; +use array::Array1; use num::{BaseFloat, BaseNum}; use point::{Point, Point3}; use quaternion::Quaternion; @@ -249,15 +250,12 @@ impl> Matrix4 { } } -pub trait Matrix where +/// A column-major matrix of arbitrary dimensions. +pub trait Matrix where // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 - Self: Array2< - Element = <::ColumnRow as Vector>::Scalar, - Column = ::ColumnRow, - Row = ::ColumnRow, - >, - Self: ApproxEq::ColumnRow as Vector>::Scalar> + Sized, - Self::Element: BaseFloat, + Self: Index::Column>, + Self: IndexMut::Column>, + Self: ApproxEq::Element>, // FIXME: blocked by rust-lang/rust#20671 // // for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>, @@ -269,65 +267,106 @@ pub trait Matrix where // for<'a> &'a Self: Div, // for<'a> &'a Self: Rem, { - // FIXME: Will not be needed once equality constraints in where clauses is implemented - type ColumnRow: Vector; + /// The type of the elements in the matrix. + type Element: BaseFloat; + + /// The row vector of the matrix. + type Row: Array1; + /// The column vector of the matrix. + type Column: Array1; + + /// The type of the transposed matrix + type Transpose: Matrix; + + /// Get the pointer to the first element of the array. + #[inline] + fn as_ptr(&self) -> *const Self::Element { + &self[0][0] + } + + /// Get a mutable pointer to the first element of the array. + #[inline] + fn as_mut_ptr(&mut self) -> *mut Self::Element { + &mut self[0][0] + } + + /// Replace a column in the array. + #[inline] + fn replace_col(&mut self, c: usize, src: Self::Column) -> Self::Column { + mem::replace(&mut self[c], src) + } + + /// Get a row from this matrix by-value. + fn row(&self, r: usize) -> Self::Row; + + /// Swap two rows of this array. + fn swap_rows(&mut self, a: usize, b: usize); + /// Swap two columns of this array. + fn swap_columns(&mut self, a: usize, b: usize); + /// Swap the values at index `a` and `b` + fn swap_elements(&mut self, a: (usize, usize), b: (usize, usize)); + + /// Create a matrix with all of the elements set to zero. + fn zero() -> Self; + + /// Multiply the matrix by another matrix, + fn mul_m(&self, other: &Self::Transpose) -> Self; + + /// Multiply the matrix by a column vector. + fn mul_v(&self, column: Self::Column) -> Self::Column; + + /// Multiply this matrix by a scalar, returning the new matrix. + fn mul_s(&self, scalar: Self::Element) -> Self; + /// Divide this matrix by a scalar, returning the new matrix. + fn div_s(&self, scalar: Self::Element) -> Self; + + /// Multiply this matrix by a scalar, in-place. + fn mul_self_s(&mut self, scalar: Self::Element); + /// Divide this matrix by a scalar, in-place. + fn div_self_s(&mut self, scalar: Self::Element); + + /// Transpose this matrix, returning a new matrix. + fn transpose(&self) -> Self::Transpose; +} + +/// A column-major major matrix where the rows and column vectors are of the same dimensions. +pub trait SquareMatrix where + Self: Matrix< + // FIXME: Can be cleaned up once equality constraints in where clauses are implemented + Column = ::ColumnRow, + Row = ::ColumnRow, + Transpose = Self, + >, +{ + // FIXME: Will not be needed once equality constraints in where clauses are implemented + /// The row/column vector of the matrix. + /// + /// This is used to constrain the column and rows to be of the same type in lieu of equality + /// constraints being implemented for `where` clauses. Once those are added, this type will + /// likely go away. + type ColumnRow: Array1; /// Create a new diagonal matrix using the supplied value. fn from_value(value: Self::Element) -> Self; /// Create a matrix from a non-uniform scale fn from_diagonal(diagonal: Self::Column) -> Self; - /// Create a matrix with all elements equal to zero. - #[inline] - fn zero() -> Self { Self::from_value(Self::Element::zero()) } /// Create a matrix where the each element of the diagonal is equal to one. - #[inline] - fn one() -> Self { Self::from_value(Self::Element::one()) } - - /// Multiply this matrix by a scalar, returning the new matrix. - #[must_use] - fn mul_s(&self, s: Self::Element) -> Self; - /// Divide this matrix by a scalar, returning the new matrix. - #[must_use] - fn div_s(&self, s: Self::Element) -> Self; - /// Take the remainder of this matrix by a scalar, returning the new - /// matrix. - #[must_use] - fn rem_s(&self, s: Self::Element) -> Self; + fn one() -> Self; /// Add this matrix with another matrix, returning the new metrix. - #[must_use] fn add_m(&self, m: &Self) -> Self; /// Subtract another matrix from this matrix, returning the new matrix. - #[must_use] fn sub_m(&self, m: &Self) -> Self; - /// Multiplay a vector by this matrix, returning a new vector. - fn mul_v(&self, v: Self::Column) -> Self::Column; - - /// Multiply this matrix by another matrix, returning the new matrix. - #[must_use] - fn mul_m(&self, m: &Self) -> Self; - - /// Multiply this matrix by a scalar, in-place. - fn mul_self_s(&mut self, s: Self::Element); - /// Divide this matrix by a scalar, in-place. - fn div_self_s(&mut self, s: Self::Element); - /// Take the remainder of this matrix, in-place. - fn rem_self_s(&mut self, s: Self::Element); - /// Add this matrix with another matrix, in-place. fn add_self_m(&mut self, m: &Self); /// Subtract another matrix from this matrix, in-place. fn sub_self_m(&mut self, m: &Self); /// Multiply this matrix by another matrix, in-place. - #[inline] fn mul_self_m(&mut self, m: &Self) { *self = self.mul_m(m); } - /// Transpose this matrix, returning a new matrix. - #[must_use] - fn transpose(&self) -> Self; /// Transpose this matrix in-place. fn transpose_self(&mut self); /// Take the determinant of this matrix. @@ -370,10 +409,11 @@ pub trait Matrix where fn is_symmetric(&self) -> bool; } -impl Array2 for Matrix2 { +impl Matrix for Matrix2 { type Element = S; type Column = Vector2; type Row = Vector2; + type Transpose = Matrix2; #[inline] fn row(&self, r: usize) -> Vector2 { @@ -386,51 +426,56 @@ impl Array2 for Matrix2 { self[0].swap_elems(a, b); self[1].swap_elems(a, b); } -} - -impl Array2 for Matrix3 { - type Element = S; - type Column = Vector3; - type Row = Vector3; #[inline] - fn row(&self, r: usize) -> Vector3 { - Vector3::new(self[0][r], - self[1][r], - self[2][r]) + fn swap_columns(&mut self, a: usize, b: usize) { + unsafe { ptr::swap(&mut self[a], &mut self[b]) }; } #[inline] - fn swap_rows(&mut self, a: usize, b: usize) { - self[0].swap_elems(a, b); - self[1].swap_elems(a, b); - self[2].swap_elems(a, b); + fn swap_elements(&mut self, a: (usize, usize), b: (usize, usize)) { + let (ac, ar) = a; + let (bc, br) = b; + unsafe { ptr::swap(&mut self[ac][ar], &mut self[bc][br]) }; + } + + #[inline] + fn zero() -> Matrix2 { + Matrix2::new(S::zero(), S::zero(), + S::zero(), S::zero()) + } + + #[inline] + fn mul_m(&self, other: &Matrix2) -> Matrix2 { self * other } + + #[inline] + fn mul_v(&self, v: Vector2) -> Vector2 { self * v } + + #[inline] + fn mul_s(&self, s: S) -> Matrix2 { self * s } + + #[inline] + fn div_s(&self, s: S) -> Matrix2 { self / s } + + #[inline] + fn mul_self_s(&mut self, s: S) { + self[0].mul_self_s(s); + self[1].mul_self_s(s); + } + + #[inline] + fn div_self_s(&mut self, s: S) { + self[0].div_self_s(s); + self[1].div_self_s(s); + } + + fn transpose(&self) -> Matrix2 { + Matrix2::new(self[0][0], self[1][0], + self[0][1], self[1][1]) } } -impl Array2 for Matrix4 { - type Element = S; - type Column = Vector4; - type Row = Vector4; - - #[inline] - fn row(&self, r: usize) -> Vector4 { - Vector4::new(self[0][r], - self[1][r], - self[2][r], - self[3][r]) - } - - #[inline] - fn swap_rows(&mut self, a: usize, b: usize) { - self[0].swap_elems(a, b); - self[1].swap_elems(a, b); - self[2].swap_elems(a, b); - self[3].swap_elems(a, b); - } -} - -impl Matrix for Matrix2 { +impl SquareMatrix for Matrix2 { type ColumnRow = Vector2; #[inline] @@ -445,31 +490,17 @@ impl Matrix for Matrix2 { S::zero(), value.y) } - #[inline] fn mul_s(&self, s: S) -> Matrix2 { self * s } - #[inline] fn div_s(&self, s: S) -> Matrix2 { self / s } - #[inline] fn rem_s(&self, s: S) -> Matrix2 { self % s } - #[inline] fn add_m(&self, m: &Matrix2) -> Matrix2 { self + m } - #[inline] fn sub_m(&self, m: &Matrix2) -> Matrix2 { self - m } - fn mul_m(&self, other: &Matrix2) -> Matrix2 { self * other } - #[inline] fn mul_v(&self, v: Vector2) -> Vector2 { self * v } - #[inline] - fn mul_self_s(&mut self, s: S) { - self[0].mul_self_s(s); - self[1].mul_self_s(s); + fn one() -> Matrix2 { + Matrix2::new(S::one(), S::zero(), + S::zero(), S::one()) } #[inline] - fn div_self_s(&mut self, s: S) { - self[0].div_self_s(s); - self[1].div_self_s(s); - } + fn add_m(&self, m: &Matrix2) -> Matrix2 { self + m } #[inline] - fn rem_self_s(&mut self, s: S) { - self[0].rem_self_s(s); - self[1].rem_self_s(s); - } + fn sub_m(&self, m: &Matrix2) -> Matrix2 { self - m } #[inline] fn add_self_m(&mut self, m: &Matrix2) { @@ -483,14 +514,9 @@ impl Matrix for Matrix2 { self[1].sub_self_v(m[1]); } - fn transpose(&self) -> Matrix2 { - Matrix2::new(self[0][0], self[1][0], - self[0][1], self[1][1]) - } - #[inline] fn transpose_self(&mut self) { - self.swap_elems((0, 1), (1, 0)); + self.swap_elements((0, 1), (1, 0)); } #[inline] @@ -530,6 +556,78 @@ impl Matrix for Matrix2 { } impl Matrix for Matrix3 { + type Element = S; + type Column = Vector3; + type Row = Vector3; + type Transpose = Matrix3; + + #[inline] + fn row(&self, r: usize) -> Vector3 { + Vector3::new(self[0][r], + self[1][r], + self[2][r]) + } + + #[inline] + fn swap_rows(&mut self, a: usize, b: usize) { + self[0].swap_elems(a, b); + self[1].swap_elems(a, b); + self[2].swap_elems(a, b); + } + + #[inline] + fn swap_columns(&mut self, a: usize, b: usize) { + unsafe { ptr::swap(&mut self[a], &mut self[b]) }; + } + + #[inline] + fn swap_elements(&mut self, a: (usize, usize), b: (usize, usize)) { + let (ac, ar) = a; + let (bc, br) = b; + unsafe { ptr::swap(&mut self[ac][ar], &mut self[bc][br]) }; + } + + #[inline] + fn zero() -> Matrix3 { + Matrix3::new(S::zero(), S::zero(), S::zero(), + S::zero(), S::zero(), S::zero(), + S::zero(), S::zero(), S::zero()) + } + + #[inline] + fn mul_m(&self, other: &Matrix3) -> Matrix3 { self * other } + + #[inline] + fn mul_v(&self, v: Vector3) -> Vector3 { self * v} + + #[inline] + fn mul_s(&self, s: S) -> Matrix3 { self * s } + + #[inline] + fn div_s(&self, s: S) -> Matrix3 { self / s } + + #[inline] + fn mul_self_s(&mut self, s: S) { + self[0].mul_self_s(s); + self[1].mul_self_s(s); + self[2].mul_self_s(s); + } + + #[inline] + fn div_self_s(&mut self, s: S) { + self[0].div_self_s(s); + self[1].div_self_s(s); + self[2].div_self_s(s); + } + + fn transpose(&self) -> Matrix3 { + Matrix3::new(self[0][0], self[1][0], self[2][0], + self[0][1], self[1][1], self[2][1], + self[0][2], self[1][2], self[2][2]) + } +} + +impl SquareMatrix for Matrix3 { type ColumnRow = Vector3; #[inline] @@ -546,34 +644,18 @@ impl Matrix for Matrix3 { S::zero(), S::zero(), value.z) } - #[inline] fn mul_s(&self, s: S) -> Matrix3 { self * s } - #[inline] fn div_s(&self, s: S) -> Matrix3 { self / s } - #[inline] fn rem_s(&self, s: S) -> Matrix3 { self % s } - #[inline] fn add_m(&self, m: &Matrix3) -> Matrix3 { self + m } - #[inline] fn sub_m(&self, m: &Matrix3) -> Matrix3 { self - m } - fn mul_m(&self, other: &Matrix3) -> Matrix3 { self * other } - #[inline] fn mul_v(&self, v: Vector3) -> Vector3 { self * v} - #[inline] - fn mul_self_s(&mut self, s: S) { - self[0].mul_self_s(s); - self[1].mul_self_s(s); - self[2].mul_self_s(s); + fn one() -> Matrix3 { + Matrix3::new(S::one(), S::zero(), S::zero(), + S::zero(), S::one(), S::zero(), + S::zero(), S::zero(), S::one()) } #[inline] - fn div_self_s(&mut self, s: S) { - self[0].div_self_s(s); - self[1].div_self_s(s); - self[2].div_self_s(s); - } + fn add_m(&self, m: &Matrix3) -> Matrix3 { self + m } #[inline] - fn rem_self_s(&mut self, s: S) { - self[0].rem_self_s(s); - self[1].rem_self_s(s); - self[2].rem_self_s(s); - } + fn sub_m(&self, m: &Matrix3) -> Matrix3 { self - m } #[inline] fn add_self_m(&mut self, m: &Matrix3) { @@ -589,17 +671,11 @@ impl Matrix for Matrix3 { self[2].sub_self_v(m[2]); } - fn transpose(&self) -> Matrix3 { - Matrix3::new(self[0][0], self[1][0], self[2][0], - self[0][1], self[1][1], self[2][1], - self[0][2], self[1][2], self[2][2]) - } - #[inline] fn transpose_self(&mut self) { - self.swap_elems((0, 1), (1, 0)); - self.swap_elems((0, 2), (2, 0)); - self.swap_elems((1, 2), (2, 1)); + self.swap_elements((0, 1), (1, 0)); + self.swap_elements((0, 2), (2, 0)); + self.swap_elements((1, 2), (2, 1)); } fn determinant(&self) -> S { @@ -648,6 +724,84 @@ impl Matrix for Matrix3 { } impl Matrix for Matrix4 { + type Element = S; + type Column = Vector4; + type Row = Vector4; + type Transpose = Matrix4; + + #[inline] + fn row(&self, r: usize) -> Vector4 { + Vector4::new(self[0][r], + self[1][r], + self[2][r], + self[3][r]) + } + + #[inline] + fn swap_rows(&mut self, a: usize, b: usize) { + self[0].swap_elems(a, b); + self[1].swap_elems(a, b); + self[2].swap_elems(a, b); + self[3].swap_elems(a, b); + } + + #[inline] + fn swap_columns(&mut self, a: usize, b: usize) { + unsafe { ptr::swap(&mut self[a], &mut self[b]) }; + } + + #[inline] + fn swap_elements(&mut self, a: (usize, usize), b: (usize, usize)) { + let (ac, ar) = a; + let (bc, br) = b; + unsafe { ptr::swap(&mut self[ac][ar], &mut self[bc][br]) }; + } + + #[inline] + fn zero() -> Matrix4 { + Matrix4::new(S::zero(), S::zero(), S::zero(), S::zero(), + S::zero(), S::zero(), S::zero(), S::zero(), + S::zero(), S::zero(), S::zero(), S::zero(), + S::zero(), S::zero(), S::zero(), S::zero()) + } + + #[inline] + fn mul_m(&self, other: &Matrix4) -> Matrix4 { self * other } + + #[inline] + fn mul_v(&self, v: Vector4) -> Vector4 { self * v } + + #[inline] + fn mul_s(&self, s: S) -> Matrix4 { self * s } + + #[inline] + fn div_s(&self, s: S) -> Matrix4 { self / s } + + #[inline] + fn mul_self_s(&mut self, s: S) { + self[0].mul_self_s(s); + self[1].mul_self_s(s); + self[2].mul_self_s(s); + self[3].mul_self_s(s); + } + + #[inline] + fn div_self_s(&mut self, s: S) { + self[0].div_self_s(s); + self[1].div_self_s(s); + self[2].div_self_s(s); + self[3].div_self_s(s); + } + + fn transpose(&self) -> Matrix4 { + Matrix4::new(self[0][0], self[1][0], self[2][0], self[3][0], + self[0][1], self[1][1], self[2][1], self[3][1], + self[0][2], self[1][2], self[2][2], self[3][2], + self[0][3], self[1][3], self[2][3], self[3][3]) + } +} + +impl SquareMatrix for Matrix4 { type ColumnRow = Vector4; #[inline] @@ -666,37 +820,19 @@ impl Matrix for Matrix4 { S::zero(), S::zero(), S::zero(), value.w) } - #[inline] fn mul_s(&self, s: S) -> Matrix4 { self * s } - #[inline] fn div_s(&self, s: S) -> Matrix4 { self / s } - #[inline] fn rem_s(&self, s: S) -> Matrix4 { self % s } - #[inline] fn add_m(&self, m: &Matrix4) -> Matrix4 { self + m } - #[inline] fn sub_m(&self, m: &Matrix4) -> Matrix4 { self - m } - fn mul_m(&self, other: &Matrix4) -> Matrix4 { self * other } - #[inline] fn mul_v(&self, v: Vector4) -> Vector4 { self * v } - #[inline] - fn mul_self_s(&mut self, s: S) { - self[0].mul_self_s(s); - self[1].mul_self_s(s); - self[2].mul_self_s(s); - self[3].mul_self_s(s); + fn one() -> Matrix4 { + Matrix4::new(S::one(), S::zero(), S::zero(), S::zero(), + S::zero(), S::one(), S::zero(), S::zero(), + S::zero(), S::zero(), S::one(), S::zero(), + S::zero(), S::zero(), S::zero(), S::one()) } #[inline] - fn div_self_s(&mut self, s: S) { - self[0].div_self_s(s); - self[1].div_self_s(s); - self[2].div_self_s(s); - self[3].div_self_s(s); - } + fn add_m(&self, m: &Matrix4) -> Matrix4 { self + m } #[inline] - fn rem_self_s(&mut self, s: S) { - self[0].rem_self_s(s); - self[1].rem_self_s(s); - self[2].rem_self_s(s); - self[3].rem_self_s(s); - } + fn sub_m(&self, m: &Matrix4) -> Matrix4 { self - m } #[inline] fn add_self_m(&mut self, m: &Matrix4) { @@ -714,20 +850,13 @@ impl Matrix for Matrix4 { self[3].sub_self_v(m[3]); } - fn transpose(&self) -> Matrix4 { - Matrix4::new(self[0][0], self[1][0], self[2][0], self[3][0], - self[0][1], self[1][1], self[2][1], self[3][1], - self[0][2], self[1][2], self[2][2], self[3][2], - self[0][3], self[1][3], self[2][3], self[3][3]) - } - fn transpose_self(&mut self) { - self.swap_elems((0, 1), (1, 0)); - self.swap_elems((0, 2), (2, 0)); - self.swap_elems((0, 3), (3, 0)); - self.swap_elems((1, 2), (2, 1)); - self.swap_elems((1, 3), (3, 1)); - self.swap_elems((2, 3), (3, 2)); + self.swap_elements((0, 1), (1, 0)); + self.swap_elements((0, 2), (2, 0)); + self.swap_elements((0, 3), (3, 0)); + self.swap_elements((1, 2), (2, 1)); + self.swap_elements((1, 3), (3, 1)); + self.swap_elements((2, 3), (3, 2)); } fn determinant(&self) -> S { @@ -852,7 +981,7 @@ impl ApproxEq for Matrix4 { } } -impl> Neg for Matrix2 { +impl Neg for Matrix2 { type Output = Matrix2; #[inline] @@ -861,7 +990,7 @@ impl> Neg for Matrix2 { } } -impl> Neg for Matrix3 { +impl Neg for Matrix3 { type Output = Matrix3; #[inline] @@ -870,7 +999,7 @@ impl> Neg for Matrix3 { } } -impl> Neg for Matrix4 { +impl Neg for Matrix4 { type Output = Matrix4; #[inline] @@ -881,7 +1010,7 @@ impl> Neg for Matrix4 { macro_rules! impl_scalar_binary_operator { ($Binop:ident :: $binop:ident, $MatrixN:ident { $($field:ident),+ }) => { - impl<'a, S: BaseNum> $Binop for &'a $MatrixN { + impl<'a, S: BaseFloat> $Binop for &'a $MatrixN { type Output = $MatrixN; #[inline] @@ -904,7 +1033,7 @@ impl_scalar_binary_operator!(Rem::rem, Matrix4 { x, y, z, w }); macro_rules! impl_binary_operator { ($Binop:ident :: $binop:ident, $MatrixN:ident { $($field:ident),+ }) => { - impl<'a, 'b, S: BaseNum> $Binop<&'a $MatrixN> for &'b $MatrixN { + impl<'a, 'b, S: BaseFloat> $Binop<&'a $MatrixN> for &'b $MatrixN { type Output = $MatrixN; #[inline] @@ -924,7 +1053,7 @@ impl_binary_operator!(Sub::sub, Matrix4 { x, y, z, w }); macro_rules! impl_vector_mul_operators { ($MatrixN:ident, $VectorN:ident { $($row_index:expr),+ }) => { - impl<'a, S: BaseNum> Mul<$VectorN> for &'a $MatrixN { + impl<'a, S: BaseFloat> Mul<$VectorN> for &'a $MatrixN { type Output = $VectorN; fn mul(self, v: $VectorN) -> $VectorN { @@ -932,7 +1061,7 @@ macro_rules! impl_vector_mul_operators { } } - impl<'a, 'b, S: BaseNum> Mul<&'a $VectorN> for &'b $MatrixN { + impl<'a, 'b, S: BaseFloat> Mul<&'a $VectorN> for &'b $MatrixN { type Output = $VectorN; fn mul(self, v: &'a $VectorN) -> $VectorN { @@ -946,7 +1075,7 @@ impl_vector_mul_operators!(Matrix2, Vector2 { 0, 1 }); impl_vector_mul_operators!(Matrix3, Vector3 { 0, 1, 2 }); impl_vector_mul_operators!(Matrix4, Vector4 { 0, 1, 2, 3 }); -impl<'a, 'b, S: BaseNum> Mul<&'a Matrix2> for &'b Matrix2 { +impl<'a, 'b, S: BaseFloat> Mul<&'a Matrix2> for &'b Matrix2 { type Output = Matrix2; fn mul(self, other: &'a Matrix2) -> Matrix2 { @@ -955,7 +1084,7 @@ impl<'a, 'b, S: BaseNum> Mul<&'a Matrix2> for &'b Matrix2 { } } -impl<'a, 'b, S: BaseNum> Mul<&'a Matrix3> for &'b Matrix3 { +impl<'a, 'b, S: BaseFloat> Mul<&'a Matrix3> for &'b Matrix3 { type Output = Matrix3; fn mul(self, other: &'a Matrix3) -> Matrix3 { @@ -965,7 +1094,7 @@ impl<'a, 'b, S: BaseNum> Mul<&'a Matrix3> for &'b Matrix3 { } } -impl<'a, 'b, S: BaseNum> Mul<&'a Matrix4> for &'b Matrix4 { +impl<'a, 'b, S: BaseFloat> Mul<&'a Matrix4> for &'b Matrix4 { type Output = Matrix4; fn mul(self, other: &'a Matrix4) -> Matrix4 { diff --git a/src/rotation.rs b/src/rotation.rs index a90f303..c13eefb 100644 --- a/src/rotation.rs +++ b/src/rotation.rs @@ -15,9 +15,8 @@ use angle::{Rad, acos}; use approx::ApproxEq; -use matrix::Matrix; -use matrix::Matrix2; -use matrix::Matrix3; +use matrix::{Matrix, SquareMatrix}; +use matrix::{Matrix2, Matrix3}; use num::BaseFloat; use point::{Point, Point2, Point3}; use quaternion::Quaternion; From 70dbef1eb1cd07da45229959d39f1fe5d639eeb8 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 14 Nov 2015 21:58:11 +1100 Subject: [PATCH 4/6] Rename Array1 to Array --- src/array.rs | 10 +++++----- src/matrix.rs | 8 ++++---- src/point.rs | 8 ++++---- src/vector.rs | 8 ++++---- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/array.rs b/src/array.rs index 3940fba..2a480df 100644 --- a/src/array.rs +++ b/src/array.rs @@ -20,10 +20,10 @@ use std::ops::*; use num::PartialOrd; /// An array containing elements of type `Element` -pub trait Array1 where +pub trait Array where // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 - Self: Index::Element>, - Self: IndexMut::Element>, + Self: Index::Element>, + Self: IndexMut::Element>, { type Element: Copy; @@ -53,10 +53,10 @@ pub trait Array1 where } /// The sum of the elements of the array. - fn sum(self) -> Self::Element where Self::Element: Add::Element>; + fn sum(self) -> Self::Element where Self::Element: Add::Element>; /// The product of the elements of the array. - fn product(self) -> Self::Element where Self::Element: Mul::Element>; + fn product(self) -> Self::Element where Self::Element: Mul::Element>; /// The minimum element of the array. fn min(self) -> Self::Element where Self::Element: PartialOrd; diff --git a/src/matrix.rs b/src/matrix.rs index 8a8ef98..3fc159d 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -27,7 +27,7 @@ use rust_num::traits::cast; use angle::{Rad, sin, cos, sin_cos}; use approx::ApproxEq; -use array::Array1; +use array::Array; use num::{BaseFloat, BaseNum}; use point::{Point, Point3}; use quaternion::Quaternion; @@ -271,9 +271,9 @@ pub trait Matrix where type Element: BaseFloat; /// The row vector of the matrix. - type Row: Array1; + type Row: Array; /// The column vector of the matrix. - type Column: Array1; + type Column: Array; /// The type of the transposed matrix type Transpose: Matrix; @@ -344,7 +344,7 @@ pub trait SquareMatrix where /// This is used to constrain the column and rows to be of the same type in lieu of equality /// constraints being implemented for `where` clauses. Once those are added, this type will /// likely go away. - type ColumnRow: Array1; + type ColumnRow: Array; /// Create a new diagonal matrix using the supplied value. fn from_value(value: Self::Element) -> Self; diff --git a/src/point.rs b/src/point.rs index 5cd3e9d..e5256c9 100644 --- a/src/point.rs +++ b/src/point.rs @@ -24,7 +24,7 @@ use std::ops::*; use rust_num::{One, Zero}; use approx::ApproxEq; -use array::Array1; +use array::Array; use matrix::Matrix; use num::{BaseNum, BaseFloat}; use vector::*; @@ -68,7 +68,7 @@ impl Point3 { /// Specifies the numeric operations for point types. pub trait Point: Copy + Clone where // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 - Self: Array1::Scalar>, + Self: Array::Scalar>, // FIXME: blocked by rust-lang/rust#20671 // // for<'a, 'b> &'a Self: Add<&'b V, Output = Self>, @@ -130,7 +130,7 @@ pub trait Point: Copy + Clone where fn max(self, p: Self) -> Self; } -impl Array1 for Point2 { +impl Array for Point2 { type Element = S; fn sum(self) -> S { @@ -226,7 +226,7 @@ impl ApproxEq for Point2 { } } -impl Array1 for Point3 { +impl Array for Point3 { type Element = S; fn sum(self) -> S { diff --git a/src/vector.rs b/src/vector.rs index 5a817c6..5861a7f 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -88,7 +88,7 @@ //! //! Several other useful methods are provided as well. Vector fields can be //! accessed using array syntax (i.e. `vector[0] == vector.x`), or by using -//! the methods provided by the [`Array1`](../array/trait.Array1.html) trait. +//! the methods provided by the [`Array`](../array/trait.Array.html) trait. //! This trait also provides a `map()` method for applying arbitrary functions. //! //! The [`Vector`](../trait.Vector.html) trait presents the most general @@ -105,7 +105,7 @@ use rust_num::{NumCast, Zero, One}; use angle::{Rad, atan2, acos}; use approx::ApproxEq; -use array::Array1; +use array::Array; use num::{BaseNum, BaseFloat, PartialOrd}; /// A trait that specifies a range of numeric operations for vectors. Not all @@ -113,7 +113,7 @@ use num::{BaseNum, BaseFloat, PartialOrd}; /// for pragmatic reasons. pub trait Vector: Copy + Clone where // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 - Self: Array1::Scalar>, + Self: Array::Scalar>, // FIXME: blocked by rust-lang/rust#20671 // // for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>, @@ -239,7 +239,7 @@ macro_rules! vec { } } - impl Array1 for $VectorN { + impl Array for $VectorN { type Element = S; #[inline] fn sum(self) -> S where S: Add { fold!(add, { $(self.$field),+ }) } From dcb0afd57bbaab8e47fc0e17c8637bd1933060e4 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 14 Nov 2015 22:04:04 +1100 Subject: [PATCH 5/6] Remove Array::replace_elem Doesn't seem very useful... --- src/array.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/array.rs b/src/array.rs index 2a480df..7589472 100644 --- a/src/array.rs +++ b/src/array.rs @@ -13,7 +13,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::mem; use std::ptr; use std::ops::*; @@ -46,12 +45,6 @@ pub trait Array where unsafe { ptr::swap(&mut self[i], &mut self[j]) }; } - /// Replace an element in the array. - #[inline] - fn replace_elem(&mut self, i: usize, src: Self::Element) -> Self::Element { - mem::replace(&mut self[i], src) - } - /// The sum of the elements of the array. fn sum(self) -> Self::Element where Self::Element: Add::Element>; From 5b2b10d65f772b068f3c46895219beede142c99c Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 14 Nov 2015 22:05:44 +1100 Subject: [PATCH 6/6] Rename Array::swap_elems to Array::swap_elements --- src/array.rs | 2 +- src/matrix.rs | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/array.rs b/src/array.rs index 7589472..3536371 100644 --- a/src/array.rs +++ b/src/array.rs @@ -40,7 +40,7 @@ pub trait Array where /// Swap the elements at indices `i` and `j` in-place. #[inline] - fn swap_elems(&mut self, i: usize, j: usize) { + fn swap_elements(&mut self, i: usize, j: usize) { // Yeah, ok borrow checker – I know what I'm doing here unsafe { ptr::swap(&mut self[i], &mut self[j]) }; } diff --git a/src/matrix.rs b/src/matrix.rs index 3fc159d..9bb96c0 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -423,8 +423,8 @@ impl Matrix for Matrix2 { #[inline] fn swap_rows(&mut self, a: usize, b: usize) { - self[0].swap_elems(a, b); - self[1].swap_elems(a, b); + self[0].swap_elements(a, b); + self[1].swap_elements(a, b); } #[inline] @@ -570,9 +570,9 @@ impl Matrix for Matrix3 { #[inline] fn swap_rows(&mut self, a: usize, b: usize) { - self[0].swap_elems(a, b); - self[1].swap_elems(a, b); - self[2].swap_elems(a, b); + self[0].swap_elements(a, b); + self[1].swap_elements(a, b); + self[2].swap_elements(a, b); } #[inline] @@ -739,10 +739,10 @@ impl Matrix for Matrix4 { #[inline] fn swap_rows(&mut self, a: usize, b: usize) { - self[0].swap_elems(a, b); - self[1].swap_elems(a, b); - self[2].swap_elems(a, b); - self[3].swap_elems(a, b); + self[0].swap_elements(a, b); + self[1].swap_elements(a, b); + self[2].swap_elements(a, b); + self[3].swap_elements(a, b); } #[inline]