Merge pull request #254 from bjz/matrix-and-array-api-changes

Matrix and Array api changes
This commit is contained in:
Brendan Zabarauskas 2015-11-17 08:27:33 +11:00
commit e05a8737fa
7 changed files with 412 additions and 304 deletions

View file

@ -13,85 +13,47 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::mem;
use std::ptr; use std::ptr;
use std::ops::*; use std::ops::*;
use num::PartialOrd;
/// An array containing elements of type `Element` /// 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 // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
Self: Index<usize, Output = <Self as Array1>::Element>, Self: Index<usize, Output = <Self as Array>::Element>,
Self: IndexMut<usize, Output = <Self as Array1>::Element>, Self: IndexMut<usize, Output = <Self as Array>::Element>,
{ {
type Element: Copy; type Element: Copy;
/// Get the pointer to the first element of the array. /// 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] &self[0]
} }
/// Get a mutable pointer to the first element of the array. /// 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] &mut self[0]
} }
/// Swap the elements at indices `i` and `j` in-place. /// Swap the elements at indices `i` and `j` in-place.
#[inline] #[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 // Yeah, ok borrow checker I know what I'm doing here
unsafe { ptr::swap(&mut self[i], &mut self[j]) }; unsafe { ptr::swap(&mut self[i], &mut self[j]) };
} }
/// Replace an element in the array. /// The sum of the elements of the array.
#[inline] fn sum(self) -> Self::Element where Self::Element: Add<Output = <Self as Array>::Element>;
fn replace_elem(&mut self, i: usize, src: Self::Element) -> Self::Element {
mem::replace(&mut self[i], src) /// The product of the elements of the array.
} fn product(self) -> Self::Element where Self::Element: Mul<Output = <Self as Array>::Element>;
}
/// The minimum element of the array.
/// A column-major array fn min(self) -> Self::Element where Self::Element: PartialOrd;
pub trait Array2 where
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 /// The maximum element of the array.
Self: Index<usize, Output = <Self as Array2>::Column>, fn max(self) -> Self::Element where Self::Element: PartialOrd;
Self: IndexMut<usize, Output = <Self as Array2>::Column>,
{
type Element: Copy;
type Column: Array1<Element = Self::Element>;
type Row: Array1<Element = Self::Element>;
/// 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]) };
}
} }

View file

@ -18,6 +18,7 @@
use std::fmt; use std::fmt;
use std::mem; use std::mem;
use std::ops::*; use std::ops::*;
use std::ptr;
use rand::{Rand, Rng}; use rand::{Rand, Rng};
@ -26,7 +27,7 @@ use rust_num::traits::cast;
use angle::{Rad, sin, cos, sin_cos}; use angle::{Rad, sin, cos, sin_cos};
use approx::ApproxEq; use approx::ApproxEq;
use array::{Array1, Array2}; use array::Array;
use num::{BaseFloat, BaseNum}; use num::{BaseFloat, BaseNum};
use point::{Point, Point3}; use point::{Point, Point3};
use quaternion::Quaternion; use quaternion::Quaternion;
@ -249,15 +250,12 @@ impl<S: Copy + Neg<Output = S>> Matrix4<S> {
} }
} }
/// A column-major matrix of arbitrary dimensions.
pub trait Matrix where pub trait Matrix where
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
Self: Array2< Self: Index<usize, Output = <Self as Matrix>::Column>,
Element = <<Self as Matrix>::ColumnRow as Vector>::Scalar, Self: IndexMut<usize, Output = <Self as Matrix>::Column>,
Column = <Self as Matrix>::ColumnRow, Self: ApproxEq<Epsilon = <Self as Matrix>::Element>,
Row = <Self as Matrix>::ColumnRow,
>,
Self: ApproxEq<Epsilon = <<Self as Matrix>::ColumnRow as Vector>::Scalar> + Sized,
Self::Element: BaseFloat,
// FIXME: blocked by rust-lang/rust#20671 // FIXME: blocked by rust-lang/rust#20671
// //
// for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>, // for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>,
@ -269,65 +267,106 @@ pub trait Matrix where
// for<'a> &'a Self: Div<S, Output = Self>, // for<'a> &'a Self: Div<S, Output = Self>,
// for<'a> &'a Self: Rem<S, Output = Self>, // for<'a> &'a Self: Rem<S, Output = Self>,
{ {
// FIXME: Will not be needed once equality constraints in where clauses is implemented /// The type of the elements in the matrix.
type ColumnRow: Vector; type Element: BaseFloat;
/// The row vector of the matrix.
type Row: Array<Element = Self::Element>;
/// The column vector of the matrix.
type Column: Array<Element = Self::Element>;
/// The type of the transposed matrix
type Transpose: Matrix<Element = Self::Element, Row = Self::Column, Column = Self::Row>;
/// 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 = <Self as SquareMatrix>::ColumnRow,
Row = <Self as SquareMatrix>::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<Element = Self::Element>;
/// Create a new diagonal matrix using the supplied value. /// Create a new diagonal matrix using the supplied value.
fn from_value(value: Self::Element) -> Self; fn from_value(value: Self::Element) -> Self;
/// Create a matrix from a non-uniform scale /// Create a matrix from a non-uniform scale
fn from_diagonal(diagonal: Self::Column) -> Self; 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. /// Create a matrix where the each element of the diagonal is equal to one.
#[inline] fn one() -> Self;
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;
/// Add this matrix with another matrix, returning the new metrix. /// Add this matrix with another matrix, returning the new metrix.
#[must_use]
fn add_m(&self, m: &Self) -> Self; fn add_m(&self, m: &Self) -> Self;
/// Subtract another matrix from this matrix, returning the new matrix. /// Subtract another matrix from this matrix, returning the new matrix.
#[must_use]
fn sub_m(&self, m: &Self) -> Self; 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. /// Add this matrix with another matrix, in-place.
fn add_self_m(&mut self, m: &Self); fn add_self_m(&mut self, m: &Self);
/// Subtract another matrix from this matrix, in-place. /// Subtract another matrix from this matrix, in-place.
fn sub_self_m(&mut self, m: &Self); fn sub_self_m(&mut self, m: &Self);
/// Multiply this matrix by another matrix, in-place. /// Multiply this matrix by another matrix, in-place.
#[inline]
fn mul_self_m(&mut self, m: &Self) { *self = self.mul_m(m); } 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. /// Transpose this matrix in-place.
fn transpose_self(&mut self); fn transpose_self(&mut self);
/// Take the determinant of this matrix. /// Take the determinant of this matrix.
@ -370,10 +409,11 @@ pub trait Matrix where
fn is_symmetric(&self) -> bool; fn is_symmetric(&self) -> bool;
} }
impl<S: Copy> Array2 for Matrix2<S> { impl<S: BaseFloat> Matrix for Matrix2<S> {
type Element = S; type Element = S;
type Column = Vector2<S>; type Column = Vector2<S>;
type Row = Vector2<S>; type Row = Vector2<S>;
type Transpose = Matrix2<S>;
#[inline] #[inline]
fn row(&self, r: usize) -> Vector2<S> { fn row(&self, r: usize) -> Vector2<S> {
@ -383,54 +423,59 @@ impl<S: Copy> Array2 for Matrix2<S> {
#[inline] #[inline]
fn swap_rows(&mut self, a: usize, b: usize) { fn swap_rows(&mut self, a: usize, b: usize) {
self[0].swap_elems(a, b); self[0].swap_elements(a, b);
self[1].swap_elems(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<S> {
Matrix2::new(S::zero(), S::zero(),
S::zero(), S::zero())
}
#[inline]
fn mul_m(&self, other: &Matrix2<S>) -> Matrix2<S> { self * other }
#[inline]
fn mul_v(&self, v: Vector2<S>) -> Vector2<S> { self * v }
#[inline]
fn mul_s(&self, s: S) -> Matrix2<S> { self * s }
#[inline]
fn div_s(&self, s: S) -> Matrix2<S> { 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<S> {
Matrix2::new(self[0][0], self[1][0],
self[0][1], self[1][1])
} }
} }
impl<S: Copy> Array2 for Matrix3<S> { impl<S: BaseFloat> SquareMatrix for Matrix2<S> {
type Element = S;
type Column = Vector3<S>;
type Row = Vector3<S>;
#[inline]
fn row(&self, r: usize) -> Vector3<S> {
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<S: Copy> Array2 for Matrix4<S> {
type Element = S;
type Column = Vector4<S>;
type Row = Vector4<S>;
#[inline]
fn row(&self, r: usize) -> Vector4<S> {
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<S: BaseFloat> Matrix for Matrix2<S> {
type ColumnRow = Vector2<S>; type ColumnRow = Vector2<S>;
#[inline] #[inline]
@ -445,31 +490,17 @@ impl<S: BaseFloat> Matrix for Matrix2<S> {
S::zero(), value.y) S::zero(), value.y)
} }
#[inline] fn mul_s(&self, s: S) -> Matrix2<S> { self * s }
#[inline] fn div_s(&self, s: S) -> Matrix2<S> { self / s }
#[inline] fn rem_s(&self, s: S) -> Matrix2<S> { self % s }
#[inline] fn add_m(&self, m: &Matrix2<S>) -> Matrix2<S> { self + m }
#[inline] fn sub_m(&self, m: &Matrix2<S>) -> Matrix2<S> { self - m }
fn mul_m(&self, other: &Matrix2<S>) -> Matrix2<S> { self * other }
#[inline] fn mul_v(&self, v: Vector2<S>) -> Vector2<S> { self * v }
#[inline] #[inline]
fn mul_self_s(&mut self, s: S) { fn one() -> Matrix2<S> {
self[0].mul_self_s(s); Matrix2::new(S::one(), S::zero(),
self[1].mul_self_s(s); S::zero(), S::one())
} }
#[inline] #[inline]
fn div_self_s(&mut self, s: S) { fn add_m(&self, m: &Matrix2<S>) -> Matrix2<S> { self + m }
self[0].div_self_s(s);
self[1].div_self_s(s);
}
#[inline] #[inline]
fn rem_self_s(&mut self, s: S) { fn sub_m(&self, m: &Matrix2<S>) -> Matrix2<S> { self - m }
self[0].rem_self_s(s);
self[1].rem_self_s(s);
}
#[inline] #[inline]
fn add_self_m(&mut self, m: &Matrix2<S>) { fn add_self_m(&mut self, m: &Matrix2<S>) {
@ -483,14 +514,9 @@ impl<S: BaseFloat> Matrix for Matrix2<S> {
self[1].sub_self_v(m[1]); self[1].sub_self_v(m[1]);
} }
fn transpose(&self) -> Matrix2<S> {
Matrix2::new(self[0][0], self[1][0],
self[0][1], self[1][1])
}
#[inline] #[inline]
fn transpose_self(&mut self) { fn transpose_self(&mut self) {
self.swap_elems((0, 1), (1, 0)); self.swap_elements((0, 1), (1, 0));
} }
#[inline] #[inline]
@ -530,6 +556,78 @@ impl<S: BaseFloat> Matrix for Matrix2<S> {
} }
impl<S: BaseFloat> Matrix for Matrix3<S> { impl<S: BaseFloat> Matrix for Matrix3<S> {
type Element = S;
type Column = Vector3<S>;
type Row = Vector3<S>;
type Transpose = Matrix3<S>;
#[inline]
fn row(&self, r: usize) -> Vector3<S> {
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<S> {
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<S>) -> Matrix3<S> { self * other }
#[inline]
fn mul_v(&self, v: Vector3<S>) -> Vector3<S> { self * v}
#[inline]
fn mul_s(&self, s: S) -> Matrix3<S> { self * s }
#[inline]
fn div_s(&self, s: S) -> Matrix3<S> { 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<S> {
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<S: BaseFloat> SquareMatrix for Matrix3<S> {
type ColumnRow = Vector3<S>; type ColumnRow = Vector3<S>;
#[inline] #[inline]
@ -546,34 +644,18 @@ impl<S: BaseFloat> Matrix for Matrix3<S> {
S::zero(), S::zero(), value.z) S::zero(), S::zero(), value.z)
} }
#[inline] fn mul_s(&self, s: S) -> Matrix3<S> { self * s }
#[inline] fn div_s(&self, s: S) -> Matrix3<S> { self / s }
#[inline] fn rem_s(&self, s: S) -> Matrix3<S> { self % s }
#[inline] fn add_m(&self, m: &Matrix3<S>) -> Matrix3<S> { self + m }
#[inline] fn sub_m(&self, m: &Matrix3<S>) -> Matrix3<S> { self - m }
fn mul_m(&self, other: &Matrix3<S>) -> Matrix3<S> { self * other }
#[inline] fn mul_v(&self, v: Vector3<S>) -> Vector3<S> { self * v}
#[inline] #[inline]
fn mul_self_s(&mut self, s: S) { fn one() -> Matrix3<S> {
self[0].mul_self_s(s); Matrix3::new(S::one(), S::zero(), S::zero(),
self[1].mul_self_s(s); S::zero(), S::one(), S::zero(),
self[2].mul_self_s(s); S::zero(), S::zero(), S::one())
} }
#[inline] #[inline]
fn div_self_s(&mut self, s: S) { fn add_m(&self, m: &Matrix3<S>) -> Matrix3<S> { self + m }
self[0].div_self_s(s);
self[1].div_self_s(s);
self[2].div_self_s(s);
}
#[inline] #[inline]
fn rem_self_s(&mut self, s: S) { fn sub_m(&self, m: &Matrix3<S>) -> Matrix3<S> { self - m }
self[0].rem_self_s(s);
self[1].rem_self_s(s);
self[2].rem_self_s(s);
}
#[inline] #[inline]
fn add_self_m(&mut self, m: &Matrix3<S>) { fn add_self_m(&mut self, m: &Matrix3<S>) {
@ -589,17 +671,11 @@ impl<S: BaseFloat> Matrix for Matrix3<S> {
self[2].sub_self_v(m[2]); self[2].sub_self_v(m[2]);
} }
fn transpose(&self) -> Matrix3<S> {
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] #[inline]
fn transpose_self(&mut self) { fn transpose_self(&mut self) {
self.swap_elems((0, 1), (1, 0)); self.swap_elements((0, 1), (1, 0));
self.swap_elems((0, 2), (2, 0)); self.swap_elements((0, 2), (2, 0));
self.swap_elems((1, 2), (2, 1)); self.swap_elements((1, 2), (2, 1));
} }
fn determinant(&self) -> S { fn determinant(&self) -> S {
@ -648,6 +724,84 @@ impl<S: BaseFloat> Matrix for Matrix3<S> {
} }
impl<S: BaseFloat> Matrix for Matrix4<S> { impl<S: BaseFloat> Matrix for Matrix4<S> {
type Element = S;
type Column = Vector4<S>;
type Row = Vector4<S>;
type Transpose = Matrix4<S>;
#[inline]
fn row(&self, r: usize) -> Vector4<S> {
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<S> {
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<S>) -> Matrix4<S> { self * other }
#[inline]
fn mul_v(&self, v: Vector4<S>) -> Vector4<S> { self * v }
#[inline]
fn mul_s(&self, s: S) -> Matrix4<S> { self * s }
#[inline]
fn div_s(&self, s: S) -> Matrix4<S> { 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<S> {
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<S: BaseFloat> SquareMatrix for Matrix4<S> {
type ColumnRow = Vector4<S>; type ColumnRow = Vector4<S>;
#[inline] #[inline]
@ -666,37 +820,19 @@ impl<S: BaseFloat> Matrix for Matrix4<S> {
S::zero(), S::zero(), S::zero(), value.w) S::zero(), S::zero(), S::zero(), value.w)
} }
#[inline] fn mul_s(&self, s: S) -> Matrix4<S> { self * s }
#[inline] fn div_s(&self, s: S) -> Matrix4<S> { self / s }
#[inline] fn rem_s(&self, s: S) -> Matrix4<S> { self % s }
#[inline] fn add_m(&self, m: &Matrix4<S>) -> Matrix4<S> { self + m }
#[inline] fn sub_m(&self, m: &Matrix4<S>) -> Matrix4<S> { self - m }
fn mul_m(&self, other: &Matrix4<S>) -> Matrix4<S> { self * other }
#[inline] fn mul_v(&self, v: Vector4<S>) -> Vector4<S> { self * v }
#[inline] #[inline]
fn mul_self_s(&mut self, s: S) { fn one() -> Matrix4<S> {
self[0].mul_self_s(s); Matrix4::new(S::one(), S::zero(), S::zero(), S::zero(),
self[1].mul_self_s(s); S::zero(), S::one(), S::zero(), S::zero(),
self[2].mul_self_s(s); S::zero(), S::zero(), S::one(), S::zero(),
self[3].mul_self_s(s); S::zero(), S::zero(), S::zero(), S::one())
} }
#[inline] #[inline]
fn div_self_s(&mut self, s: S) { fn add_m(&self, m: &Matrix4<S>) -> Matrix4<S> { self + m }
self[0].div_self_s(s);
self[1].div_self_s(s);
self[2].div_self_s(s);
self[3].div_self_s(s);
}
#[inline] #[inline]
fn rem_self_s(&mut self, s: S) { fn sub_m(&self, m: &Matrix4<S>) -> Matrix4<S> { self - m }
self[0].rem_self_s(s);
self[1].rem_self_s(s);
self[2].rem_self_s(s);
self[3].rem_self_s(s);
}
#[inline] #[inline]
fn add_self_m(&mut self, m: &Matrix4<S>) { fn add_self_m(&mut self, m: &Matrix4<S>) {
@ -714,20 +850,13 @@ impl<S: BaseFloat> Matrix for Matrix4<S> {
self[3].sub_self_v(m[3]); self[3].sub_self_v(m[3]);
} }
fn transpose(&self) -> Matrix4<S> {
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) { fn transpose_self(&mut self) {
self.swap_elems((0, 1), (1, 0)); self.swap_elements((0, 1), (1, 0));
self.swap_elems((0, 2), (2, 0)); self.swap_elements((0, 2), (2, 0));
self.swap_elems((0, 3), (3, 0)); self.swap_elements((0, 3), (3, 0));
self.swap_elems((1, 2), (2, 1)); self.swap_elements((1, 2), (2, 1));
self.swap_elems((1, 3), (3, 1)); self.swap_elements((1, 3), (3, 1));
self.swap_elems((2, 3), (3, 2)); self.swap_elements((2, 3), (3, 2));
} }
fn determinant(&self) -> S { fn determinant(&self) -> S {
@ -852,7 +981,7 @@ impl<S: BaseFloat> ApproxEq for Matrix4<S> {
} }
} }
impl<S: Neg<Output = S>> Neg for Matrix2<S> { impl<S: BaseFloat> Neg for Matrix2<S> {
type Output = Matrix2<S>; type Output = Matrix2<S>;
#[inline] #[inline]
@ -861,7 +990,7 @@ impl<S: Neg<Output = S>> Neg for Matrix2<S> {
} }
} }
impl<S: Neg<Output = S>> Neg for Matrix3<S> { impl<S: BaseFloat> Neg for Matrix3<S> {
type Output = Matrix3<S>; type Output = Matrix3<S>;
#[inline] #[inline]
@ -870,7 +999,7 @@ impl<S: Neg<Output = S>> Neg for Matrix3<S> {
} }
} }
impl<S: Neg<Output = S>> Neg for Matrix4<S> { impl<S: BaseFloat> Neg for Matrix4<S> {
type Output = Matrix4<S>; type Output = Matrix4<S>;
#[inline] #[inline]
@ -881,7 +1010,7 @@ impl<S: Neg<Output = S>> Neg for Matrix4<S> {
macro_rules! impl_scalar_binary_operator { macro_rules! impl_scalar_binary_operator {
($Binop:ident :: $binop:ident, $MatrixN:ident { $($field:ident),+ }) => { ($Binop:ident :: $binop:ident, $MatrixN:ident { $($field:ident),+ }) => {
impl<'a, S: BaseNum> $Binop<S> for &'a $MatrixN<S> { impl<'a, S: BaseFloat> $Binop<S> for &'a $MatrixN<S> {
type Output = $MatrixN<S>; type Output = $MatrixN<S>;
#[inline] #[inline]
@ -904,7 +1033,7 @@ impl_scalar_binary_operator!(Rem::rem, Matrix4 { x, y, z, w });
macro_rules! impl_binary_operator { macro_rules! impl_binary_operator {
($Binop:ident :: $binop:ident, $MatrixN:ident { $($field:ident),+ }) => { ($Binop:ident :: $binop:ident, $MatrixN:ident { $($field:ident),+ }) => {
impl<'a, 'b, S: BaseNum> $Binop<&'a $MatrixN<S>> for &'b $MatrixN<S> { impl<'a, 'b, S: BaseFloat> $Binop<&'a $MatrixN<S>> for &'b $MatrixN<S> {
type Output = $MatrixN<S>; type Output = $MatrixN<S>;
#[inline] #[inline]
@ -924,7 +1053,7 @@ impl_binary_operator!(Sub::sub, Matrix4 { x, y, z, w });
macro_rules! impl_vector_mul_operators { macro_rules! impl_vector_mul_operators {
($MatrixN:ident, $VectorN:ident { $($row_index:expr),+ }) => { ($MatrixN:ident, $VectorN:ident { $($row_index:expr),+ }) => {
impl<'a, S: BaseNum> Mul<$VectorN<S>> for &'a $MatrixN<S> { impl<'a, S: BaseFloat> Mul<$VectorN<S>> for &'a $MatrixN<S> {
type Output = $VectorN<S>; type Output = $VectorN<S>;
fn mul(self, v: $VectorN<S>) -> $VectorN<S> { fn mul(self, v: $VectorN<S>) -> $VectorN<S> {
@ -932,7 +1061,7 @@ macro_rules! impl_vector_mul_operators {
} }
} }
impl<'a, 'b, S: BaseNum> Mul<&'a $VectorN<S>> for &'b $MatrixN<S> { impl<'a, 'b, S: BaseFloat> Mul<&'a $VectorN<S>> for &'b $MatrixN<S> {
type Output = $VectorN<S>; type Output = $VectorN<S>;
fn mul(self, v: &'a $VectorN<S>) -> $VectorN<S> { fn mul(self, v: &'a $VectorN<S>) -> $VectorN<S> {
@ -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!(Matrix3, Vector3 { 0, 1, 2 });
impl_vector_mul_operators!(Matrix4, Vector4 { 0, 1, 2, 3 }); impl_vector_mul_operators!(Matrix4, Vector4 { 0, 1, 2, 3 });
impl<'a, 'b, S: BaseNum> Mul<&'a Matrix2<S>> for &'b Matrix2<S> { impl<'a, 'b, S: BaseFloat> Mul<&'a Matrix2<S>> for &'b Matrix2<S> {
type Output = Matrix2<S>; type Output = Matrix2<S>;
fn mul(self, other: &'a Matrix2<S>) -> Matrix2<S> { fn mul(self, other: &'a Matrix2<S>) -> Matrix2<S> {
@ -955,7 +1084,7 @@ impl<'a, 'b, S: BaseNum> Mul<&'a Matrix2<S>> for &'b Matrix2<S> {
} }
} }
impl<'a, 'b, S: BaseNum> Mul<&'a Matrix3<S>> for &'b Matrix3<S> { impl<'a, 'b, S: BaseFloat> Mul<&'a Matrix3<S>> for &'b Matrix3<S> {
type Output = Matrix3<S>; type Output = Matrix3<S>;
fn mul(self, other: &'a Matrix3<S>) -> Matrix3<S> { fn mul(self, other: &'a Matrix3<S>) -> Matrix3<S> {
@ -965,7 +1094,7 @@ impl<'a, 'b, S: BaseNum> Mul<&'a Matrix3<S>> for &'b Matrix3<S> {
} }
} }
impl<'a, 'b, S: BaseNum> Mul<&'a Matrix4<S>> for &'b Matrix4<S> { impl<'a, 'b, S: BaseFloat> Mul<&'a Matrix4<S>> for &'b Matrix4<S> {
type Output = Matrix4<S>; type Output = Matrix4<S>;
fn mul(self, other: &'a Matrix4<S>) -> Matrix4<S> { fn mul(self, other: &'a Matrix4<S>) -> Matrix4<S> {

View file

@ -24,7 +24,7 @@ use std::ops::*;
use rust_num::{One, Zero}; use rust_num::{One, Zero};
use approx::ApproxEq; use approx::ApproxEq;
use array::Array1; use array::Array;
use matrix::Matrix; use matrix::Matrix;
use num::{BaseNum, BaseFloat}; use num::{BaseNum, BaseFloat};
use vector::*; use vector::*;
@ -68,7 +68,7 @@ impl<S: BaseNum> Point3<S> {
/// Specifies the numeric operations for point types. /// Specifies the numeric operations for point types.
pub trait Point: Copy + Clone where pub trait Point: Copy + Clone where
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
Self: Array1<Element = <Self as Point>::Scalar>, Self: Array<Element = <Self as Point>::Scalar>,
// FIXME: blocked by rust-lang/rust#20671 // FIXME: blocked by rust-lang/rust#20671
// //
// for<'a, 'b> &'a Self: Add<&'b V, Output = Self>, // 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; fn max(self, p: Self) -> Self;
} }
impl<S: BaseNum> Array1 for Point2<S> { impl<S: BaseNum> Array for Point2<S> {
type Element = S; 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<S: BaseNum> Point for Point2<S> { impl<S: BaseNum> Point for Point2<S> {
@ -210,8 +226,24 @@ impl<S: BaseFloat> ApproxEq for Point2<S> {
} }
} }
impl<S: BaseNum> Array1 for Point3<S> { impl<S: BaseNum> Array for Point3<S> {
type Element = S; 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<S: BaseNum> Point for Point3<S> { impl<S: BaseNum> Point for Point3<S> {

View file

@ -24,7 +24,6 @@ use rust_num::traits::cast;
use angle::{Angle, Rad, acos, sin, sin_cos, rad}; use angle::{Angle, Rad, acos, sin, sin_cos, rad};
use approx::ApproxEq; use approx::ApproxEq;
use array::Array1;
use matrix::{Matrix3, Matrix4}; use matrix::{Matrix3, Matrix4};
use num::BaseFloat; use num::BaseFloat;
use point::Point3; use point::Point3;
@ -40,10 +39,6 @@ pub struct Quaternion<S> {
pub v: Vector3<S>, pub v: Vector3<S>,
} }
impl<S: Copy + BaseFloat> Array1 for Quaternion<S> {
type Element = S;
}
impl<S: BaseFloat> Quaternion<S> { impl<S: BaseFloat> Quaternion<S> {
/// Construct a new quaternion from one scalar component and three /// Construct a new quaternion from one scalar component and three
/// imaginary components /// imaginary components

View file

@ -15,9 +15,8 @@
use angle::{Rad, acos}; use angle::{Rad, acos};
use approx::ApproxEq; use approx::ApproxEq;
use matrix::Matrix; use matrix::{Matrix, SquareMatrix};
use matrix::Matrix2; use matrix::{Matrix2, Matrix3};
use matrix::Matrix3;
use num::BaseFloat; use num::BaseFloat;
use point::{Point, Point2, Point3}; use point::{Point, Point2, Point3};
use quaternion::Quaternion; use quaternion::Quaternion;

View file

@ -88,7 +88,7 @@
//! //!
//! Several other useful methods are provided as well. Vector fields can be //! 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 //! 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. //! This trait also provides a `map()` method for applying arbitrary functions.
//! //!
//! The [`Vector`](../trait.Vector.html) trait presents the most general //! 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 angle::{Rad, atan2, acos};
use approx::ApproxEq; use approx::ApproxEq;
use array::Array1; use array::Array;
use num::{BaseNum, BaseFloat}; use num::{BaseNum, BaseFloat, PartialOrd};
/// A trait that specifies a range of numeric operations for vectors. Not all /// 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 /// of these make sense from a linear algebra point of view, but are included
/// for pragmatic reasons. /// for pragmatic reasons.
pub trait Vector: Copy + Clone where pub trait Vector: Copy + Clone where
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
Self: Array1<Element = <Self as Vector>::Scalar>, Self: Array<Element = <Self as Vector>::Scalar>,
// FIXME: blocked by rust-lang/rust#20671 // FIXME: blocked by rust-lang/rust#20671
// //
// for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>, // 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. /// Take the remainder of this vector by another, in-place.
fn rem_self_v(&mut self, v: Self); fn rem_self_v(&mut self, v: Self);
/// The sum of the components of the vector. /// Vector dot product
fn sum(self) -> Self::Scalar; fn dot(self, other: 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;
} }
/// Dot product of two vectors. /// Dot product of two vectors.
@ -250,8 +239,13 @@ macro_rules! vec {
} }
} }
impl<S: Copy> Array1 for $VectorN<S> { impl<S: Copy> Array for $VectorN<S> {
type Element = S; type Element = S;
#[inline] fn sum(self) -> S where S: Add<Output = S> { fold!(add, { $(self.$field),+ }) }
#[inline] fn product(self) -> S where S: Mul<Output = S> { 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<S: BaseNum> Vector for $VectorN<S> { impl<S: BaseNum> Vector for $VectorN<S> {
@ -283,10 +277,7 @@ macro_rules! vec {
#[inline] fn div_self_v(&mut self, v: $VectorN<S>) { *self = &*self / v; } #[inline] fn div_self_v(&mut self, v: $VectorN<S>) { *self = &*self / v; }
#[inline] fn rem_self_v(&mut self, v: $VectorN<S>) { *self = &*self % v; } #[inline] fn rem_self_v(&mut self, v: $VectorN<S>) { *self = &*self % v; }
#[inline] fn sum(self) -> S { fold!(add, { $(self.$field),+ }) } #[inline] fn dot(self, other: $VectorN<S>) -> S { (self * other).sum() }
#[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),+ }) }
} }
impl<S: Neg<Output = S>> Neg for $VectorN<S> { impl<S: Neg<Output = S>> Neg for $VectorN<S> {

View file

@ -63,25 +63,25 @@ fn test_product() {
} }
#[test] #[test]
fn test_comp_min() { fn test_min() {
assert_eq!(Vector2::new(1isize, 2isize).comp_min(), 1isize); assert_eq!(Vector2::new(1isize, 2isize).min(), 1isize);
assert_eq!(Vector3::new(1isize, 2isize, 3isize).comp_min(), 1isize); assert_eq!(Vector3::new(1isize, 2isize, 3isize).min(), 1isize);
assert_eq!(Vector4::new(1isize, 2isize, 3isize, 4isize).comp_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!(Vector2::new(3.0f64, 4.0f64).min(), 3.0f64);
assert_eq!(Vector3::new(4.0f64, 5.0f64, 6.0f64).comp_min(), 4.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).comp_min(), 5.0f64); assert_eq!(Vector4::new(5.0f64, 6.0f64, 7.0f64, 8.0f64).min(), 5.0f64);
} }
#[test] #[test]
fn test_comp_max() { fn test_max() {
assert_eq!(Vector2::new(1isize, 2isize).comp_max(), 2isize); assert_eq!(Vector2::new(1isize, 2isize).max(), 2isize);
assert_eq!(Vector3::new(1isize, 2isize, 3isize).comp_max(), 3isize); assert_eq!(Vector3::new(1isize, 2isize, 3isize).max(), 3isize);
assert_eq!(Vector4::new(1isize, 2isize, 3isize, 4isize).comp_max(), 4isize); assert_eq!(Vector4::new(1isize, 2isize, 3isize, 4isize).max(), 4isize);
assert_eq!(Vector2::new(3.0f64, 4.0f64).comp_max(), 4.0f64); assert_eq!(Vector2::new(3.0f64, 4.0f64).max(), 4.0f64);
assert_eq!(Vector3::new(4.0f64, 5.0f64, 6.0f64).comp_max(), 6.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).comp_max(), 8.0f64); assert_eq!(Vector4::new(5.0f64, 6.0f64, 7.0f64, 8.0f64).max(), 8.0f64);
} }
#[test] #[test]