Merge pull request #281 from bjz/matrix-ops
Implement all by-ref/val permutations of matrix operators, and remove operator methods
This commit is contained in:
commit
1b4420d2af
11 changed files with 204 additions and 471 deletions
18
CHANGELOG.md
18
CHANGELOG.md
|
@ -7,16 +7,16 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- Add missing by-ref and by-val permutations of `Quaternion` and `Angle`
|
||||
operators.
|
||||
- Add missing by-ref and by-val permutations of `Vector`, `Matrix`, `Point`,
|
||||
`Quaternion` and `Angle` operators.
|
||||
- Ease lifetime constraints by removing `'static` from some scalar type
|
||||
parameters.
|
||||
- Weaken type constraints on `perspective` function to take an `Into<Rad<S>>`.
|
||||
- Add `Angle::new` for constructing angles from a unitless scalar.
|
||||
|
||||
### Changed
|
||||
- `Vector`, `Point`, and `Angle` are now constrained to require specific
|
||||
operators to be overloaded. This means that generic code can now use
|
||||
- `Vector`, `Matrix`, `Point`, and `Angle` are now constrained to require
|
||||
specific operators to be overloaded. This means that generic code can now use
|
||||
operators, instead of the operator methods.
|
||||
- Take a `Rad` for `ProjectionFov::fovy`, rather than arbitrary `Angle`s. This
|
||||
simplifies the signature of `PerspectiveFov` from `PerspectiveFov<S, A>` to
|
||||
|
@ -42,11 +42,11 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||
- Remove `Vector::one`. Vectors don't really have a multiplicative identity.
|
||||
If you really want a `one` vector, you can do something like:
|
||||
`Vector::from_value(1.0)`.
|
||||
- Remove operator methods from `Vector`, `Point`, and `Angle` traits in favor of
|
||||
operator overloading.
|
||||
- Remove `*_self` methods from `Vector`, `Point`, and `Angle`. These were of
|
||||
little performance benefit, and assignment operator overloading will be
|
||||
coming soon!
|
||||
- Remove operator methods from `Vector`, `Matrix`, `Point`, and `Angle` traits
|
||||
in favor of operator overloading.
|
||||
- Remove `*_self` methods from `Vector`, `Matrix`, `Point`, and `Angle`. These
|
||||
were of little performance benefit, and assignment operator overloading will
|
||||
be coming soon!
|
||||
- Remove `#[derive(Hash)]` from `Deg` and `Rad`. This could never really be used
|
||||
these types, because they expect to be given a `BaseFloat` under normal
|
||||
circumstances.
|
||||
|
|
12
src/angle.rs
12
src/angle.rs
|
@ -167,23 +167,23 @@ macro_rules! impl_angle {
|
|||
fn neg(self) -> $Angle<S> { $Angle::new(-self.s) }
|
||||
}
|
||||
|
||||
impl_binary_operator!(<S: BaseFloat> Add<$Angle<S> > for $Angle<S> {
|
||||
impl_operator!(<S: BaseFloat> Add<$Angle<S> > for $Angle<S> {
|
||||
fn add(lhs, rhs) -> $Angle<S> { $Angle::new(lhs.s + rhs.s) }
|
||||
});
|
||||
impl_binary_operator!(<S: BaseFloat> Sub<$Angle<S> > for $Angle<S> {
|
||||
impl_operator!(<S: BaseFloat> Sub<$Angle<S> > for $Angle<S> {
|
||||
fn sub(lhs, rhs) -> $Angle<S> { $Angle::new(lhs.s - rhs.s) }
|
||||
});
|
||||
impl_binary_operator!(<S: BaseFloat> Div<$Angle<S> > for $Angle<S> {
|
||||
impl_operator!(<S: BaseFloat> Div<$Angle<S> > for $Angle<S> {
|
||||
fn div(lhs, rhs) -> S { lhs.s / rhs.s }
|
||||
});
|
||||
impl_binary_operator!(<S: BaseFloat> Rem<$Angle<S> > for $Angle<S> {
|
||||
impl_operator!(<S: BaseFloat> Rem<$Angle<S> > for $Angle<S> {
|
||||
fn rem(lhs, rhs) -> $Angle<S> { $Angle::new(lhs.s % rhs.s) }
|
||||
});
|
||||
|
||||
impl_binary_operator!(<S: BaseFloat> Mul<S> for $Angle<S> {
|
||||
impl_operator!(<S: BaseFloat> Mul<S> for $Angle<S> {
|
||||
fn mul(lhs, scalar) -> $Angle<S> { $Angle::new(lhs.s * scalar) }
|
||||
});
|
||||
impl_binary_operator!(<S: BaseFloat> Div<S> for $Angle<S> {
|
||||
impl_operator!(<S: BaseFloat> Div<S> for $Angle<S> {
|
||||
fn div(lhs, scalar) -> $Angle<S> { $Angle::new(lhs.s / scalar) }
|
||||
});
|
||||
|
||||
|
|
|
@ -18,59 +18,79 @@
|
|||
#![macro_use]
|
||||
|
||||
/// Generates a binary operator implementation for the permutations of by-ref and by-val
|
||||
macro_rules! impl_binary_operator {
|
||||
// When the right operand is a scalar
|
||||
(<$S:ident: $Constraint:ident> $Binop:ident<$Rhs:ident> for $Lhs:ty {
|
||||
fn $binop:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr }
|
||||
macro_rules! impl_operator {
|
||||
// When it is an unary operator
|
||||
(<$S:ident: $Constraint:ident> $Op:ident for $Lhs:ty {
|
||||
fn $op:ident($x:ident) -> $Output:ty { $body:expr }
|
||||
}) => {
|
||||
impl<$S: $Constraint> $Binop<$Rhs> for $Lhs {
|
||||
impl<$S: $Constraint> $Op for $Lhs {
|
||||
type Output = $Output;
|
||||
#[inline]
|
||||
fn $binop(self, other: $Rhs) -> $Output {
|
||||
fn $op(self) -> $Output {
|
||||
let $x = self; $body
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $S: $Constraint> $Op for &'a $Lhs {
|
||||
type Output = $Output;
|
||||
#[inline]
|
||||
fn $op(self) -> $Output {
|
||||
let $x = self; $body
|
||||
}
|
||||
}
|
||||
};
|
||||
// When the right operand is a scalar
|
||||
(<$S:ident: $Constraint:ident> $Op:ident<$Rhs:ident> for $Lhs:ty {
|
||||
fn $op:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr }
|
||||
}) => {
|
||||
impl<$S: $Constraint> $Op<$Rhs> for $Lhs {
|
||||
type Output = $Output;
|
||||
#[inline]
|
||||
fn $op(self, other: $Rhs) -> $Output {
|
||||
let ($lhs, $rhs) = (self, other); $body
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $S: $Constraint> $Binop<$Rhs> for &'a $Lhs {
|
||||
impl<'a, $S: $Constraint> $Op<$Rhs> for &'a $Lhs {
|
||||
type Output = $Output;
|
||||
#[inline]
|
||||
fn $binop(self, other: $Rhs) -> $Output {
|
||||
fn $op(self, other: $Rhs) -> $Output {
|
||||
let ($lhs, $rhs) = (self, other); $body
|
||||
}
|
||||
}
|
||||
};
|
||||
// When the right operand is a compound type
|
||||
(<$S:ident: $Constraint:ident> $Binop:ident<$Rhs:ty> for $Lhs:ty {
|
||||
fn $binop:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr }
|
||||
(<$S:ident: $Constraint:ident> $Op:ident<$Rhs:ty> for $Lhs:ty {
|
||||
fn $op:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr }
|
||||
}) => {
|
||||
impl<$S: $Constraint> $Binop<$Rhs> for $Lhs {
|
||||
impl<$S: $Constraint> $Op<$Rhs> for $Lhs {
|
||||
type Output = $Output;
|
||||
#[inline]
|
||||
fn $binop(self, other: $Rhs) -> $Output {
|
||||
fn $op(self, other: $Rhs) -> $Output {
|
||||
let ($lhs, $rhs) = (self, other); $body
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $S: $Constraint> $Binop<&'a $Rhs> for $Lhs {
|
||||
impl<'a, $S: $Constraint> $Op<&'a $Rhs> for $Lhs {
|
||||
type Output = $Output;
|
||||
#[inline]
|
||||
fn $binop(self, other: &'a $Rhs) -> $Output {
|
||||
fn $op(self, other: &'a $Rhs) -> $Output {
|
||||
let ($lhs, $rhs) = (self, other); $body
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $S: $Constraint> $Binop<$Rhs> for &'a $Lhs {
|
||||
impl<'a, $S: $Constraint> $Op<$Rhs> for &'a $Lhs {
|
||||
type Output = $Output;
|
||||
#[inline]
|
||||
fn $binop(self, other: $Rhs) -> $Output {
|
||||
fn $op(self, other: $Rhs) -> $Output {
|
||||
let ($lhs, $rhs) = (self, other); $body
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, $S: $Constraint> $Binop<&'a $Rhs> for &'b $Lhs {
|
||||
impl<'a, 'b, $S: $Constraint> $Op<&'a $Rhs> for &'b $Lhs {
|
||||
type Output = $Output;
|
||||
#[inline]
|
||||
fn $binop(self, other: &'a $Rhs) -> $Output {
|
||||
fn $op(self, other: &'a $Rhs) -> $Output {
|
||||
let ($lhs, $rhs) = (self, other); $body
|
||||
}
|
||||
}
|
||||
|
|
374
src/matrix.rs
374
src/matrix.rs
|
@ -263,16 +263,13 @@ pub trait Matrix where
|
|||
Self: Index<usize, Output = <Self as Matrix>::Column>,
|
||||
Self: IndexMut<usize, Output = <Self as Matrix>::Column>,
|
||||
Self: ApproxEq<Epsilon = <Self as Matrix>::Element>,
|
||||
// FIXME: blocked by rust-lang/rust#20671
|
||||
//
|
||||
// for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>,
|
||||
// for<'a, 'b> &'a Self: Sub<&'b Self, Output = Self>,
|
||||
// for<'a, 'b> &'a Self: Mul<&'b Self, Output = Self>,
|
||||
// for<'a, 'b> &'a Self: Mul<&'b V, Output = V>,
|
||||
//
|
||||
// for<'a> &'a Self: Mul<S, Output = Self>,
|
||||
// for<'a> &'a Self: Div<S, Output = Self>,
|
||||
// for<'a> &'a Self: Rem<S, Output = Self>,
|
||||
|
||||
Self: Add<Self, Output = Self>,
|
||||
Self: Sub<Self, Output = Self>,
|
||||
|
||||
Self: Mul<<Self as Matrix>::Element, Output = Self>,
|
||||
Self: Div<<Self as Matrix>::Element, Output = Self>,
|
||||
Self: Rem<<Self as Matrix>::Element, Output = Self>,
|
||||
{
|
||||
/// The type of the elements in the matrix.
|
||||
type Element: BaseFloat;
|
||||
|
@ -316,22 +313,6 @@ pub trait Matrix where
|
|||
/// 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;
|
||||
}
|
||||
|
@ -344,6 +325,8 @@ pub trait SquareMatrix where
|
|||
Row = <Self as SquareMatrix>::ColumnRow,
|
||||
Transpose = Self,
|
||||
>,
|
||||
Self: Mul<<Self as SquareMatrix>::ColumnRow, Output = <Self as SquareMatrix>::ColumnRow>,
|
||||
Self: Mul<Self, Output = Self>,
|
||||
{
|
||||
// FIXME: Will not be needed once equality constraints in where clauses are implemented
|
||||
/// The row/column vector of the matrix.
|
||||
|
@ -362,19 +345,6 @@ pub trait SquareMatrix where
|
|||
/// matrix with another has no effect.
|
||||
fn identity() -> Self;
|
||||
|
||||
/// Add this matrix with another matrix, returning the new metrix.
|
||||
fn add_m(&self, m: &Self) -> Self;
|
||||
/// Subtract another matrix from this matrix, returning the new matrix.
|
||||
fn sub_m(&self, m: &Self) -> Self;
|
||||
|
||||
/// 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.
|
||||
fn mul_self_m(&mut self, m: &Self) { *self = self.mul_m(m); }
|
||||
|
||||
/// Transpose this matrix in-place.
|
||||
fn transpose_self(&mut self);
|
||||
/// Take the determinant of this matrix.
|
||||
|
@ -453,30 +423,6 @@ impl<S: BaseFloat> Matrix for Matrix2<S> {
|
|||
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] = self[0] * s;
|
||||
self[1] = self[1] * s;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn div_self_s(&mut self, s: S) {
|
||||
self[0] = self[0] / s;
|
||||
self[1] = self[1] / s;
|
||||
}
|
||||
|
||||
fn transpose(&self) -> Matrix2<S> {
|
||||
Matrix2::new(self[0][0], self[1][0],
|
||||
self[0][1], self[1][1])
|
||||
|
@ -503,24 +449,6 @@ impl<S: BaseFloat> SquareMatrix for Matrix2<S> {
|
|||
Matrix2::from_value(S::one())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add_m(&self, m: &Matrix2<S>) -> Matrix2<S> { self + m }
|
||||
|
||||
#[inline]
|
||||
fn sub_m(&self, m: &Matrix2<S>) -> Matrix2<S> { self - m }
|
||||
|
||||
#[inline]
|
||||
fn add_self_m(&mut self, m: &Matrix2<S>) {
|
||||
self[0] = self[0] + m[0];
|
||||
self[1] = self[1] + m[1];
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sub_self_m(&mut self, m: &Matrix2<S>) {
|
||||
self[0] = self[0] - m[0];
|
||||
self[1] = self[1] - m[1];
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn transpose_self(&mut self) {
|
||||
self.swap_elements((0, 1), (1, 0));
|
||||
|
@ -601,32 +529,6 @@ impl<S: BaseFloat> Matrix for Matrix3<S> {
|
|||
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] = self[0] * s;
|
||||
self[1] = self[1] * s;
|
||||
self[2] = self[2] * s;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn div_self_s(&mut self, s: S) {
|
||||
self[0] = self[0] / s;
|
||||
self[1] = self[1] / s;
|
||||
self[2] = self[2] / 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],
|
||||
|
@ -656,26 +558,6 @@ impl<S: BaseFloat> SquareMatrix for Matrix3<S> {
|
|||
Matrix3::from_value(S::one())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add_m(&self, m: &Matrix3<S>) -> Matrix3<S> { self + m }
|
||||
|
||||
#[inline]
|
||||
fn sub_m(&self, m: &Matrix3<S>) -> Matrix3<S> { self - m }
|
||||
|
||||
#[inline]
|
||||
fn add_self_m(&mut self, m: &Matrix3<S>) {
|
||||
self[0] = self[0] + m[0];
|
||||
self[1] = self[1] + m[1];
|
||||
self[2] = self[2] + m[2];
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sub_self_m(&mut self, m: &Matrix3<S>) {
|
||||
self[0] = self[0] - m[0];
|
||||
self[1] = self[1] - m[1];
|
||||
self[2] = self[2] - m[2];
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn transpose_self(&mut self) {
|
||||
self.swap_elements((0, 1), (1, 0));
|
||||
|
@ -770,34 +652,6 @@ impl<S: BaseFloat> Matrix for Matrix4<S> {
|
|||
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] = self[0] * s;
|
||||
self[1] = self[1] * s;
|
||||
self[2] = self[2] * s;
|
||||
self[3] = self[3] * s;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn div_self_s(&mut self, s: S) {
|
||||
self[0] = self[0] / s;
|
||||
self[1] = self[1] / s;
|
||||
self[2] = self[2] / s;
|
||||
self[3] = self[3] / 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],
|
||||
|
@ -830,28 +684,6 @@ impl<S: BaseFloat> SquareMatrix for Matrix4<S> {
|
|||
Matrix4::from_value(S::one())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add_m(&self, m: &Matrix4<S>) -> Matrix4<S> { self + m }
|
||||
|
||||
#[inline]
|
||||
fn sub_m(&self, m: &Matrix4<S>) -> Matrix4<S> { self - m }
|
||||
|
||||
#[inline]
|
||||
fn add_self_m(&mut self, m: &Matrix4<S>) {
|
||||
self[0] = self[0] + m[0];
|
||||
self[1] = self[1] + m[1];
|
||||
self[2] = self[2] + m[2];
|
||||
self[3] = self[3] + m[3];
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sub_self_m(&mut self, m: &Matrix4<S>) {
|
||||
self[0] = self[0] - m[0];
|
||||
self[1] = self[1] - m[1];
|
||||
self[2] = self[2] - m[2];
|
||||
self[3] = self[3] - m[3];
|
||||
}
|
||||
|
||||
fn transpose_self(&mut self) {
|
||||
self.swap_elements((0, 1), (1, 0));
|
||||
self.swap_elements((0, 2), (2, 0));
|
||||
|
@ -983,143 +815,75 @@ impl<S: BaseFloat> ApproxEq for Matrix4<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> Neg for Matrix2<S> {
|
||||
type Output = Matrix2<S>;
|
||||
macro_rules! impl_operators {
|
||||
($MatrixN:ident, $VectorN:ident { $($field:ident : $row_index:expr),+ }) => {
|
||||
impl_operator!(<S: BaseFloat> Neg for $MatrixN<S> {
|
||||
fn neg(matrix) -> $MatrixN<S> { $MatrixN { $($field: -matrix.$field),+ } }
|
||||
});
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> Matrix2<S> {
|
||||
Matrix2::from_cols(-self.x, -self.y)
|
||||
impl_operator!(<S: BaseFloat> Mul<S> for $MatrixN<S> {
|
||||
fn mul(matrix, scalar) -> $MatrixN<S> { $MatrixN { $($field: matrix.$field * scalar),+ } }
|
||||
});
|
||||
impl_operator!(<S: BaseFloat> Div<S> for $MatrixN<S> {
|
||||
fn div(matrix, scalar) -> $MatrixN<S> { $MatrixN { $($field: matrix.$field / scalar),+ } }
|
||||
});
|
||||
impl_operator!(<S: BaseFloat> Rem<S> for $MatrixN<S> {
|
||||
fn rem(matrix, scalar) -> $MatrixN<S> { $MatrixN { $($field: matrix.$field % scalar),+ } }
|
||||
});
|
||||
|
||||
impl_operator!(<S: BaseFloat> Add<$MatrixN<S> > for $MatrixN<S> {
|
||||
fn add(lhs, rhs) -> $MatrixN<S> { $MatrixN { $($field: lhs.$field + rhs.$field),+ } }
|
||||
});
|
||||
impl_operator!(<S: BaseFloat> Sub<$MatrixN<S> > for $MatrixN<S> {
|
||||
fn sub(lhs, rhs) -> $MatrixN<S> { $MatrixN { $($field: lhs.$field - rhs.$field),+ } }
|
||||
});
|
||||
|
||||
impl_operator!(<S: BaseFloat> Mul<$VectorN<S> > for $MatrixN<S> {
|
||||
fn mul(matrix, vector) -> $VectorN<S> { $VectorN::new($(matrix.row($row_index).dot(vector.clone())),+) }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> Neg for Matrix3<S> {
|
||||
type Output = Matrix3<S>;
|
||||
impl_operators!(Matrix2, Vector2 { x: 0, y: 1 });
|
||||
impl_operators!(Matrix3, Vector3 { x: 0, y: 1, z: 2 });
|
||||
impl_operators!(Matrix4, Vector4 { x: 0, y: 1, z: 2, w: 3 });
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> Matrix3<S> {
|
||||
Matrix3::from_cols(-self.x, -self.y, -self.z)
|
||||
impl_operator!(<S: BaseFloat> Mul<Matrix2<S> > for Matrix2<S> {
|
||||
fn mul(lhs, rhs) -> Matrix2<S> {
|
||||
Matrix2::new(lhs.row(0).dot(rhs[0]), lhs.row(1).dot(rhs[0]),
|
||||
lhs.row(0).dot(rhs[1]), lhs.row(1).dot(rhs[1]))
|
||||
}
|
||||
});
|
||||
|
||||
impl_operator!(<S: BaseFloat> Mul<Matrix3<S> > for Matrix3<S> {
|
||||
fn mul(lhs, rhs) -> Matrix3<S> {
|
||||
Matrix3::new(lhs.row(0).dot(rhs[0]), lhs.row(1).dot(rhs[0]), lhs.row(2).dot(rhs[0]),
|
||||
lhs.row(0).dot(rhs[1]), lhs.row(1).dot(rhs[1]), lhs.row(2).dot(rhs[1]),
|
||||
lhs.row(0).dot(rhs[2]), lhs.row(1).dot(rhs[2]), lhs.row(2).dot(rhs[2]))
|
||||
}
|
||||
});
|
||||
|
||||
// Using self.row(0).dot(other[0]) like the other matrix multiplies
|
||||
// causes the LLVM to miss identical loads and multiplies. This optimization
|
||||
// causes the code to be auto vectorized properly increasing the performance
|
||||
// around ~4 times.
|
||||
macro_rules! dot_matrix4 {
|
||||
($A:expr, $B:expr, $I:expr, $J:expr) => {
|
||||
($A[0][$I]) * ($B[$J][0]) +
|
||||
($A[1][$I]) * ($B[$J][1]) +
|
||||
($A[2][$I]) * ($B[$J][2]) +
|
||||
($A[3][$I]) * ($B[$J][3])
|
||||
};
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> Neg for Matrix4<S> {
|
||||
type Output = Matrix4<S>;
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> Matrix4<S> {
|
||||
Matrix4::from_cols(-self.x, -self.y, -self.z, -self.w)
|
||||
impl_operator!(<S: BaseFloat> Mul<Matrix4<S> > for Matrix4<S> {
|
||||
fn mul(lhs, rhs) -> Matrix4<S> {
|
||||
Matrix4::new(dot_matrix4!(lhs, rhs, 0, 0), dot_matrix4!(lhs, rhs, 1, 0), dot_matrix4!(lhs, rhs, 2, 0), dot_matrix4!(lhs, rhs, 3, 0),
|
||||
dot_matrix4!(lhs, rhs, 0, 1), dot_matrix4!(lhs, rhs, 1, 1), dot_matrix4!(lhs, rhs, 2, 1), dot_matrix4!(lhs, rhs, 3, 1),
|
||||
dot_matrix4!(lhs, rhs, 0, 2), dot_matrix4!(lhs, rhs, 1, 2), dot_matrix4!(lhs, rhs, 2, 2), dot_matrix4!(lhs, rhs, 3, 2),
|
||||
dot_matrix4!(lhs, rhs, 0, 3), dot_matrix4!(lhs, rhs, 1, 3), dot_matrix4!(lhs, rhs, 2, 3), dot_matrix4!(lhs, rhs, 3, 3))
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_scalar_binary_operator {
|
||||
($Binop:ident :: $binop:ident, $MatrixN:ident { $($field:ident),+ }) => {
|
||||
impl<'a, S: BaseFloat> $Binop<S> for &'a $MatrixN<S> {
|
||||
type Output = $MatrixN<S>;
|
||||
|
||||
#[inline]
|
||||
fn $binop(self, s: S) -> $MatrixN<S> {
|
||||
$MatrixN { $($field: self.$field.$binop(s)),+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_scalar_binary_operator!(Mul::mul, Matrix2 { x, y });
|
||||
impl_scalar_binary_operator!(Mul::mul, Matrix3 { x, y, z });
|
||||
impl_scalar_binary_operator!(Mul::mul, Matrix4 { x, y, z, w });
|
||||
impl_scalar_binary_operator!(Div::div, Matrix2 { x, y });
|
||||
impl_scalar_binary_operator!(Div::div, Matrix3 { x, y, z });
|
||||
impl_scalar_binary_operator!(Div::div, Matrix4 { x, y, z, w });
|
||||
impl_scalar_binary_operator!(Rem::rem, Matrix2 { x, y });
|
||||
impl_scalar_binary_operator!(Rem::rem, Matrix3 { x, y, z });
|
||||
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: BaseFloat> $Binop<&'a $MatrixN<S>> for &'b $MatrixN<S> {
|
||||
type Output = $MatrixN<S>;
|
||||
|
||||
#[inline]
|
||||
fn $binop(self, other: &'a $MatrixN<S>) -> $MatrixN<S> {
|
||||
$MatrixN { $($field: self.$field.$binop(other.$field)),+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_binary_operator!(Add::add, Matrix2 { x, y });
|
||||
impl_binary_operator!(Add::add, Matrix3 { x, y, z });
|
||||
impl_binary_operator!(Add::add, Matrix4 { x, y, z, w });
|
||||
impl_binary_operator!(Sub::sub, Matrix2 { x, y });
|
||||
impl_binary_operator!(Sub::sub, Matrix3 { x, y, z });
|
||||
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: BaseFloat> Mul<$VectorN<S>> for &'a $MatrixN<S> {
|
||||
type Output = $VectorN<S>;
|
||||
|
||||
fn mul(self, v: $VectorN<S>) -> $VectorN<S> {
|
||||
$VectorN::new($(self.row($row_index).dot(v)),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, S: BaseFloat> Mul<&'a $VectorN<S>> for &'b $MatrixN<S> {
|
||||
type Output = $VectorN<S>;
|
||||
|
||||
fn mul(self, v: &'a $VectorN<S>) -> $VectorN<S> {
|
||||
$VectorN::new($(self.row($row_index).dot(*v)),+)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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: BaseFloat> Mul<&'a Matrix2<S>> for &'b Matrix2<S> {
|
||||
type Output = Matrix2<S>;
|
||||
|
||||
fn mul(self, other: &'a Matrix2<S>) -> Matrix2<S> {
|
||||
Matrix2::new(self.row(0).dot(other[0]), self.row(1).dot(other[0]),
|
||||
self.row(0).dot(other[1]), self.row(1).dot(other[1]))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, S: BaseFloat> Mul<&'a Matrix3<S>> for &'b Matrix3<S> {
|
||||
type Output = Matrix3<S>;
|
||||
|
||||
fn mul(self, other: &'a Matrix3<S>) -> Matrix3<S> {
|
||||
Matrix3::new(self.row(0).dot(other[0]),self.row(1).dot(other[0]),self.row(2).dot(other[0]),
|
||||
self.row(0).dot(other[1]),self.row(1).dot(other[1]),self.row(2).dot(other[1]),
|
||||
self.row(0).dot(other[2]),self.row(1).dot(other[2]),self.row(2).dot(other[2]))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, S: BaseFloat> Mul<&'a Matrix4<S>> for &'b Matrix4<S> {
|
||||
type Output = Matrix4<S>;
|
||||
|
||||
fn mul(self, other: &'a Matrix4<S>) -> Matrix4<S> {
|
||||
// Using self.row(0).dot(other[0]) like the other matrix multiplies
|
||||
// causes the LLVM to miss identical loads and multiplies. This optimization
|
||||
// causes the code to be auto vectorized properly increasing the performance
|
||||
// around ~4 times.
|
||||
macro_rules! dot_matrix4 {
|
||||
($A:expr, $B:expr, $I:expr, $J:expr) => {
|
||||
($A[0][$I]) * ($B[$J][0]) +
|
||||
($A[1][$I]) * ($B[$J][1]) +
|
||||
($A[2][$I]) * ($B[$J][2]) +
|
||||
($A[3][$I]) * ($B[$J][3])
|
||||
};
|
||||
};
|
||||
|
||||
Matrix4::new(dot_matrix4!(self, other, 0, 0), dot_matrix4!(self, other, 1, 0), dot_matrix4!(self, other, 2, 0), dot_matrix4!(self, other, 3, 0),
|
||||
dot_matrix4!(self, other, 0, 1), dot_matrix4!(self, other, 1, 1), dot_matrix4!(self, other, 2, 1), dot_matrix4!(self, other, 3, 1),
|
||||
dot_matrix4!(self, other, 0, 2), dot_matrix4!(self, other, 1, 2), dot_matrix4!(self, other, 2, 2), dot_matrix4!(self, other, 3, 2),
|
||||
dot_matrix4!(self, other, 0, 3), dot_matrix4!(self, other, 1, 3), dot_matrix4!(self, other, 2, 3), dot_matrix4!(self, other, 3, 3))
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
macro_rules! index_operators {
|
||||
($MatrixN:ident<$S:ident>, $n:expr, $Output:ty, $I:ty) => {
|
||||
|
|
10
src/point.rs
10
src/point.rs
|
@ -142,23 +142,23 @@ macro_rules! impl_point {
|
|||
}
|
||||
}
|
||||
|
||||
impl_binary_operator!(<S: BaseNum> Add<$VectorN<S> > for $PointN<S> {
|
||||
impl_operator!(<S: BaseNum> Add<$VectorN<S> > for $PointN<S> {
|
||||
fn add(lhs, rhs) -> $PointN<S> { $PointN::new($(lhs.$field + rhs.$field),+) }
|
||||
});
|
||||
|
||||
impl_binary_operator!(<S: BaseNum> Sub<$PointN<S> > for $PointN<S> {
|
||||
impl_operator!(<S: BaseNum> Sub<$PointN<S> > for $PointN<S> {
|
||||
fn sub(lhs, rhs) -> $VectorN<S> { $VectorN::new($(lhs.$field - rhs.$field),+) }
|
||||
});
|
||||
|
||||
impl_binary_operator!(<S: BaseNum> Mul<S> for $PointN<S> {
|
||||
impl_operator!(<S: BaseNum> Mul<S> for $PointN<S> {
|
||||
fn mul(point, scalar) -> $PointN<S> { $PointN::new($(point.$field * scalar),+) }
|
||||
});
|
||||
|
||||
impl_binary_operator!(<S: BaseNum> Div<S> for $PointN<S> {
|
||||
impl_operator!(<S: BaseNum> Div<S> for $PointN<S> {
|
||||
fn div(point, scalar) -> $PointN<S> { $PointN::new($(point.$field / scalar),+) }
|
||||
});
|
||||
|
||||
impl_binary_operator!(<S: BaseNum> Rem<S> for $PointN<S> {
|
||||
impl_operator!(<S: BaseNum> Rem<S> for $PointN<S> {
|
||||
fn rem(point, scalar) -> $PointN<S> { $PointN::new($(point.$field % scalar),+) }
|
||||
});
|
||||
|
||||
|
|
|
@ -108,33 +108,25 @@ impl<S: BaseFloat> Quaternion<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> Neg for Quaternion<S> {
|
||||
type Output = Quaternion<S>;
|
||||
impl_operator!(<S: BaseFloat> Neg for Quaternion<S> {
|
||||
fn neg(quat) -> Quaternion<S> {
|
||||
Quaternion::from_sv(-quat.s, -quat.v)
|
||||
}
|
||||
});
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> Quaternion<S> { Quaternion::from_sv(-self.s, -self.v) }
|
||||
}
|
||||
|
||||
impl<'a, S: BaseFloat> Neg for &'a Quaternion<S> {
|
||||
type Output = Quaternion<S>;
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> Quaternion<S> { Quaternion::from_sv(-self.s, -self.v) }
|
||||
}
|
||||
|
||||
impl_binary_operator!(<S: BaseFloat> Mul<S> for Quaternion<S> {
|
||||
impl_operator!(<S: BaseFloat> Mul<S> for Quaternion<S> {
|
||||
fn mul(lhs, rhs) -> Quaternion<S> {
|
||||
Quaternion::from_sv(lhs.s * rhs, lhs.v * rhs)
|
||||
}
|
||||
});
|
||||
|
||||
impl_binary_operator!(<S: BaseFloat> Div<S> for Quaternion<S> {
|
||||
impl_operator!(<S: BaseFloat> Div<S> for Quaternion<S> {
|
||||
fn div(lhs, rhs) -> Quaternion<S> {
|
||||
Quaternion::from_sv(lhs.s / rhs, lhs.v / rhs)
|
||||
}
|
||||
});
|
||||
|
||||
impl_binary_operator!(<S: BaseFloat> Mul<Vector3<S> > for Quaternion<S> {
|
||||
impl_operator!(<S: BaseFloat> Mul<Vector3<S> > for Quaternion<S> {
|
||||
fn mul(lhs, rhs) -> Vector3<S> {{
|
||||
let rhs = rhs.clone();
|
||||
let two: S = cast(2i8).unwrap();
|
||||
|
@ -143,19 +135,19 @@ impl_binary_operator!(<S: BaseFloat> Mul<Vector3<S> > for Quaternion<S> {
|
|||
}}
|
||||
});
|
||||
|
||||
impl_binary_operator!(<S: BaseFloat> Add<Quaternion<S> > for Quaternion<S> {
|
||||
impl_operator!(<S: BaseFloat> Add<Quaternion<S> > for Quaternion<S> {
|
||||
fn add(lhs, rhs) -> Quaternion<S> {
|
||||
Quaternion::from_sv(lhs.s + rhs.s, lhs.v + rhs.v)
|
||||
}
|
||||
});
|
||||
|
||||
impl_binary_operator!(<S: BaseFloat> Sub<Quaternion<S> > for Quaternion<S> {
|
||||
impl_operator!(<S: BaseFloat> Sub<Quaternion<S> > for Quaternion<S> {
|
||||
fn sub(lhs, rhs) -> Quaternion<S> {
|
||||
Quaternion::from_sv(lhs.s - rhs.s, lhs.v - rhs.v)
|
||||
}
|
||||
});
|
||||
|
||||
impl_binary_operator!(<S: BaseFloat> Mul<Quaternion<S> > for Quaternion<S> {
|
||||
impl_operator!(<S: BaseFloat> Mul<Quaternion<S> > for Quaternion<S> {
|
||||
fn mul(lhs, rhs) -> Quaternion<S> {
|
||||
Quaternion::new(lhs.s * rhs.s - lhs.v.x * rhs.v.x - lhs.v.y * rhs.v.y - lhs.v.z * rhs.v.z,
|
||||
lhs.s * rhs.v.x + lhs.v.x * rhs.s + lhs.v.y * rhs.v.z - lhs.v.z * rhs.v.y,
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
use angle::{Angle, Rad};
|
||||
use approx::ApproxEq;
|
||||
use matrix::{Matrix, SquareMatrix};
|
||||
use matrix::SquareMatrix;
|
||||
use matrix::{Matrix2, Matrix3};
|
||||
use num::BaseFloat;
|
||||
use point::{Point, Point2, Point3};
|
||||
|
@ -150,7 +150,7 @@ pub trait Rotation3<S: BaseFloat>: Rotation<Point3<S>>
|
|||
///
|
||||
/// // This is exactly equivalent to using the raw matrix itself:
|
||||
/// let unit_y2: Matrix2<_> = rot.into();
|
||||
/// let unit_y2 = unit_y2.mul_v(unit_x);
|
||||
/// let unit_y2 = unit_y2 * unit_x;
|
||||
/// assert_eq!(unit_y2, unit_y);
|
||||
///
|
||||
/// // Note that we can also concatenate rotations:
|
||||
|
@ -190,13 +190,13 @@ impl<S: BaseFloat> Rotation<Point2<S>> for Basis2<S> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn rotate_vector(&self, vec: Vector2<S>) -> Vector2<S> { self.mat.mul_v(vec) }
|
||||
fn rotate_vector(&self, vec: Vector2<S>) -> Vector2<S> { self.mat * vec }
|
||||
|
||||
#[inline]
|
||||
fn concat(&self, other: &Basis2<S>) -> Basis2<S> { Basis2 { mat: self.mat.mul_m(&other.mat) } }
|
||||
fn concat(&self, other: &Basis2<S>) -> Basis2<S> { Basis2 { mat: self.mat * other.mat } }
|
||||
|
||||
#[inline]
|
||||
fn concat_self(&mut self, other: &Basis2<S>) { self.mat.mul_self_m(&other.mat); }
|
||||
fn concat_self(&mut self, other: &Basis2<S>) { self.mat = self.mat * other.mat; }
|
||||
|
||||
// TODO: we know the matrix is orthogonal, so this could be re-written
|
||||
// to be faster
|
||||
|
@ -274,13 +274,13 @@ impl<S: BaseFloat> Rotation<Point3<S>> for Basis3<S> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn rotate_vector(&self, vec: Vector3<S>) -> Vector3<S> { self.mat.mul_v(vec) }
|
||||
fn rotate_vector(&self, vec: Vector3<S>) -> Vector3<S> { self.mat * vec }
|
||||
|
||||
#[inline]
|
||||
fn concat(&self, other: &Basis3<S>) -> Basis3<S> { Basis3 { mat: self.mat.mul_m(&other.mat) } }
|
||||
fn concat(&self, other: &Basis3<S>) -> Basis3<S> { Basis3 { mat: self.mat * other.mat } }
|
||||
|
||||
#[inline]
|
||||
fn concat_self(&mut self, other: &Basis3<S>) { self.mat.mul_self_m(&other.mat); }
|
||||
fn concat_self(&mut self, other: &Basis3<S>) { self.mat = self.mat * other.mat; }
|
||||
|
||||
// TODO: we know the matrix is orthogonal, so this could be re-written
|
||||
// to be faster
|
||||
|
|
|
@ -189,17 +189,17 @@ impl<S: BaseFloat> Transform<Point3<S>> for AffineMatrix3<S> {
|
|||
|
||||
#[inline]
|
||||
fn transform_vector(&self, vec: Vector3<S>) -> Vector3<S> {
|
||||
self.mat.mul_v(vec.extend(S::zero())).truncate()
|
||||
(self.mat * vec.extend(S::zero())).truncate()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn transform_point(&self, point: Point3<S>) -> Point3<S> {
|
||||
Point3::from_homogeneous(self.mat.mul_v(point.to_homogeneous()))
|
||||
Point3::from_homogeneous(self.mat * point.to_homogeneous())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn concat(&self, other: &AffineMatrix3<S>) -> AffineMatrix3<S> {
|
||||
AffineMatrix3 { mat: self.mat.mul_m(&other.mat) }
|
||||
AffineMatrix3 { mat: self.mat * other.mat }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -212,38 +212,38 @@ macro_rules! impl_vector {
|
|||
}
|
||||
}
|
||||
|
||||
impl_binary_operator!(<S: BaseNum> Add<S> for $VectorN<S> {
|
||||
impl_operator!(<S: BaseNum> Add<S> for $VectorN<S> {
|
||||
fn add(vector, scalar) -> $VectorN<S> { $VectorN::new($(vector.$field + scalar),+) }
|
||||
});
|
||||
impl_binary_operator!(<S: BaseNum> Add<$VectorN<S> > for $VectorN<S> {
|
||||
impl_operator!(<S: BaseNum> Add<$VectorN<S> > for $VectorN<S> {
|
||||
fn add(lhs, rhs) -> $VectorN<S> { $VectorN::new($(lhs.$field + rhs.$field),+) }
|
||||
});
|
||||
|
||||
impl_binary_operator!(<S: BaseNum> Sub<S> for $VectorN<S> {
|
||||
impl_operator!(<S: BaseNum> Sub<S> for $VectorN<S> {
|
||||
fn sub(vector, scalar) -> $VectorN<S> { $VectorN::new($(vector.$field - scalar),+) }
|
||||
});
|
||||
impl_binary_operator!(<S: BaseNum> Sub<$VectorN<S> > for $VectorN<S> {
|
||||
impl_operator!(<S: BaseNum> Sub<$VectorN<S> > for $VectorN<S> {
|
||||
fn sub(lhs, rhs) -> $VectorN<S> { $VectorN::new($(lhs.$field - rhs.$field),+) }
|
||||
});
|
||||
|
||||
impl_binary_operator!(<S: BaseNum> Mul<S> for $VectorN<S> {
|
||||
impl_operator!(<S: BaseNum> Mul<S> for $VectorN<S> {
|
||||
fn mul(vector, scalar) -> $VectorN<S> { $VectorN::new($(vector.$field * scalar),+) }
|
||||
});
|
||||
impl_binary_operator!(<S: BaseNum> Mul<$VectorN<S> > for $VectorN<S> {
|
||||
impl_operator!(<S: BaseNum> Mul<$VectorN<S> > for $VectorN<S> {
|
||||
fn mul(lhs, rhs) -> $VectorN<S> { $VectorN::new($(lhs.$field * rhs.$field),+) }
|
||||
});
|
||||
|
||||
impl_binary_operator!(<S: BaseNum> Div<S> for $VectorN<S> {
|
||||
impl_operator!(<S: BaseNum> Div<S> for $VectorN<S> {
|
||||
fn div(vector, scalar) -> $VectorN<S> { $VectorN::new($(vector.$field / scalar),+) }
|
||||
});
|
||||
impl_binary_operator!(<S: BaseNum> Div<$VectorN<S> > for $VectorN<S> {
|
||||
impl_operator!(<S: BaseNum> Div<$VectorN<S> > for $VectorN<S> {
|
||||
fn div(lhs, rhs) -> $VectorN<S> { $VectorN::new($(lhs.$field / rhs.$field),+) }
|
||||
});
|
||||
|
||||
impl_binary_operator!(<S: BaseNum> Rem<S> for $VectorN<S> {
|
||||
impl_operator!(<S: BaseNum> Rem<S> for $VectorN<S> {
|
||||
fn rem(vector, scalar) -> $VectorN<S> { $VectorN::new($(vector.$field % scalar),+) }
|
||||
});
|
||||
impl_binary_operator!(<S: BaseNum> Rem<$VectorN<S> > for $VectorN<S> {
|
||||
impl_operator!(<S: BaseNum> Rem<$VectorN<S> > for $VectorN<S> {
|
||||
fn rem(lhs, rhs) -> $VectorN<S> { $VectorN::new($(lhs.$field % rhs.$field),+) }
|
||||
});
|
||||
|
||||
|
|
113
tests/matrix.rs
113
tests/matrix.rs
|
@ -78,16 +78,15 @@ pub mod matrix4 {
|
|||
|
||||
#[test]
|
||||
fn test_neg() {
|
||||
// Matrix2
|
||||
assert_eq!(-matrix2::A,
|
||||
Matrix2::new(-1.0f64, -3.0f64,
|
||||
-2.0f64, -4.0f64));
|
||||
// Matrix3
|
||||
|
||||
assert_eq!(-matrix3::A,
|
||||
Matrix3::new(-1.0f64, -4.0f64, -7.0f64,
|
||||
-2.0f64, -5.0f64, -8.0f64,
|
||||
-3.0f64, -6.0f64, -9.0f64));
|
||||
// Matrix4
|
||||
|
||||
assert_eq!(-matrix4::A,
|
||||
Matrix4::new(-1.0f64, -5.0f64, -9.0f64, -13.0f64,
|
||||
-2.0f64, -6.0f64, -10.0f64, -14.0f64,
|
||||
|
@ -96,126 +95,84 @@ fn test_neg() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_mul_s() {
|
||||
// Matrix2
|
||||
assert_eq!(matrix2::A.mul_s(matrix2::F),
|
||||
fn test_mul_scalar() {
|
||||
assert_eq!(matrix2::A * matrix2::F,
|
||||
Matrix2::new(0.5f64, 1.5f64,
|
||||
1.0f64, 2.0f64));
|
||||
let mut mut_a = matrix2::A;
|
||||
mut_a.mul_self_s(matrix2::F);
|
||||
assert_eq!(mut_a, matrix2::A.mul_s(matrix2::F));
|
||||
|
||||
// Matrix3
|
||||
assert_eq!(matrix3::A.mul_s(matrix3::F),
|
||||
assert_eq!(matrix3::A * matrix3::F,
|
||||
Matrix3::new(0.5f64, 2.0f64, 3.5f64,
|
||||
1.0f64, 2.5f64, 4.0f64,
|
||||
1.5f64, 3.0f64, 4.5f64));
|
||||
let mut mut_a = matrix3::A;
|
||||
mut_a.mul_self_s(matrix3::F);
|
||||
assert_eq!(mut_a, matrix3::A.mul_s(matrix3::F));
|
||||
|
||||
// Matrix4
|
||||
assert_eq!(matrix4::A.mul_s(matrix4::F),
|
||||
assert_eq!(matrix4::A * matrix4::F,
|
||||
Matrix4::new(0.5f64, 2.5f64, 4.5f64, 6.5f64,
|
||||
1.0f64, 3.0f64, 5.0f64, 7.0f64,
|
||||
1.5f64, 3.5f64, 5.5f64, 7.5f64,
|
||||
2.0f64, 4.0f64, 6.0f64, 8.0f64));
|
||||
let mut mut_a = matrix4::A;
|
||||
mut_a.mul_self_s(matrix4::F);
|
||||
assert_eq!(mut_a, matrix4::A.mul_s(matrix4::F));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_m() {
|
||||
// Matrix2
|
||||
assert_eq!(matrix2::A.add_m(&matrix2::B),
|
||||
fn test_add_matrix() {
|
||||
assert_eq!(matrix2::A + matrix2::B,
|
||||
Matrix2::new(3.0f64, 7.0f64,
|
||||
5.0f64, 9.0f64));
|
||||
let mut mut_a = matrix2::A;
|
||||
mut_a.add_self_m(&matrix2::B);
|
||||
assert_eq!(mut_a, matrix2::A.add_m(&matrix2::B));
|
||||
assert_eq!(mut_a, &matrix2::A + &matrix2::B);
|
||||
|
||||
// Matrix3
|
||||
assert_eq!(matrix3::A.add_m(&matrix3::B),
|
||||
assert_eq!(matrix3::A + matrix3::B,
|
||||
Matrix3::new(3.0f64, 9.0f64, 15.0f64,
|
||||
5.0f64, 11.0f64, 17.0f64,
|
||||
7.0f64, 13.0f64, 19.0f64));
|
||||
let mut mut_a = matrix3::A;
|
||||
mut_a.add_self_m(&matrix3::B);
|
||||
assert_eq!(mut_a, matrix3::A.add_m(&matrix3::B));
|
||||
assert_eq!(mut_a, &matrix3::A + &matrix3::B);
|
||||
|
||||
// Matrix4
|
||||
assert_eq!(matrix4::A.add_m(&matrix4::B),
|
||||
assert_eq!(matrix4::A + matrix4::B,
|
||||
Matrix4::new(3.0f64, 11.0f64, 19.0f64, 27.0f64,
|
||||
5.0f64, 13.0f64, 21.0f64, 29.0f64,
|
||||
7.0f64, 15.0f64, 23.0f64, 31.0f64,
|
||||
9.0f64, 17.0f64, 25.0f64, 33.0f64));
|
||||
let mut mut_a = matrix4::A;
|
||||
mut_a.add_self_m(&matrix4::B);
|
||||
assert_eq!(mut_a, matrix4::A.add_m(&matrix4::B));
|
||||
assert_eq!(mut_a, &matrix4::A + &matrix4::B);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sub_m() {
|
||||
// Matrix2
|
||||
assert_eq!(matrix2::A.sub_m(&matrix2::B),
|
||||
fn test_sub_matrix() {
|
||||
assert_eq!(matrix2::A - matrix2::B,
|
||||
Matrix2::new(-1.0f64, -1.0f64,
|
||||
-1.0f64, -1.0f64));
|
||||
let mut mut_a = matrix2::A;
|
||||
mut_a.sub_self_m(&matrix2::B);
|
||||
assert_eq!(mut_a, matrix2::A.sub_m(&matrix2::B));
|
||||
assert_eq!(matrix2::A.sub_m(&matrix2::B), &matrix2::A - &matrix2::B);
|
||||
|
||||
// Matrix3
|
||||
assert_eq!(matrix3::A.sub_m(&matrix3::B),
|
||||
assert_eq!(matrix3::A - matrix3::B,
|
||||
Matrix3::new(-1.0f64, -1.0f64, -1.0f64,
|
||||
-1.0f64, -1.0f64, -1.0f64,
|
||||
-1.0f64, -1.0f64, -1.0f64));
|
||||
let mut mut_a = matrix3::A;
|
||||
mut_a.sub_self_m(&matrix3::B);
|
||||
assert_eq!(mut_a, matrix3::A.sub_m(&matrix3::B));
|
||||
assert_eq!(matrix3::A.sub_m(&matrix3::B), &matrix3::A - &matrix3::B);
|
||||
|
||||
// Matrix4
|
||||
assert_eq!(matrix4::A.sub_m(&matrix4::B),
|
||||
assert_eq!(matrix4::A - matrix4::B,
|
||||
Matrix4::new(-1.0f64, -1.0f64, -1.0f64, -1.0f64,
|
||||
-1.0f64, -1.0f64, -1.0f64, -1.0f64,
|
||||
-1.0f64, -1.0f64, -1.0f64, -1.0f64,
|
||||
-1.0f64, -1.0f64, -1.0f64, -1.0f64));
|
||||
let mut mut_a = matrix4::A;
|
||||
mut_a.sub_self_m(&matrix4::B);
|
||||
assert_eq!(mut_a, matrix4::A.sub_m(&matrix4::B));
|
||||
assert_eq!(matrix4::A.sub_m(&matrix4::B), &matrix4::A - &matrix4::B);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mul_v() {
|
||||
assert_eq!(matrix2::A.mul_v(matrix2::V), Vector2::new(5.0f64, 11.0f64));
|
||||
assert_eq!(matrix3::A.mul_v(matrix3::V), Vector3::new(14.0f64, 32.0f64, 50.0f64));
|
||||
assert_eq!(matrix4::A.mul_v(matrix4::V), Vector4::new(30.0f64, 70.0f64, 110.0f64, 150.0f64));
|
||||
fn test_mul_vector() {
|
||||
assert_eq!(matrix2::A * matrix2::V, Vector2::new(5.0f64, 11.0f64));
|
||||
assert_eq!(matrix3::A * matrix3::V, Vector3::new(14.0f64, 32.0f64, 50.0f64));
|
||||
assert_eq!(matrix4::A * matrix4::V, Vector4::new(30.0f64, 70.0f64, 110.0f64, 150.0f64));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mul_m() {
|
||||
assert_eq!(matrix2::A.mul_m(&matrix2::B),
|
||||
fn test_mul_matrix() {
|
||||
assert_eq!(matrix2::A * matrix2::B,
|
||||
Matrix2::new(10.0f64, 22.0f64,
|
||||
13.0f64, 29.0f64));
|
||||
assert_eq!(matrix3::A.mul_m(&matrix3::B),
|
||||
assert_eq!(matrix3::A * matrix3::B,
|
||||
Matrix3::new(36.0f64, 81.0f64, 126.0f64,
|
||||
42.0f64, 96.0f64, 150.0f64,
|
||||
48.0f64, 111.0f64, 174.0f64));
|
||||
assert_eq!(matrix4::A.mul_m(&matrix4::B),
|
||||
assert_eq!(matrix4::A * matrix4::B,
|
||||
Matrix4::new(100.0f64, 228.0f64, 356.0f64, 484.0f64,
|
||||
110.0f64, 254.0f64, 398.0f64, 542.0f64,
|
||||
120.0f64, 280.0f64, 440.0f64, 600.0f64,
|
||||
130.0f64, 306.0f64, 482.0f64, 658.0f64));
|
||||
|
||||
assert_eq!(matrix2::A.mul_m(&matrix2::B), &matrix2::A * &matrix2::B);
|
||||
assert_eq!(matrix3::A.mul_m(&matrix3::B), &matrix3::A * &matrix3::B);
|
||||
assert_eq!(matrix4::A.mul_m(&matrix4::B), &matrix4::A * &matrix4::B);
|
||||
assert_eq!(matrix2::A * matrix2::B, &matrix2::A * &matrix2::B);
|
||||
assert_eq!(matrix3::A * matrix3::B, &matrix3::A * &matrix3::B);
|
||||
assert_eq!(matrix4::A * matrix4::B, &matrix4::A * &matrix4::B);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -292,11 +249,11 @@ fn test_invert() {
|
|||
// Matrix4
|
||||
assert!(Matrix4::<f64>::identity().invert().unwrap().is_identity());
|
||||
|
||||
assert!(matrix4::C.invert().unwrap().approx_eq(&
|
||||
assert!(matrix4::C.invert().unwrap().approx_eq(&(
|
||||
Matrix4::new( 5.0f64, -4.0f64, 1.0f64, 0.0f64,
|
||||
-4.0f64, 8.0f64, -4.0f64, 0.0f64,
|
||||
4.0f64, -8.0f64, 4.0f64, 8.0f64,
|
||||
-3.0f64, 4.0f64, 1.0f64, -8.0f64).mul_s(0.125f64)));
|
||||
-3.0f64, 4.0f64, 1.0f64, -8.0f64) * 0.125f64)));
|
||||
let mut mut_c = matrix4::C;
|
||||
mut_c.invert_self();
|
||||
assert_eq!(mut_c, matrix4::C.invert().unwrap());
|
||||
|
@ -305,32 +262,32 @@ fn test_invert() {
|
|||
-0., 0.631364f64, 0.775487f64, 0.0f64,
|
||||
-0.991261f64, 0.1023f64, -0.083287f64, 0.0f64,
|
||||
0., -1.262728f64, -1.550973f64, 1.0f64);
|
||||
assert!(mat_c.invert().unwrap().mul_m(&mat_c).is_identity());
|
||||
assert!((mat_c.invert().unwrap() * mat_c).is_identity());
|
||||
|
||||
let mat_d = Matrix4::new( 0.065455f64, -0.720002f64, 0.690879f64, 0.0f64,
|
||||
-0., 0.692364f64, 0.721549f64, 0.0f64,
|
||||
-0.997856f64, -0.047229f64, 0.045318f64, 0.0f64,
|
||||
0., -1.384727f64, -1.443098f64, 1.0f64);
|
||||
assert!(mat_d.invert().unwrap().mul_m(&mat_d).is_identity());
|
||||
assert!((mat_d.invert().unwrap() * mat_d).is_identity());
|
||||
|
||||
let mat_e = Matrix4::new( 0.409936f64, 0.683812f64, -0.603617f64, 0.0f64,
|
||||
0., 0.661778f64, 0.7497f64, 0.0f64,
|
||||
0.912114f64, -0.307329f64, 0.271286f64, 0.0f64,
|
||||
-0., -1.323555f64, -1.499401f64, 1.0f64);
|
||||
assert!(mat_e.invert().unwrap().mul_m(&mat_e).is_identity());
|
||||
assert!((mat_e.invert().unwrap() * mat_e).is_identity());
|
||||
|
||||
let mat_f = Matrix4::new(-0.160691f64, -0.772608f64, 0.614211f64, 0.0f64,
|
||||
-0., 0.622298f64, 0.78278f64, 0.0f64,
|
||||
-0.987005f64, 0.125786f64, -0.099998f64, 0.0f64,
|
||||
0., -1.244597f64, -1.565561f64, 1.0f64);
|
||||
assert!(mat_f.invert().unwrap().mul_m(&mat_f).is_identity());
|
||||
assert!((mat_f.invert().unwrap() * mat_f).is_identity());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_translation() {
|
||||
let mat = Matrix4::from_translation(Vector3::new(1.0f64, 2.0f64, 3.0f64));
|
||||
let vertex = Vector4::new(0.0f64, 0.0f64, 0.0f64, 1.0f64);
|
||||
let res = mat.mul_v(vertex);
|
||||
let res = mat * vertex;
|
||||
assert_eq!(res, Vector4::new(1., 2., 3., 1.));
|
||||
}
|
||||
|
||||
|
@ -398,13 +355,13 @@ fn test_predicates() {
|
|||
fn test_from_angle() {
|
||||
// Rotate the vector (1, 0) by π/2 radians to the vector (0, 1)
|
||||
let rot1 = Matrix2::from_angle(rad(0.5f64 * f64::consts::PI));
|
||||
assert!(rot1.mul_v(Vector2::unit_x()).approx_eq(&Vector2::unit_y()));
|
||||
assert!((rot1 * Vector2::unit_x()).approx_eq(&Vector2::unit_y()));
|
||||
|
||||
// Rotate the vector (-1, 0) by -π/2 radians to the vector (0, 1)
|
||||
let rot2 = -rot1;
|
||||
assert!(rot2.mul_v(-Vector2::unit_x()).approx_eq(&Vector2::unit_y()));
|
||||
assert!((rot2 * -Vector2::unit_x()).approx_eq(&Vector2::unit_y()));
|
||||
|
||||
// Rotate the vector (1, 1) by π radians to the vector (-1, -1)
|
||||
let rot3: Matrix2<f64> = Matrix2::from_angle(rad(f64::consts::PI));
|
||||
assert!(rot3.mul_v(Vector2::new(1.0, 1.0)).approx_eq(&Vector2::new(-1.0, -1.0)));
|
||||
assert!((rot3 * Vector2::new(1.0, 1.0)).approx_eq(&Vector2::new(-1.0, -1.0)));
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
extern crate cgmath;
|
||||
|
||||
use cgmath::{Vector4, ortho, Matrix, Matrix4};
|
||||
use cgmath::{Vector4, ortho, Matrix4};
|
||||
|
||||
#[test]
|
||||
fn test_ortho_scale() {
|
||||
|
@ -28,9 +28,9 @@ fn test_ortho_scale() {
|
|||
let vec_far: Vector4<f32> = Vector4::new(1., 1., 1., 1.);
|
||||
|
||||
let o: Matrix4<f32> = ortho(-1., 1., -1., 1., -1., 1.);
|
||||
let near = o.mul_v(vec_near);
|
||||
let orig = o.mul_v(vec_orig);
|
||||
let far = o.mul_v(vec_far);
|
||||
let near = o * vec_near;
|
||||
let orig = o * vec_orig;
|
||||
let far = o * vec_far;
|
||||
|
||||
assert_eq!(near, Vector4::new(-1f32, -1., 1., 1.));
|
||||
assert_eq!(orig, Vector4::new(0f32, 0., 0., 1.));
|
||||
|
@ -38,9 +38,9 @@ fn test_ortho_scale() {
|
|||
|
||||
|
||||
let o: Matrix4<f32> = ortho(-2., 2., -2., 2., -2., 2.);
|
||||
let near = o.mul_v(vec_near);
|
||||
let orig = o.mul_v(vec_orig);
|
||||
let far = o.mul_v(vec_far);
|
||||
let near = o * vec_near;
|
||||
let orig = o * vec_orig;
|
||||
let far = o * vec_far;
|
||||
|
||||
assert_eq!(near, Vector4::new(-0.5f32, -0.5, 0.5, 1.));
|
||||
assert_eq!(orig, Vector4::new(0f32, 0., 0., 1.));
|
||||
|
@ -56,14 +56,14 @@ fn test_ortho_translate() {
|
|||
let vec_orig: Vector4<f32> = Vector4::new(0., 0., 0., 1.);
|
||||
|
||||
let o: Matrix4<f32> = ortho(-1., 1., -1., 1., -1., 1.);
|
||||
let orig = o.mul_v(vec_orig);
|
||||
let orig = o * vec_orig;
|
||||
assert_eq!(orig, Vector4::new(0., 0., 0., 1.));
|
||||
|
||||
let o: Matrix4<f32> = ortho(0., 2., 0., 2., 0., 2.);
|
||||
let orig = o.mul_v(vec_orig);
|
||||
let orig = o * vec_orig;
|
||||
assert_eq!(orig, Vector4::new(-1., -1., -1., 1.));
|
||||
|
||||
let o: Matrix4<f32> = ortho(-2., 0., -2., 0., -2., 0.);
|
||||
let orig = o.mul_v(vec_orig);
|
||||
let orig = o * vec_orig;
|
||||
assert_eq!(orig, Vector4::new(1., 1., 1., 1.));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue