diff --git a/src/mat.rs b/src/mat.rs deleted file mode 100644 index 0f3e10b6..00000000 --- a/src/mat.rs +++ /dev/null @@ -1,209 +0,0 @@ -use std::cast; -use std::uint::iterate; -use std::num::{One, Zero}; -use std::cmp::ApproxEq; -use std::iterator::IteratorUtil; -use std::vec::{VecIterator, VecMutIterator}; -use vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6}; -use traits::dim::Dim; -use traits::ring::Ring; -use traits::inv::Inv; -use traits::division_ring::DivisionRing; -use traits::transpose::Transpose; -use traits::rlmul::{RMul, LMul}; -use traits::transformation::Transform; -use traits::homogeneous::{FromHomogeneous, ToHomogeneous}; -use traits::indexable::Indexable; -use traits::column::Column; -use traits::iterable::{Iterable, IterableMut}; - -mod mat_impl; - -#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] -pub struct Mat1 -{ m11: N } - -mat_impl!(Mat1, 1, m11) -one_impl!(Mat1, _1) -iterable_impl!(Mat1, 1) -iterable_mut_impl!(Mat1, 1) -dim_impl!(Mat1, 1) -indexable_impl!(Mat1, 1) -mul_impl!(Mat1, 1) -rmul_impl!(Mat1, Vec1, 1) -lmul_impl!(Mat1, Vec1, 1) -transform_impl!(Mat1, Vec1) -// (specialized) inv_impl!(Mat1, 1) -transpose_impl!(Mat1, 1) -approx_eq_impl!(Mat1) -column_impl!(Mat1, 1) -to_homogeneous_impl!(Mat1, Mat2, 1, 2) -from_homogeneous_impl!(Mat1, Mat2, 1, 2) - -#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] -pub struct Mat2 -{ - m11: N, m12: N, - m21: N, m22: N -} - -mat_impl!(Mat2, 2, m11, m12, - m21, m22) -one_impl!(Mat2, _1, _0, - _0, _1) -iterable_impl!(Mat2, 2) -iterable_mut_impl!(Mat2, 2) -dim_impl!(Mat2, 2) -indexable_impl!(Mat2, 2) -mul_impl!(Mat2, 2) -rmul_impl!(Mat2, Vec2, 2) -lmul_impl!(Mat2, Vec2, 2) -transform_impl!(Mat2, Vec2) -// (specialized) inv_impl!(Mat2, 2) -transpose_impl!(Mat2, 2) -approx_eq_impl!(Mat2) -column_impl!(Mat2, 2) -to_homogeneous_impl!(Mat2, Mat3, 2, 3) -from_homogeneous_impl!(Mat2, Mat3, 2, 3) - -#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] -pub struct Mat3 -{ - m11: N, m12: N, m13: N, - m21: N, m22: N, m23: N, - m31: N, m32: N, m33: N -} - -mat_impl!(Mat3, 3, m11, m12, m13, - m21, m22, m23, - m31, m32, m33) -one_impl!(Mat3, _1, _0, _0, - _0, _1, _0, - _0, _0, _1) -iterable_impl!(Mat3, 3) -iterable_mut_impl!(Mat3, 3) -dim_impl!(Mat3, 3) -indexable_impl!(Mat3, 3) -mul_impl!(Mat3, 3) -rmul_impl!(Mat3, Vec3, 3) -lmul_impl!(Mat3, Vec3, 3) -transform_impl!(Mat3, Vec3) -// (specialized) inv_impl!(Mat3, 3) -transpose_impl!(Mat3, 3) -approx_eq_impl!(Mat3) -column_impl!(Mat3, 3) -to_homogeneous_impl!(Mat3, Mat4, 3, 4) -from_homogeneous_impl!(Mat3, Mat4, 3, 4) - -#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] -pub struct Mat4 -{ - m11: N, m12: N, m13: N, m14: N, - m21: N, m22: N, m23: N, m24: N, - m31: N, m32: N, m33: N, m34: N, - m41: N, m42: N, m43: N, m44: N -} - -mat_impl!(Mat4, 4, - m11, m12, m13, m14, - m21, m22, m23, m24, - m31, m32, m33, m34, - m41, m42, m43, m44 -) -one_impl!(Mat4, _1, _0, _0, _0, - _0, _1, _0, _0, - _0, _0, _1, _0, - _0, _0, _0, _1) -iterable_impl!(Mat4, 4) -iterable_mut_impl!(Mat4, 4) -dim_impl!(Mat4, 4) -indexable_impl!(Mat4, 4) -mul_impl!(Mat4, 4) -rmul_impl!(Mat4, Vec4, 4) -lmul_impl!(Mat4, Vec4, 4) -transform_impl!(Mat4, Vec4) -inv_impl!(Mat4, 4) -transpose_impl!(Mat4, 4) -approx_eq_impl!(Mat4) -column_impl!(Mat4, 4) -to_homogeneous_impl!(Mat4, Mat5, 4, 5) -from_homogeneous_impl!(Mat4, Mat5, 4, 5) - -#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] -pub struct Mat5 -{ - m11: N, m12: N, m13: N, m14: N, m15: N, - m21: N, m22: N, m23: N, m24: N, m25: N, - m31: N, m32: N, m33: N, m34: N, m35: N, - m41: N, m42: N, m43: N, m44: N, m45: N, - m51: N, m52: N, m53: N, m54: N, m55: N -} - -mat_impl!(Mat5, 5, - m11, m12, m13, m14, m15, - m21, m22, m23, m24, m25, - m31, m32, m33, m34, m35, - m41, m42, m43, m44, m45, - m51, m52, m53, m54, m55 -) -one_impl!(Mat5, - _1, _0, _0, _0, _0, - _0, _1, _0, _0, _0, - _0, _0, _1, _0, _0, - _0, _0, _0, _1, _0, - _0, _0, _0, _0, _1 -) -iterable_impl!(Mat5, 5) -iterable_mut_impl!(Mat5, 5) -dim_impl!(Mat5, 5) -indexable_impl!(Mat5, 5) -mul_impl!(Mat5, 5) -rmul_impl!(Mat5, Vec5, 5) -lmul_impl!(Mat5, Vec5, 5) -transform_impl!(Mat5, Vec5) -inv_impl!(Mat5, 5) -transpose_impl!(Mat5, 5) -approx_eq_impl!(Mat5) -column_impl!(Mat5, 5) -to_homogeneous_impl!(Mat5, Mat6, 5, 6) -from_homogeneous_impl!(Mat5, Mat6, 5, 6) - -#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] -pub struct Mat6 -{ - m11: N, m12: N, m13: N, m14: N, m15: N, m16: N, - m21: N, m22: N, m23: N, m24: N, m25: N, m26: N, - m31: N, m32: N, m33: N, m34: N, m35: N, m36: N, - m41: N, m42: N, m43: N, m44: N, m45: N, m46: N, - m51: N, m52: N, m53: N, m54: N, m55: N, m56: N, - m61: N, m62: N, m63: N, m64: N, m65: N, m66: N -} - -mat_impl!(Mat6, 6, - m11, m12, m13, m14, m15, m16, - m21, m22, m23, m24, m25, m26, - m31, m32, m33, m34, m35, m36, - m41, m42, m43, m44, m45, m46, - m51, m52, m53, m54, m55, m56, - m61, m62, m63, m64, m65, m66 -) -one_impl!(Mat6, - _1, _0, _0, _0, _0, _0, - _0, _1, _0, _0, _0, _0, - _0, _0, _1, _0, _0, _0, - _0, _0, _0, _1, _0, _0, - _0, _0, _0, _0, _1, _0, - _0, _0, _0, _0, _0, _1 -) -iterable_impl!(Mat6, 6) -iterable_mut_impl!(Mat6, 6) -dim_impl!(Mat6, 6) -indexable_impl!(Mat6, 6) -mul_impl!(Mat6, 6) -rmul_impl!(Mat6, Vec6, 6) -lmul_impl!(Mat6, Vec6, 6) -transform_impl!(Mat6, Vec6) -inv_impl!(Mat6, 6) -transpose_impl!(Mat6, 6) -approx_eq_impl!(Mat6) -column_impl!(Mat6, 6) diff --git a/src/mat_impl.rs b/src/mat_impl.rs index f5a996c6..3204687e 100644 --- a/src/mat_impl.rs +++ b/src/mat_impl.rs @@ -1,408 +1,209 @@ -#[macro_escape]; +use std::cast; +use std::uint::iterate; +use std::num::{One, Zero}; +use std::cmp::ApproxEq; +use std::iterator::IteratorUtil; +use std::vec::{VecIterator, VecMutIterator}; +use vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6}; +use traits::dim::Dim; +use traits::ring::Ring; +use traits::inv::Inv; +use traits::division_ring::DivisionRing; +use traits::transpose::Transpose; +use traits::rlmul::{RMul, LMul}; +use traits::transformation::Transform; +use traits::homogeneous::{FromHomogeneous, ToHomogeneous}; +use traits::indexable::Indexable; +use traits::column::Column; +use traits::iterable::{Iterable, IterableMut}; -macro_rules! mat_impl( - ($t: ident, $dim: expr, $comp0: ident $(,$compN: ident)*) => ( - impl $t - { - #[inline] - pub fn new($comp0: N $(, $compN: N )*) -> $t - { - $t { - $comp0: $comp0 - $(, $compN: $compN )* - } - } - } - ) +mod mat_macros; + +#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] +pub struct Mat1 +{ m11: N } + +mat_impl!(Mat1, 1, m11) +one_impl!(Mat1, _1) +iterable_impl!(Mat1, 1) +iterable_mut_impl!(Mat1, 1) +dim_impl!(Mat1, 1) +indexable_impl!(Mat1, 1) +mul_impl!(Mat1, 1) +rmul_impl!(Mat1, Vec1, 1) +lmul_impl!(Mat1, Vec1, 1) +transform_impl!(Mat1, Vec1) +// (specialized) inv_impl!(Mat1, 1) +transpose_impl!(Mat1, 1) +approx_eq_impl!(Mat1) +column_impl!(Mat1, 1) +to_homogeneous_impl!(Mat1, Mat2, 1, 2) +from_homogeneous_impl!(Mat1, Mat2, 1, 2) + +#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] +pub struct Mat2 +{ + m11: N, m12: N, + m21: N, m22: N +} + +mat_impl!(Mat2, 2, m11, m12, + m21, m22) +one_impl!(Mat2, _1, _0, + _0, _1) +iterable_impl!(Mat2, 2) +iterable_mut_impl!(Mat2, 2) +dim_impl!(Mat2, 2) +indexable_impl!(Mat2, 2) +mul_impl!(Mat2, 2) +rmul_impl!(Mat2, Vec2, 2) +lmul_impl!(Mat2, Vec2, 2) +transform_impl!(Mat2, Vec2) +// (specialized) inv_impl!(Mat2, 2) +transpose_impl!(Mat2, 2) +approx_eq_impl!(Mat2) +column_impl!(Mat2, 2) +to_homogeneous_impl!(Mat2, Mat3, 2, 3) +from_homogeneous_impl!(Mat2, Mat3, 2, 3) + +#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] +pub struct Mat3 +{ + m11: N, m12: N, m13: N, + m21: N, m22: N, m23: N, + m31: N, m32: N, m33: N +} + +mat_impl!(Mat3, 3, m11, m12, m13, + m21, m22, m23, + m31, m32, m33) +one_impl!(Mat3, _1, _0, _0, + _0, _1, _0, + _0, _0, _1) +iterable_impl!(Mat3, 3) +iterable_mut_impl!(Mat3, 3) +dim_impl!(Mat3, 3) +indexable_impl!(Mat3, 3) +mul_impl!(Mat3, 3) +rmul_impl!(Mat3, Vec3, 3) +lmul_impl!(Mat3, Vec3, 3) +transform_impl!(Mat3, Vec3) +// (specialized) inv_impl!(Mat3, 3) +transpose_impl!(Mat3, 3) +approx_eq_impl!(Mat3) +column_impl!(Mat3, 3) +to_homogeneous_impl!(Mat3, Mat4, 3, 4) +from_homogeneous_impl!(Mat3, Mat4, 3, 4) + +#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] +pub struct Mat4 +{ + m11: N, m12: N, m13: N, m14: N, + m21: N, m22: N, m23: N, m24: N, + m31: N, m32: N, m33: N, m34: N, + m41: N, m42: N, m43: N, m44: N +} + +mat_impl!(Mat4, 4, + m11, m12, m13, m14, + m21, m22, m23, m24, + m31, m32, m33, m34, + m41, m42, m43, m44 ) +one_impl!(Mat4, _1, _0, _0, _0, + _0, _1, _0, _0, + _0, _0, _1, _0, + _0, _0, _0, _1) +iterable_impl!(Mat4, 4) +iterable_mut_impl!(Mat4, 4) +dim_impl!(Mat4, 4) +indexable_impl!(Mat4, 4) +mul_impl!(Mat4, 4) +rmul_impl!(Mat4, Vec4, 4) +lmul_impl!(Mat4, Vec4, 4) +transform_impl!(Mat4, Vec4) +inv_impl!(Mat4, 4) +transpose_impl!(Mat4, 4) +approx_eq_impl!(Mat4) +column_impl!(Mat4, 4) +to_homogeneous_impl!(Mat4, Mat5, 4, 5) +from_homogeneous_impl!(Mat4, Mat5, 4, 5) -macro_rules! iterable_impl( - ($t: ident, $dim: expr) => ( - impl Iterable for $t - { - fn iter<'l>(&'l self) -> VecIterator<'l, N> - { unsafe { cast::transmute::<&'l $t, &'l [N, ..$dim * $dim]>(self).iter() } } - } - ) +#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] +pub struct Mat5 +{ + m11: N, m12: N, m13: N, m14: N, m15: N, + m21: N, m22: N, m23: N, m24: N, m25: N, + m31: N, m32: N, m33: N, m34: N, m35: N, + m41: N, m42: N, m43: N, m44: N, m45: N, + m51: N, m52: N, m53: N, m54: N, m55: N +} + +mat_impl!(Mat5, 5, + m11, m12, m13, m14, m15, + m21, m22, m23, m24, m25, + m31, m32, m33, m34, m35, + m41, m42, m43, m44, m45, + m51, m52, m53, m54, m55 ) - -macro_rules! iterable_mut_impl( - ($t: ident, $dim: expr) => ( - impl IterableMut for $t - { - fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N> - { unsafe { cast::transmute::<&'l mut $t, &'l mut [N, ..$dim * $dim]>(self).mut_iter() } } - } - ) +one_impl!(Mat5, + _1, _0, _0, _0, _0, + _0, _1, _0, _0, _0, + _0, _0, _1, _0, _0, + _0, _0, _0, _1, _0, + _0, _0, _0, _0, _1 ) +iterable_impl!(Mat5, 5) +iterable_mut_impl!(Mat5, 5) +dim_impl!(Mat5, 5) +indexable_impl!(Mat5, 5) +mul_impl!(Mat5, 5) +rmul_impl!(Mat5, Vec5, 5) +lmul_impl!(Mat5, Vec5, 5) +transform_impl!(Mat5, Vec5) +inv_impl!(Mat5, 5) +transpose_impl!(Mat5, 5) +approx_eq_impl!(Mat5) +column_impl!(Mat5, 5) +to_homogeneous_impl!(Mat5, Mat6, 5, 6) +from_homogeneous_impl!(Mat5, Mat6, 5, 6) -macro_rules! one_impl( - ($t: ident, $value0: ident $(, $valueN: ident)* ) => ( - impl One for $t - { - #[inline] - fn one() -> $t - { - let (_0, _1) = (Zero::zero::(), One::one::()); - return $t::new($value0.clone() $(, $valueN.clone() )*) - } - } - ) +#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] +pub struct Mat6 +{ + m11: N, m12: N, m13: N, m14: N, m15: N, m16: N, + m21: N, m22: N, m23: N, m24: N, m25: N, m26: N, + m31: N, m32: N, m33: N, m34: N, m35: N, m36: N, + m41: N, m42: N, m43: N, m44: N, m45: N, m46: N, + m51: N, m52: N, m53: N, m54: N, m55: N, m56: N, + m61: N, m62: N, m63: N, m64: N, m65: N, m66: N +} + +mat_impl!(Mat6, 6, + m11, m12, m13, m14, m15, m16, + m21, m22, m23, m24, m25, m26, + m31, m32, m33, m34, m35, m36, + m41, m42, m43, m44, m45, m46, + m51, m52, m53, m54, m55, m56, + m61, m62, m63, m64, m65, m66 ) - -macro_rules! dim_impl( - ($t: ident, $dim: expr) => ( - impl Dim for $t - { - #[inline] - fn dim() -> uint - { $dim } - } - ) -) - -macro_rules! indexable_impl( - ($t: ident, $dim: expr) => ( - impl Indexable<(uint, uint), N> for $t - { - #[inline] - pub fn at(&self, (i, j): (uint, uint)) -> N - { unsafe { cast::transmute::<&$t, &[N, ..$dim * $dim]>(self)[i * $dim + j].clone() } } - - #[inline] - pub fn set(&mut self, (i, j): (uint, uint), val: N) - { unsafe { cast::transmute::<&mut $t, &mut [N, ..$dim * $dim]>(self)[i * $dim + j] = val } } - - #[inline] - pub fn swap(&mut self, (i1, j1): (uint, uint), (i2, j2): (uint, uint)) - { - unsafe { - cast::transmute::<&mut $t, &mut [N, ..$dim * $dim]>(self) - .swap(i1 * $dim + j1, i2 * $dim + j2) - } - } - } - ) -) - -macro_rules! column_impl( - ($t: ident, $dim: expr) => ( - impl + IterableMut> Column for $t - { - fn set_column(&mut self, col: uint, v: V) - { - for v.iter().enumerate().advance |(i, e)| - { - if i == Dim::dim::<$t>() - { break } - - self.set((i, col), e.clone()); - } - } - - fn column(&self, col: uint) -> V - { - let mut res = Zero::zero::(); - - for res.mut_iter().enumerate().advance |(i, e)| - { - if i >= Dim::dim::<$t>() - { break } - - *e = self.at((i, col)); - } - - res - } - } - ) -) - -macro_rules! mul_impl( - ($t: ident, $dim: expr) => ( - impl - Mul<$t, $t> for $t - { - fn mul(&self, other: &$t) -> $t - { - let mut res: $t = Zero::zero(); - - for iterate(0u, $dim) |i| - { - for iterate(0u, $dim) |j| - { - let mut acc = Zero::zero::(); - - for iterate(0u, $dim) |k| - { acc = acc + self.at((i, k)) * other.at((k, j)); } - - res.set((i, j), acc); - } - } - - res - } - } - ) -) - -macro_rules! rmul_impl( - ($t: ident, $v: ident, $dim: expr) => ( - impl - RMul<$v> for $t - { - fn rmul(&self, other: &$v) -> $v - { - let mut res : $v = Zero::zero(); - - for iterate(0u, $dim) |i| - { - for iterate(0u, $dim) |j| - { - let val = res.at(i) + other.at(j) * self.at((i, j)); - res.set(i, val) - } - } - - res - } - } - ) -) - -macro_rules! lmul_impl( - ($t: ident, $v: ident, $dim: expr) => ( - impl - LMul<$v> for $t - { - fn lmul(&self, other: &$v) -> $v - { - - let mut res : $v = Zero::zero(); - - for iterate(0u, $dim) |i| - { - for iterate(0u, $dim) |j| - { - let val = res.at(i) + other.at(j) * self.at((j, i)); - res.set(i, val) - } - } - - res - } - } - ) -) - -macro_rules! transform_impl( - ($t: ident, $v: ident) => ( - impl - Transform<$v> for $t - { - #[inline] - fn transform_vec(&self, v: &$v) -> $v - { self.rmul(v) } - - #[inline] - fn inv_transform(&self, v: &$v) -> $v - { - match self.inverse() - { - Some(t) => t.transform_vec(v), - None => fail!("Cannot use inv_transform on a non-inversible matrix.") - } - } - } - ) -) - -macro_rules! inv_impl( - ($t: ident, $dim: expr) => ( - impl - Inv for $t - { - #[inline] - fn inverse(&self) -> Option<$t> - { - let mut res : $t = self.clone(); - - if res.inplace_inverse() - { Some(res) } - else - { None } - } - - fn inplace_inverse(&mut self) -> bool - { - let mut res: $t = One::one(); - let _0N: N = Zero::zero(); - - // inversion using Gauss-Jordan elimination - for iterate(0u, $dim) |k| - { - // search a non-zero value on the k-th column - // FIXME: would it be worth it to spend some more time searching for the - // max instead? - - let mut n0 = k; // index of a non-zero entry - - while (n0 != $dim) - { - if self.at((n0, k)) != _0N - { break; } - - n0 = n0 + 1; - } - - if n0 == $dim - { return false } - - // swap pivot line - if n0 != k - { - for iterate(0u, $dim) |j| - { - self.swap((n0, j), (k, j)); - res.swap((n0, j), (k, j)); - } - } - - let pivot = self.at((k, k)); - - for iterate(k, $dim) |j| - { - let selfval = self.at((k, j)) / pivot; - self.set((k, j), selfval); - } - - for iterate(0u, $dim) |j| - { - let resval = res.at((k, j)) / pivot; - res.set((k, j), resval); - } - - for iterate(0u, $dim) |l| - { - if l != k - { - let normalizer = self.at((l, k)); - - for iterate(k, $dim) |j| - { - let selfval = self.at((l, j)) - self.at((k, j)) * normalizer; - self.set((l, j), selfval); - } - - for iterate(0u, $dim) |j| - { - let resval = res.at((l, j)) - res.at((k, j)) * normalizer; - res.set((l, j), resval); - } - } - } - } - - *self = res; - - true - } - } - ) -) - -macro_rules! transpose_impl( - ($t: ident, $dim: expr) => ( - impl Transpose for $t - { - #[inline] - fn transposed(&self) -> $t - { - let mut res = self.clone(); - - res.transpose(); - - res - } - - fn transpose(&mut self) - { - for iterate(1u, $dim) |i| - { - for iterate(0u, $dim - 1) |j| - { self.swap((i, j), (j, i)) } - } - } - } - ) -) - -macro_rules! approx_eq_impl( - ($t: ident) => ( - impl> ApproxEq for $t - { - #[inline] - fn approx_epsilon() -> N - { ApproxEq::approx_epsilon::() } - - #[inline] - fn approx_eq(&self, other: &$t) -> bool - { - let mut zip = self.iter().zip(other.iter()); - - do zip.all |(a, b)| { a.approx_eq(b) } - } - - #[inline] - fn approx_eq_eps(&self, other: &$t, epsilon: &N) -> bool - { - let mut zip = self.iter().zip(other.iter()); - - do zip.all |(a, b)| { a.approx_eq_eps(b, epsilon) } - } - } - ) -) - -macro_rules! to_homogeneous_impl( - ($t: ident, $t2: ident, $dim: expr, $dim2: expr) => ( - impl ToHomogeneous<$t2> for $t - { - fn to_homogeneous(&self) -> $t2 - { - let mut res: $t2 = One::one(); - - for iterate(0, $dim) |i| - { - for iterate(0, $dim) |j| - { res.set((i, j), self.at((i, j))) } - } - - res - } - } - ) -) - -macro_rules! from_homogeneous_impl( - ($t: ident, $t2: ident, $dim: expr, $dim2: expr) => ( - impl FromHomogeneous<$t2> for $t - { - fn from_homogeneous(m: &$t2) -> $t - { - let mut res: $t = One::one(); - - for iterate(0, $dim2) |i| - { - for iterate(0, $dim2) |j| - { res.set((i, j), m.at((i, j))) } - } - - // FIXME: do we have to deal the lost components - // (like if the 1 is not a 1… do we have to divide?) - - res - } - } - ) +one_impl!(Mat6, + _1, _0, _0, _0, _0, _0, + _0, _1, _0, _0, _0, _0, + _0, _0, _1, _0, _0, _0, + _0, _0, _0, _1, _0, _0, + _0, _0, _0, _0, _1, _0, + _0, _0, _0, _0, _0, _1 ) +iterable_impl!(Mat6, 6) +iterable_mut_impl!(Mat6, 6) +dim_impl!(Mat6, 6) +indexable_impl!(Mat6, 6) +mul_impl!(Mat6, 6) +rmul_impl!(Mat6, Vec6, 6) +lmul_impl!(Mat6, Vec6, 6) +transform_impl!(Mat6, Vec6) +inv_impl!(Mat6, 6) +transpose_impl!(Mat6, 6) +approx_eq_impl!(Mat6) +column_impl!(Mat6, 6) diff --git a/src/mat_macros.rs b/src/mat_macros.rs new file mode 100644 index 00000000..f5a996c6 --- /dev/null +++ b/src/mat_macros.rs @@ -0,0 +1,408 @@ +#[macro_escape]; + +macro_rules! mat_impl( + ($t: ident, $dim: expr, $comp0: ident $(,$compN: ident)*) => ( + impl $t + { + #[inline] + pub fn new($comp0: N $(, $compN: N )*) -> $t + { + $t { + $comp0: $comp0 + $(, $compN: $compN )* + } + } + } + ) +) + +macro_rules! iterable_impl( + ($t: ident, $dim: expr) => ( + impl Iterable for $t + { + fn iter<'l>(&'l self) -> VecIterator<'l, N> + { unsafe { cast::transmute::<&'l $t, &'l [N, ..$dim * $dim]>(self).iter() } } + } + ) +) + +macro_rules! iterable_mut_impl( + ($t: ident, $dim: expr) => ( + impl IterableMut for $t + { + fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N> + { unsafe { cast::transmute::<&'l mut $t, &'l mut [N, ..$dim * $dim]>(self).mut_iter() } } + } + ) +) + +macro_rules! one_impl( + ($t: ident, $value0: ident $(, $valueN: ident)* ) => ( + impl One for $t + { + #[inline] + fn one() -> $t + { + let (_0, _1) = (Zero::zero::(), One::one::()); + return $t::new($value0.clone() $(, $valueN.clone() )*) + } + } + ) +) + +macro_rules! dim_impl( + ($t: ident, $dim: expr) => ( + impl Dim for $t + { + #[inline] + fn dim() -> uint + { $dim } + } + ) +) + +macro_rules! indexable_impl( + ($t: ident, $dim: expr) => ( + impl Indexable<(uint, uint), N> for $t + { + #[inline] + pub fn at(&self, (i, j): (uint, uint)) -> N + { unsafe { cast::transmute::<&$t, &[N, ..$dim * $dim]>(self)[i * $dim + j].clone() } } + + #[inline] + pub fn set(&mut self, (i, j): (uint, uint), val: N) + { unsafe { cast::transmute::<&mut $t, &mut [N, ..$dim * $dim]>(self)[i * $dim + j] = val } } + + #[inline] + pub fn swap(&mut self, (i1, j1): (uint, uint), (i2, j2): (uint, uint)) + { + unsafe { + cast::transmute::<&mut $t, &mut [N, ..$dim * $dim]>(self) + .swap(i1 * $dim + j1, i2 * $dim + j2) + } + } + } + ) +) + +macro_rules! column_impl( + ($t: ident, $dim: expr) => ( + impl + IterableMut> Column for $t + { + fn set_column(&mut self, col: uint, v: V) + { + for v.iter().enumerate().advance |(i, e)| + { + if i == Dim::dim::<$t>() + { break } + + self.set((i, col), e.clone()); + } + } + + fn column(&self, col: uint) -> V + { + let mut res = Zero::zero::(); + + for res.mut_iter().enumerate().advance |(i, e)| + { + if i >= Dim::dim::<$t>() + { break } + + *e = self.at((i, col)); + } + + res + } + } + ) +) + +macro_rules! mul_impl( + ($t: ident, $dim: expr) => ( + impl + Mul<$t, $t> for $t + { + fn mul(&self, other: &$t) -> $t + { + let mut res: $t = Zero::zero(); + + for iterate(0u, $dim) |i| + { + for iterate(0u, $dim) |j| + { + let mut acc = Zero::zero::(); + + for iterate(0u, $dim) |k| + { acc = acc + self.at((i, k)) * other.at((k, j)); } + + res.set((i, j), acc); + } + } + + res + } + } + ) +) + +macro_rules! rmul_impl( + ($t: ident, $v: ident, $dim: expr) => ( + impl + RMul<$v> for $t + { + fn rmul(&self, other: &$v) -> $v + { + let mut res : $v = Zero::zero(); + + for iterate(0u, $dim) |i| + { + for iterate(0u, $dim) |j| + { + let val = res.at(i) + other.at(j) * self.at((i, j)); + res.set(i, val) + } + } + + res + } + } + ) +) + +macro_rules! lmul_impl( + ($t: ident, $v: ident, $dim: expr) => ( + impl + LMul<$v> for $t + { + fn lmul(&self, other: &$v) -> $v + { + + let mut res : $v = Zero::zero(); + + for iterate(0u, $dim) |i| + { + for iterate(0u, $dim) |j| + { + let val = res.at(i) + other.at(j) * self.at((j, i)); + res.set(i, val) + } + } + + res + } + } + ) +) + +macro_rules! transform_impl( + ($t: ident, $v: ident) => ( + impl + Transform<$v> for $t + { + #[inline] + fn transform_vec(&self, v: &$v) -> $v + { self.rmul(v) } + + #[inline] + fn inv_transform(&self, v: &$v) -> $v + { + match self.inverse() + { + Some(t) => t.transform_vec(v), + None => fail!("Cannot use inv_transform on a non-inversible matrix.") + } + } + } + ) +) + +macro_rules! inv_impl( + ($t: ident, $dim: expr) => ( + impl + Inv for $t + { + #[inline] + fn inverse(&self) -> Option<$t> + { + let mut res : $t = self.clone(); + + if res.inplace_inverse() + { Some(res) } + else + { None } + } + + fn inplace_inverse(&mut self) -> bool + { + let mut res: $t = One::one(); + let _0N: N = Zero::zero(); + + // inversion using Gauss-Jordan elimination + for iterate(0u, $dim) |k| + { + // search a non-zero value on the k-th column + // FIXME: would it be worth it to spend some more time searching for the + // max instead? + + let mut n0 = k; // index of a non-zero entry + + while (n0 != $dim) + { + if self.at((n0, k)) != _0N + { break; } + + n0 = n0 + 1; + } + + if n0 == $dim + { return false } + + // swap pivot line + if n0 != k + { + for iterate(0u, $dim) |j| + { + self.swap((n0, j), (k, j)); + res.swap((n0, j), (k, j)); + } + } + + let pivot = self.at((k, k)); + + for iterate(k, $dim) |j| + { + let selfval = self.at((k, j)) / pivot; + self.set((k, j), selfval); + } + + for iterate(0u, $dim) |j| + { + let resval = res.at((k, j)) / pivot; + res.set((k, j), resval); + } + + for iterate(0u, $dim) |l| + { + if l != k + { + let normalizer = self.at((l, k)); + + for iterate(k, $dim) |j| + { + let selfval = self.at((l, j)) - self.at((k, j)) * normalizer; + self.set((l, j), selfval); + } + + for iterate(0u, $dim) |j| + { + let resval = res.at((l, j)) - res.at((k, j)) * normalizer; + res.set((l, j), resval); + } + } + } + } + + *self = res; + + true + } + } + ) +) + +macro_rules! transpose_impl( + ($t: ident, $dim: expr) => ( + impl Transpose for $t + { + #[inline] + fn transposed(&self) -> $t + { + let mut res = self.clone(); + + res.transpose(); + + res + } + + fn transpose(&mut self) + { + for iterate(1u, $dim) |i| + { + for iterate(0u, $dim - 1) |j| + { self.swap((i, j), (j, i)) } + } + } + } + ) +) + +macro_rules! approx_eq_impl( + ($t: ident) => ( + impl> ApproxEq for $t + { + #[inline] + fn approx_epsilon() -> N + { ApproxEq::approx_epsilon::() } + + #[inline] + fn approx_eq(&self, other: &$t) -> bool + { + let mut zip = self.iter().zip(other.iter()); + + do zip.all |(a, b)| { a.approx_eq(b) } + } + + #[inline] + fn approx_eq_eps(&self, other: &$t, epsilon: &N) -> bool + { + let mut zip = self.iter().zip(other.iter()); + + do zip.all |(a, b)| { a.approx_eq_eps(b, epsilon) } + } + } + ) +) + +macro_rules! to_homogeneous_impl( + ($t: ident, $t2: ident, $dim: expr, $dim2: expr) => ( + impl ToHomogeneous<$t2> for $t + { + fn to_homogeneous(&self) -> $t2 + { + let mut res: $t2 = One::one(); + + for iterate(0, $dim) |i| + { + for iterate(0, $dim) |j| + { res.set((i, j), self.at((i, j))) } + } + + res + } + } + ) +) + +macro_rules! from_homogeneous_impl( + ($t: ident, $t2: ident, $dim: expr, $dim2: expr) => ( + impl FromHomogeneous<$t2> for $t + { + fn from_homogeneous(m: &$t2) -> $t + { + let mut res: $t = One::one(); + + for iterate(0, $dim2) |i| + { + for iterate(0, $dim2) |j| + { res.set((i, j), m.at((i, j))) } + } + + // FIXME: do we have to deal the lost components + // (like if the 1 is not a 1… do we have to divide?) + + res + } + } + ) +) diff --git a/src/nalgebra.rc b/src/nalgebra.rc index 361428b9..f14aa969 100644 --- a/src/nalgebra.rc +++ b/src/nalgebra.rc @@ -13,10 +13,10 @@ extern mod std; extern mod extra; -pub mod vec; -pub mod mat; -pub mod dmat; -pub mod dvec; +mod dmat; +mod dvec; +mod vec_impl; +mod mat_impl; // specialization for some 1d, 2d and 3d operations pub mod mat_spec; @@ -30,9 +30,43 @@ pub mod adaptors pub mod transform; } +pub mod vec +{ + pub use vec_impl::*; + pub use dvec::*; + pub use traits::sample::*; + pub use traits::dot::*; + pub use traits::cross::*; + pub use traits::basis::*; + pub use traits::norm::*; + pub use traits::vector_space::*; + pub use traits::sub_dot::*; + pub use traits::scalar_op::*; +} + +pub mod mat +{ + pub use mat_impl::*; + pub use dmat::*; + pub use traits::column::*; + pub use traits::inv::*; + pub use traits::transpose::*; + pub use traits::rotation::*; + pub use traits::translation::*; + pub use traits::transformation::*; +} + /// Useful linear-algebra related traits. pub mod traits { + pub use traits::indexable::*; + pub use traits::iterable::*; + pub use traits::dim::*; + pub use traits::ring::*; + pub use traits::division_ring::*; + pub use traits::rlmul::*; + pub use traits::homogeneous::*; + pub mod sample; pub mod indexable; pub mod column; diff --git a/src/vec.rs b/src/vec.rs deleted file mode 100644 index 0a385f49..00000000 --- a/src/vec.rs +++ /dev/null @@ -1,227 +0,0 @@ -use std::cast; -use std::num::{Zero, One, Algebraic, Bounded}; -use std::rand::Rng; -use std::vec::{VecIterator, VecMutIterator}; -use std::iterator::{Iterator, IteratorUtil, FromIterator}; -use std::cmp::ApproxEq; -use std::uint::iterate; -use traits::iterable::{Iterable, IterableMut}; -use traits::basis::Basis; -use traits::dim::Dim; -use traits::dot::Dot; -use traits::sub_dot::SubDot; -use traits::norm::Norm; -use traits::translation::{Translation, Translatable}; -use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub}; -use traits::ring::Ring; -use traits::division_ring::DivisionRing; -use traits::homogeneous::{FromHomogeneous, ToHomogeneous}; -use traits::indexable::Indexable; - -mod vec_impl; - -#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, Rand, Zero, ToStr)] -pub struct Vec0; - -#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] -pub struct Vec1 -{ x: N } - -new_impl!(Vec1, x) -indexable_impl!(Vec1, 1) -new_repeat_impl!(Vec1, val, x) -dim_impl!(Vec1, 1) -// (specialized) basis_impl!(Vec1, 1) -add_impl!(Vec1, x) -sub_impl!(Vec1, x) -neg_impl!(Vec1, x) -dot_impl!(Vec1, x) -sub_dot_impl!(Vec1, x) -scalar_mul_impl!(Vec1, x) -scalar_div_impl!(Vec1, x) -scalar_add_impl!(Vec1, x) -scalar_sub_impl!(Vec1, x) -translation_impl!(Vec1) -translatable_impl!(Vec1) -norm_impl!(Vec1) -approx_eq_impl!(Vec1, x) -one_impl!(Vec1) -from_iterator_impl!(Vec1, iterator) -bounded_impl!(Vec1) -iterable_impl!(Vec1, 1) -iterable_mut_impl!(Vec1, 1) -to_homogeneous_impl!(Vec1, Vec2, y, x) -from_homogeneous_impl!(Vec1, Vec2, y, x) - -#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] -pub struct Vec2 -{ - x: N, - y: N -} - -new_impl!(Vec2, x, y) -indexable_impl!(Vec2, 2) -new_repeat_impl!(Vec2, val, x, y) -dim_impl!(Vec2, 2) -// (specialized) basis_impl!(Vec2, 1) -add_impl!(Vec2, x, y) -sub_impl!(Vec2, x, y) -neg_impl!(Vec2, x, y) -dot_impl!(Vec2, x, y) -sub_dot_impl!(Vec2, x, y) -scalar_mul_impl!(Vec2, x, y) -scalar_div_impl!(Vec2, x, y) -scalar_add_impl!(Vec2, x, y) -scalar_sub_impl!(Vec2, x, y) -translation_impl!(Vec2) -translatable_impl!(Vec2) -norm_impl!(Vec2) -approx_eq_impl!(Vec2, x, y) -one_impl!(Vec2) -from_iterator_impl!(Vec2, iterator, iterator) -bounded_impl!(Vec2) -iterable_impl!(Vec2, 2) -iterable_mut_impl!(Vec2, 2) -to_homogeneous_impl!(Vec2, Vec3, z, x, y) -from_homogeneous_impl!(Vec2, Vec3, z, x, y) - -#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] -pub struct Vec3 -{ - x: N, - y: N, - z: N -} - -new_impl!(Vec3, x, y, z) -indexable_impl!(Vec3, 3) -new_repeat_impl!(Vec3, val, x, y, z) -dim_impl!(Vec3, 3) -// (specialized) basis_impl!(Vec3, 1) -add_impl!(Vec3, x, y, z) -sub_impl!(Vec3, x, y, z) -neg_impl!(Vec3, x, y, z) -dot_impl!(Vec3, x, y, z) -sub_dot_impl!(Vec3, x, y, z) -scalar_mul_impl!(Vec3, x, y, z) -scalar_div_impl!(Vec3, x, y, z) -scalar_add_impl!(Vec3, x, y, z) -scalar_sub_impl!(Vec3, x, y, z) -translation_impl!(Vec3) -translatable_impl!(Vec3) -norm_impl!(Vec3) -approx_eq_impl!(Vec3, x, y, z) -one_impl!(Vec3) -from_iterator_impl!(Vec3, iterator, iterator, iterator) -bounded_impl!(Vec3) -iterable_impl!(Vec3, 3) -iterable_mut_impl!(Vec3, 3) -to_homogeneous_impl!(Vec3, Vec4, w, x, y, z) -from_homogeneous_impl!(Vec3, Vec4, w, x, y, z) - -#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] -pub struct Vec4 -{ - x: N, - y: N, - z: N, - w: N -} - -new_impl!(Vec4, x, y, z, w) -indexable_impl!(Vec4, 4) -new_repeat_impl!(Vec4, val, x, y, z, w) -dim_impl!(Vec4, 4) -basis_impl!(Vec4, 4) -add_impl!(Vec4, x, y, z, w) -sub_impl!(Vec4, x, y, z, w) -neg_impl!(Vec4, x, y, z, w) -dot_impl!(Vec4, x, y, z, w) -sub_dot_impl!(Vec4, x, y, z, w) -scalar_mul_impl!(Vec4, x, y, z, w) -scalar_div_impl!(Vec4, x, y, z, w) -scalar_add_impl!(Vec4, x, y, z, w) -scalar_sub_impl!(Vec4, x, y, z, w) -translation_impl!(Vec4) -translatable_impl!(Vec4) -norm_impl!(Vec4) -approx_eq_impl!(Vec4, x, y, z, w) -one_impl!(Vec4) -from_iterator_impl!(Vec4, iterator, iterator, iterator, iterator) -bounded_impl!(Vec4) -iterable_impl!(Vec4, 4) -iterable_mut_impl!(Vec4, 4) -to_homogeneous_impl!(Vec4, Vec5, a, x, y, z, w) -from_homogeneous_impl!(Vec4, Vec5, a, x, y, z, w) - -#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] -pub struct Vec5 -{ - x: N, - y: N, - z: N, - w: N, - a: N, -} - -new_impl!(Vec5, x, y, z, w, a) -indexable_impl!(Vec5, 5) -new_repeat_impl!(Vec5, val, x, y, z, w, a) -dim_impl!(Vec5, 5) -basis_impl!(Vec5, 5) -add_impl!(Vec5, x, y, z, w, a) -sub_impl!(Vec5, x, y, z, w, a) -neg_impl!(Vec5, x, y, z, w, a) -dot_impl!(Vec5, x, y, z, w, a) -sub_dot_impl!(Vec5, x, y, z, w, a) -scalar_mul_impl!(Vec5, x, y, z, w, a) -scalar_div_impl!(Vec5, x, y, z, w, a) -scalar_add_impl!(Vec5, x, y, z, w, a) -scalar_sub_impl!(Vec5, x, y, z, w, a) -translation_impl!(Vec5) -translatable_impl!(Vec5) -norm_impl!(Vec5) -approx_eq_impl!(Vec5, x, y, z, w, a) -one_impl!(Vec5) -from_iterator_impl!(Vec5, iterator, iterator, iterator, iterator, iterator) -bounded_impl!(Vec5) -iterable_impl!(Vec5, 5) -iterable_mut_impl!(Vec5, 5) -to_homogeneous_impl!(Vec5, Vec6, b, x, y, z, w, a) -from_homogeneous_impl!(Vec5, Vec6, b, x, y, z, w, a) - -#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] -pub struct Vec6 -{ - x: N, - y: N, - z: N, - w: N, - a: N, - b: N -} - -new_impl!(Vec6, x, y, z, w, a, b) -indexable_impl!(Vec6, 6) -new_repeat_impl!(Vec6, val, x, y, z, w, a, b) -dim_impl!(Vec6, 6) -basis_impl!(Vec6, 6) -add_impl!(Vec6, x, y, z, w, a, b) -sub_impl!(Vec6, x, y, z, w, a, b) -neg_impl!(Vec6, x, y, z, w, a, b) -dot_impl!(Vec6, x, y, z, w, a, b) -sub_dot_impl!(Vec6, x, y, z, w, a, b) -scalar_mul_impl!(Vec6, x, y, z, w, a, b) -scalar_div_impl!(Vec6, x, y, z, w, a, b) -scalar_add_impl!(Vec6, x, y, z, w, a, b) -scalar_sub_impl!(Vec6, x, y, z, w, a, b) -translation_impl!(Vec6) -translatable_impl!(Vec6) -norm_impl!(Vec6) -approx_eq_impl!(Vec6, x, y, z, w, a, b) -one_impl!(Vec6) -from_iterator_impl!(Vec6, iterator, iterator, iterator, iterator, iterator, iterator) -bounded_impl!(Vec6) -iterable_impl!(Vec6, 6) -iterable_mut_impl!(Vec6, 6) diff --git a/src/vec_impl.rs b/src/vec_impl.rs index 85c3e20b..5f9f9c05 100644 --- a/src/vec_impl.rs +++ b/src/vec_impl.rs @@ -1,418 +1,227 @@ -#[macro_escape]; +use std::cast; +use std::num::{Zero, One, Algebraic, Bounded}; +use std::rand::Rng; +use std::vec::{VecIterator, VecMutIterator}; +use std::iterator::{Iterator, IteratorUtil, FromIterator}; +use std::cmp::ApproxEq; +use std::uint::iterate; +use traits::iterable::{Iterable, IterableMut}; +use traits::basis::Basis; +use traits::dim::Dim; +use traits::dot::Dot; +use traits::sub_dot::SubDot; +use traits::norm::Norm; +use traits::translation::{Translation, Translatable}; +use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub}; +use traits::ring::Ring; +use traits::division_ring::DivisionRing; +use traits::homogeneous::{FromHomogeneous, ToHomogeneous}; +use traits::indexable::Indexable; -macro_rules! new_impl( - ($t: ident, $comp0: ident $(,$compN: ident)*) => ( - impl $t - { - #[inline] - pub fn new($comp0: N $( , $compN: N )*) -> $t - { - $t { - $comp0: $comp0 - $(, $compN: $compN )* - } - } - } - ) -) +mod vec_macros; -macro_rules! indexable_impl( - ($t: ident, $dim: expr) => ( - impl Indexable for $t - { - #[inline] - pub fn at(&self, i: uint) -> N - { unsafe { cast::transmute::<&$t, &[N, ..$dim]>(self)[i].clone() } } +#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, Rand, Zero, ToStr)] +pub struct Vec0; - #[inline] - pub fn set(&mut self, i: uint, val: N) - { unsafe { cast::transmute::<&mut $t, &mut [N, ..$dim]>(self)[i] = val } } +#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] +pub struct Vec1 +{ x: N } - #[inline] - pub fn swap(&mut self, i1: uint, i2: uint) - { unsafe { cast::transmute::<&mut $t, &mut [N, ..$dim]>(self).swap(i1, i2) } } - } - ) -) +new_impl!(Vec1, x) +indexable_impl!(Vec1, 1) +new_repeat_impl!(Vec1, val, x) +dim_impl!(Vec1, 1) +// (specialized) basis_impl!(Vec1, 1) +add_impl!(Vec1, x) +sub_impl!(Vec1, x) +neg_impl!(Vec1, x) +dot_impl!(Vec1, x) +sub_dot_impl!(Vec1, x) +scalar_mul_impl!(Vec1, x) +scalar_div_impl!(Vec1, x) +scalar_add_impl!(Vec1, x) +scalar_sub_impl!(Vec1, x) +translation_impl!(Vec1) +translatable_impl!(Vec1) +norm_impl!(Vec1) +approx_eq_impl!(Vec1, x) +one_impl!(Vec1) +from_iterator_impl!(Vec1, iterator) +bounded_impl!(Vec1) +iterable_impl!(Vec1, 1) +iterable_mut_impl!(Vec1, 1) +to_homogeneous_impl!(Vec1, Vec2, y, x) +from_homogeneous_impl!(Vec1, Vec2, y, x) -macro_rules! new_repeat_impl( - ($t: ident, $param: ident, $comp0: ident $(,$compN: ident)*) => ( - impl $t - { - #[inline] - pub fn new_repeat($param: N) -> $t - { - $t{ - $comp0: $param.clone() - $(, $compN: $param.clone() )* - } - } - } - ) -) +#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] +pub struct Vec2 +{ + x: N, + y: N +} -macro_rules! iterable_impl( - ($t: ident, $dim: expr) => ( - impl Iterable for $t - { - fn iter<'l>(&'l self) -> VecIterator<'l, N> - { unsafe { cast::transmute::<&'l $t, &'l [N, ..$dim]>(self).iter() } } - } - ) -) +new_impl!(Vec2, x, y) +indexable_impl!(Vec2, 2) +new_repeat_impl!(Vec2, val, x, y) +dim_impl!(Vec2, 2) +// (specialized) basis_impl!(Vec2, 1) +add_impl!(Vec2, x, y) +sub_impl!(Vec2, x, y) +neg_impl!(Vec2, x, y) +dot_impl!(Vec2, x, y) +sub_dot_impl!(Vec2, x, y) +scalar_mul_impl!(Vec2, x, y) +scalar_div_impl!(Vec2, x, y) +scalar_add_impl!(Vec2, x, y) +scalar_sub_impl!(Vec2, x, y) +translation_impl!(Vec2) +translatable_impl!(Vec2) +norm_impl!(Vec2) +approx_eq_impl!(Vec2, x, y) +one_impl!(Vec2) +from_iterator_impl!(Vec2, iterator, iterator) +bounded_impl!(Vec2) +iterable_impl!(Vec2, 2) +iterable_mut_impl!(Vec2, 2) +to_homogeneous_impl!(Vec2, Vec3, z, x, y) +from_homogeneous_impl!(Vec2, Vec3, z, x, y) -macro_rules! iterable_mut_impl( - ($t: ident, $dim: expr) => ( - impl IterableMut for $t - { - fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N> - { unsafe { cast::transmute::<&'l mut $t, &'l mut [N, ..$dim]>(self).mut_iter() } } - } - ) -) +#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] +pub struct Vec3 +{ + x: N, + y: N, + z: N +} -macro_rules! dim_impl( - ($t: ident, $dim: expr) => ( - impl Dim for $t - { - #[inline] - fn dim() -> uint - { $dim } - } - ) -) +new_impl!(Vec3, x, y, z) +indexable_impl!(Vec3, 3) +new_repeat_impl!(Vec3, val, x, y, z) +dim_impl!(Vec3, 3) +// (specialized) basis_impl!(Vec3, 1) +add_impl!(Vec3, x, y, z) +sub_impl!(Vec3, x, y, z) +neg_impl!(Vec3, x, y, z) +dot_impl!(Vec3, x, y, z) +sub_dot_impl!(Vec3, x, y, z) +scalar_mul_impl!(Vec3, x, y, z) +scalar_div_impl!(Vec3, x, y, z) +scalar_add_impl!(Vec3, x, y, z) +scalar_sub_impl!(Vec3, x, y, z) +translation_impl!(Vec3) +translatable_impl!(Vec3) +norm_impl!(Vec3) +approx_eq_impl!(Vec3, x, y, z) +one_impl!(Vec3) +from_iterator_impl!(Vec3, iterator, iterator, iterator) +bounded_impl!(Vec3) +iterable_impl!(Vec3, 3) +iterable_mut_impl!(Vec3, 3) +to_homogeneous_impl!(Vec3, Vec4, w, x, y, z) +from_homogeneous_impl!(Vec3, Vec4, w, x, y, z) -macro_rules! basis_impl( - ($t: ident, $dim: expr) => ( - impl> Basis for $t - { - pub fn canonical_basis(f: &fn($t)) - { - for iterate(0u, $dim) |i| - { - let mut basis_element : $t = Zero::zero(); - - basis_element.set(i, One::one()); - - f(basis_element); - } - } - - pub fn orthonormal_subspace_basis(&self, f: &fn($t)) - { - // compute the basis of the orthogonal subspace using Gram-Schmidt - // orthogonalization algorithm - let mut basis: ~[$t] = ~[]; - - for iterate(0u, $dim) |i| - { - let mut basis_element : $t = Zero::zero(); - - basis_element.set(i, One::one()); - - if basis.len() == $dim - 1 - { break; } - - let mut elt = basis_element.clone(); - - elt = elt - self.scalar_mul(&basis_element.dot(self)); - - for basis.iter().advance |v| - { elt = elt - v.scalar_mul(&elt.dot(v)) }; - - if !elt.sqnorm().approx_eq(&Zero::zero()) - { - let new_element = elt.normalized(); +#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] +pub struct Vec4 +{ + x: N, + y: N, + z: N, + w: N +} - f(new_element.clone()); +new_impl!(Vec4, x, y, z, w) +indexable_impl!(Vec4, 4) +new_repeat_impl!(Vec4, val, x, y, z, w) +dim_impl!(Vec4, 4) +basis_impl!(Vec4, 4) +add_impl!(Vec4, x, y, z, w) +sub_impl!(Vec4, x, y, z, w) +neg_impl!(Vec4, x, y, z, w) +dot_impl!(Vec4, x, y, z, w) +sub_dot_impl!(Vec4, x, y, z, w) +scalar_mul_impl!(Vec4, x, y, z, w) +scalar_div_impl!(Vec4, x, y, z, w) +scalar_add_impl!(Vec4, x, y, z, w) +scalar_sub_impl!(Vec4, x, y, z, w) +translation_impl!(Vec4) +translatable_impl!(Vec4) +norm_impl!(Vec4) +approx_eq_impl!(Vec4, x, y, z, w) +one_impl!(Vec4) +from_iterator_impl!(Vec4, iterator, iterator, iterator, iterator) +bounded_impl!(Vec4) +iterable_impl!(Vec4, 4) +iterable_mut_impl!(Vec4, 4) +to_homogeneous_impl!(Vec4, Vec5, a, x, y, z, w) +from_homogeneous_impl!(Vec4, Vec5, a, x, y, z, w) - basis.push(new_element); - } - } - } - } - ) -) +#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] +pub struct Vec5 +{ + x: N, + y: N, + z: N, + w: N, + a: N, +} -macro_rules! add_impl( - ($t: ident, $comp0: ident $(,$compN: ident)*) => ( - impl> Add<$t, $t> for $t - { - #[inline] - fn add(&self, other: &$t) -> $t - { $t::new(self.$comp0 + other.$comp0 $(, self.$compN + other.$compN)*) } - } - ) -) +new_impl!(Vec5, x, y, z, w, a) +indexable_impl!(Vec5, 5) +new_repeat_impl!(Vec5, val, x, y, z, w, a) +dim_impl!(Vec5, 5) +basis_impl!(Vec5, 5) +add_impl!(Vec5, x, y, z, w, a) +sub_impl!(Vec5, x, y, z, w, a) +neg_impl!(Vec5, x, y, z, w, a) +dot_impl!(Vec5, x, y, z, w, a) +sub_dot_impl!(Vec5, x, y, z, w, a) +scalar_mul_impl!(Vec5, x, y, z, w, a) +scalar_div_impl!(Vec5, x, y, z, w, a) +scalar_add_impl!(Vec5, x, y, z, w, a) +scalar_sub_impl!(Vec5, x, y, z, w, a) +translation_impl!(Vec5) +translatable_impl!(Vec5) +norm_impl!(Vec5) +approx_eq_impl!(Vec5, x, y, z, w, a) +one_impl!(Vec5) +from_iterator_impl!(Vec5, iterator, iterator, iterator, iterator, iterator) +bounded_impl!(Vec5) +iterable_impl!(Vec5, 5) +iterable_mut_impl!(Vec5, 5) +to_homogeneous_impl!(Vec5, Vec6, b, x, y, z, w, a) +from_homogeneous_impl!(Vec5, Vec6, b, x, y, z, w, a) -macro_rules! sub_impl( - ($t: ident, $comp0: ident $(,$compN: ident)*) => ( - impl> Sub<$t, $t> for $t - { - #[inline] - fn sub(&self, other: &$t) -> $t - { $t::new(self.$comp0 - other.$comp0 $(, self.$compN - other.$compN)*) } - } - ) -) +#[deriving(Eq, Ord, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)] +pub struct Vec6 +{ + x: N, + y: N, + z: N, + w: N, + a: N, + b: N +} -macro_rules! neg_impl( - ($t: ident, $comp0: ident $(,$compN: ident)*) => ( - impl> Neg<$t> for $t - { - #[inline] - fn neg(&self) -> $t - { $t::new(-self.$comp0 $(, -self.$compN )*) } - } - ) -) - -macro_rules! dot_impl( - ($t: ident, $comp0: ident $(,$compN: ident)*) => ( - impl Dot for $t - { - #[inline] - fn dot(&self, other: &$t) -> N - { self.$comp0 * other.$comp0 $(+ self.$compN * other.$compN )* } - } - ) -) - -macro_rules! sub_dot_impl( - ($t: ident, $comp0: ident $(,$compN: ident)*) => ( - impl SubDot for $t - { - #[inline] - fn sub_dot(&self, a: &$t, b: &$t) -> N - { (self.$comp0 - a.$comp0) * b.$comp0 $(+ (self.$compN - a.$compN) * b.$compN )* } - } - ) -) - -macro_rules! scalar_mul_impl( - ($t: ident, $comp0: ident $(,$compN: ident)*) => ( - impl> ScalarMul for $t - { - #[inline] - fn scalar_mul(&self, s: &N) -> $t - { $t::new(self.$comp0 * *s $(, self.$compN * *s)*) } - - #[inline] - fn scalar_mul_inplace(&mut self, s: &N) - { - self.$comp0 = self.$comp0 * *s; - $(self.$compN = self.$compN * *s;)* - } - } - ) -) - -macro_rules! scalar_div_impl( - ($t: ident, $comp0: ident $(,$compN: ident)*) => ( - impl> ScalarDiv for $t - { - #[inline] - fn scalar_div(&self, s: &N) -> $t - { $t::new(self.$comp0 / *s $(, self.$compN / *s)*) } - - #[inline] - fn scalar_div_inplace(&mut self, s: &N) - { - self.$comp0 = self.$comp0 / *s; - $(self.$compN = self.$compN / *s;)* - } - } - ) -) - -macro_rules! scalar_add_impl( - ($t: ident, $comp0: ident $(,$compN: ident)*) => ( - impl> ScalarAdd for $t - { - #[inline] - fn scalar_add(&self, s: &N) -> $t - { $t::new(self.$comp0 + *s $(, self.$compN + *s)*) } - - #[inline] - fn scalar_add_inplace(&mut self, s: &N) - { - self.$comp0 = self.$comp0 + *s; - $(self.$compN = self.$compN + *s;)* - } - } - ) -) - -macro_rules! scalar_sub_impl( - ($t: ident, $comp0: ident $(,$compN: ident)*) => ( - impl> ScalarSub for $t - { - #[inline] - fn scalar_sub(&self, s: &N) -> $t - { $t::new(self.$comp0 - *s $(, self.$compN - *s)*) } - - #[inline] - fn scalar_sub_inplace(&mut self, s: &N) - { - self.$comp0 = self.$comp0 - *s; - $(self.$compN = self.$compN - *s;)* - } - } - ) -) - -macro_rules! translation_impl( - ($t: ident) => ( - impl + Neg> Translation<$t> for $t - { - #[inline] - fn translation(&self) -> $t - { self.clone() } - - #[inline] - fn inv_translation(&self) -> $t - { -self } - - #[inline] - fn translate_by(&mut self, t: &$t) - { *self = *self + *t; } - } - ) -) - -macro_rules! translatable_impl( - ($t: ident) => ( - impl + Neg + Clone> Translatable<$t, $t> for $t - { - #[inline] - fn translated(&self, t: &$t) -> $t - { self + *t } - } - ) -) - -macro_rules! norm_impl( - ($t: ident) => ( - impl Norm for $t - { - #[inline] - fn sqnorm(&self) -> N - { self.dot(self) } - - #[inline] - fn norm(&self) -> N - { self.sqnorm().sqrt() } - - #[inline] - fn normalized(&self) -> $t - { - let mut res : $t = self.clone(); - - res.normalize(); - - res - } - - #[inline] - fn normalize(&mut self) -> N - { - let l = self.norm(); - - self.scalar_div_inplace(&l); - - l - } - } - ) -) - -macro_rules! approx_eq_impl( - ($t: ident, $comp0: ident $(,$compN: ident)*) => ( - impl> ApproxEq for $t - { - #[inline] - fn approx_epsilon() -> N - { ApproxEq::approx_epsilon::() } - - #[inline] - fn approx_eq(&self, other: &$t) -> bool - { self.$comp0.approx_eq(&other.$comp0) $(&& self.$compN.approx_eq(&other.$compN))* } - - #[inline] - fn approx_eq_eps(&self, other: &$t, eps: &N) -> bool - { self.$comp0.approx_eq_eps(&other.$comp0, eps) $(&& self.$compN.approx_eq_eps(&other.$compN, eps))* } - } - ) -) - -macro_rules! one_impl( - ($t: ident) => ( - impl One for $t - { - #[inline] - fn one() -> $t - { $t::new_repeat(One::one()) } - } - ) -) - -macro_rules! from_iterator_impl( - ($t: ident, $param0: ident $(, $paramN: ident)*) => ( - impl> FromIterator for $t - { - fn from_iterator($param0: &mut Iter) -> $t - { $t::new($param0.next().unwrap() $(, $paramN.next().unwrap())*) } - } - ) -) - -macro_rules! bounded_impl( - ($t: ident) => ( - impl Bounded for $t - { - #[inline] - fn max_value() -> $t - { $t::new_repeat(Bounded::max_value()) } - - #[inline] - fn min_value() -> $t - { $t::new_repeat(Bounded::min_value()) } - } - ) -) - -macro_rules! to_homogeneous_impl( - ($t: ident, $t2: ident, $extra: ident, $comp0: ident $(,$compN: ident)*) => ( - impl ToHomogeneous<$t2> for $t - { - fn to_homogeneous(&self) -> $t2 - { - let mut res: $t2 = One::one(); - - res.$comp0 = self.$comp0.clone(); - $( res.$compN = self.$compN.clone(); )* - - res - } - } - ) -) - -macro_rules! from_homogeneous_impl( - ($t: ident, $t2: ident, $extra: ident, $comp0: ident $(,$compN: ident)*) => ( - impl + One + Zero> FromHomogeneous<$t2> for $t - { - fn from_homogeneous(v: &$t2) -> $t - { - let mut res: $t = Zero::zero(); - - res.$comp0 = v.$comp0.clone(); - $( res.$compN = v.$compN.clone(); )* - - res.scalar_div(&v.$extra); - - res - } - } - ) -) +new_impl!(Vec6, x, y, z, w, a, b) +indexable_impl!(Vec6, 6) +new_repeat_impl!(Vec6, val, x, y, z, w, a, b) +dim_impl!(Vec6, 6) +basis_impl!(Vec6, 6) +add_impl!(Vec6, x, y, z, w, a, b) +sub_impl!(Vec6, x, y, z, w, a, b) +neg_impl!(Vec6, x, y, z, w, a, b) +dot_impl!(Vec6, x, y, z, w, a, b) +sub_dot_impl!(Vec6, x, y, z, w, a, b) +scalar_mul_impl!(Vec6, x, y, z, w, a, b) +scalar_div_impl!(Vec6, x, y, z, w, a, b) +scalar_add_impl!(Vec6, x, y, z, w, a, b) +scalar_sub_impl!(Vec6, x, y, z, w, a, b) +translation_impl!(Vec6) +translatable_impl!(Vec6) +norm_impl!(Vec6) +approx_eq_impl!(Vec6, x, y, z, w, a, b) +one_impl!(Vec6) +from_iterator_impl!(Vec6, iterator, iterator, iterator, iterator, iterator, iterator) +bounded_impl!(Vec6) +iterable_impl!(Vec6, 6) +iterable_mut_impl!(Vec6, 6) diff --git a/src/vec_macros.rs b/src/vec_macros.rs new file mode 100644 index 00000000..85c3e20b --- /dev/null +++ b/src/vec_macros.rs @@ -0,0 +1,418 @@ +#[macro_escape]; + +macro_rules! new_impl( + ($t: ident, $comp0: ident $(,$compN: ident)*) => ( + impl $t + { + #[inline] + pub fn new($comp0: N $( , $compN: N )*) -> $t + { + $t { + $comp0: $comp0 + $(, $compN: $compN )* + } + } + } + ) +) + +macro_rules! indexable_impl( + ($t: ident, $dim: expr) => ( + impl Indexable for $t + { + #[inline] + pub fn at(&self, i: uint) -> N + { unsafe { cast::transmute::<&$t, &[N, ..$dim]>(self)[i].clone() } } + + #[inline] + pub fn set(&mut self, i: uint, val: N) + { unsafe { cast::transmute::<&mut $t, &mut [N, ..$dim]>(self)[i] = val } } + + #[inline] + pub fn swap(&mut self, i1: uint, i2: uint) + { unsafe { cast::transmute::<&mut $t, &mut [N, ..$dim]>(self).swap(i1, i2) } } + } + ) +) + +macro_rules! new_repeat_impl( + ($t: ident, $param: ident, $comp0: ident $(,$compN: ident)*) => ( + impl $t + { + #[inline] + pub fn new_repeat($param: N) -> $t + { + $t{ + $comp0: $param.clone() + $(, $compN: $param.clone() )* + } + } + } + ) +) + +macro_rules! iterable_impl( + ($t: ident, $dim: expr) => ( + impl Iterable for $t + { + fn iter<'l>(&'l self) -> VecIterator<'l, N> + { unsafe { cast::transmute::<&'l $t, &'l [N, ..$dim]>(self).iter() } } + } + ) +) + +macro_rules! iterable_mut_impl( + ($t: ident, $dim: expr) => ( + impl IterableMut for $t + { + fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N> + { unsafe { cast::transmute::<&'l mut $t, &'l mut [N, ..$dim]>(self).mut_iter() } } + } + ) +) + +macro_rules! dim_impl( + ($t: ident, $dim: expr) => ( + impl Dim for $t + { + #[inline] + fn dim() -> uint + { $dim } + } + ) +) + +macro_rules! basis_impl( + ($t: ident, $dim: expr) => ( + impl> Basis for $t + { + pub fn canonical_basis(f: &fn($t)) + { + for iterate(0u, $dim) |i| + { + let mut basis_element : $t = Zero::zero(); + + basis_element.set(i, One::one()); + + f(basis_element); + } + } + + pub fn orthonormal_subspace_basis(&self, f: &fn($t)) + { + // compute the basis of the orthogonal subspace using Gram-Schmidt + // orthogonalization algorithm + let mut basis: ~[$t] = ~[]; + + for iterate(0u, $dim) |i| + { + let mut basis_element : $t = Zero::zero(); + + basis_element.set(i, One::one()); + + if basis.len() == $dim - 1 + { break; } + + let mut elt = basis_element.clone(); + + elt = elt - self.scalar_mul(&basis_element.dot(self)); + + for basis.iter().advance |v| + { elt = elt - v.scalar_mul(&elt.dot(v)) }; + + if !elt.sqnorm().approx_eq(&Zero::zero()) + { + let new_element = elt.normalized(); + + f(new_element.clone()); + + basis.push(new_element); + } + } + } + } + ) +) + +macro_rules! add_impl( + ($t: ident, $comp0: ident $(,$compN: ident)*) => ( + impl> Add<$t, $t> for $t + { + #[inline] + fn add(&self, other: &$t) -> $t + { $t::new(self.$comp0 + other.$comp0 $(, self.$compN + other.$compN)*) } + } + ) +) + +macro_rules! sub_impl( + ($t: ident, $comp0: ident $(,$compN: ident)*) => ( + impl> Sub<$t, $t> for $t + { + #[inline] + fn sub(&self, other: &$t) -> $t + { $t::new(self.$comp0 - other.$comp0 $(, self.$compN - other.$compN)*) } + } + ) +) + +macro_rules! neg_impl( + ($t: ident, $comp0: ident $(,$compN: ident)*) => ( + impl> Neg<$t> for $t + { + #[inline] + fn neg(&self) -> $t + { $t::new(-self.$comp0 $(, -self.$compN )*) } + } + ) +) + +macro_rules! dot_impl( + ($t: ident, $comp0: ident $(,$compN: ident)*) => ( + impl Dot for $t + { + #[inline] + fn dot(&self, other: &$t) -> N + { self.$comp0 * other.$comp0 $(+ self.$compN * other.$compN )* } + } + ) +) + +macro_rules! sub_dot_impl( + ($t: ident, $comp0: ident $(,$compN: ident)*) => ( + impl SubDot for $t + { + #[inline] + fn sub_dot(&self, a: &$t, b: &$t) -> N + { (self.$comp0 - a.$comp0) * b.$comp0 $(+ (self.$compN - a.$compN) * b.$compN )* } + } + ) +) + +macro_rules! scalar_mul_impl( + ($t: ident, $comp0: ident $(,$compN: ident)*) => ( + impl> ScalarMul for $t + { + #[inline] + fn scalar_mul(&self, s: &N) -> $t + { $t::new(self.$comp0 * *s $(, self.$compN * *s)*) } + + #[inline] + fn scalar_mul_inplace(&mut self, s: &N) + { + self.$comp0 = self.$comp0 * *s; + $(self.$compN = self.$compN * *s;)* + } + } + ) +) + +macro_rules! scalar_div_impl( + ($t: ident, $comp0: ident $(,$compN: ident)*) => ( + impl> ScalarDiv for $t + { + #[inline] + fn scalar_div(&self, s: &N) -> $t + { $t::new(self.$comp0 / *s $(, self.$compN / *s)*) } + + #[inline] + fn scalar_div_inplace(&mut self, s: &N) + { + self.$comp0 = self.$comp0 / *s; + $(self.$compN = self.$compN / *s;)* + } + } + ) +) + +macro_rules! scalar_add_impl( + ($t: ident, $comp0: ident $(,$compN: ident)*) => ( + impl> ScalarAdd for $t + { + #[inline] + fn scalar_add(&self, s: &N) -> $t + { $t::new(self.$comp0 + *s $(, self.$compN + *s)*) } + + #[inline] + fn scalar_add_inplace(&mut self, s: &N) + { + self.$comp0 = self.$comp0 + *s; + $(self.$compN = self.$compN + *s;)* + } + } + ) +) + +macro_rules! scalar_sub_impl( + ($t: ident, $comp0: ident $(,$compN: ident)*) => ( + impl> ScalarSub for $t + { + #[inline] + fn scalar_sub(&self, s: &N) -> $t + { $t::new(self.$comp0 - *s $(, self.$compN - *s)*) } + + #[inline] + fn scalar_sub_inplace(&mut self, s: &N) + { + self.$comp0 = self.$comp0 - *s; + $(self.$compN = self.$compN - *s;)* + } + } + ) +) + +macro_rules! translation_impl( + ($t: ident) => ( + impl + Neg> Translation<$t> for $t + { + #[inline] + fn translation(&self) -> $t + { self.clone() } + + #[inline] + fn inv_translation(&self) -> $t + { -self } + + #[inline] + fn translate_by(&mut self, t: &$t) + { *self = *self + *t; } + } + ) +) + +macro_rules! translatable_impl( + ($t: ident) => ( + impl + Neg + Clone> Translatable<$t, $t> for $t + { + #[inline] + fn translated(&self, t: &$t) -> $t + { self + *t } + } + ) +) + +macro_rules! norm_impl( + ($t: ident) => ( + impl Norm for $t + { + #[inline] + fn sqnorm(&self) -> N + { self.dot(self) } + + #[inline] + fn norm(&self) -> N + { self.sqnorm().sqrt() } + + #[inline] + fn normalized(&self) -> $t + { + let mut res : $t = self.clone(); + + res.normalize(); + + res + } + + #[inline] + fn normalize(&mut self) -> N + { + let l = self.norm(); + + self.scalar_div_inplace(&l); + + l + } + } + ) +) + +macro_rules! approx_eq_impl( + ($t: ident, $comp0: ident $(,$compN: ident)*) => ( + impl> ApproxEq for $t + { + #[inline] + fn approx_epsilon() -> N + { ApproxEq::approx_epsilon::() } + + #[inline] + fn approx_eq(&self, other: &$t) -> bool + { self.$comp0.approx_eq(&other.$comp0) $(&& self.$compN.approx_eq(&other.$compN))* } + + #[inline] + fn approx_eq_eps(&self, other: &$t, eps: &N) -> bool + { self.$comp0.approx_eq_eps(&other.$comp0, eps) $(&& self.$compN.approx_eq_eps(&other.$compN, eps))* } + } + ) +) + +macro_rules! one_impl( + ($t: ident) => ( + impl One for $t + { + #[inline] + fn one() -> $t + { $t::new_repeat(One::one()) } + } + ) +) + +macro_rules! from_iterator_impl( + ($t: ident, $param0: ident $(, $paramN: ident)*) => ( + impl> FromIterator for $t + { + fn from_iterator($param0: &mut Iter) -> $t + { $t::new($param0.next().unwrap() $(, $paramN.next().unwrap())*) } + } + ) +) + +macro_rules! bounded_impl( + ($t: ident) => ( + impl Bounded for $t + { + #[inline] + fn max_value() -> $t + { $t::new_repeat(Bounded::max_value()) } + + #[inline] + fn min_value() -> $t + { $t::new_repeat(Bounded::min_value()) } + } + ) +) + +macro_rules! to_homogeneous_impl( + ($t: ident, $t2: ident, $extra: ident, $comp0: ident $(,$compN: ident)*) => ( + impl ToHomogeneous<$t2> for $t + { + fn to_homogeneous(&self) -> $t2 + { + let mut res: $t2 = One::one(); + + res.$comp0 = self.$comp0.clone(); + $( res.$compN = self.$compN.clone(); )* + + res + } + } + ) +) + +macro_rules! from_homogeneous_impl( + ($t: ident, $t2: ident, $extra: ident, $comp0: ident $(,$compN: ident)*) => ( + impl + One + Zero> FromHomogeneous<$t2> for $t + { + fn from_homogeneous(v: &$t2) -> $t + { + let mut res: $t = Zero::zero(); + + res.$comp0 = v.$comp0.clone(); + $( res.$compN = v.$compN.clone(); )* + + res.scalar_div(&v.$extra); + + res + } + } + ) +)