diff --git a/src/cgmath/aabb.rs b/src/cgmath/aabb.rs index 68bd905..60a555c 100644 --- a/src/cgmath/aabb.rs +++ b/src/cgmath/aabb.rs @@ -22,19 +22,11 @@ use point::{Point, Point2, Point3}; use vector::{Vector, Vector2, Vector3}; -use array::build; use num::BaseNum; use std::fmt; use std::num::{zero, one}; -use std::iter::Iterator; -pub trait Aabb -< - S: BaseNum, - V: Vector, - P: Point, - Slice -> { +pub trait Aabb, P: Point> { /// Create a new AABB using two points as opposing corners. fn new(p1: P, p2: P) -> Self; @@ -45,28 +37,29 @@ pub trait Aabb fn max<'a>(&'a self) -> &'a P; /// 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. - #[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. - #[inline] fn center(&self) -> P { + #[inline] + fn center(&self) -> P { let two = one::() + one::(); self.min().add_v(&self.dim().div_s(two)) } /// Tests whether a point is cointained in the box, inclusive for min corner /// and exclusive for the max corner. - #[inline] fn contains(&self, p: &P) -> bool { - p.sub_p(self.min()).iter().all(|x| *x >= zero::()) && - self.max().sub_p(p).iter().all(|x| *x > zero::()) - } + #[inline] + fn contains(&self, p: &P) -> bool; /// Returns a new AABB that is grown to include the given point. fn grow(&self, p: &P) -> Self { - let min : P = build(|i| self.min().i(i).partial_min(*p.i(i))); - let max : P = build(|i| self.max().i(i).partial_max(*p.i(i))); + let min = self.min().min(p); + let max = self.max().max(p); Aabb::new(min, max) } @@ -108,10 +101,23 @@ impl Aabb2 { } } -impl Aabb, Point2, [S, ..2]> for Aabb2 { +impl Aabb, Point2> for Aabb2 { + #[inline] fn new(p1: Point2, p2: Point2) -> Aabb2 { Aabb2::new(p1, p2) } - #[inline] fn min<'a>(&'a self) -> &'a Point2 { &self.min } - #[inline] fn max<'a>(&'a self) -> &'a Point2 { &self.max } + + #[inline] + fn min<'a>(&'a self) -> &'a Point2 { &self.min } + + #[inline] + fn max<'a>(&'a self) -> &'a Point2 { &self.max } + + #[inline] + fn contains(&self, p: &Point2) -> 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 fmt::Show for Aabb2 { @@ -142,10 +148,23 @@ impl Aabb3 { } } -impl Aabb, Point3, [S, ..3]> for Aabb3 { +impl Aabb, Point3> for Aabb3 { + #[inline] fn new(p1: Point3, p2: Point3) -> Aabb3 { Aabb3::new(p1, p2) } - #[inline] fn min<'a>(&'a self) -> &'a Point3 { &self.min } - #[inline] fn max<'a>(&'a self) -> &'a Point3 { &self.max } + + #[inline] + fn min<'a>(&'a self) -> &'a Point3 { &self.min } + + #[inline] + fn max<'a>(&'a self) -> &'a Point3 { &self.max } + + #[inline] + fn contains(&self, p: &Point3) -> 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 fmt::Show for Aabb3 { diff --git a/src/cgmath/approx.rs b/src/cgmath/approx.rs index 3827c80..dced6dd 100644 --- a/src/cgmath/approx.rs +++ b/src/cgmath/approx.rs @@ -15,12 +15,6 @@ 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 { fn approx_epsilon(_hack: Option) -> T { num::cast(1.0e-5).unwrap() @@ -35,7 +29,7 @@ pub trait ApproxEq { } -macro_rules! approx_simple( +macro_rules! approx_float( ($S:ident) => ( impl ApproxEq<$S> for $S { #[inline] @@ -46,31 +40,5 @@ macro_rules! approx_simple( ) ) -approx_simple!(f32) -approx_simple!(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 Matrix2) -approx_array!(impl Matrix3) -approx_array!(impl Matrix4) - -approx_array!(impl Quaternion) - -approx_array!(impl Vector2) -approx_array!(impl Vector3) -approx_array!(impl Vector4) - -approx_array!(impl Point2) -approx_array!(impl Point3) +approx_float!(f32) +approx_float!(f64) diff --git a/src/cgmath/array.rs b/src/cgmath/array.rs index 4f0417d..ea1a2d2 100644 --- a/src/cgmath/array.rs +++ b/src/cgmath/array.rs @@ -13,138 +13,84 @@ // See the License for the specific language governing permissions and // 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 { + /// 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 { /// 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. - fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut T; - - /// 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>; + fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut Element; #[inline] /// Swap the elements at indices `a` and `b` in-place. - fn swap(&mut self, a: uint, b: uint) { - let tmp = self.i(a).clone(); - *self.mut_i(a) = self.i(b).clone(); - *self.mut_i(b) = tmp; + fn swap_i(&mut self, a: uint, b: uint) { + // Yeah, ok borrow checker – I know what I'm doing here + unsafe { ptr::swap(self.mut_i(a), self.mut_i(b)) }; } - /// Fold over this array, creating the same type as the type of the - /// elements. Use `.iter().fold(...)` for a more flexible fold. The first - /// element passed to the fold is the accumulator. It starts as the first - /// value in the array. - 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|); + /// Replace an element in the array. + #[inline] + fn replace_i(&mut self, i: uint, src: Element) -> Element { + mem::replace(self.mut_i(i), src) + } } -macro_rules! array( - (impl<$S:ident> $Self:ty -> [$T:ty, ..$n:expr] $_n:ident) => ( - impl<$S: Clone> Array<$T, [$T,..$n]> for $Self { - #[inline] - fn i<'a>(&'a self, i: uint) -> &'a $T { - &'a self.as_slice()[i] - } +/// A column-major array +pub trait Array2, Row: Array1, Element: Copy> { + /// Get the pointer to the first element of the array. + fn ptr<'a>(&'a self) -> &'a Element; - #[inline] - fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut $T { - &'a mut self.as_mut_slice()[i] - } + /// Get a mutable pointer to the first element of the array. + fn mut_ptr<'a>(&'a mut self) -> &'a mut Element; - #[inline] - fn as_slice<'a>(&'a self) -> &'a [$T,..$n] { - unsafe { ::std::mem::transmute(self) } - } + /// Get a shared reference to a column of this array. + fn c<'a>(&'a self, c: uint) -> &'a Column; - #[inline] - fn as_mut_slice<'a>(&'a mut self) -> &'a mut [$T,..$n] { - unsafe { ::std::mem::transmute(self) } - } + /// Get a mutable reference to a column of this array. + fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut Column; - #[inline] - fn from_repr(slice: [$T,..$n]) -> $Self { - unsafe { ::std::mem::transmute(slice) } - } + /// Swap two columns of this array. + #[inline] + fn swap_c(&mut self, a: uint, b: uint) { + unsafe { ptr::swap(self.mut_c(a), self.mut_c(b)) }; + } - #[inline] - fn build(builder: |i: uint| -> $T) -> $Self { - Array::from_repr(gen_builder!($_n)) - } + /// Replace a column in the array. + #[inline] + fn replace_c(&mut self, c: uint, src: Column) -> Column { + mem::replace(self.mut_c(c), src) + } - #[inline] - fn iter<'a>(&'a self) -> ::std::slice::Items<'a, $T> { - self.as_slice().iter() - } + /// Get a row from this array by-value. + fn r(&self, r: uint) -> Row; - #[inline] - fn mut_iter<'a>(&'a mut self) -> ::std::slice::MutItems<'a, $T> { - self.as_mut_slice().mut_iter() - } + /// Swap two rows of this array. + fn swap_r(&mut self, a: uint, b: uint); - #[inline] - fn fold(&self, f: |&$T, &$T| -> $T) -> $T { - gen_fold!($_n) - } + /// Return a shared reference to the element at column `c` and row `r`. + #[inline] + fn cr(&self, c: uint, r: uint) -> Element { self.c(c).i(r) } - #[inline] - fn each_mut(&mut self, f: |i: uint, x: &mut $T|) { - gen_each_mut!($_n) - } - } - ) -) + /// 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 Element { + self.mut_c(c).mut_i(r) + } -#[inline] -pub fn build>(builder: |i: uint| -> T) -> A { - Array::build(builder) + /// Swap the values at index `a` and `b` + #[inline] + 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)); }); -) - diff --git a/src/cgmath/frustum.rs b/src/cgmath/frustum.rs index a14f99b..2456c0c 100644 --- a/src/cgmath/frustum.rs +++ b/src/cgmath/frustum.rs @@ -15,7 +15,8 @@ //! View frustum for visibility determination -use matrix::{Matrix, Matrix4}; +use array::Array2; +use matrix::Matrix4; use num::BaseFloat; use plane::Plane; use point::Point3; diff --git a/src/cgmath/lib.rs b/src/cgmath/lib.rs index 00a222b..308c920 100644 --- a/src/cgmath/lib.rs +++ b/src/cgmath/lib.rs @@ -36,8 +36,6 @@ //! `look_at`, `from_angle`, `from_euler`, and `from_axis_angle` methods. //! These are provided for convenience. -pub use array::Array; - mod array; pub mod matrix; @@ -63,5 +61,3 @@ pub mod sphere; pub mod approx; pub mod num; -pub mod ptr; - diff --git a/src/cgmath/line.rs b/src/cgmath/line.rs index 72771f5..de4a365 100644 --- a/src/cgmath/line.rs +++ b/src/cgmath/line.rs @@ -24,20 +24,12 @@ use intersect::Intersect; /// A generic directed line segment from `origin` to `dest`. #[deriving(Clone, Eq)] -pub struct Line

-{ +pub struct Line

{ pub origin: P, pub dest: P, } -impl -< - S: BaseNum, - Slice, - V: Vector, - P: Point -> Line

-{ +impl, P: Point> Line

{ pub fn new(origin: P, dest: P) -> Line

{ Line { origin:origin, dest:dest } } diff --git a/src/cgmath/matrix.rs b/src/cgmath/matrix.rs index e5620ed..7fa08e3 100644 --- a/src/cgmath/matrix.rs +++ b/src/cgmath/matrix.rs @@ -16,11 +16,12 @@ //! Column major, square matrix types and traits. use std::fmt; +use std::mem; use std::num::{Zero, zero, One, one, cast}; use angle::{Rad, sin, cos, sin_cos}; use approx::ApproxEq; -use array::{Array, build}; +use array::{Array1, Array2}; use num::{BaseFloat, BaseNum}; use point::{Point, Point3}; use quaternion::{Quaternion, ToQuaternion}; @@ -267,107 +268,47 @@ Matrix4 { } } -array!(impl Matrix2 -> [Vector2, ..2] _2) -array!(impl Matrix3 -> [Vector3, ..3] _3) -array!(impl Matrix4 -> [Vector4, ..4] _4) - -pub trait Matrix -< - S: BaseFloat, Slice, - V: Clone + Vector + Array, VSlice -> -: Array -+ Neg -+ Zero + One -+ ApproxEq -{ - /// 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()) } - +pub trait Matrix>: Array2 + + Neg + + Zero + One + + ApproxEq { /// 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. - #[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 /// 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. - #[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. - #[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. - #[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. - 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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. fn transpose(&self) -> Self; @@ -377,8 +318,7 @@ pub trait Matrix fn determinant(&self) -> S; /// Return a vector containing the diagonal of this matrix. - #[inline] - fn diagonal(&self) -> V { build(|i| self.cr(i, i).clone()) } + fn diagonal(&self) -> V; /// Return the trace of this matrix. That is, the sum of the diagonal. #[inline] @@ -397,16 +337,12 @@ pub trait Matrix /// Test if this matrix is invertible. #[inline] - fn is_invertible(&self) -> bool { - !self.determinant().approx_eq(&zero()) - } + fn is_invertible(&self) -> bool { !self.determinant().approx_eq(&zero()) } /// Test if this matrix is the identity matrix. That is, it is diagonal /// and every element in the diagonal is one. #[inline] - fn is_identity(&self) -> bool { - self.approx_eq(&one()) - } + fn is_identity(&self) -> bool { self.approx_eq(&one()) } /// Test if this is a diagonal matrix. That is, every element outside of /// the diagonal is 0. @@ -425,9 +361,9 @@ impl Sub, Matrix2> for Matrix2 { #[inline] fn sub impl Sub, Matrix3> for Matrix3 { #[inline] fn sub(&self, other: &Matrix3) -> Matrix3 { self.sub_m(other) } } impl Sub, Matrix4> for Matrix4 { #[inline] fn sub(&self, other: &Matrix4) -> Matrix4 { self.sub_m(other) } } -impl Neg> for Matrix2 { #[inline] fn neg(&self) -> Matrix2 { build(|i| self.i(i).neg()) } } -impl Neg> for Matrix3 { #[inline] fn neg(&self) -> Matrix3 { build(|i| self.i(i).neg()) } } -impl Neg> for Matrix4 { #[inline] fn neg(&self) -> Matrix4 { build(|i| self.i(i).neg()) } } +impl Neg> for Matrix2 { #[inline] fn neg(&self) -> Matrix2 { Matrix2::from_cols(self.c(0).neg(), self.c(1).neg()) } } +impl Neg> for Matrix3 { #[inline] fn neg(&self) -> Matrix3 { Matrix3::from_cols(self.c(0).neg(), self.c(1).neg(), self.c(2).neg()) } } +impl Neg> for Matrix4 { #[inline] fn neg(&self) -> Matrix4 { Matrix4::from_cols(self.c(0).neg(), self.c(1).neg(), self.c(2).neg(), self.c(3).neg()) } } impl Zero for Matrix2 { #[inline] fn zero() -> Matrix2 { Matrix2::zero() } #[inline] fn is_zero(&self) -> bool { *self == zero() } } impl Zero for Matrix3 { #[inline] fn zero() -> Matrix3 { Matrix3::zero() } #[inline] fn is_zero(&self) -> bool { *self == zero() } } @@ -441,15 +377,186 @@ impl One for Matrix2 { #[inline] fn one() -> Matrix2 { Matri impl One for Matrix3 { #[inline] fn one() -> Matrix3 { Matrix3::identity() } } impl One for Matrix4 { #[inline] fn one() -> Matrix4 { Matrix4::identity() } } -impl -Matrix, ..2], Vector2, [S, ..2]> -for Matrix2 -{ +impl Array2, Vector2, S> for Matrix2 { + #[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 Vector2 { + let slice: &'a [Vector2, ..2] = unsafe { mem::transmute(self) }; + &'a slice[c] + } + + #[inline] + fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut Vector2 { + let slice: &'a mut [Vector2, ..2] = unsafe { mem::transmute(self) }; + &'a mut slice[c] + } + + #[inline] + fn r(&self, r: uint) -> Vector2 { + 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 Array2, Vector3, S> for Matrix3 { + #[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 { + let slice: &'a [Vector3, ..3] = unsafe { mem::transmute(self) }; + &'a slice[c] + } + + #[inline] + fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut Vector3 { + let slice: &'a mut [Vector3, ..3] = unsafe { mem::transmute(self) }; + &'a mut slice[c] + } + + #[inline] + fn r(&self, r: uint) -> Vector3 { + 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 Array2, Vector4, S> for Matrix4 { + #[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 { + let slice: &'a [Vector4, ..4] = unsafe { mem::transmute(self) }; + &'a slice[c] + } + + #[inline] + fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut Vector4 { + let slice: &'a mut [Vector4, ..4] = unsafe { mem::transmute(self) }; + &'a mut slice[c] + } + + #[inline] + fn r(&self, r: uint) -> Vector4 { + 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 Matrix> for Matrix2 { + #[inline] + fn mul_s(&self, s: S) -> Matrix2 { + Matrix2::from_cols(self.c(0).mul_s(s), + self.c(1).mul_s(s)) + } + + #[inline] + fn div_s(&self, s: S) -> Matrix2 { + Matrix2::from_cols(self.c(0).div_s(s), + self.c(1).div_s(s)) + } + + #[inline] + fn rem_s(&self, s: S) -> Matrix2 { + Matrix2::from_cols(self.c(0).rem_s(s), + self.c(1).rem_s(s)) + } + + #[inline] + fn add_m(&self, m: &Matrix2) -> Matrix2 { + 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) -> Matrix2 { + 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) -> Vector2 { + Vector2::new(self.r(0).dot(v), + self.r(1).dot(v)) + } + fn mul_m(&self, other: &Matrix2) -> Matrix2 { 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))) } + #[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) { + 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) { + self.mut_c(0).sub_self_v(m.c(0)); + self.mut_c(1).sub_self_v(m.c(1)); + } + fn transpose(&self) -> Matrix2 { Matrix2::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(), self.cr(0, 1).clone(), self.cr(1, 1).clone()) @@ -462,7 +569,13 @@ for Matrix2 #[inline] 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 { + Vector2::new(self.cr(0, 0), + self.cr(1, 1)) } #[inline] @@ -471,8 +584,8 @@ for Matrix2 if det.approx_eq(&zero()) { None } else { - Some(Matrix2::new( *self.cr(1, 1) / det, -*self.cr(0, 1) / det, - -*self.cr(1, 0) / det, *self.cr(0, 0) / det)) + Some(Matrix2::new( self.cr(1, 1) / det, -self.cr(0, 1) / det, + -self.cr(1, 0) / det, self.cr(0, 0) / det)) } } @@ -485,21 +598,102 @@ for Matrix2 #[inline] fn is_symmetric(&self) -> bool { - self.cr(0, 1).approx_eq(self.cr(1, 0)) && - self.cr(1, 0).approx_eq(self.cr(0, 1)) + self.cr(0, 1).approx_eq(&self.cr(1, 0)) && + self.cr(1, 0).approx_eq(&self.cr(0, 1)) } } -impl -Matrix, ..3], Vector3, [S, ..3]> -for Matrix3 -{ +impl Matrix> for Matrix3 { + #[inline] + fn mul_s(&self, s: S) -> Matrix3 { + 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 { + 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 { + 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) -> Matrix3 { + 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) -> Matrix3 { + 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) -> Vector3 { + Vector3::new(self.r(0).dot(v), + self.r(1).dot(v), + self.r(2).dot(v)) + } + fn mul_m(&self, other: &Matrix3) -> Matrix3 { 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(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) { + 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) { + 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 { 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(), @@ -514,9 +708,16 @@ for Matrix3 } 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(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(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(2, 0) * (self.cr(0, 1) * self.cr(1, 2) - self.cr(1, 1) * self.cr(0, 2)) + } + + #[inline] + fn diagonal(&self) -> Vector3 { + Vector3::new(self.cr(0, 0), + self.cr(1, 1), + self.cr(2, 2)) } fn invert(&self) -> Option> { @@ -540,14 +741,14 @@ for Matrix3 } fn is_symmetric(&self) -> bool { - self.cr(0, 1).approx_eq(self.cr(1, 0)) && - self.cr(0, 2).approx_eq(self.cr(2, 0)) && + self.cr(0, 1).approx_eq(&self.cr(1, 0)) && + self.cr(0, 2).approx_eq(&self.cr(2, 0)) && - self.cr(1, 0).approx_eq(self.cr(0, 1)) && - self.cr(1, 2).approx_eq(self.cr(2, 1)) && + self.cr(1, 0).approx_eq(&self.cr(0, 1)) && + self.cr(1, 2).approx_eq(&self.cr(2, 1)) && - self.cr(2, 0).approx_eq(self.cr(0, 2)) && - self.cr(2, 1).approx_eq(self.cr(1, 2)) + self.cr(2, 0).approx_eq(&self.cr(0, 2)) && + self.cr(2, 1).approx_eq(&self.cr(1, 2)) } } @@ -557,16 +758,61 @@ for Matrix3 // around ~4 times. macro_rules! dot_matrix4( ($A:expr, $B:expr, $I:expr, $J:expr) => ( - (*$A.cr(0, $I)) * (*$B.cr($J, 0)) + - (*$A.cr(1, $I)) * (*$B.cr($J, 1)) + - (*$A.cr(2, $I)) * (*$B.cr($J, 2)) + - (*$A.cr(3, $I)) * (*$B.cr($J, 3)) + ($A.cr(0, $I)) * ($B.cr($J, 0)) + + ($A.cr(1, $I)) * ($B.cr($J, 1)) + + ($A.cr(2, $I)) * ($B.cr($J, 2)) + + ($A.cr(3, $I)) * ($B.cr($J, 3)) )) -impl -Matrix, ..4], Vector4, [S, ..4]> -for Matrix4 -{ +impl Matrix> for Matrix4 { + #[inline] + fn mul_s(&self, s: S) -> Matrix4 { + 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 { + 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 { + 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) -> Matrix4 { + 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) -> Matrix4 { + 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) -> Vector4 { + 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) -> Matrix4 { 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), @@ -574,6 +820,54 @@ for Matrix4 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) { + 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) { + 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 { 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(), @@ -604,10 +898,18 @@ for Matrix4 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, 0) * m0.determinant() - - *self.cr(1, 0) * m1.determinant() + - *self.cr(2, 0) * m2.determinant() - - *self.cr(3, 0) * m3.determinant() + self.cr(0, 0) * m0.determinant() - + self.cr(1, 0) * m1.determinant() + + self.cr(2, 0) * m2.determinant() - + self.cr(3, 0) * m3.determinant() + } + + #[inline] + fn diagonal(&self) -> Vector4 { + Vector4::new(self.cr(0, 0), + self.cr(1, 1), + self.cr(2, 2), + self.cr(3, 3)) } fn invert(&self) -> Option> { @@ -673,21 +975,48 @@ for Matrix4 } fn is_symmetric(&self) -> bool { - self.cr(0, 1).approx_eq(self.cr(1, 0)) && - self.cr(0, 2).approx_eq(self.cr(2, 0)) && - self.cr(0, 3).approx_eq(self.cr(3, 0)) && + self.cr(0, 1).approx_eq(&self.cr(1, 0)) && + self.cr(0, 2).approx_eq(&self.cr(2, 0)) && + self.cr(0, 3).approx_eq(&self.cr(3, 0)) && - self.cr(1, 0).approx_eq(self.cr(0, 1)) && - self.cr(1, 2).approx_eq(self.cr(2, 1)) && - self.cr(1, 3).approx_eq(self.cr(3, 1)) && + self.cr(1, 0).approx_eq(&self.cr(0, 1)) && + self.cr(1, 2).approx_eq(&self.cr(2, 1)) && + self.cr(1, 3).approx_eq(&self.cr(3, 1)) && - self.cr(2, 0).approx_eq(self.cr(0, 2)) && - self.cr(2, 1).approx_eq(self.cr(1, 2)) && - self.cr(2, 3).approx_eq(self.cr(3, 2)) && + self.cr(2, 0).approx_eq(&self.cr(0, 2)) && + self.cr(2, 1).approx_eq(&self.cr(1, 2)) && + self.cr(2, 3).approx_eq(&self.cr(3, 2)) && - self.cr(3, 0).approx_eq(self.cr(0, 3)) && - self.cr(3, 1).approx_eq(self.cr(1, 3)) && - self.cr(3, 2).approx_eq(self.cr(2, 3)) + self.cr(3, 0).approx_eq(&self.cr(0, 3)) && + self.cr(3, 1).approx_eq(&self.cr(1, 3)) && + self.cr(3, 2).approx_eq(&self.cr(2, 3)) + } +} + +impl ApproxEq for Matrix2 { + #[inline] + fn approx_eq_eps(&self, other: &Matrix2, epsilon: &S) -> bool { + self.c(0).approx_eq_eps(other.c(0), epsilon) && + self.c(1).approx_eq_eps(other.c(1), epsilon) + } +} + +impl ApproxEq for Matrix3 { + #[inline] + fn approx_eq_eps(&self, other: &Matrix3, 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 ApproxEq for Matrix4 { + #[inline] + fn approx_eq_eps(&self, other: &Matrix4, 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 { fn to_matrix4(&self) -> Matrix4; } -impl -ToMatrix3 for Matrix2 { +impl ToMatrix3 for Matrix2 { /// Clone the elements of a 2-dimensional matrix into the top-left corner /// of a 3-dimensional identity matrix. fn to_matrix3(&self) -> Matrix3 { @@ -722,8 +1050,7 @@ ToMatrix3 for Matrix2 { } } -impl -ToMatrix4 for Matrix2 { +impl ToMatrix4 for Matrix2 { /// Clone the elements of a 2-dimensional matrix into the top-left corner /// of a 4-dimensional identity matrix. fn to_matrix4(&self) -> Matrix4 { @@ -734,8 +1061,7 @@ ToMatrix4 for Matrix2 { } } -impl -ToMatrix4 for Matrix3 { +impl ToMatrix4 for Matrix3 { /// Clone the elements of a 3-dimensional matrix into the top-left corner /// of a 4-dimensional identity matrix. fn to_matrix4(&self) -> Matrix4 { @@ -746,8 +1072,7 @@ ToMatrix4 for Matrix3 { } } -impl -ToQuaternion for Matrix3 { +impl ToQuaternion for Matrix3 { /// Convert the matrix to a quaternion fn to_quaternion(&self) -> Quaternion { // http://www.cs.ucr.edu/~vbz/resources/quatut.pdf @@ -758,43 +1083,43 @@ ToQuaternion for Matrix3 { let s = (one::() + trace).sqrt(); let w = half * s; let s = half / s; - let x = (*self.cr(1, 2) - *self.cr(2, 1)) * s; - let y = (*self.cr(2, 0) - *self.cr(0, 2)) * s; - let z = (*self.cr(0, 1) - *self.cr(1, 0)) * s; + let x = (self.cr(1, 2) - self.cr(2, 1)) * s; + let y = (self.cr(2, 0) - self.cr(0, 2)) * s; + let z = (self.cr(0, 1) - self.cr(1, 0)) * s; Quaternion::new(w, x, y, z) } - () 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(); + () 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 w = half * s; let s = half / s; - let x = (*self.cr(0, 1) - *self.cr(1, 0)) * s; - let y = (*self.cr(2, 0) - *self.cr(0, 2)) * s; - let z = (*self.cr(1, 2) - *self.cr(2, 1)) * s; + let x = (self.cr(0, 1) - self.cr(1, 0)) * s; + let y = (self.cr(2, 0) - self.cr(0, 2)) * s; + let z = (self.cr(1, 2) - self.cr(2, 1)) * s; Quaternion::new(w, x, y, z) } - () 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(); + () 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 w = half * s; let s = half / s; - let x = (*self.cr(0, 1) - *self.cr(1, 0)) * s; - let y = (*self.cr(1, 2) - *self.cr(2, 1)) * s; - let z = (*self.cr(2, 0) - *self.cr(0, 2)) * s; + let x = (self.cr(0, 1) - self.cr(1, 0)) * s; + let y = (self.cr(1, 2) - self.cr(2, 1)) * s; + let z = (self.cr(2, 0) - self.cr(0, 2)) * s; 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 s = half / s; - let x = (*self.cr(2, 0) - *self.cr(0, 2)) * s; - let y = (*self.cr(1, 2) - *self.cr(2, 1)) * s; - let z = (*self.cr(0, 1) - *self.cr(1, 0)) * s; + let x = (self.cr(2, 0) - self.cr(0, 2)) * s; + let y = (self.cr(1, 2) - self.cr(2, 1)) * s; + let z = (self.cr(0, 1) - self.cr(1, 0)) * s; Quaternion::new(w, x, y, z) } } } } -impl fmt::Show for Matrix2 { +impl fmt::Show for Matrix2 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "[[{}, {}], [{}, {}]]", self.cr(0, 0), self.cr(0, 1), @@ -802,7 +1127,7 @@ impl fmt::Show for Matrix2 { } } -impl fmt::Show for Matrix3 { +impl fmt::Show for Matrix3 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "[[{}, {}, {}], [{}, {}, {}], [{}, {}, {}]]", self.cr(0, 0), self.cr(0, 1), self.cr(0, 2), @@ -811,7 +1136,7 @@ impl fmt::Show for Matrix3 { } } -impl fmt::Show for Matrix4 { +impl fmt::Show for Matrix4 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "[[{}, {}, {}, {}], [{}, {}, {}, {}], [{}, {}, {}, {}], [{}, {}, {}, {}]]", self.cr(0, 0), self.cr(0, 1), self.cr(0, 2), self.cr(0, 3), diff --git a/src/cgmath/point.rs b/src/cgmath/point.rs index 8769859..e0416fa 100644 --- a/src/cgmath/point.rs +++ b/src/cgmath/point.rs @@ -18,10 +18,12 @@ //! not have a fixed position. use std::fmt; +use std::mem; use std::num::{one, zero}; -use array::*; -use num::BaseNum; +use approx::ApproxEq; +use array::Array1; +use num::{BaseNum, BaseFloat}; use vector::*; /// A point in 2-dimensional space. @@ -61,56 +63,294 @@ impl Point3 { } /// Specifies the numeric operations for point types. -pub trait Point -< - S: BaseNum, - V: Vector, - Slice -> -: Array -{ +pub trait Point>: Array1 + Clone { /// Create a point at the origin. - #[inline] fn origin() -> Self{ build(|_i| zero::()) } + fn origin() -> Self; /// 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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. + fn dot(&self, v: &V) -> S; + + fn min(&self, p: &Self) -> Self; + + fn max(&self, p: &Self) -> Self; +} + +impl Array1 for Point2 { #[inline] - fn dot(&self, v: &V) -> S { - build::(|i| self.i(i).mul(v.i(i))).comp_add() + 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, ..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 Point2 -> [S, ..2] _2) -array!(impl Point3 -> [S, ..3] _3) +impl Point> for Point2 { + #[inline] + fn origin() -> Point2 { + Point2::new(zero(), zero()) + } -impl Point, [S, ..2]> for Point2 {} -impl Point, [S, ..3]> for Point3 {} + #[inline] + fn from_vec(v: &Vector2) -> Point2 { + Point2::new(v.x, v.y) + } + + #[inline] + fn to_vec(&self) -> Vector2 { + Vector2::new(self.x, + self.y) + } + + #[inline] + fn mul_s(&self, s: S) -> Point2 { + Point2::new(self.x * s, + self.y * s) + } + + #[inline] + fn div_s(&self, s: S) -> Point2 { + Point2::new(self.x / s, + self.y / s) + } + + #[inline] + fn rem_s(&self, s: S) -> Point2 { + Point2::new(self.x % s, + self.y % s) + } + + #[inline] + fn add_v(&self, v: &Vector2) -> Point2 { + Point2::new(self.x + v.x, + self.y + v.y) + } + + #[inline] + fn sub_p(&self, p: &Point2) -> Vector2 { + 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) { + self.x = self.x + v.x; + self.y = self.y + v.y; + } + + #[inline] + fn dot(&self, v: &Vector2) -> S { + self.x * v.x + + self.y * v.y + } + + #[inline] + fn min(&self, p: &Point2) -> Point2 { + Point2::new(self.x.partial_min(p.x), + self.y.partial_min(p.y)) + } + + #[inline] + fn max(&self, p: &Point2) -> Point2 { + Point2::new(self.x.partial_max(p.x), + self.y.partial_max(p.y)) + } +} + +impl ApproxEq for Point2 { + #[inline] + fn approx_eq_eps(&self, other: &Point2, epsilon: &S) -> bool { + self.x.approx_eq_eps(&other.x, epsilon) && + self.y.approx_eq_eps(&other.y, epsilon) + } +} + +impl Array1 for Point3 { + #[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 Point> for Point3 { + #[inline] + fn origin() -> Point3 { + Point3::new(zero(), zero(), zero()) + } + + #[inline] + fn from_vec(v: &Vector3) -> Point3 { + Point3::new(v.x, v.y, v.z) + } + + #[inline] + fn to_vec(&self) -> Vector3 { + Vector3::new(self.x, + self.y, + self.z) + } + + #[inline] + fn mul_s(&self, s: S) -> Point3 { + Point3::new(self.x * s, + self.y * s, + self.z * s) + } + + #[inline] + fn div_s(&self, s: S) -> Point3 { + Point3::new(self.x / s, + self.y / s, + self.z / s) + } + + #[inline] + fn rem_s(&self, s: S) -> Point3 { + Point3::new(self.x % s, + self.y % s, + self.z % s) + } + + #[inline] + fn add_v(&self, v: &Vector3) -> Point3 { + Point3::new(self.x + v.x, + self.y + v.y, + self.z + v.z) + } + + #[inline] + fn sub_p(&self, p: &Point3) -> Vector3 { + 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) { + 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 { + self.x * v.x + + self.y * v.y + + self.z * v.z + } + + #[inline] + fn min(&self, p: &Point3) -> Point3 { + 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) -> Point3 { + Point3::new(self.x.partial_max(p.x), + self.y.partial_max(p.y), + self.z.partial_max(p.z)) + } +} + +impl ApproxEq for Point3 { + #[inline] + fn approx_eq_eps(&self, other: &Point3, 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 fmt::Show for Point2 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/cgmath/ptr.rs b/src/cgmath/ptr.rs deleted file mode 100644 index d3565e1..0000000 --- a/src/cgmath/ptr.rs +++ /dev/null @@ -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 { - fn ptr<'a>(&'a self) -> &'a T; -} - -impl Ptr for Vector2 { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } } -impl Ptr for Vector3 { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } } -impl Ptr for Vector4 { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } } - -impl Ptr for Point2 { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } } -impl Ptr for Point3 { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } } - -impl Ptr for Matrix2 { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0).i(0) } } -impl Ptr for Matrix3 { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0).i(0) } } -impl Ptr for Matrix4 { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0).i(0) } } - -impl<'a, T, P: Ptr> Ptr for &'a [P] { - #[inline] fn ptr<'a>(&'a self) -> &'a T { self[0].ptr() } -} diff --git a/src/cgmath/quaternion.rs b/src/cgmath/quaternion.rs index 9783859..2a5fd8e 100644 --- a/src/cgmath/quaternion.rs +++ b/src/cgmath/quaternion.rs @@ -14,13 +14,15 @@ // limitations under the License. use std::fmt; +use std::mem; use std::num::{zero, one, cast}; 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 num::BaseFloat; -use point::{Point3}; +use point::Point3; use rotation::{Rotation, Rotation3, Basis3, ToBasis3}; use vector::{Vector3, Vector, EuclideanVector}; @@ -29,14 +31,32 @@ use vector::{Vector3, Vector, EuclideanVector}; #[deriving(Clone, Eq)] pub struct Quaternion { pub s: S, pub v: Vector3 } -array!(impl Quaternion -> [S, ..4] _4) - /// Represents types which can be expressed as a quaternion. pub trait ToQuaternion { /// Convert this value to a quaternion. fn to_quaternion(&self) -> Quaternion; } +impl Array1 for Quaternion { + #[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 Quaternion { /// Construct a new quaternion from one scalar component and three /// imaginary components @@ -85,13 +105,13 @@ impl Quaternion { /// The sum of this quaternion and `other` #[inline] pub fn add_q(&self, other: &Quaternion) -> Quaternion { - 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` #[inline] pub fn sub_q(&self, other: &Quaternion) -> Quaternion { - 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` @@ -105,37 +125,42 @@ impl Quaternion { /// Multiply this quaternion by a scalar, in-place. #[inline] 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. #[inline] 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. #[inline] - pub fn add_self_q(&mut self, other: &Quaternion) { - self.each_mut(|i, x| *x = x.add(other.i(i))); + pub fn add_self_q(&mut self, q: &Quaternion) { + self.s = self.s + q.s; + self.v.add_self_v(&q.v); } /// Subtract another quaternion from this one, in-place. #[inline] - pub fn sub_self_q(&mut self, other: &Quaternion) { - self.each_mut(|i, x| *x = x.sub(other.i(i))); + pub fn sub_self_q(&mut self, q: &Quaternion) { + self.s = self.s - q.s; + self.v.sub_self_v(&q.v); } /// Multiply this quaternion by another, in-place. #[inline] - pub fn mul_self_q(&mut self, other: &Quaternion) { - *self = self.mul_q(other); + pub fn mul_self_q(&mut self, q: &Quaternion) { + 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] - pub fn dot(&self, other: &Quaternion) -> S { - self.s * other.s + self.v.dot(&other.v) + pub fn dot(&self, q: &Quaternion) -> S { + self.s * q.s + self.v.dot(&q.v) } /// The conjugate of the quaternion. @@ -176,6 +201,14 @@ impl Quaternion { } } +impl ApproxEq for Quaternion { + #[inline] + fn approx_eq_eps(&self, other: &Quaternion, epsilon: &S) -> bool { + self.s.approx_eq_eps(&other.s, epsilon) && + self.v.approx_eq_eps(&other.v, epsilon) + } +} + impl Quaternion { /// Spherical Linear Intoperlation /// @@ -305,7 +338,7 @@ impl ToQuaternion for Quaternion { fn to_quaternion(&self) -> Quaternion { self.clone() } } -impl Rotation, Point3> for Quaternion { +impl Rotation, Point3> for Quaternion { #[inline] fn identity() -> Quaternion { Quaternion::identity() } diff --git a/src/cgmath/ray.rs b/src/cgmath/ray.rs index 9e1d028..75bdcd8 100644 --- a/src/cgmath/ray.rs +++ b/src/cgmath/ray.rs @@ -25,7 +25,7 @@ pub struct Ray { pub direction: V, } -impl, P: Point> Ray { +impl, P: Point> Ray { pub fn new(origin: P, direction: V) -> Ray { Ray { origin: origin, direction: direction } } diff --git a/src/cgmath/rotation.rs b/src/cgmath/rotation.rs index b80f0ca..9fe930e 100644 --- a/src/cgmath/rotation.rs +++ b/src/cgmath/rotation.rs @@ -15,7 +15,6 @@ use angle::{Rad, acos}; use approx::ApproxEq; -use array::Array; use matrix::Matrix; use matrix::{Matrix2, ToMatrix2}; 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 /// creates a circular motion, and preserves at least one point in the space. -pub trait Rotation -< - S: BaseNum, - Slice, - V: Vector, - P: Point -> -: Eq -+ ApproxEq -{ +pub trait Rotation, P: Point>: Eq + ApproxEq { /// Create the identity transform (causes no transformation). fn identity() -> Self; @@ -59,10 +49,8 @@ pub trait Rotation /// Rotate a ray using this rotation. #[inline] - fn rotate_ray(&self, ray: &Ray) -> Ray { - Ray::new( //FIXME: use clone derived from Array - Array::build(|i| ray.origin.i(i).clone()), - self.rotate_vector(&ray.direction) ) + fn rotate_ray(&self, ray: &Ray) -> Ray { + Ray::new(ray.origin.clone(), self.rotate_vector(&ray.direction)) } /// Create a new rotation which combines both this rotation, and another. @@ -86,29 +74,19 @@ pub trait Rotation } /// A two-dimensional rotation. -pub trait Rotation2 -< - S -> -: Rotation, Point2> -+ ToMatrix2 -+ ToBasis2 -{ +pub trait Rotation2: Rotation, Point2> + + ToMatrix2 + + ToBasis2 { /// Create a rotation by a given angle. Thus is a redundant case of both /// from_axis_angle() and from_euler() for 2D space. fn from_angle(theta: Rad) -> Self; } /// A three-dimensional rotation. -pub trait Rotation3 -< - S: BaseNum -> -: Rotation, Point3> -+ ToMatrix3 -+ ToBasis3 -+ ToQuaternion -{ +pub trait Rotation3: Rotation, Point3> + + ToMatrix3 + + ToBasis3 + + ToQuaternion{ /// Create a rotation using an angle around a given axis. fn from_axis_angle(axis: &Vector3, angle: Rad) -> Self; @@ -174,7 +152,7 @@ impl ToMatrix2 for Basis2 { fn to_matrix2(&self) -> Matrix2 { self.mat.clone() } } -impl Rotation, Point2> for Basis2 { +impl Rotation, Point2> for Basis2 { #[inline] fn identity() -> Basis2 { Basis2{ mat: Matrix2::identity() } } @@ -263,7 +241,7 @@ impl ToQuaternion for Basis3 { fn to_quaternion(&self) -> Quaternion { self.mat.to_quaternion() } } -impl Rotation, Point3> for Basis3 { +impl Rotation, Point3> for Basis3 { #[inline] fn identity() -> Basis3 { Basis3{ mat: Matrix3::identity() } } diff --git a/src/cgmath/transform.rs b/src/cgmath/transform.rs index 7c91d81..fe5a543 100644 --- a/src/cgmath/transform.rs +++ b/src/cgmath/transform.rs @@ -29,14 +29,7 @@ use vector::{Vector, Vector3}; /// A trait representing an [affine /// transformation](https://en.wikipedia.org/wiki/Affine_transformation) that /// can be applied to points or vectors. An affine transformation is one which -pub trait Transform -< - S: BaseNum, - Slice, - V: Vector, - P: Point -> -{ +pub trait Transform, P: Point> { /// Create an identity transformation. That is, a transformation which /// does nothing. fn identity() -> Self; @@ -92,15 +85,7 @@ pub struct Decomposed { pub disp: V, } -impl -< - S: BaseFloat, - Slice, - V: Vector, - P: Point, - R: Rotation -> -Transform for Decomposed { +impl, P: Point, R: Rotation> Transform for Decomposed { #[inline] fn identity() -> Decomposed { Decomposed { @@ -157,10 +142,7 @@ Transform for Decomposed { } } -pub trait Transform3 -: Transform, Point3> -+ ToMatrix4 -{} +pub trait Transform3: Transform, Point3>+ ToMatrix4 {} impl> ToMatrix4 for Decomposed, R> { fn to_matrix4(&self) -> Matrix4 { @@ -185,7 +167,7 @@ pub struct AffineMatrix3 { pub mat: Matrix4, } -impl Transform, Point3> for AffineMatrix3 { +impl Transform, Point3> for AffineMatrix3 { #[inline] fn identity() -> AffineMatrix3 { AffineMatrix3 { mat: Matrix4::identity() } @@ -226,7 +208,7 @@ impl Transform3 for AffineMatrix3 {} /// A transformation in three dimensions consisting of a rotation, /// displacement vector and scale amount. -pub struct Transform3D( Decomposed,Quaternion> ); +pub struct Transform3D(Decomposed,Quaternion>); impl Transform3D { #[inline] diff --git a/src/cgmath/vector.rs b/src/cgmath/vector.rs index 14dfb7e..4193dde 100644 --- a/src/cgmath/vector.rs +++ b/src/cgmath/vector.rs @@ -14,90 +14,85 @@ // limitations under the License. use std::fmt; +use std::mem; use std::num::{Zero, zero, One, one}; use angle::{Rad, atan2, acos}; use approx::ApproxEq; -use array::{Array, build}; -use num::{BaseNum, BaseFloat, PartialOrd}; +use array::Array1; +use num::{BaseNum, BaseFloat}; /// A trait that specifies a range of numeric operations for vectors. Not all /// of these make sense from a linear algebra point of view, but are included /// for pragmatic reasons. -pub trait Vector -< - S: BaseNum, - Slice -> -: Array -+ Neg -+ Zero + One -{ +pub trait Vector: Array1 + + Neg + + Zero + + One { /// 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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[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. - #[inline] fn comp_mul(&self) -> S { self.fold(|a, b| a.mul(b)) } + fn comp_mul(&self) -> S; /// 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. - #[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. - #[inline] fn comp_max(&self) -> S { self.fold(|a, b| a.partial_max(*b)) } + fn comp_max(&self) -> S; } /// Dot product of two vectors. -#[inline] pub fn dot>(a: V, b: V) -> S { a.dot(&b) } +#[inline] pub fn dot>(a: V, b: V) -> S { a.dot(&b) } // Utility macro for generating associated functions for the vectors macro_rules! vec( @@ -105,19 +100,23 @@ macro_rules! vec( #[deriving(Eq, TotalEq, Clone, Hash)] pub struct $Self { $(pub $field: S),+ } - impl<$S: BaseNum> $Self<$S> { + impl<$S> $Self<$S> { /// Construct a new vector, using the provided values. #[inline] pub fn new($($field: $S),+) -> $Self<$S> { $Self { $($field: $field),+ } } + } + impl<$S: Clone> $Self<$S> { /// Construct a vector from a single value, replicating it. #[inline] pub fn from_value(value: $S) -> $Self<$S> { $Self { $($field: value.clone()),+ } } + } + impl<$S: BaseNum> $Self<$S> { /// The additive identity of the vector. #[inline] 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()) } } + impl Array1 for $Self { + #[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 Vector for $Self { + #[inline] fn add_s(&self, s: S) -> $Self { $Self::new($(self.$field + s),+) } + #[inline] fn sub_s(&self, s: S) -> $Self { $Self::new($(self.$field - s),+) } + #[inline] fn mul_s(&self, s: S) -> $Self { $Self::new($(self.$field * s),+) } + #[inline] fn div_s(&self, s: S) -> $Self { $Self::new($(self.$field / s),+) } + #[inline] fn rem_s(&self, s: S) -> $Self { $Self::new($(self.$field % s),+) } + + #[inline] fn add_v(&self, v: &$Self) -> $Self { $Self::new($(self.$field + v.$field),+) } + #[inline] fn sub_v(&self, v: &$Self) -> $Self { $Self::new($(self.$field - v.$field),+) } + #[inline] fn mul_v(&self, v: &$Self) -> $Self { $Self::new($(self.$field * v.$field),+) } + #[inline] fn div_v(&self, v: &$Self) -> $Self { $Self::new($(self.$field / v.$field),+) } + #[inline] fn rem_v(&self, v: &$Self) -> $Self { $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) { $(self.$field = self.$field + v.$field;)+ } + #[inline] fn sub_self_v(&mut self, v: &$Self) { $(self.$field = self.$field - v.$field;)+ } + #[inline] fn mul_self_v(&mut self, v: &$Self) { $(self.$field = self.$field * v.$field;)+ } + #[inline] fn div_self_v(&mut self, v: &$Self) { $(self.$field = self.$field / v.$field;)+ } + #[inline] fn rem_self_v(&mut self, v: &$Self) { $(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 Add<$Self, $Self> for $Self { - #[inline] fn add(&self, other: &$Self) -> $Self { self.add_v(other) } + #[inline] fn add(&self, v: &$Self) -> $Self { self.add_v(v) } } impl Sub<$Self, $Self> for $Self { - #[inline] fn sub(&self, other: &$Self) -> $Self { self.sub_v(other) } + #[inline] fn sub(&self, v: &$Self) -> $Self { self.sub_v(v) } } impl Zero for $Self { @@ -141,29 +193,39 @@ macro_rules! vec( } impl Neg<$Self> for $Self { - #[inline] fn neg(&self) -> $Self { build(|i| self.i(i).neg()) } + #[inline] fn neg(&self) -> $Self { $Self::new($(-self.$field),+) } } impl Mul<$Self, $Self> for $Self { - #[inline] fn mul(&self, other: &$Self) -> $Self { self.mul_v(other) } + #[inline] fn mul(&self, v: &$Self) -> $Self { self.mul_v(v) } } impl One for $Self { #[inline] fn one() -> $Self { $Self::from_value(one()) } } - impl Vector for $Self {} + impl ApproxEq for $Self { + #[inline] + fn approx_eq_eps(&self, other: &$Self, 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 { x, y }, 2) vec!(Vector3 { x, y, z }, 3) vec!(Vector4 { x, y, z, w }, 4) -array!(impl Vector2 -> [S, ..2] _2) -array!(impl Vector3 -> [S, ..3] _3) -array!(impl Vector4 -> [S, ..4] _4) - /// Operations specific to numeric two-dimensional vectors. impl Vector2 { /// A unit vector in the `x` direction. @@ -243,14 +305,8 @@ impl Vector4 { /// Specifies geometric operations for vectors. This is only implemented for /// 2-dimensional and 3-dimensional vectors. -pub trait EuclideanVector -< - S: BaseFloat, - Slice -> -: Vector -+ ApproxEq -{ +pub trait EuclideanVector: Vector + + ApproxEq { /// Returns `true` if the vector is perpendicular (at right angles) to the /// other vector. fn is_perpendicular(&self, other: &Self) -> bool { @@ -316,43 +372,40 @@ pub trait EuclideanVector } } -impl -EuclideanVector for Vector2 { +impl EuclideanVector for Vector2 { #[inline] fn angle(&self, other: &Vector2) -> Rad { atan2(self.perp_dot(other), self.dot(other)) } } -impl -EuclideanVector for Vector3 { +impl EuclideanVector for Vector3 { #[inline] fn angle(&self, other: &Vector3) -> Rad { atan2(self.cross(other).length(), self.dot(other)) } } -impl -EuclideanVector for Vector4 { +impl EuclideanVector for Vector4 { #[inline] fn angle(&self, other: &Vector4) -> Rad { acos(self.dot(other) / (self.length() * other.length())) } } -impl fmt::Show for Vector2 { +impl fmt::Show for Vector2 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "[{}, {}]", self.x, self.y) } } -impl fmt::Show for Vector3 { +impl fmt::Show for Vector3 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "[{}, {}, {}]", self.x, self.y, self.z) } } -impl fmt::Show for Vector4 { +impl fmt::Show for Vector4 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) }