Simplify type signatures and make function implementations more strait-forward

This results in more code duplication, but the resulting type signatures are much simpler and the implementations are far easier to understand. It should be easier for llvm to optimise things too, seeing as closures are not used.
This commit is contained in:
Brendan Zabarauskas 2014-05-27 18:59:03 -07:00
parent 07006afeac
commit 3559ab2e35
14 changed files with 1057 additions and 562 deletions

View file

@ -22,19 +22,11 @@
use point::{Point, Point2, Point3}; use point::{Point, Point2, Point3};
use vector::{Vector, Vector2, Vector3}; use vector::{Vector, Vector2, Vector3};
use array::build;
use num::BaseNum; use num::BaseNum;
use std::fmt; use std::fmt;
use std::num::{zero, one}; use std::num::{zero, one};
use std::iter::Iterator;
pub trait Aabb pub trait Aabb<S: BaseNum, V: Vector<S>, P: Point<S, V>> {
<
S: BaseNum,
V: Vector<S, Slice>,
P: Point<S, V, Slice>,
Slice
> {
/// Create a new AABB using two points as opposing corners. /// Create a new AABB using two points as opposing corners.
fn new(p1: P, p2: P) -> Self; fn new(p1: P, p2: P) -> Self;
@ -45,28 +37,29 @@ pub trait Aabb
fn max<'a>(&'a self) -> &'a P; fn max<'a>(&'a self) -> &'a P;
/// Return the dimensions of this AABB. /// Return the dimensions of this AABB.
#[inline] fn dim(&self) -> V { self.max().sub_p(self.min()) } #[inline]
fn dim(&self) -> V { self.max().sub_p(self.min()) }
/// Return the volume this AABB encloses. /// Return the volume this AABB encloses.
#[inline] fn volume(&self) -> S { self.dim().comp_mul() } #[inline]
fn volume(&self) -> S { self.dim().comp_mul() }
/// Return the center point of this AABB. /// Return the center point of this AABB.
#[inline] fn center(&self) -> P { #[inline]
fn center(&self) -> P {
let two = one::<S>() + one::<S>(); let two = one::<S>() + one::<S>();
self.min().add_v(&self.dim().div_s(two)) self.min().add_v(&self.dim().div_s(two))
} }
/// Tests whether a point is cointained in the box, inclusive for min corner /// Tests whether a point is cointained in the box, inclusive for min corner
/// and exclusive for the max corner. /// and exclusive for the max corner.
#[inline] fn contains(&self, p: &P) -> bool { #[inline]
p.sub_p(self.min()).iter().all(|x| *x >= zero::<S>()) && fn contains(&self, p: &P) -> bool;
self.max().sub_p(p).iter().all(|x| *x > zero::<S>())
}
/// Returns a new AABB that is grown to include the given point. /// Returns a new AABB that is grown to include the given point.
fn grow(&self, p: &P) -> Self { fn grow(&self, p: &P) -> Self {
let min : P = build(|i| self.min().i(i).partial_min(*p.i(i))); let min = self.min().min(p);
let max : P = build(|i| self.max().i(i).partial_max(*p.i(i))); let max = self.max().max(p);
Aabb::new(min, max) Aabb::new(min, max)
} }
@ -108,10 +101,23 @@ impl<S: BaseNum> Aabb2<S> {
} }
} }
impl<S: BaseNum> Aabb<S, Vector2<S>, Point2<S>, [S, ..2]> for Aabb2<S> { impl<S: BaseNum> Aabb<S, Vector2<S>, Point2<S>> for Aabb2<S> {
#[inline]
fn new(p1: Point2<S>, p2: Point2<S>) -> Aabb2<S> { Aabb2::new(p1, p2) } fn new(p1: Point2<S>, p2: Point2<S>) -> Aabb2<S> { Aabb2::new(p1, p2) }
#[inline] fn min<'a>(&'a self) -> &'a Point2<S> { &self.min }
#[inline] fn max<'a>(&'a self) -> &'a Point2<S> { &self.max } #[inline]
fn min<'a>(&'a self) -> &'a Point2<S> { &self.min }
#[inline]
fn max<'a>(&'a self) -> &'a Point2<S> { &self.max }
#[inline]
fn contains(&self, p: &Point2<S>) -> bool {
let v_min = p.sub_p(self.min());
let v_max = self.max().sub_p(p);
v_min.x >= zero() && v_min.y >= zero() &&
v_max.x > zero() && v_max.y > zero()
}
} }
impl<S: BaseNum> fmt::Show for Aabb2<S> { impl<S: BaseNum> fmt::Show for Aabb2<S> {
@ -142,10 +148,23 @@ impl<S: BaseNum> Aabb3<S> {
} }
} }
impl<S: BaseNum> Aabb<S, Vector3<S>, Point3<S>, [S, ..3]> for Aabb3<S> { impl<S: BaseNum> Aabb<S, Vector3<S>, Point3<S>> for Aabb3<S> {
#[inline]
fn new(p1: Point3<S>, p2: Point3<S>) -> Aabb3<S> { Aabb3::new(p1, p2) } fn new(p1: Point3<S>, p2: Point3<S>) -> Aabb3<S> { Aabb3::new(p1, p2) }
#[inline] fn min<'a>(&'a self) -> &'a Point3<S> { &self.min }
#[inline] fn max<'a>(&'a self) -> &'a Point3<S> { &self.max } #[inline]
fn min<'a>(&'a self) -> &'a Point3<S> { &self.min }
#[inline]
fn max<'a>(&'a self) -> &'a Point3<S> { &self.max }
#[inline]
fn contains(&self, p: &Point3<S>) -> bool {
let v_min = p.sub_p(self.min());
let v_max = self.max().sub_p(p);
v_min.x >= zero() && v_min.y >= zero() && v_min.z >= zero() &&
v_max.x > zero() && v_max.y > zero() && v_max.z > zero()
}
} }
impl<S: BaseNum> fmt::Show for Aabb3<S> { impl<S: BaseNum> fmt::Show for Aabb3<S> {

View file

@ -15,12 +15,6 @@
use std::num; use std::num;
use array::Array;
use matrix::{Matrix2, Matrix3, Matrix4};
use point::{Point2, Point3};
use quaternion::Quaternion;
use vector::{Vector2, Vector3, Vector4};
pub trait ApproxEq<T: Float> { pub trait ApproxEq<T: Float> {
fn approx_epsilon(_hack: Option<Self>) -> T { fn approx_epsilon(_hack: Option<Self>) -> T {
num::cast(1.0e-5).unwrap() num::cast(1.0e-5).unwrap()
@ -35,7 +29,7 @@ pub trait ApproxEq<T: Float> {
} }
macro_rules! approx_simple( macro_rules! approx_float(
($S:ident) => ( ($S:ident) => (
impl ApproxEq<$S> for $S { impl ApproxEq<$S> for $S {
#[inline] #[inline]
@ -46,31 +40,5 @@ macro_rules! approx_simple(
) )
) )
approx_simple!(f32) approx_float!(f32)
approx_simple!(f64) approx_float!(f64)
macro_rules! approx_array(
(impl<$S:ident> $Self:ty) => (
impl<$S: Float + Clone + ApproxEq<$S>> ApproxEq<$S> for $Self {
#[inline]
fn approx_eq_eps(&self, other: &$Self, epsilon: &$S) -> bool {
self.iter().zip(other.iter())
.all(|(a, b)| a.approx_eq_eps(b, epsilon))
}
}
)
)
approx_array!(impl<S> Matrix2<S>)
approx_array!(impl<S> Matrix3<S>)
approx_array!(impl<S> Matrix4<S>)
approx_array!(impl<S> Quaternion<S>)
approx_array!(impl<S> Vector2<S>)
approx_array!(impl<S> Vector3<S>)
approx_array!(impl<S> Vector4<S>)
approx_array!(impl<S> Point2<S>)
approx_array!(impl<S> Point3<S>)

View file

@ -13,138 +13,84 @@
// 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.
#![macro_escape] use std::mem;
use std::ptr;
use std::slice::{Items, MutItems}; /// An array containing elements of type `Element`
pub trait Array1<Element: Copy> {
/// Get the pointer to the first element of the array.
fn ptr<'a>(&'a self) -> &'a Element;
/// Get a mutable pointer to the first element of the array.
fn mut_ptr<'a>(&'a mut self) -> &'a mut Element;
/// An array containing elements of type `T` represented with `Repr`
///
/// This trait abstracts over [T, ..N], and is manually implemented for arrays
/// of length 2, 3, and 4.
pub trait Array<T: Clone, Repr> {
/// Get a shared reference to the `i`th value. /// Get a shared reference to the `i`th value.
fn i<'a>(&'a self, i: uint) -> &'a T; fn i(&self, i: uint) -> Element;
/// Get a mutable reference to the `i`th value. /// Get a mutable reference to the `i`th value.
fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut T; fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut Element;
/// Get a shared reference to this array's data as `Repr`.
fn as_slice<'a>(&'a self) -> &'a Repr;
/// Get a mutable reference to this array's data as `Repr`.
fn as_mut_slice<'a>(&'a mut self) -> &'a mut Repr;
/// Construct a new Array from its representation.
fn from_repr(repr: Repr) -> Self;
/// Create a new `Array` using a closure to generate the elements. The
/// closure is passed the index of the element it should produce.
fn build(builder: |i: uint| -> T) -> Self;
/// Iterate over the elements of this `Array`, yielding shared references
/// to items.
fn iter<'a>(&'a self) -> Items<'a, T>;
/// Iterate over the elements of this `Array`, yielding mutable references
/// to items.
fn mut_iter<'a>(&'a mut self) -> MutItems<'a, T>;
#[inline] #[inline]
/// Swap the elements at indices `a` and `b` in-place. /// Swap the elements at indices `a` and `b` in-place.
fn swap(&mut self, a: uint, b: uint) { fn swap_i(&mut self, a: uint, b: uint) {
let tmp = self.i(a).clone(); // Yeah, ok borrow checker I know what I'm doing here
*self.mut_i(a) = self.i(b).clone(); unsafe { ptr::swap(self.mut_i(a), self.mut_i(b)) };
*self.mut_i(b) = tmp;
} }
/// Fold over this array, creating the same type as the type of the /// Replace an element in the array.
/// elements. Use `.iter().fold(...)` for a more flexible fold. The first #[inline]
/// element passed to the fold is the accumulator. It starts as the first fn replace_i(&mut self, i: uint, src: Element) -> Element {
/// value in the array. mem::replace(self.mut_i(i), src)
fn fold(&self, f: |&T, &T| -> T) -> T; }
/// Iterate over this array, yielding mutable references to items. The
/// closure is passed the index of the element the reference is pointing
/// at.
fn each_mut(&mut self, f: |i: uint, x: &mut T|);
} }
macro_rules! array( /// A column-major array
(impl<$S:ident> $Self:ty -> [$T:ty, ..$n:expr] $_n:ident) => ( pub trait Array2<Column: Array1<Element>, Row: Array1<Element>, Element: Copy> {
impl<$S: Clone> Array<$T, [$T,..$n]> for $Self { /// Get the pointer to the first element of the array.
#[inline] fn ptr<'a>(&'a self) -> &'a Element;
fn i<'a>(&'a self, i: uint) -> &'a $T {
&'a self.as_slice()[i]
}
#[inline] /// Get a mutable pointer to the first element of the array.
fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut $T { fn mut_ptr<'a>(&'a mut self) -> &'a mut Element;
&'a mut self.as_mut_slice()[i]
}
#[inline] /// Get a shared reference to a column of this array.
fn as_slice<'a>(&'a self) -> &'a [$T,..$n] { fn c<'a>(&'a self, c: uint) -> &'a Column;
unsafe { ::std::mem::transmute(self) }
}
#[inline] /// Get a mutable reference to a column of this array.
fn as_mut_slice<'a>(&'a mut self) -> &'a mut [$T,..$n] { fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut Column;
unsafe { ::std::mem::transmute(self) }
}
#[inline] /// Swap two columns of this array.
fn from_repr(slice: [$T,..$n]) -> $Self { #[inline]
unsafe { ::std::mem::transmute(slice) } fn swap_c(&mut self, a: uint, b: uint) {
} unsafe { ptr::swap(self.mut_c(a), self.mut_c(b)) };
}
#[inline] /// Replace a column in the array.
fn build(builder: |i: uint| -> $T) -> $Self { #[inline]
Array::from_repr(gen_builder!($_n)) fn replace_c(&mut self, c: uint, src: Column) -> Column {
} mem::replace(self.mut_c(c), src)
}
#[inline] /// Get a row from this array by-value.
fn iter<'a>(&'a self) -> ::std::slice::Items<'a, $T> { fn r(&self, r: uint) -> Row;
self.as_slice().iter()
}
#[inline] /// Swap two rows of this array.
fn mut_iter<'a>(&'a mut self) -> ::std::slice::MutItems<'a, $T> { fn swap_r(&mut self, a: uint, b: uint);
self.as_mut_slice().mut_iter()
}
#[inline] /// Return a shared reference to the element at column `c` and row `r`.
fn fold(&self, f: |&$T, &$T| -> $T) -> $T { #[inline]
gen_fold!($_n) fn cr(&self, c: uint, r: uint) -> Element { self.c(c).i(r) }
}
#[inline] /// Return a mutable reference to the element at column `c` and row `r`.
fn each_mut(&mut self, f: |i: uint, x: &mut $T|) { #[inline]
gen_each_mut!($_n) fn mut_cr<'a>(&'a mut self, c: uint, r: uint) -> &'a mut Element {
} self.mut_c(c).mut_i(r)
} }
)
)
#[inline] /// Swap the values at index `a` and `b`
pub fn build<T: Clone, Slice, A: Array<T, Slice>>(builder: |i: uint| -> T) -> A { #[inline]
Array::build(builder) fn swap_cr(&mut self, a: (uint, uint), b: (uint, uint)) {
let (ac, ar) = a;
let (bc, br) = b;
unsafe { ptr::swap(self.mut_cr(ac, ar), self.mut_cr(bc, br)) };
}
} }
macro_rules! gen_builder(
(_2) => ({ [builder(0), builder(1)] });
(_3) => ({ [builder(0), builder(1), builder(2)] });
(_4) => ({ [builder(0), builder(1), builder(2), builder(3)] });
)
macro_rules! gen_fold(
(_2) => ({ f(self.i(0), self.i(1)) });
(_3) => ({ let tmp = f(self.i(0), self.i(1)); f(&tmp, self.i(2)) });
(_4) => ({ let tmp1 = f(self.i(0), self.i(1)); let tmp2 = f(&tmp1, self.i(2)); f(&tmp2, self.i(3)) });
)
macro_rules! gen_each_mut(
(_2) => ({ f(0, self.mut_i(0)); f(1, self.mut_i(1)); });
(_3) => ({ f(0, self.mut_i(0)); f(1, self.mut_i(1)); f(2, self.mut_i(2)); });
(_4) => ({ f(0, self.mut_i(0)); f(1, self.mut_i(1)); f(2, self.mut_i(2)); f(3, self.mut_i(3)); });
)

View file

@ -15,7 +15,8 @@
//! View frustum for visibility determination //! View frustum for visibility determination
use matrix::{Matrix, Matrix4}; use array::Array2;
use matrix::Matrix4;
use num::BaseFloat; use num::BaseFloat;
use plane::Plane; use plane::Plane;
use point::Point3; use point::Point3;

View file

@ -36,8 +36,6 @@
//! `look_at`, `from_angle`, `from_euler`, and `from_axis_angle` methods. //! `look_at`, `from_angle`, `from_euler`, and `from_axis_angle` methods.
//! These are provided for convenience. //! These are provided for convenience.
pub use array::Array;
mod array; mod array;
pub mod matrix; pub mod matrix;
@ -63,5 +61,3 @@ pub mod sphere;
pub mod approx; pub mod approx;
pub mod num; pub mod num;
pub mod ptr;

View file

@ -24,20 +24,12 @@ use intersect::Intersect;
/// A generic directed line segment from `origin` to `dest`. /// A generic directed line segment from `origin` to `dest`.
#[deriving(Clone, Eq)] #[deriving(Clone, Eq)]
pub struct Line<P> pub struct Line<P> {
{
pub origin: P, pub origin: P,
pub dest: P, pub dest: P,
} }
impl impl<S: BaseNum, V: Vector<S>, P: Point<S, V>> Line<P> {
<
S: BaseNum,
Slice,
V: Vector<S,Slice>,
P: Point<S,V,Slice>
> Line<P>
{
pub fn new(origin: P, dest: P) -> Line<P> { pub fn new(origin: P, dest: P) -> Line<P> {
Line { origin:origin, dest:dest } Line { origin:origin, dest:dest }
} }

View file

@ -16,11 +16,12 @@
//! Column major, square matrix types and traits. //! Column major, square matrix types and traits.
use std::fmt; use std::fmt;
use std::mem;
use std::num::{Zero, zero, One, one, cast}; use std::num::{Zero, zero, One, one, cast};
use angle::{Rad, sin, cos, sin_cos}; use angle::{Rad, sin, cos, sin_cos};
use approx::ApproxEq; use approx::ApproxEq;
use array::{Array, build}; use array::{Array1, Array2};
use num::{BaseFloat, BaseNum}; use num::{BaseFloat, BaseNum};
use point::{Point, Point3}; use point::{Point, Point3};
use quaternion::{Quaternion, ToQuaternion}; use quaternion::{Quaternion, ToQuaternion};
@ -267,107 +268,47 @@ Matrix4<S> {
} }
} }
array!(impl<S> Matrix2<S> -> [Vector2<S>, ..2] _2) pub trait Matrix<S: BaseFloat, V: Clone + Vector<S>>: Array2<V, V, S>
array!(impl<S> Matrix3<S> -> [Vector3<S>, ..3] _3) + Neg<Self>
array!(impl<S> Matrix4<S> -> [Vector4<S>, ..4] _4) + Zero + One
+ ApproxEq<S> {
pub trait Matrix
<
S: BaseFloat, Slice,
V: Clone + Vector<S, VSlice> + Array<S, VSlice>, VSlice
>
: Array<V, Slice>
+ Neg<Self>
+ Zero + One
+ ApproxEq<S>
{
/// Get a shared reference to a column of this matrix.
#[inline]
fn c<'a>(&'a self, c: uint) -> &'a V { self.i(c) }
/// Get a mutable reference to a column of this matrix.
#[inline]
fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut V { self.mut_i(c) }
/// Swap two columns of this matrix.
#[inline]
fn swap_c(&mut self, a: uint, b: uint) {
let tmp = self.c(a).clone();
*self.mut_c(a) = self.c(b).clone();
*self.mut_c(b) = tmp;
}
/// Get a row from this matrix.
///
/// Since matrixes in cgmath are stored column-major, this cannot return a
/// reference. It creates a new copy of the row instead.
#[inline]
fn r(&self, r: uint) -> V {
build(|i| self.i(i).i(r).clone())
}
/// Swap two rows of this matrix.
#[inline]
fn swap_r(&mut self, a: uint, b: uint) {
self.each_mut(|_, c| c.swap(a, b))
}
/// Return a shared reference to the element at column `c` and row `r`.
#[inline]
fn cr<'a>(&'a self, c: uint, r: uint) -> &'a S { self.i(c).i(r) }
/// Return a mutable reference to the element at column `c` and row `r`.
#[inline]
fn mut_cr<'a>(&'a mut self, c: uint, r: uint) -> &'a mut S {
self.mut_i(c).mut_i(r)
}
/// Swap the values at index `a` and `b`
#[inline]
fn swap_cr(&mut self, a: (uint, uint), b: (uint, uint)) {
let (ca, ra) = a;
let (cb, rb) = b;
let tmp = self.cr(ca, ra).clone();
*self.mut_cr(ca, ra) = self.cr(cb, rb).clone();
*self.mut_cr(cb, rb) = tmp;
}
/// Negate this matrix in-place (multiply by scalar -1).
#[inline] fn neg_self(&mut self) { self.each_mut(|_, x| *x = x.neg()) }
/// Multiply this matrix by a scalar, returning the new matrix. /// Multiply this matrix by a scalar, returning the new matrix.
#[inline] fn mul_s(&self, s: S) -> Self { build(|i| self.c(i).mul_s(s.clone())) } fn mul_s(&self, s: S) -> Self;
/// Divide this matrix by a scalar, returning the new matrix. /// Divide this matrix by a scalar, returning the new matrix.
#[inline] fn div_s(&self, s: S) -> Self { build(|i| self.c(i).div_s(s.clone())) } fn div_s(&self, s: S) -> Self;
/// Take the remainder of this matrix by a scalar, returning the new /// Take the remainder of this matrix by a scalar, returning the new
/// matrix. /// matrix.
#[inline] fn rem_s(&self, s: S) -> Self { build(|i| self.c(i).rem_s(s.clone())) } fn rem_s(&self, s: S) -> Self;
/// Add this matrix with another matrix, returning the new metrix. /// Add this matrix with another matrix, returning the new metrix.
#[inline] fn add_m(&self, other: &Self) -> Self { build(|i| self.i(i).add_v(other.i(i))) } 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.
#[inline] fn sub_m(&self, other: &Self) -> Self { build(|i| self.i(i).sub_v(other.i(i))) } fn sub_m(&self, m: &Self) -> Self;
/// Multiplay a vector by this matrix, returning a new vector. /// Multiplay a vector by this matrix, returning a new vector.
#[inline] fn mul_v(&self, v: &V) -> V { build(|i| self.r(i).dot(v)) } fn mul_v(&self, v: &V) -> V;
/// Multiply this matrix by another matrix, returning the new matrix. /// Multiply this matrix by another matrix, returning the new matrix.
fn mul_m(&self, other: &Self) -> Self; fn mul_m(&self, m: &Self) -> Self;
/// Negate this matrix in-place (multiply by scalar -1).
fn neg_self(&mut self);
/// Multiply this matrix by a scalar, in-place. /// Multiply this matrix by a scalar, in-place.
#[inline] fn mul_self_s(&mut self, s: S) { self.each_mut(|_, c| *c = c.mul_s(s.clone())) } fn mul_self_s(&mut self, s: S);
/// Divide this matrix by a scalar, in-place. /// Divide this matrix by a scalar, in-place.
#[inline] fn div_self_s(&mut self, s: S) { self.each_mut(|_, c| *c = c.div_s(s.clone())) } fn div_self_s(&mut self, s: S);
/// Take the remainder of this matrix, in-place. /// Take the remainder of this matrix, in-place.
#[inline] fn rem_self_s(&mut self, s: S) { self.each_mut(|_, c| *c = c.rem_s(s.clone())) } fn rem_self_s(&mut self, s: S);
/// Add this matrix with another matrix, in-place. /// Add this matrix with another matrix, in-place.
#[inline] fn add_self_m(&mut self, other: &Self) { self.each_mut(|i, c| *c = c.add_v(other.c(i))) } fn add_self_m(&mut self, m: &Self);
/// Subtract another matrix from this matrix, in-place. /// Subtract another matrix from this matrix, in-place.
#[inline] fn sub_self_m(&mut self, other: &Self) { self.each_mut(|i, c| *c = c.sub_v(other.c(i))) } 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, other: &Self) { *self = self.mul_m(other); } #[inline]
fn mul_self_m(&mut self, m: &Self) { *self = self.mul_m(m); }
/// Transpose this matrix, returning a new matrix. /// Transpose this matrix, returning a new matrix.
fn transpose(&self) -> Self; fn transpose(&self) -> Self;
@ -377,8 +318,7 @@ pub trait Matrix
fn determinant(&self) -> S; fn determinant(&self) -> S;
/// Return a vector containing the diagonal of this matrix. /// Return a vector containing the diagonal of this matrix.
#[inline] fn diagonal(&self) -> V;
fn diagonal(&self) -> V { build(|i| self.cr(i, i).clone()) }
/// Return the trace of this matrix. That is, the sum of the diagonal. /// Return the trace of this matrix. That is, the sum of the diagonal.
#[inline] #[inline]
@ -397,16 +337,12 @@ pub trait Matrix
/// Test if this matrix is invertible. /// Test if this matrix is invertible.
#[inline] #[inline]
fn is_invertible(&self) -> bool { fn is_invertible(&self) -> bool { !self.determinant().approx_eq(&zero()) }
!self.determinant().approx_eq(&zero())
}
/// Test if this matrix is the identity matrix. That is, it is diagonal /// Test if this matrix is the identity matrix. That is, it is diagonal
/// and every element in the diagonal is one. /// and every element in the diagonal is one.
#[inline] #[inline]
fn is_identity(&self) -> bool { fn is_identity(&self) -> bool { self.approx_eq(&one()) }
self.approx_eq(&one())
}
/// Test if this is a diagonal matrix. That is, every element outside of /// Test if this is a diagonal matrix. That is, every element outside of
/// the diagonal is 0. /// the diagonal is 0.
@ -425,9 +361,9 @@ impl<S: BaseFloat> Sub<Matrix2<S>, Matrix2<S>> for Matrix2<S> { #[inline] fn sub
impl<S: BaseFloat> Sub<Matrix3<S>, Matrix3<S>> for Matrix3<S> { #[inline] fn sub(&self, other: &Matrix3<S>) -> Matrix3<S> { self.sub_m(other) } } impl<S: BaseFloat> Sub<Matrix3<S>, Matrix3<S>> for Matrix3<S> { #[inline] fn sub(&self, other: &Matrix3<S>) -> Matrix3<S> { self.sub_m(other) } }
impl<S: BaseFloat> Sub<Matrix4<S>, Matrix4<S>> for Matrix4<S> { #[inline] fn sub(&self, other: &Matrix4<S>) -> Matrix4<S> { self.sub_m(other) } } impl<S: BaseFloat> Sub<Matrix4<S>, Matrix4<S>> for Matrix4<S> { #[inline] fn sub(&self, other: &Matrix4<S>) -> Matrix4<S> { self.sub_m(other) } }
impl<S: BaseFloat> Neg<Matrix2<S>> for Matrix2<S> { #[inline] fn neg(&self) -> Matrix2<S> { build(|i| self.i(i).neg()) } } impl<S: BaseFloat> Neg<Matrix2<S>> for Matrix2<S> { #[inline] fn neg(&self) -> Matrix2<S> { Matrix2::from_cols(self.c(0).neg(), self.c(1).neg()) } }
impl<S: BaseFloat> Neg<Matrix3<S>> for Matrix3<S> { #[inline] fn neg(&self) -> Matrix3<S> { build(|i| self.i(i).neg()) } } impl<S: BaseFloat> Neg<Matrix3<S>> for Matrix3<S> { #[inline] fn neg(&self) -> Matrix3<S> { Matrix3::from_cols(self.c(0).neg(), self.c(1).neg(), self.c(2).neg()) } }
impl<S: BaseFloat> Neg<Matrix4<S>> for Matrix4<S> { #[inline] fn neg(&self) -> Matrix4<S> { build(|i| self.i(i).neg()) } } impl<S: BaseFloat> Neg<Matrix4<S>> for Matrix4<S> { #[inline] fn neg(&self) -> Matrix4<S> { Matrix4::from_cols(self.c(0).neg(), self.c(1).neg(), self.c(2).neg(), self.c(3).neg()) } }
impl<S: BaseFloat> Zero for Matrix2<S> { #[inline] fn zero() -> Matrix2<S> { Matrix2::zero() } #[inline] fn is_zero(&self) -> bool { *self == zero() } } impl<S: BaseFloat> Zero for Matrix2<S> { #[inline] fn zero() -> Matrix2<S> { Matrix2::zero() } #[inline] fn is_zero(&self) -> bool { *self == zero() } }
impl<S: BaseFloat> Zero for Matrix3<S> { #[inline] fn zero() -> Matrix3<S> { Matrix3::zero() } #[inline] fn is_zero(&self) -> bool { *self == zero() } } impl<S: BaseFloat> Zero for Matrix3<S> { #[inline] fn zero() -> Matrix3<S> { Matrix3::zero() } #[inline] fn is_zero(&self) -> bool { *self == zero() } }
@ -441,15 +377,186 @@ impl<S: BaseFloat> One for Matrix2<S> { #[inline] fn one() -> Matrix2<S> { Matri
impl<S: BaseFloat> One for Matrix3<S> { #[inline] fn one() -> Matrix3<S> { Matrix3::identity() } } impl<S: BaseFloat> One for Matrix3<S> { #[inline] fn one() -> Matrix3<S> { Matrix3::identity() } }
impl<S: BaseFloat> One for Matrix4<S> { #[inline] fn one() -> Matrix4<S> { Matrix4::identity() } } impl<S: BaseFloat> One for Matrix4<S> { #[inline] fn one() -> Matrix4<S> { Matrix4::identity() } }
impl<S: BaseFloat> impl<S: Copy> Array2<Vector2<S>, Vector2<S>, S> for Matrix2<S> {
Matrix<S, [Vector2<S>, ..2], Vector2<S>, [S, ..2]> #[inline]
for Matrix2<S> fn ptr<'a>(&'a self) -> &'a S { &self.x.x }
{
#[inline]
fn mut_ptr<'a>(&'a mut self) -> &'a mut S { &mut self.x.x }
#[inline]
fn c<'a>(&'a self, c: uint) -> &'a Vector2<S> {
let slice: &'a [Vector2<S>, ..2] = unsafe { mem::transmute(self) };
&'a slice[c]
}
#[inline]
fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut Vector2<S> {
let slice: &'a mut [Vector2<S>, ..2] = unsafe { mem::transmute(self) };
&'a mut slice[c]
}
#[inline]
fn r(&self, r: uint) -> Vector2<S> {
Vector2::new(self.cr(0, r),
self.cr(1, r))
}
#[inline]
fn swap_r(&mut self, a: uint, b: uint) {
self.mut_c(0).swap_i(a, b);
self.mut_c(1).swap_i(a, b);
}
}
impl<S: Copy> Array2<Vector3<S>, Vector3<S>, S> for Matrix3<S> {
#[inline]
fn ptr<'a>(&'a self) -> &'a S { &self.x.x }
#[inline]
fn mut_ptr<'a>(&'a mut self) -> &'a mut S { &mut self.x.x }
#[inline]
fn c<'a>(&'a self, c: uint) -> &'a Vector3<S> {
let slice: &'a [Vector3<S>, ..3] = unsafe { mem::transmute(self) };
&'a slice[c]
}
#[inline]
fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut Vector3<S> {
let slice: &'a mut [Vector3<S>, ..3] = unsafe { mem::transmute(self) };
&'a mut slice[c]
}
#[inline]
fn r(&self, r: uint) -> Vector3<S> {
Vector3::new(self.cr(0, r),
self.cr(1, r),
self.cr(2, r))
}
#[inline]
fn swap_r(&mut self, a: uint, b: uint) {
self.mut_c(0).swap_i(a, b);
self.mut_c(1).swap_i(a, b);
self.mut_c(2).swap_i(a, b);
}
}
impl<S: Copy> Array2<Vector4<S>, Vector4<S>, S> for Matrix4<S> {
#[inline]
fn ptr<'a>(&'a self) -> &'a S { &self.x.x }
#[inline]
fn mut_ptr<'a>(&'a mut self) -> &'a mut S { &mut self.x.x }
#[inline]
fn c<'a>(&'a self, c: uint) -> &'a Vector4<S> {
let slice: &'a [Vector4<S>, ..4] = unsafe { mem::transmute(self) };
&'a slice[c]
}
#[inline]
fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut Vector4<S> {
let slice: &'a mut [Vector4<S>, ..4] = unsafe { mem::transmute(self) };
&'a mut slice[c]
}
#[inline]
fn r(&self, r: uint) -> Vector4<S> {
Vector4::new(self.cr(0, r),
self.cr(1, r),
self.cr(2, r),
self.cr(3, r))
}
#[inline]
fn swap_r(&mut self, a: uint, b: uint) {
self.mut_c(0).swap_i(a, b);
self.mut_c(1).swap_i(a, b);
self.mut_c(2).swap_i(a, b);
self.mut_c(3).swap_i(a, b);
}
}
impl<S: BaseFloat> Matrix<S, Vector2<S>> for Matrix2<S> {
#[inline]
fn mul_s(&self, s: S) -> Matrix2<S> {
Matrix2::from_cols(self.c(0).mul_s(s),
self.c(1).mul_s(s))
}
#[inline]
fn div_s(&self, s: S) -> Matrix2<S> {
Matrix2::from_cols(self.c(0).div_s(s),
self.c(1).div_s(s))
}
#[inline]
fn rem_s(&self, s: S) -> Matrix2<S> {
Matrix2::from_cols(self.c(0).rem_s(s),
self.c(1).rem_s(s))
}
#[inline]
fn add_m(&self, m: &Matrix2<S>) -> Matrix2<S> {
Matrix2::from_cols(self.c(0).add_v(m.c(0)),
self.c(1).add_v(m.c(1)))
}
#[inline]
fn sub_m(&self, m: &Matrix2<S>) -> Matrix2<S> {
Matrix2::from_cols(self.c(0).sub_v(m.c(0)),
self.c(1).sub_v(m.c(1)))
}
#[inline]
fn mul_v(&self, v: &Vector2<S>) -> Vector2<S> {
Vector2::new(self.r(0).dot(v),
self.r(1).dot(v))
}
fn mul_m(&self, other: &Matrix2<S>) -> Matrix2<S> { fn mul_m(&self, other: &Matrix2<S>) -> Matrix2<S> {
Matrix2::new(self.r(0).dot(other.c(0)), self.r(1).dot(other.c(0)), Matrix2::new(self.r(0).dot(other.c(0)), self.r(1).dot(other.c(0)),
self.r(0).dot(other.c(1)), self.r(1).dot(other.c(1))) self.r(0).dot(other.c(1)), self.r(1).dot(other.c(1)))
} }
#[inline]
fn neg_self(&mut self) {
self.mut_c(0).neg_self();
self.mut_c(1).neg_self();
}
#[inline]
fn mul_self_s(&mut self, s: S) {
self.mut_c(0).mul_self_s(s);
self.mut_c(1).mul_self_s(s);
}
#[inline]
fn div_self_s(&mut self, s: S) {
self.mut_c(0).div_self_s(s);
self.mut_c(1).div_self_s(s);
}
#[inline]
fn rem_self_s(&mut self, s: S) {
self.mut_c(0).rem_self_s(s);
self.mut_c(1).rem_self_s(s);
}
#[inline]
fn add_self_m(&mut self, m: &Matrix2<S>) {
self.mut_c(0).add_self_v(m.c(0));
self.mut_c(1).add_self_v(m.c(1));
}
#[inline]
fn sub_self_m(&mut self, m: &Matrix2<S>) {
self.mut_c(0).sub_self_v(m.c(0));
self.mut_c(1).sub_self_v(m.c(1));
}
fn transpose(&self) -> Matrix2<S> { fn transpose(&self) -> Matrix2<S> {
Matrix2::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(), Matrix2::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(),
self.cr(0, 1).clone(), self.cr(1, 1).clone()) self.cr(0, 1).clone(), self.cr(1, 1).clone())
@ -462,7 +569,13 @@ for Matrix2<S>
#[inline] #[inline]
fn determinant(&self) -> S { fn determinant(&self) -> S {
*self.cr(0, 0) * *self.cr(1, 1) - *self.cr(1, 0) * *self.cr(0, 1) self.cr(0, 0) * self.cr(1, 1) - self.cr(1, 0) * self.cr(0, 1)
}
#[inline]
fn diagonal(&self) -> Vector2<S> {
Vector2::new(self.cr(0, 0),
self.cr(1, 1))
} }
#[inline] #[inline]
@ -471,8 +584,8 @@ for Matrix2<S>
if det.approx_eq(&zero()) { if det.approx_eq(&zero()) {
None None
} else { } else {
Some(Matrix2::new( *self.cr(1, 1) / det, -*self.cr(0, 1) / det, Some(Matrix2::new( self.cr(1, 1) / det, -self.cr(0, 1) / det,
-*self.cr(1, 0) / det, *self.cr(0, 0) / det)) -self.cr(1, 0) / det, self.cr(0, 0) / det))
} }
} }
@ -485,21 +598,102 @@ for Matrix2<S>
#[inline] #[inline]
fn is_symmetric(&self) -> bool { fn is_symmetric(&self) -> bool {
self.cr(0, 1).approx_eq(self.cr(1, 0)) && self.cr(0, 1).approx_eq(&self.cr(1, 0)) &&
self.cr(1, 0).approx_eq(self.cr(0, 1)) self.cr(1, 0).approx_eq(&self.cr(0, 1))
} }
} }
impl<S: BaseFloat> impl<S: BaseFloat> Matrix<S, Vector3<S>> for Matrix3<S> {
Matrix<S, [Vector3<S>, ..3], Vector3<S>, [S, ..3]> #[inline]
for Matrix3<S> fn mul_s(&self, s: S) -> Matrix3<S> {
{ Matrix3::from_cols(self.c(0).mul_s(s),
self.c(1).mul_s(s),
self.c(2).mul_s(s))
}
#[inline]
fn div_s(&self, s: S) -> Matrix3<S> {
Matrix3::from_cols(self.c(0).div_s(s),
self.c(1).div_s(s),
self.c(2).div_s(s))
}
#[inline]
fn rem_s(&self, s: S) -> Matrix3<S> {
Matrix3::from_cols(self.c(0).rem_s(s),
self.c(1).rem_s(s),
self.c(2).rem_s(s))
}
#[inline]
fn add_m(&self, m: &Matrix3<S>) -> Matrix3<S> {
Matrix3::from_cols(self.c(0).add_v(m.c(0)),
self.c(1).add_v(m.c(1)),
self.c(2).add_v(m.c(2)))
}
#[inline]
fn sub_m(&self, m: &Matrix3<S>) -> Matrix3<S> {
Matrix3::from_cols(self.c(0).sub_v(m.c(0)),
self.c(1).sub_v(m.c(1)),
self.c(2).sub_v(m.c(2)))
}
#[inline]
fn mul_v(&self, v: &Vector3<S>) -> Vector3<S> {
Vector3::new(self.r(0).dot(v),
self.r(1).dot(v),
self.r(2).dot(v))
}
fn mul_m(&self, other: &Matrix3<S>) -> Matrix3<S> { fn mul_m(&self, other: &Matrix3<S>) -> Matrix3<S> {
Matrix3::new(self.r(0).dot(other.c(0)),self.r(1).dot(other.c(0)),self.r(2).dot(other.c(0)), Matrix3::new(self.r(0).dot(other.c(0)),self.r(1).dot(other.c(0)),self.r(2).dot(other.c(0)),
self.r(0).dot(other.c(1)),self.r(1).dot(other.c(1)),self.r(2).dot(other.c(1)), self.r(0).dot(other.c(1)),self.r(1).dot(other.c(1)),self.r(2).dot(other.c(1)),
self.r(0).dot(other.c(2)),self.r(1).dot(other.c(2)),self.r(2).dot(other.c(2))) self.r(0).dot(other.c(2)),self.r(1).dot(other.c(2)),self.r(2).dot(other.c(2)))
} }
#[inline]
fn neg_self(&mut self) {
self.mut_c(0).neg_self();
self.mut_c(1).neg_self();
self.mut_c(2).neg_self();
}
#[inline]
fn mul_self_s(&mut self, s: S) {
self.mut_c(0).mul_self_s(s);
self.mut_c(1).mul_self_s(s);
self.mut_c(2).mul_self_s(s);
}
#[inline]
fn div_self_s(&mut self, s: S) {
self.mut_c(0).div_self_s(s);
self.mut_c(1).div_self_s(s);
self.mut_c(2).div_self_s(s);
}
#[inline]
fn rem_self_s(&mut self, s: S) {
self.mut_c(0).rem_self_s(s);
self.mut_c(1).rem_self_s(s);
self.mut_c(2).rem_self_s(s);
}
#[inline]
fn add_self_m(&mut self, m: &Matrix3<S>) {
self.mut_c(0).add_self_v(m.c(0));
self.mut_c(1).add_self_v(m.c(1));
self.mut_c(2).add_self_v(m.c(2));
}
#[inline]
fn sub_self_m(&mut self, m: &Matrix3<S>) {
self.mut_c(0).sub_self_v(m.c(0));
self.mut_c(1).sub_self_v(m.c(1));
self.mut_c(2).sub_self_v(m.c(2));
}
fn transpose(&self) -> Matrix3<S> { fn transpose(&self) -> Matrix3<S> {
Matrix3::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(), self.cr(2, 0).clone(), Matrix3::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(), self.cr(2, 0).clone(),
self.cr(0, 1).clone(), self.cr(1, 1).clone(), self.cr(2, 1).clone(), self.cr(0, 1).clone(), self.cr(1, 1).clone(), self.cr(2, 1).clone(),
@ -514,9 +708,16 @@ for Matrix3<S>
} }
fn determinant(&self) -> S { fn determinant(&self) -> S {
*self.cr(0, 0) * (*self.cr(1, 1) * *self.cr(2, 2) - *self.cr(2, 1) * *self.cr(1, 2)) - self.cr(0, 0) * (self.cr(1, 1) * self.cr(2, 2) - self.cr(2, 1) * self.cr(1, 2)) -
*self.cr(1, 0) * (*self.cr(0, 1) * *self.cr(2, 2) - *self.cr(2, 1) * *self.cr(0, 2)) + self.cr(1, 0) * (self.cr(0, 1) * self.cr(2, 2) - self.cr(2, 1) * self.cr(0, 2)) +
*self.cr(2, 0) * (*self.cr(0, 1) * *self.cr(1, 2) - *self.cr(1, 1) * *self.cr(0, 2)) self.cr(2, 0) * (self.cr(0, 1) * self.cr(1, 2) - self.cr(1, 1) * self.cr(0, 2))
}
#[inline]
fn diagonal(&self) -> Vector3<S> {
Vector3::new(self.cr(0, 0),
self.cr(1, 1),
self.cr(2, 2))
} }
fn invert(&self) -> Option<Matrix3<S>> { fn invert(&self) -> Option<Matrix3<S>> {
@ -540,14 +741,14 @@ for Matrix3<S>
} }
fn is_symmetric(&self) -> bool { fn is_symmetric(&self) -> bool {
self.cr(0, 1).approx_eq(self.cr(1, 0)) && self.cr(0, 1).approx_eq(&self.cr(1, 0)) &&
self.cr(0, 2).approx_eq(self.cr(2, 0)) && self.cr(0, 2).approx_eq(&self.cr(2, 0)) &&
self.cr(1, 0).approx_eq(self.cr(0, 1)) && self.cr(1, 0).approx_eq(&self.cr(0, 1)) &&
self.cr(1, 2).approx_eq(self.cr(2, 1)) && self.cr(1, 2).approx_eq(&self.cr(2, 1)) &&
self.cr(2, 0).approx_eq(self.cr(0, 2)) && self.cr(2, 0).approx_eq(&self.cr(0, 2)) &&
self.cr(2, 1).approx_eq(self.cr(1, 2)) self.cr(2, 1).approx_eq(&self.cr(1, 2))
} }
} }
@ -557,16 +758,61 @@ for Matrix3<S>
// around ~4 times. // around ~4 times.
macro_rules! dot_matrix4( macro_rules! dot_matrix4(
($A:expr, $B:expr, $I:expr, $J:expr) => ( ($A:expr, $B:expr, $I:expr, $J:expr) => (
(*$A.cr(0, $I)) * (*$B.cr($J, 0)) + ($A.cr(0, $I)) * ($B.cr($J, 0)) +
(*$A.cr(1, $I)) * (*$B.cr($J, 1)) + ($A.cr(1, $I)) * ($B.cr($J, 1)) +
(*$A.cr(2, $I)) * (*$B.cr($J, 2)) + ($A.cr(2, $I)) * ($B.cr($J, 2)) +
(*$A.cr(3, $I)) * (*$B.cr($J, 3)) ($A.cr(3, $I)) * ($B.cr($J, 3))
)) ))
impl<S: BaseFloat> impl<S: BaseFloat> Matrix<S, Vector4<S>> for Matrix4<S> {
Matrix<S, [Vector4<S>, ..4], Vector4<S>, [S, ..4]> #[inline]
for Matrix4<S> fn mul_s(&self, s: S) -> Matrix4<S> {
{ Matrix4::from_cols(self.c(0).mul_s(s),
self.c(1).mul_s(s),
self.c(2).mul_s(s),
self.c(3).mul_s(s))
}
#[inline]
fn div_s(&self, s: S) -> Matrix4<S> {
Matrix4::from_cols(self.c(0).div_s(s),
self.c(1).div_s(s),
self.c(2).div_s(s),
self.c(3).div_s(s))
}
#[inline]
fn rem_s(&self, s: S) -> Matrix4<S> {
Matrix4::from_cols(self.c(0).rem_s(s),
self.c(1).rem_s(s),
self.c(2).rem_s(s),
self.c(3).rem_s(s))
}
#[inline]
fn add_m(&self, m: &Matrix4<S>) -> Matrix4<S> {
Matrix4::from_cols(self.c(0).add_v(m.c(0)),
self.c(1).add_v(m.c(1)),
self.c(2).add_v(m.c(2)),
self.c(3).add_v(m.c(3)))
}
#[inline]
fn sub_m(&self, m: &Matrix4<S>) -> Matrix4<S> {
Matrix4::from_cols(self.c(0).sub_v(m.c(0)),
self.c(1).sub_v(m.c(1)),
self.c(2).sub_v(m.c(2)),
self.c(3).sub_v(m.c(3)))
}
#[inline]
fn mul_v(&self, v: &Vector4<S>) -> Vector4<S> {
Vector4::new(self.r(0).dot(v),
self.r(1).dot(v),
self.r(2).dot(v),
self.r(3).dot(v))
}
fn mul_m(&self, other: &Matrix4<S>) -> Matrix4<S> { fn mul_m(&self, other: &Matrix4<S>) -> Matrix4<S> {
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), 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, 1), dot_matrix4!(self, other, 1, 1), dot_matrix4!(self, other, 2, 1), dot_matrix4!(self, other, 3, 1),
@ -574,6 +820,54 @@ for Matrix4<S>
dot_matrix4!(self, other, 0, 3), dot_matrix4!(self, other, 1, 3), dot_matrix4!(self, other, 2, 3), dot_matrix4!(self, other, 3, 3)) dot_matrix4!(self, other, 0, 3), dot_matrix4!(self, other, 1, 3), dot_matrix4!(self, other, 2, 3), dot_matrix4!(self, other, 3, 3))
} }
#[inline]
fn neg_self(&mut self) {
self.mut_c(0).neg_self();
self.mut_c(1).neg_self();
self.mut_c(2).neg_self();
self.mut_c(3).neg_self();
}
#[inline]
fn mul_self_s(&mut self, s: S) {
self.mut_c(0).mul_self_s(s);
self.mut_c(1).mul_self_s(s);
self.mut_c(2).mul_self_s(s);
self.mut_c(3).mul_self_s(s);
}
#[inline]
fn div_self_s(&mut self, s: S) {
self.mut_c(0).div_self_s(s);
self.mut_c(1).div_self_s(s);
self.mut_c(2).div_self_s(s);
self.mut_c(3).div_self_s(s);
}
#[inline]
fn rem_self_s(&mut self, s: S) {
self.mut_c(0).rem_self_s(s);
self.mut_c(1).rem_self_s(s);
self.mut_c(2).rem_self_s(s);
self.mut_c(3).rem_self_s(s);
}
#[inline]
fn add_self_m(&mut self, m: &Matrix4<S>) {
self.mut_c(0).add_self_v(m.c(0));
self.mut_c(1).add_self_v(m.c(1));
self.mut_c(2).add_self_v(m.c(2));
self.mut_c(3).add_self_v(m.c(3));
}
#[inline]
fn sub_self_m(&mut self, m: &Matrix4<S>) {
self.mut_c(0).sub_self_v(m.c(0));
self.mut_c(1).sub_self_v(m.c(1));
self.mut_c(2).sub_self_v(m.c(2));
self.mut_c(3).sub_self_v(m.c(3));
}
fn transpose(&self) -> Matrix4<S> { fn transpose(&self) -> Matrix4<S> {
Matrix4::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(), self.cr(2, 0).clone(), self.cr(3, 0).clone(), Matrix4::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(), self.cr(2, 0).clone(), self.cr(3, 0).clone(),
self.cr(0, 1).clone(), self.cr(1, 1).clone(), self.cr(2, 1).clone(), self.cr(3, 1).clone(), self.cr(0, 1).clone(), self.cr(1, 1).clone(), self.cr(2, 1).clone(), self.cr(3, 1).clone(),
@ -604,10 +898,18 @@ for Matrix4<S>
self.cr(0, 2).clone(), self.cr(1, 2).clone(), self.cr(2, 2).clone(), self.cr(0, 2).clone(), self.cr(1, 2).clone(), self.cr(2, 2).clone(),
self.cr(0, 3).clone(), self.cr(1, 3).clone(), self.cr(2, 3).clone()); self.cr(0, 3).clone(), self.cr(1, 3).clone(), self.cr(2, 3).clone());
*self.cr(0, 0) * m0.determinant() - self.cr(0, 0) * m0.determinant() -
*self.cr(1, 0) * m1.determinant() + self.cr(1, 0) * m1.determinant() +
*self.cr(2, 0) * m2.determinant() - self.cr(2, 0) * m2.determinant() -
*self.cr(3, 0) * m3.determinant() self.cr(3, 0) * m3.determinant()
}
#[inline]
fn diagonal(&self) -> Vector4<S> {
Vector4::new(self.cr(0, 0),
self.cr(1, 1),
self.cr(2, 2),
self.cr(3, 3))
} }
fn invert(&self) -> Option<Matrix4<S>> { fn invert(&self) -> Option<Matrix4<S>> {
@ -673,21 +975,48 @@ for Matrix4<S>
} }
fn is_symmetric(&self) -> bool { fn is_symmetric(&self) -> bool {
self.cr(0, 1).approx_eq(self.cr(1, 0)) && self.cr(0, 1).approx_eq(&self.cr(1, 0)) &&
self.cr(0, 2).approx_eq(self.cr(2, 0)) && self.cr(0, 2).approx_eq(&self.cr(2, 0)) &&
self.cr(0, 3).approx_eq(self.cr(3, 0)) && self.cr(0, 3).approx_eq(&self.cr(3, 0)) &&
self.cr(1, 0).approx_eq(self.cr(0, 1)) && self.cr(1, 0).approx_eq(&self.cr(0, 1)) &&
self.cr(1, 2).approx_eq(self.cr(2, 1)) && self.cr(1, 2).approx_eq(&self.cr(2, 1)) &&
self.cr(1, 3).approx_eq(self.cr(3, 1)) && self.cr(1, 3).approx_eq(&self.cr(3, 1)) &&
self.cr(2, 0).approx_eq(self.cr(0, 2)) && self.cr(2, 0).approx_eq(&self.cr(0, 2)) &&
self.cr(2, 1).approx_eq(self.cr(1, 2)) && self.cr(2, 1).approx_eq(&self.cr(1, 2)) &&
self.cr(2, 3).approx_eq(self.cr(3, 2)) && self.cr(2, 3).approx_eq(&self.cr(3, 2)) &&
self.cr(3, 0).approx_eq(self.cr(0, 3)) && self.cr(3, 0).approx_eq(&self.cr(0, 3)) &&
self.cr(3, 1).approx_eq(self.cr(1, 3)) && self.cr(3, 1).approx_eq(&self.cr(1, 3)) &&
self.cr(3, 2).approx_eq(self.cr(2, 3)) self.cr(3, 2).approx_eq(&self.cr(2, 3))
}
}
impl<S: BaseFloat> ApproxEq<S> for Matrix2<S> {
#[inline]
fn approx_eq_eps(&self, other: &Matrix2<S>, epsilon: &S) -> bool {
self.c(0).approx_eq_eps(other.c(0), epsilon) &&
self.c(1).approx_eq_eps(other.c(1), epsilon)
}
}
impl<S: BaseFloat> ApproxEq<S> for Matrix3<S> {
#[inline]
fn approx_eq_eps(&self, other: &Matrix3<S>, epsilon: &S) -> bool {
self.c(0).approx_eq_eps(other.c(0), epsilon) &&
self.c(1).approx_eq_eps(other.c(1), epsilon) &&
self.c(2).approx_eq_eps(other.c(2), epsilon)
}
}
impl<S: BaseFloat> ApproxEq<S> for Matrix4<S> {
#[inline]
fn approx_eq_eps(&self, other: &Matrix4<S>, epsilon: &S) -> bool {
self.c(0).approx_eq_eps(other.c(0), epsilon) &&
self.c(1).approx_eq_eps(other.c(1), epsilon) &&
self.c(2).approx_eq_eps(other.c(2), epsilon) &&
self.c(3).approx_eq_eps(other.c(3), epsilon)
} }
} }
@ -711,8 +1040,7 @@ pub trait ToMatrix4<S: BaseNum> {
fn to_matrix4(&self) -> Matrix4<S>; fn to_matrix4(&self) -> Matrix4<S>;
} }
impl<S: BaseFloat> impl<S: BaseFloat> ToMatrix3<S> for Matrix2<S> {
ToMatrix3<S> for Matrix2<S> {
/// Clone the elements of a 2-dimensional matrix into the top-left corner /// Clone the elements of a 2-dimensional matrix into the top-left corner
/// of a 3-dimensional identity matrix. /// of a 3-dimensional identity matrix.
fn to_matrix3(&self) -> Matrix3<S> { fn to_matrix3(&self) -> Matrix3<S> {
@ -722,8 +1050,7 @@ ToMatrix3<S> for Matrix2<S> {
} }
} }
impl<S: BaseFloat> impl<S: BaseFloat> ToMatrix4<S> for Matrix2<S> {
ToMatrix4<S> for Matrix2<S> {
/// Clone the elements of a 2-dimensional matrix into the top-left corner /// Clone the elements of a 2-dimensional matrix into the top-left corner
/// of a 4-dimensional identity matrix. /// of a 4-dimensional identity matrix.
fn to_matrix4(&self) -> Matrix4<S> { fn to_matrix4(&self) -> Matrix4<S> {
@ -734,8 +1061,7 @@ ToMatrix4<S> for Matrix2<S> {
} }
} }
impl<S: BaseFloat> impl<S: BaseFloat> ToMatrix4<S> for Matrix3<S> {
ToMatrix4<S> for Matrix3<S> {
/// Clone the elements of a 3-dimensional matrix into the top-left corner /// Clone the elements of a 3-dimensional matrix into the top-left corner
/// of a 4-dimensional identity matrix. /// of a 4-dimensional identity matrix.
fn to_matrix4(&self) -> Matrix4<S> { fn to_matrix4(&self) -> Matrix4<S> {
@ -746,8 +1072,7 @@ ToMatrix4<S> for Matrix3<S> {
} }
} }
impl<S: BaseFloat> impl<S: BaseFloat> ToQuaternion<S> for Matrix3<S> {
ToQuaternion<S> for Matrix3<S> {
/// Convert the matrix to a quaternion /// Convert the matrix to a quaternion
fn to_quaternion(&self) -> Quaternion<S> { fn to_quaternion(&self) -> Quaternion<S> {
// http://www.cs.ucr.edu/~vbz/resources/quatut.pdf // http://www.cs.ucr.edu/~vbz/resources/quatut.pdf
@ -758,43 +1083,43 @@ ToQuaternion<S> for Matrix3<S> {
let s = (one::<S>() + trace).sqrt(); let s = (one::<S>() + trace).sqrt();
let w = half * s; let w = half * s;
let s = half / s; let s = half / s;
let x = (*self.cr(1, 2) - *self.cr(2, 1)) * s; let x = (self.cr(1, 2) - self.cr(2, 1)) * s;
let y = (*self.cr(2, 0) - *self.cr(0, 2)) * s; let y = (self.cr(2, 0) - self.cr(0, 2)) * s;
let z = (*self.cr(0, 1) - *self.cr(1, 0)) * s; let z = (self.cr(0, 1) - self.cr(1, 0)) * s;
Quaternion::new(w, x, y, z) Quaternion::new(w, x, y, z)
} }
() if (*self.cr(0, 0) > *self.cr(1, 1)) && (*self.cr(0, 0) > *self.cr(2, 2)) => { () if (self.cr(0, 0) > self.cr(1, 1)) && (self.cr(0, 0) > self.cr(2, 2)) => {
let s = (half + (*self.cr(0, 0) - *self.cr(1, 1) - *self.cr(2, 2))).sqrt(); let s = (half + (self.cr(0, 0) - self.cr(1, 1) - self.cr(2, 2))).sqrt();
let w = half * s; let w = half * s;
let s = half / s; let s = half / s;
let x = (*self.cr(0, 1) - *self.cr(1, 0)) * s; let x = (self.cr(0, 1) - self.cr(1, 0)) * s;
let y = (*self.cr(2, 0) - *self.cr(0, 2)) * s; let y = (self.cr(2, 0) - self.cr(0, 2)) * s;
let z = (*self.cr(1, 2) - *self.cr(2, 1)) * s; let z = (self.cr(1, 2) - self.cr(2, 1)) * s;
Quaternion::new(w, x, y, z) Quaternion::new(w, x, y, z)
} }
() if *self.cr(1, 1) > *self.cr(2, 2) => { () if self.cr(1, 1) > self.cr(2, 2) => {
let s = (half + (*self.cr(1, 1) - *self.cr(0, 0) - *self.cr(2, 2))).sqrt(); let s = (half + (self.cr(1, 1) - self.cr(0, 0) - self.cr(2, 2))).sqrt();
let w = half * s; let w = half * s;
let s = half / s; let s = half / s;
let x = (*self.cr(0, 1) - *self.cr(1, 0)) * s; let x = (self.cr(0, 1) - self.cr(1, 0)) * s;
let y = (*self.cr(1, 2) - *self.cr(2, 1)) * s; let y = (self.cr(1, 2) - self.cr(2, 1)) * s;
let z = (*self.cr(2, 0) - *self.cr(0, 2)) * s; let z = (self.cr(2, 0) - self.cr(0, 2)) * s;
Quaternion::new(w, x, y, z) Quaternion::new(w, x, y, z)
} }
() => { () => {
let s = (half + (*self.cr(2, 2) - *self.cr(0, 0) - *self.cr(1, 1))).sqrt(); let s = (half + (self.cr(2, 2) - self.cr(0, 0) - self.cr(1, 1))).sqrt();
let w = half * s; let w = half * s;
let s = half / s; let s = half / s;
let x = (*self.cr(2, 0) - *self.cr(0, 2)) * s; let x = (self.cr(2, 0) - self.cr(0, 2)) * s;
let y = (*self.cr(1, 2) - *self.cr(2, 1)) * s; let y = (self.cr(1, 2) - self.cr(2, 1)) * s;
let z = (*self.cr(0, 1) - *self.cr(1, 0)) * s; let z = (self.cr(0, 1) - self.cr(1, 0)) * s;
Quaternion::new(w, x, y, z) Quaternion::new(w, x, y, z)
} }
} }
} }
} }
impl<S: BaseFloat> fmt::Show for Matrix2<S> { impl<S: BaseNum> fmt::Show for Matrix2<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[[{}, {}], [{}, {}]]", write!(f, "[[{}, {}], [{}, {}]]",
self.cr(0, 0), self.cr(0, 1), self.cr(0, 0), self.cr(0, 1),
@ -802,7 +1127,7 @@ impl<S: BaseFloat> fmt::Show for Matrix2<S> {
} }
} }
impl<S: BaseFloat> fmt::Show for Matrix3<S> { impl<S: BaseNum> fmt::Show for Matrix3<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[[{}, {}, {}], [{}, {}, {}], [{}, {}, {}]]", write!(f, "[[{}, {}, {}], [{}, {}, {}], [{}, {}, {}]]",
self.cr(0, 0), self.cr(0, 1), self.cr(0, 2), self.cr(0, 0), self.cr(0, 1), self.cr(0, 2),
@ -811,7 +1136,7 @@ impl<S: BaseFloat> fmt::Show for Matrix3<S> {
} }
} }
impl<S: BaseFloat> fmt::Show for Matrix4<S> { impl<S: BaseNum> fmt::Show for Matrix4<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[[{}, {}, {}, {}], [{}, {}, {}, {}], [{}, {}, {}, {}], [{}, {}, {}, {}]]", write!(f, "[[{}, {}, {}, {}], [{}, {}, {}, {}], [{}, {}, {}, {}], [{}, {}, {}, {}]]",
self.cr(0, 0), self.cr(0, 1), self.cr(0, 2), self.cr(0, 3), self.cr(0, 0), self.cr(0, 1), self.cr(0, 2), self.cr(0, 3),

View file

@ -18,10 +18,12 @@
//! not have a fixed position. //! not have a fixed position.
use std::fmt; use std::fmt;
use std::mem;
use std::num::{one, zero}; use std::num::{one, zero};
use array::*; use approx::ApproxEq;
use num::BaseNum; use array::Array1;
use num::{BaseNum, BaseFloat};
use vector::*; use vector::*;
/// A point in 2-dimensional space. /// A point in 2-dimensional space.
@ -61,56 +63,294 @@ impl<S: BaseNum> Point3<S> {
} }
/// Specifies the numeric operations for point types. /// Specifies the numeric operations for point types.
pub trait Point pub trait Point<S: BaseNum, V: Vector<S>>: Array1<S> + Clone {
<
S: BaseNum,
V: Vector<S, Slice>,
Slice
>
: Array<S, Slice>
{
/// Create a point at the origin. /// Create a point at the origin.
#[inline] fn origin() -> Self{ build(|_i| zero::<S>()) } fn origin() -> Self;
/// Create a point from a vector. /// Create a point from a vector.
#[inline] fn from_vec(v: &V) -> Self { build(|i| v.i(i).clone()) } fn from_vec(v: &V) -> Self;
/// Convert a point to a vector. /// Convert a point to a vector.
#[inline] fn to_vec(&self) -> V { build(|i| self.i(i).clone()) } fn to_vec(&self) -> V;
/// Multiply each component by a scalar, returning the new point. /// Multiply each component by a scalar, returning the new point.
#[inline] fn mul_s(&self, s: S) -> Self { build(|i| self.i(i).mul(&s)) } fn mul_s(&self, s: S) -> Self;
/// Divide each component by a scalar, returning the new point. /// Divide each component by a scalar, returning the new point.
#[inline] fn div_s(&self, s: S) -> Self { build(|i| self.i(i).div(&s)) } fn div_s(&self, s: S) -> Self;
/// Subtract a scalar from each component, returning the new point. /// Subtract a scalar from each component, returning the new point.
#[inline] fn rem_s(&self, s: S) -> Self { build(|i| self.i(i).rem(&s)) } fn rem_s(&self, s: S) -> Self;
/// Add a vector to this point, returning the new point. /// Add a vector to this point, returning the new point.
#[inline] fn add_v(&self, other: &V) -> Self { build(|i| self.i(i).add(other.i(i))) } fn add_v(&self, v: &V) -> Self;
/// Subtract another point from this one, returning a new vector. /// Subtract another point from this one, returning a new vector.
#[inline] fn sub_p(&self, other: &Self) -> V { build(|i| self.i(i).sub(other.i(i))) } fn sub_p(&self, p: &Self) -> V;
/// Multiply each component by a scalar, in-place. /// Multiply each component by a scalar, in-place.
#[inline] fn mul_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.mul(&s)) } fn mul_self_s(&mut self, s: S);
/// Divide each component by a scalar, in-place. /// Divide each component by a scalar, in-place.
#[inline] fn div_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.div(&s)) } fn div_self_s(&mut self, s: S);
/// Take the remainder of each component by a scalar, in-place. /// Take the remainder of each component by a scalar, in-place.
#[inline] fn rem_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.rem(&s)) } fn rem_self_s(&mut self, s: S);
/// Add a vector to this point, in-place. /// Add a vector to this point, in-place.
#[inline] fn add_self_v(&mut self, other: &V) { self.each_mut(|i, x| *x = x.add(other.i(i))) } fn add_self_v(&mut self, v: &V);
/// This is a weird one, but its useful for plane calculations. /// This is a weird one, but its useful for plane calculations.
fn dot(&self, v: &V) -> S;
fn min(&self, p: &Self) -> Self;
fn max(&self, p: &Self) -> Self;
}
impl<S: BaseNum> Array1<S> for Point2<S> {
#[inline] #[inline]
fn dot(&self, v: &V) -> S { fn ptr<'a>(&'a self) -> &'a S { &self.x }
build::<S, Slice, V>(|i| self.i(i).mul(v.i(i))).comp_add()
#[inline]
fn mut_ptr<'a>(&'a mut self) -> &'a mut S { &mut self.x }
#[inline]
fn i(&self, i: uint) -> S {
let slice: &[S, ..2] = unsafe { mem::transmute(self) };
slice[i]
}
#[inline]
fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut S {
let slice: &'a mut [S, ..2] = unsafe { mem::transmute(self) };
&'a mut slice[i]
} }
} }
array!(impl<S> Point2<S> -> [S, ..2] _2) impl<S: BaseNum> Point<S, Vector2<S>> for Point2<S> {
array!(impl<S> Point3<S> -> [S, ..3] _3) #[inline]
fn origin() -> Point2<S> {
Point2::new(zero(), zero())
}
impl<S: BaseNum> Point<S, Vector2<S>, [S, ..2]> for Point2<S> {} #[inline]
impl<S: BaseNum> Point<S, Vector3<S>, [S, ..3]> for Point3<S> {} fn from_vec(v: &Vector2<S>) -> Point2<S> {
Point2::new(v.x, v.y)
}
#[inline]
fn to_vec(&self) -> Vector2<S> {
Vector2::new(self.x,
self.y)
}
#[inline]
fn mul_s(&self, s: S) -> Point2<S> {
Point2::new(self.x * s,
self.y * s)
}
#[inline]
fn div_s(&self, s: S) -> Point2<S> {
Point2::new(self.x / s,
self.y / s)
}
#[inline]
fn rem_s(&self, s: S) -> Point2<S> {
Point2::new(self.x % s,
self.y % s)
}
#[inline]
fn add_v(&self, v: &Vector2<S>) -> Point2<S> {
Point2::new(self.x + v.x,
self.y + v.y)
}
#[inline]
fn sub_p(&self, p: &Point2<S>) -> Vector2<S> {
Vector2::new(self.x - p.x,
self.y - p.y)
}
#[inline]
fn mul_self_s(&mut self, s: S) {
self.x = self.x * s;
self.y = self.y * s;
}
#[inline]
fn div_self_s(&mut self, s: S) {
self.x = self.x / s;
self.y = self.y / s;
}
#[inline]
fn rem_self_s(&mut self, s: S) {
self.x = self.x % s;
self.y = self.y % s;
}
#[inline]
fn add_self_v(&mut self, v: &Vector2<S>) {
self.x = self.x + v.x;
self.y = self.y + v.y;
}
#[inline]
fn dot(&self, v: &Vector2<S>) -> S {
self.x * v.x +
self.y * v.y
}
#[inline]
fn min(&self, p: &Point2<S>) -> Point2<S> {
Point2::new(self.x.partial_min(p.x),
self.y.partial_min(p.y))
}
#[inline]
fn max(&self, p: &Point2<S>) -> Point2<S> {
Point2::new(self.x.partial_max(p.x),
self.y.partial_max(p.y))
}
}
impl<S: BaseFloat> ApproxEq<S> for Point2<S> {
#[inline]
fn approx_eq_eps(&self, other: &Point2<S>, epsilon: &S) -> bool {
self.x.approx_eq_eps(&other.x, epsilon) &&
self.y.approx_eq_eps(&other.y, epsilon)
}
}
impl<S: BaseNum> Array1<S> for Point3<S> {
#[inline]
fn ptr<'a>(&'a self) -> &'a S { &self.x }
#[inline]
fn mut_ptr<'a>(&'a mut self) -> &'a mut S { &mut self.x }
#[inline]
fn i(&self, i: uint) -> S {
let slice: &[S, ..3] = unsafe { mem::transmute(self) };
slice[i]
}
#[inline]
fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut S {
let slice: &'a mut [S, ..3] = unsafe { mem::transmute(self) };
&'a mut slice[i]
}
}
impl<S: BaseNum> Point<S, Vector3<S>> for Point3<S> {
#[inline]
fn origin() -> Point3<S> {
Point3::new(zero(), zero(), zero())
}
#[inline]
fn from_vec(v: &Vector3<S>) -> Point3<S> {
Point3::new(v.x, v.y, v.z)
}
#[inline]
fn to_vec(&self) -> Vector3<S> {
Vector3::new(self.x,
self.y,
self.z)
}
#[inline]
fn mul_s(&self, s: S) -> Point3<S> {
Point3::new(self.x * s,
self.y * s,
self.z * s)
}
#[inline]
fn div_s(&self, s: S) -> Point3<S> {
Point3::new(self.x / s,
self.y / s,
self.z / s)
}
#[inline]
fn rem_s(&self, s: S) -> Point3<S> {
Point3::new(self.x % s,
self.y % s,
self.z % s)
}
#[inline]
fn add_v(&self, v: &Vector3<S>) -> Point3<S> {
Point3::new(self.x + v.x,
self.y + v.y,
self.z + v.z)
}
#[inline]
fn sub_p(&self, p: &Point3<S>) -> Vector3<S> {
Vector3::new(self.x - p.x,
self.y - p.y,
self.z - p.z)
}
#[inline]
fn mul_self_s(&mut self, s: S) {
self.x = self.x * s;
self.y = self.y * s;
self.z = self.z * s;
}
#[inline]
fn div_self_s(&mut self, s: S) {
self.x = self.x / s;
self.y = self.y / s;
self.z = self.z / s;
}
#[inline]
fn rem_self_s(&mut self, s: S) {
self.x = self.x % s;
self.y = self.y % s;
self.z = self.z % s;
}
#[inline]
fn add_self_v(&mut self, v: &Vector3<S>) {
self.x = self.x + v.x;
self.y = self.y + v.y;
self.z = self.z + v.z;
}
#[inline]
fn dot(&self, v: &Vector3<S>) -> S {
self.x * v.x +
self.y * v.y +
self.z * v.z
}
#[inline]
fn min(&self, p: &Point3<S>) -> Point3<S> {
Point3::new(self.x.partial_min(p.x),
self.y.partial_min(p.y),
self.z.partial_min(p.z))
}
#[inline]
fn max(&self, p: &Point3<S>) -> Point3<S> {
Point3::new(self.x.partial_max(p.x),
self.y.partial_max(p.y),
self.z.partial_max(p.z))
}
}
impl<S: BaseFloat> ApproxEq<S> for Point3<S> {
#[inline]
fn approx_eq_eps(&self, other: &Point3<S>, epsilon: &S) -> bool {
self.x.approx_eq_eps(&other.x, epsilon) &&
self.y.approx_eq_eps(&other.y, epsilon) &&
self.z.approx_eq_eps(&other.z, epsilon)
}
}
impl<S: BaseNum> fmt::Show for Point2<S> { impl<S: BaseNum> fmt::Show for Point2<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

View file

@ -1,38 +0,0 @@
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use array::Array;
use matrix::{Matrix2, Matrix3, Matrix4};
use point::{Point2, Point3};
use vector::{Vector2, Vector3, Vector4};
pub trait Ptr<T> {
fn ptr<'a>(&'a self) -> &'a T;
}
impl<S: Clone> Ptr<S> for Vector2<S> { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } }
impl<S: Clone> Ptr<S> for Vector3<S> { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } }
impl<S: Clone> Ptr<S> for Vector4<S> { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } }
impl<S: Clone> Ptr<S> for Point2<S> { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } }
impl<S: Clone> Ptr<S> for Point3<S> { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } }
impl<S: Clone> Ptr<S> for Matrix2<S> { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0).i(0) } }
impl<S: Clone> Ptr<S> for Matrix3<S> { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0).i(0) } }
impl<S: Clone> Ptr<S> for Matrix4<S> { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0).i(0) } }
impl<'a, T, P: Ptr<T>> Ptr<T> for &'a [P] {
#[inline] fn ptr<'a>(&'a self) -> &'a T { self[0].ptr() }
}

View file

@ -14,13 +14,15 @@
// limitations under the License. // limitations under the License.
use std::fmt; use std::fmt;
use std::mem;
use std::num::{zero, one, cast}; use std::num::{zero, one, cast};
use angle::{Angle, Rad, acos, sin, sin_cos}; use angle::{Angle, Rad, acos, sin, sin_cos};
use array::{Array, build}; use approx::ApproxEq;
use array::Array1;
use matrix::{Matrix3, ToMatrix3, ToMatrix4, Matrix4}; use matrix::{Matrix3, ToMatrix3, ToMatrix4, Matrix4};
use num::BaseFloat; use num::BaseFloat;
use point::{Point3}; use point::Point3;
use rotation::{Rotation, Rotation3, Basis3, ToBasis3}; use rotation::{Rotation, Rotation3, Basis3, ToBasis3};
use vector::{Vector3, Vector, EuclideanVector}; use vector::{Vector3, Vector, EuclideanVector};
@ -29,14 +31,32 @@ use vector::{Vector3, Vector, EuclideanVector};
#[deriving(Clone, Eq)] #[deriving(Clone, Eq)]
pub struct Quaternion<S> { pub s: S, pub v: Vector3<S> } pub struct Quaternion<S> { pub s: S, pub v: Vector3<S> }
array!(impl<S> Quaternion<S> -> [S, ..4] _4)
/// Represents types which can be expressed as a quaternion. /// Represents types which can be expressed as a quaternion.
pub trait ToQuaternion<S: BaseFloat> { pub trait ToQuaternion<S: BaseFloat> {
/// Convert this value to a quaternion. /// Convert this value to a quaternion.
fn to_quaternion(&self) -> Quaternion<S>; fn to_quaternion(&self) -> Quaternion<S>;
} }
impl<S: Copy> Array1<S> for Quaternion<S> {
#[inline]
fn ptr<'a>(&'a self) -> &'a S { &self.s }
#[inline]
fn mut_ptr<'a>(&'a mut self) -> &'a mut S { &mut self.s }
#[inline]
fn i(&self, i: uint) -> S {
let slice: &[S, ..4] = unsafe { mem::transmute(self) };
slice[i]
}
#[inline]
fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut S {
let slice: &'a mut [S, ..4] = unsafe { mem::transmute(self) };
&'a mut slice[i]
}
}
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
@ -85,13 +105,13 @@ impl<S: BaseFloat> Quaternion<S> {
/// The sum of this quaternion and `other` /// The sum of this quaternion and `other`
#[inline] #[inline]
pub fn add_q(&self, other: &Quaternion<S>) -> Quaternion<S> { pub fn add_q(&self, other: &Quaternion<S>) -> Quaternion<S> {
build(|i| self.i(i).add(other.i(i))) Quaternion::from_sv(self.s + other.s, self.v + other.v)
} }
/// The difference between this quaternion and `other` /// The difference between this quaternion and `other`
#[inline] #[inline]
pub fn sub_q(&self, other: &Quaternion<S>) -> Quaternion<S> { pub fn sub_q(&self, other: &Quaternion<S>) -> Quaternion<S> {
build(|i| self.i(i).add(other.i(i))) Quaternion::from_sv(self.s - other.s, self.v - other.v)
} }
/// The result of multipliplying the quaternion by `other` /// The result of multipliplying the quaternion by `other`
@ -105,37 +125,42 @@ impl<S: BaseFloat> Quaternion<S> {
/// Multiply this quaternion by a scalar, in-place. /// Multiply this quaternion by a scalar, in-place.
#[inline] #[inline]
pub fn mul_self_s(&mut self, s: S) { pub fn mul_self_s(&mut self, s: S) {
self.each_mut(|_, x| *x = x.mul(&s)) self.s = self.s * s;
self.v.mul_self_s(s);
} }
/// Divide this quaternion by a scalar, in-place. /// Divide this quaternion by a scalar, in-place.
#[inline] #[inline]
pub fn div_self_s(&mut self, s: S) { pub fn div_self_s(&mut self, s: S) {
self.each_mut(|_, x| *x = x.div(&s)) self.s = self.s / s;
self.v.div_self_s(s);
} }
/// Add this quaternion by another, in-place. /// Add this quaternion by another, in-place.
#[inline] #[inline]
pub fn add_self_q(&mut self, other: &Quaternion<S>) { pub fn add_self_q(&mut self, q: &Quaternion<S>) {
self.each_mut(|i, x| *x = x.add(other.i(i))); self.s = self.s + q.s;
self.v.add_self_v(&q.v);
} }
/// Subtract another quaternion from this one, in-place. /// Subtract another quaternion from this one, in-place.
#[inline] #[inline]
pub fn sub_self_q(&mut self, other: &Quaternion<S>) { pub fn sub_self_q(&mut self, q: &Quaternion<S>) {
self.each_mut(|i, x| *x = x.sub(other.i(i))); self.s = self.s - q.s;
self.v.sub_self_v(&q.v);
} }
/// Multiply this quaternion by another, in-place. /// Multiply this quaternion by another, in-place.
#[inline] #[inline]
pub fn mul_self_q(&mut self, other: &Quaternion<S>) { pub fn mul_self_q(&mut self, q: &Quaternion<S>) {
*self = self.mul_q(other); self.s = self.s * q.s;
self.v.mul_self_v(&q.v);
} }
/// The dot product of the quaternion and `other`. /// The dot product of the quaternion and `q`.
#[inline] #[inline]
pub fn dot(&self, other: &Quaternion<S>) -> S { pub fn dot(&self, q: &Quaternion<S>) -> S {
self.s * other.s + self.v.dot(&other.v) self.s * q.s + self.v.dot(&q.v)
} }
/// The conjugate of the quaternion. /// The conjugate of the quaternion.
@ -176,6 +201,14 @@ impl<S: BaseFloat> Quaternion<S> {
} }
} }
impl<S: BaseFloat> ApproxEq<S> for Quaternion<S> {
#[inline]
fn approx_eq_eps(&self, other: &Quaternion<S>, epsilon: &S) -> bool {
self.s.approx_eq_eps(&other.s, epsilon) &&
self.v.approx_eq_eps(&other.v, epsilon)
}
}
impl<S: BaseFloat> Quaternion<S> { impl<S: BaseFloat> Quaternion<S> {
/// Spherical Linear Intoperlation /// Spherical Linear Intoperlation
/// ///
@ -305,7 +338,7 @@ impl<S: BaseFloat> ToQuaternion<S> for Quaternion<S> {
fn to_quaternion(&self) -> Quaternion<S> { self.clone() } fn to_quaternion(&self) -> Quaternion<S> { self.clone() }
} }
impl<S: BaseFloat> Rotation<S, [S, ..3], Vector3<S>, Point3<S>> for Quaternion<S> { impl<S: BaseFloat> Rotation<S, Vector3<S>, Point3<S>> for Quaternion<S> {
#[inline] #[inline]
fn identity() -> Quaternion<S> { Quaternion::identity() } fn identity() -> Quaternion<S> { Quaternion::identity() }

View file

@ -25,7 +25,7 @@ pub struct Ray<P,V> {
pub direction: V, pub direction: V,
} }
impl<S: BaseNum, Slice, V: Vector<S, Slice>, P: Point<S, V, Slice>> Ray<P, V> { impl<S: BaseNum, V: Vector<S>, P: Point<S, V>> Ray<P, V> {
pub fn new(origin: P, direction: V) -> Ray<P,V> { pub fn new(origin: P, direction: V) -> Ray<P,V> {
Ray { origin: origin, direction: direction } Ray { origin: origin, direction: direction }
} }

View file

@ -15,7 +15,6 @@
use angle::{Rad, acos}; use angle::{Rad, acos};
use approx::ApproxEq; use approx::ApproxEq;
use array::Array;
use matrix::Matrix; use matrix::Matrix;
use matrix::{Matrix2, ToMatrix2}; use matrix::{Matrix2, ToMatrix2};
use matrix::{Matrix3, ToMatrix3}; use matrix::{Matrix3, ToMatrix3};
@ -27,16 +26,7 @@ use vector::{Vector, Vector2, Vector3};
/// A trait for a generic rotation. A rotation is a transformation that /// A trait for a generic rotation. A rotation is a transformation that
/// creates a circular motion, and preserves at least one point in the space. /// creates a circular motion, and preserves at least one point in the space.
pub trait Rotation pub trait Rotation<S: BaseNum, V: Vector<S>, P: Point<S, V>>: Eq + ApproxEq<S> {
<
S: BaseNum,
Slice,
V: Vector<S,Slice>,
P: Point<S,V,Slice>
>
: Eq
+ ApproxEq<S>
{
/// Create the identity transform (causes no transformation). /// Create the identity transform (causes no transformation).
fn identity() -> Self; fn identity() -> Self;
@ -59,10 +49,8 @@ pub trait Rotation
/// Rotate a ray using this rotation. /// Rotate a ray using this rotation.
#[inline] #[inline]
fn rotate_ray(&self, ray: &Ray<P,V>) -> Ray<P,V> { fn rotate_ray(&self, ray: &Ray<P, V>) -> Ray<P,V> {
Ray::new( //FIXME: use clone derived from Array Ray::new(ray.origin.clone(), self.rotate_vector(&ray.direction))
Array::build(|i| ray.origin.i(i).clone()),
self.rotate_vector(&ray.direction) )
} }
/// Create a new rotation which combines both this rotation, and another. /// Create a new rotation which combines both this rotation, and another.
@ -86,29 +74,19 @@ pub trait Rotation
} }
/// A two-dimensional rotation. /// A two-dimensional rotation.
pub trait Rotation2 pub trait Rotation2<S>: Rotation<S, Vector2<S>, Point2<S>>
< + ToMatrix2<S>
S + ToBasis2<S> {
>
: Rotation<S, [S, ..2], Vector2<S>, Point2<S>>
+ ToMatrix2<S>
+ ToBasis2<S>
{
/// Create a rotation by a given angle. Thus is a redundant case of both /// Create a rotation by a given angle. Thus is a redundant case of both
/// from_axis_angle() and from_euler() for 2D space. /// from_axis_angle() and from_euler() for 2D space.
fn from_angle(theta: Rad<S>) -> Self; fn from_angle(theta: Rad<S>) -> Self;
} }
/// A three-dimensional rotation. /// A three-dimensional rotation.
pub trait Rotation3 pub trait Rotation3<S: BaseNum>: Rotation<S, Vector3<S>, Point3<S>>
< + ToMatrix3<S>
S: BaseNum + ToBasis3<S>
> + ToQuaternion<S>{
: Rotation<S, [S, ..3], Vector3<S>, Point3<S>>
+ ToMatrix3<S>
+ ToBasis3<S>
+ ToQuaternion<S>
{
/// Create a rotation using an angle around a given axis. /// Create a rotation using an angle around a given axis.
fn from_axis_angle(axis: &Vector3<S>, angle: Rad<S>) -> Self; fn from_axis_angle(axis: &Vector3<S>, angle: Rad<S>) -> Self;
@ -174,7 +152,7 @@ impl<S: BaseFloat> ToMatrix2<S> for Basis2<S> {
fn to_matrix2(&self) -> Matrix2<S> { self.mat.clone() } fn to_matrix2(&self) -> Matrix2<S> { self.mat.clone() }
} }
impl<S: BaseFloat> Rotation<S, [S, ..2], Vector2<S>, Point2<S>> for Basis2<S> { impl<S: BaseFloat> Rotation<S, Vector2<S>, Point2<S>> for Basis2<S> {
#[inline] #[inline]
fn identity() -> Basis2<S> { Basis2{ mat: Matrix2::identity() } } fn identity() -> Basis2<S> { Basis2{ mat: Matrix2::identity() } }
@ -263,7 +241,7 @@ impl<S: BaseFloat> ToQuaternion<S> for Basis3<S> {
fn to_quaternion(&self) -> Quaternion<S> { self.mat.to_quaternion() } fn to_quaternion(&self) -> Quaternion<S> { self.mat.to_quaternion() }
} }
impl<S: BaseFloat> Rotation<S, [S, ..3], Vector3<S>, Point3<S>> for Basis3<S> { impl<S: BaseFloat> Rotation<S, Vector3<S>, Point3<S>> for Basis3<S> {
#[inline] #[inline]
fn identity() -> Basis3<S> { Basis3{ mat: Matrix3::identity() } } fn identity() -> Basis3<S> { Basis3{ mat: Matrix3::identity() } }

View file

@ -29,14 +29,7 @@ use vector::{Vector, Vector3};
/// A trait representing an [affine /// A trait representing an [affine
/// transformation](https://en.wikipedia.org/wiki/Affine_transformation) that /// transformation](https://en.wikipedia.org/wiki/Affine_transformation) that
/// can be applied to points or vectors. An affine transformation is one which /// can be applied to points or vectors. An affine transformation is one which
pub trait Transform pub trait Transform<S: BaseNum, V: Vector<S>, P: Point<S,V>> {
<
S: BaseNum,
Slice,
V: Vector<S,Slice>,
P: Point<S,V,Slice>
>
{
/// Create an identity transformation. That is, a transformation which /// Create an identity transformation. That is, a transformation which
/// does nothing. /// does nothing.
fn identity() -> Self; fn identity() -> Self;
@ -92,15 +85,7 @@ pub struct Decomposed<S,V,R> {
pub disp: V, pub disp: V,
} }
impl impl<S: BaseFloat, V: Vector<S>, P: Point<S, V>, R: Rotation<S, V, P>> Transform<S, V, P> for Decomposed<S,V,R> {
<
S: BaseFloat,
Slice,
V: Vector<S, Slice>,
P: Point<S, V, Slice>,
R: Rotation<S, Slice, V, P>
>
Transform<S, Slice, V, P> for Decomposed<S,V,R> {
#[inline] #[inline]
fn identity() -> Decomposed<S,V,R> { fn identity() -> Decomposed<S,V,R> {
Decomposed { Decomposed {
@ -157,10 +142,7 @@ Transform<S, Slice, V, P> for Decomposed<S,V,R> {
} }
} }
pub trait Transform3<S> pub trait Transform3<S>: Transform<S, Vector3<S>, Point3<S>>+ ToMatrix4<S> {}
: Transform<S, [S, ..3], Vector3<S>, Point3<S>>
+ ToMatrix4<S>
{}
impl<S: BaseFloat, R: Rotation3<S>> ToMatrix4<S> for Decomposed<S, Vector3<S>, R> { impl<S: BaseFloat, R: Rotation3<S>> ToMatrix4<S> for Decomposed<S, Vector3<S>, R> {
fn to_matrix4(&self) -> Matrix4<S> { fn to_matrix4(&self) -> Matrix4<S> {
@ -185,7 +167,7 @@ pub struct AffineMatrix3<S> {
pub mat: Matrix4<S>, pub mat: Matrix4<S>,
} }
impl<S : BaseFloat> Transform<S, [S, ..3], Vector3<S>, Point3<S>> for AffineMatrix3<S> { impl<S : BaseFloat> Transform<S, Vector3<S>, Point3<S>> for AffineMatrix3<S> {
#[inline] #[inline]
fn identity() -> AffineMatrix3<S> { fn identity() -> AffineMatrix3<S> {
AffineMatrix3 { mat: Matrix4::identity() } AffineMatrix3 { mat: Matrix4::identity() }
@ -226,7 +208,7 @@ impl<S: BaseFloat> Transform3<S> for AffineMatrix3<S> {}
/// A transformation in three dimensions consisting of a rotation, /// A transformation in three dimensions consisting of a rotation,
/// displacement vector and scale amount. /// displacement vector and scale amount.
pub struct Transform3D<S>( Decomposed<S,Vector3<S>,Quaternion<S>> ); pub struct Transform3D<S>(Decomposed<S,Vector3<S>,Quaternion<S>>);
impl<S: BaseFloat> Transform3D<S> { impl<S: BaseFloat> Transform3D<S> {
#[inline] #[inline]

View file

@ -14,90 +14,85 @@
// limitations under the License. // limitations under the License.
use std::fmt; use std::fmt;
use std::mem;
use std::num::{Zero, zero, One, one}; use std::num::{Zero, zero, One, one};
use angle::{Rad, atan2, acos}; use angle::{Rad, atan2, acos};
use approx::ApproxEq; use approx::ApproxEq;
use array::{Array, build}; use array::Array1;
use num::{BaseNum, BaseFloat, PartialOrd}; use num::{BaseNum, BaseFloat};
/// 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 pub trait Vector<S: BaseNum>: Array1<S>
< + Neg<Self>
S: BaseNum, + Zero
Slice + One {
>
: Array<S, Slice>
+ Neg<Self>
+ Zero + One
{
/// Add a scalar to this vector, returning a new vector. /// Add a scalar to this vector, returning a new vector.
#[inline] fn add_s(&self, s: S) -> Self { build(|i| self.i(i).add(&s)) } fn add_s(&self, s: S) -> Self;
/// Subtract a scalar from this vector, returning a new vector. /// Subtract a scalar from this vector, returning a new vector.
#[inline] fn sub_s(&self, s: S) -> Self { build(|i| self.i(i).sub(&s)) } fn sub_s(&self, s: S) -> Self;
/// Multiply this vector by a scalar, returning a new vector. /// Multiply this vector by a scalar, returning a new vector.
#[inline] fn mul_s(&self, s: S) -> Self { build(|i| self.i(i).mul(&s)) } fn mul_s(&self, s: S) -> Self;
/// Divide this vector by a scalar, returning a new vector. /// Divide this vector by a scalar, returning a new vector.
#[inline] fn div_s(&self, s: S) -> Self { build(|i| self.i(i).div(&s)) } fn div_s(&self, s: S) -> Self;
/// Take the remainder of this vector by a scalar, returning a new vector. /// Take the remainder of this vector by a scalar, returning a new vector.
#[inline] fn rem_s(&self, s: S) -> Self { build(|i| self.i(i).rem(&s)) } fn rem_s(&self, s: S) -> Self;
/// Add this vector to another, returning a new vector. /// Add this vector to another, returning a new vector.
#[inline] fn add_v(&self, other: &Self) -> Self { build(|i| self.i(i).add(other.i(i))) } fn add_v(&self, v: &Self) -> Self;
/// Subtract another vector from this one, returning a new vector. /// Subtract another vector from this one, returning a new vector.
#[inline] fn sub_v(&self, other: &Self) -> Self { build(|i| self.i(i).sub(other.i(i))) } fn sub_v(&self, v: &Self) -> Self;
/// Multiply this vector by another, returning a new vector. /// Multiply this vector by another, returning a new vector.
#[inline] fn mul_v(&self, other: &Self) -> Self { build(|i| self.i(i).mul(other.i(i))) } fn mul_v(&self, v: &Self) -> Self;
/// Divide this vector by another, returning a new vector. /// Divide this vector by another, returning a new vector.
#[inline] fn div_v(&self, other: &Self) -> Self { build(|i| self.i(i).div(other.i(i))) } fn div_v(&self, v: &Self) -> Self;
/// Take the remainder of this vector by another, returning a new scalar. /// Take the remainder of this vector by another, returning a new scalar.
#[inline] fn rem_v(&self, other: &Self) -> Self { build(|i| self.i(i).rem(other.i(i))) } fn rem_v(&self, v: &Self) -> Self;
/// Negate this vector in-place. /// Negate this vector in-place.
#[inline] fn neg_self(&mut self) { self.each_mut(|_, x| *x = x.neg()) } fn neg_self(&mut self);
/// Add a scalar to this vector in-place. /// Add a scalar to this vector in-place.
#[inline] fn add_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.add(&s)) } fn add_self_s(&mut self, s: S);
/// Subtract a scalar from this vector, in-place. /// Subtract a scalar from this vector, in-place.
#[inline] fn sub_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.sub(&s)) } fn sub_self_s(&mut self, s: S);
/// Multiply this vector by a scalar, in-place. /// Multiply this vector by a scalar, in-place.
#[inline] fn mul_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.mul(&s)) } fn mul_self_s(&mut self, s: S);
/// Divide this vector by a scalar, in-place. /// Divide this vector by a scalar, in-place.
#[inline] fn div_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.div(&s)) } fn div_self_s(&mut self, s: S);
/// Take the remainder of this vector by a scalar, in-place. /// Take the remainder of this vector by a scalar, in-place.
#[inline] fn rem_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.rem(&s)) } fn rem_self_s(&mut self, s: S);
/// Add another vector to this one, in-place. /// Add another vector to this one, in-place.
#[inline] fn add_self_v(&mut self, other: &Self) { self.each_mut(|i, x| *x = x.add(other.i(i))) } fn add_self_v(&mut self, v: &Self);
/// Subtract another vector from this one, in-place. /// Subtract another vector from this one, in-place.
#[inline] fn sub_self_v(&mut self, other: &Self) { self.each_mut(|i, x| *x = x.sub(other.i(i))) } fn sub_self_v(&mut self, v: &Self);
/// Multiply this matrix by another, in-place. /// Multiply this matrix by another, in-place.
#[inline] fn mul_self_v(&mut self, other: &Self) { self.each_mut(|i, x| *x = x.mul(other.i(i))) } fn mul_self_v(&mut self, v: &Self);
/// Divide this matrix by anothor, in-place. /// Divide this matrix by anothor, in-place.
#[inline] fn div_self_v(&mut self, other: &Self) { self.each_mut(|i, x| *x = x.div(other.i(i))) } fn div_self_v(&mut self, v: &Self);
/// Take the remainder of this vector by another, in-place. /// Take the remainder of this vector by another, in-place.
#[inline] fn rem_self_v(&mut self, other: &Self) { self.each_mut(|i, x| *x = x.rem(other.i(i))) } fn rem_self_v(&mut self, v: &Self);
/// The sum of each component of the vector. /// The sum of each component of the vector.
#[inline] fn comp_add(&self) -> S { self.fold(|a, b| a.add(b)) } fn comp_add(&self) -> S;
/// The product of each component of the vector. /// The product of each component of the vector.
#[inline] fn comp_mul(&self) -> S { self.fold(|a, b| a.mul(b)) } fn comp_mul(&self) -> S;
/// Vector dot product. /// Vector dot product.
#[inline] fn dot(&self, other: &Self) -> S { self.mul_v(other).comp_add() } #[inline]
fn dot(&self, v: &Self) -> S { self.mul_v(v).comp_add() }
/// The minimum component of the vector. /// The minimum component of the vector.
#[inline] fn comp_min(&self) -> S { self.fold(|a, b| a.partial_min(*b)) } fn comp_min(&self) -> S;
/// The maximum component of the vector. /// The maximum component of the vector.
#[inline] fn comp_max(&self) -> S { self.fold(|a, b| a.partial_max(*b)) } fn comp_max(&self) -> S;
} }
/// Dot product of two vectors. /// Dot product of two vectors.
#[inline] pub fn dot<S: BaseNum, Slice, V: Vector<S, Slice>>(a: V, b: V) -> S { a.dot(&b) } #[inline] pub fn dot<S: BaseNum, V: Vector<S>>(a: V, b: V) -> S { a.dot(&b) }
// Utility macro for generating associated functions for the vectors // Utility macro for generating associated functions for the vectors
macro_rules! vec( macro_rules! vec(
@ -105,19 +100,23 @@ macro_rules! vec(
#[deriving(Eq, TotalEq, Clone, Hash)] #[deriving(Eq, TotalEq, Clone, Hash)]
pub struct $Self<S> { $(pub $field: S),+ } pub struct $Self<S> { $(pub $field: S),+ }
impl<$S: BaseNum> $Self<$S> { impl<$S> $Self<$S> {
/// Construct a new vector, using the provided values. /// Construct a new vector, using the provided values.
#[inline] #[inline]
pub fn new($($field: $S),+) -> $Self<$S> { pub fn new($($field: $S),+) -> $Self<$S> {
$Self { $($field: $field),+ } $Self { $($field: $field),+ }
} }
}
impl<$S: Clone> $Self<$S> {
/// Construct a vector from a single value, replicating it. /// Construct a vector from a single value, replicating it.
#[inline] #[inline]
pub fn from_value(value: $S) -> $Self<$S> { pub fn from_value(value: $S) -> $Self<$S> {
$Self { $($field: value.clone()),+ } $Self { $($field: value.clone()),+ }
} }
}
impl<$S: BaseNum> $Self<$S> {
/// The additive identity of the vector. /// The additive identity of the vector.
#[inline] #[inline]
pub fn zero() -> $Self<$S> { $Self::from_value(zero()) } pub fn zero() -> $Self<$S> { $Self::from_value(zero()) }
@ -127,12 +126,65 @@ macro_rules! vec(
pub fn ident() -> $Self<$S> { $Self::from_value(one()) } pub fn ident() -> $Self<$S> { $Self::from_value(one()) }
} }
impl<S: Copy> Array1<S> for $Self<S> {
#[inline]
fn ptr<'a>(&'a self) -> &'a S { &self.x }
#[inline]
fn mut_ptr<'a>(&'a mut self) -> &'a mut S { &mut self.x }
#[inline]
fn i(&self, i: uint) -> S {
let slice: &[S, ..$n] = unsafe { mem::transmute(self) };
slice[i]
}
#[inline]
fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut S {
let slice: &'a mut [S, ..$n] = unsafe { mem::transmute(self) };
&'a mut slice[i]
}
}
impl<S: BaseNum> Vector<S> for $Self<S> {
#[inline] fn add_s(&self, s: S) -> $Self<S> { $Self::new($(self.$field + s),+) }
#[inline] fn sub_s(&self, s: S) -> $Self<S> { $Self::new($(self.$field - s),+) }
#[inline] fn mul_s(&self, s: S) -> $Self<S> { $Self::new($(self.$field * s),+) }
#[inline] fn div_s(&self, s: S) -> $Self<S> { $Self::new($(self.$field / s),+) }
#[inline] fn rem_s(&self, s: S) -> $Self<S> { $Self::new($(self.$field % s),+) }
#[inline] fn add_v(&self, v: &$Self<S>) -> $Self<S> { $Self::new($(self.$field + v.$field),+) }
#[inline] fn sub_v(&self, v: &$Self<S>) -> $Self<S> { $Self::new($(self.$field - v.$field),+) }
#[inline] fn mul_v(&self, v: &$Self<S>) -> $Self<S> { $Self::new($(self.$field * v.$field),+) }
#[inline] fn div_v(&self, v: &$Self<S>) -> $Self<S> { $Self::new($(self.$field / v.$field),+) }
#[inline] fn rem_v(&self, v: &$Self<S>) -> $Self<S> { $Self::new($(self.$field % v.$field),+) }
#[inline] fn neg_self(&mut self) { $(self.$field = -self.$field;)+ }
#[inline] fn add_self_s(&mut self, s: S) { $(self.$field = self.$field + s;)+ }
#[inline] fn sub_self_s(&mut self, s: S) { $(self.$field = self.$field - s;)+ }
#[inline] fn mul_self_s(&mut self, s: S) { $(self.$field = self.$field * s;)+ }
#[inline] fn div_self_s(&mut self, s: S) { $(self.$field = self.$field / s;)+ }
#[inline] fn rem_self_s(&mut self, s: S) { $(self.$field = self.$field % s;)+ }
#[inline] fn add_self_v(&mut self, v: &$Self<S>) { $(self.$field = self.$field + v.$field;)+ }
#[inline] fn sub_self_v(&mut self, v: &$Self<S>) { $(self.$field = self.$field - v.$field;)+ }
#[inline] fn mul_self_v(&mut self, v: &$Self<S>) { $(self.$field = self.$field * v.$field;)+ }
#[inline] fn div_self_v(&mut self, v: &$Self<S>) { $(self.$field = self.$field / v.$field;)+ }
#[inline] fn rem_self_v(&mut self, v: &$Self<S>) { $(self.$field = self.$field % v.$field;)+ }
#[inline] fn comp_add(&self) -> S { fold!(&add, { $(self.$field),+ }) }
#[inline] fn comp_mul(&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: BaseNum> Add<$Self<S>, $Self<S>> for $Self<S> { impl<S: BaseNum> Add<$Self<S>, $Self<S>> for $Self<S> {
#[inline] fn add(&self, other: &$Self<S>) -> $Self<S> { self.add_v(other) } #[inline] fn add(&self, v: &$Self<S>) -> $Self<S> { self.add_v(v) }
} }
impl<S: BaseNum> Sub<$Self<S>, $Self<S>> for $Self<S> { impl<S: BaseNum> Sub<$Self<S>, $Self<S>> for $Self<S> {
#[inline] fn sub(&self, other: &$Self<S>) -> $Self<S> { self.sub_v(other) } #[inline] fn sub(&self, v: &$Self<S>) -> $Self<S> { self.sub_v(v) }
} }
impl<S: BaseNum> Zero for $Self<S> { impl<S: BaseNum> Zero for $Self<S> {
@ -141,29 +193,39 @@ macro_rules! vec(
} }
impl<S: BaseNum> Neg<$Self<S>> for $Self<S> { impl<S: BaseNum> Neg<$Self<S>> for $Self<S> {
#[inline] fn neg(&self) -> $Self<S> { build(|i| self.i(i).neg()) } #[inline] fn neg(&self) -> $Self<S> { $Self::new($(-self.$field),+) }
} }
impl<S: BaseNum> Mul<$Self<S>, $Self<S>> for $Self<S> { impl<S: BaseNum> Mul<$Self<S>, $Self<S>> for $Self<S> {
#[inline] fn mul(&self, other: &$Self<S>) -> $Self<S> { self.mul_v(other) } #[inline] fn mul(&self, v: &$Self<S>) -> $Self<S> { self.mul_v(v) }
} }
impl<S: BaseNum> One for $Self<S> { impl<S: BaseNum> One for $Self<S> {
#[inline] fn one() -> $Self<S> { $Self::from_value(one()) } #[inline] fn one() -> $Self<S> { $Self::from_value(one()) }
} }
impl<S: BaseNum> Vector<S, [S, ..$n]> for $Self<S> {} impl<S: BaseFloat> ApproxEq<S> for $Self<S> {
#[inline]
fn approx_eq_eps(&self, other: &$Self<S>, epsilon: &S) -> bool {
$(self.$field.approx_eq_eps(&other.$field, epsilon))&&+
}
}
) )
) )
macro_rules! fold {
(&$method:ident, { $x:expr, $y:expr }) => { $x.$method(&$y) };
(&$method:ident, { $x:expr, $y:expr, $z:expr }) => { $x.$method(&$y).$method(&$z) };
(&$method:ident, { $x:expr, $y:expr, $z:expr, $w:expr }) => { $x.$method(&$y).$method(&$z).$method(&$w) };
($method:ident, { $x:expr, $y:expr }) => { $x.$method($y) };
($method:ident, { $x:expr, $y:expr, $z:expr }) => { $x.$method($y).$method($z) };
($method:ident, { $x:expr, $y:expr, $z:expr, $w:expr }) => { $x.$method($y).$method($z).$method($w) };
}
vec!(Vector2<S> { x, y }, 2) vec!(Vector2<S> { x, y }, 2)
vec!(Vector3<S> { x, y, z }, 3) vec!(Vector3<S> { x, y, z }, 3)
vec!(Vector4<S> { x, y, z, w }, 4) vec!(Vector4<S> { x, y, z, w }, 4)
array!(impl<S> Vector2<S> -> [S, ..2] _2)
array!(impl<S> Vector3<S> -> [S, ..3] _3)
array!(impl<S> Vector4<S> -> [S, ..4] _4)
/// Operations specific to numeric two-dimensional vectors. /// Operations specific to numeric two-dimensional vectors.
impl<S: BaseNum> Vector2<S> { impl<S: BaseNum> Vector2<S> {
/// A unit vector in the `x` direction. /// A unit vector in the `x` direction.
@ -243,14 +305,8 @@ impl<S: BaseNum> Vector4<S> {
/// Specifies geometric operations for vectors. This is only implemented for /// Specifies geometric operations for vectors. This is only implemented for
/// 2-dimensional and 3-dimensional vectors. /// 2-dimensional and 3-dimensional vectors.
pub trait EuclideanVector pub trait EuclideanVector<S: BaseFloat>: Vector<S>
< + ApproxEq<S> {
S: BaseFloat,
Slice
>
: Vector<S, Slice>
+ ApproxEq<S>
{
/// Returns `true` if the vector is perpendicular (at right angles) to the /// Returns `true` if the vector is perpendicular (at right angles) to the
/// other vector. /// other vector.
fn is_perpendicular(&self, other: &Self) -> bool { fn is_perpendicular(&self, other: &Self) -> bool {
@ -316,43 +372,40 @@ pub trait EuclideanVector
} }
} }
impl<S: BaseFloat> impl<S: BaseFloat> EuclideanVector<S> for Vector2<S> {
EuclideanVector<S, [S, ..2]> for Vector2<S> {
#[inline] #[inline]
fn angle(&self, other: &Vector2<S>) -> Rad<S> { fn angle(&self, other: &Vector2<S>) -> Rad<S> {
atan2(self.perp_dot(other), self.dot(other)) atan2(self.perp_dot(other), self.dot(other))
} }
} }
impl<S: BaseFloat> impl<S: BaseFloat> EuclideanVector<S> for Vector3<S> {
EuclideanVector<S, [S, ..3]> for Vector3<S> {
#[inline] #[inline]
fn angle(&self, other: &Vector3<S>) -> Rad<S> { fn angle(&self, other: &Vector3<S>) -> Rad<S> {
atan2(self.cross(other).length(), self.dot(other)) atan2(self.cross(other).length(), self.dot(other))
} }
} }
impl<S: BaseFloat> impl<S: BaseFloat> EuclideanVector<S> for Vector4<S> {
EuclideanVector<S, [S, ..4]> for Vector4<S> {
#[inline] #[inline]
fn angle(&self, other: &Vector4<S>) -> Rad<S> { fn angle(&self, other: &Vector4<S>) -> Rad<S> {
acos(self.dot(other) / (self.length() * other.length())) acos(self.dot(other) / (self.length() * other.length()))
} }
} }
impl<S: fmt::Show> fmt::Show for Vector2<S> { impl<S: BaseNum> fmt::Show for Vector2<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}, {}]", self.x, self.y) write!(f, "[{}, {}]", self.x, self.y)
} }
} }
impl<S: fmt::Show> fmt::Show for Vector3<S> { impl<S: BaseNum> fmt::Show for Vector3<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}, {}, {}]", self.x, self.y, self.z) write!(f, "[{}, {}, {}]", self.x, self.y, self.z)
} }
} }
impl<S: fmt::Show> fmt::Show for Vector4<S> { impl<S: BaseNum> fmt::Show for Vector4<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
} }