diff --git a/src/array.rs b/src/array.rs index ba8fb55..3536371 100644 --- a/src/array.rs +++ b/src/array.rs @@ -13,85 +13,47 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::mem; use std::ptr; 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; /// 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] } /// 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]) }; } - /// 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) - } -} - -/// 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. - fn ptr<'a>(&'a self) -> &'a 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 { - &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]) }; - } + /// 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; } diff --git a/src/matrix.rs b/src/matrix.rs index add1c4d..9bb96c0 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::Array; 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: Array; + /// The column vector of the matrix. + type Column: Array; + + /// 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: Array; /// 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 { @@ -383,54 +423,59 @@ impl Array2 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] + 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() -> 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 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]) - } - - #[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); - } -} - -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_elements(a, b); + self[1].swap_elements(a, b); + self[2].swap_elements(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_elements(a, b); + self[1].swap_elements(a, b); + self[2].swap_elements(a, b); + self[3].swap_elements(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/point.rs b/src/point.rs index cbccab7..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,8 +130,24 @@ 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 { + 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 { @@ -210,8 +226,24 @@ impl ApproxEq for Point2 { } } -impl Array1 for Point3 { +impl Array 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/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; diff --git a/src/vector.rs b/src/vector.rs index 64df9fe..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,15 +105,15 @@ use rust_num::{NumCast, Zero, One}; use angle::{Rad, atan2, acos}; use approx::ApproxEq; -use array::Array1; -use num::{BaseNum, BaseFloat}; +use array::Array; +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 /// 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>, @@ -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. @@ -250,8 +239,13 @@ 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),+ }) } + #[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]