#![macro_escape] macro_rules! new_impl( ($t: ident, $comp0: ident $(,$compN: ident)*) => ( impl $t { /// Creates a new vector. #[inline] pub fn new($comp0: N $( , $compN: N )*) -> $t { $t { $comp0: $comp0 $(, $compN: $compN )* } } } ) ) macro_rules! as_slice_impl( ($t: ident, $dim: expr) => ( impl $t { /// Slices this vector. pub fn as_slice<'a>(&'a self) -> &'a [N] { unsafe { mem::transmute::<&$t, &[N, ..$dim]>(self).as_slice() } } /// Mutably slices this vector. pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [N] { unsafe { mem::transmute::<&mut $t, &mut [N, ..$dim]>(self).as_mut_slice() } } } ) ) macro_rules! at_fast_impl( ($t: ident, $dim: expr) => ( impl $t { /// Unsafe read access to a vector element by index. #[inline] pub unsafe fn at_fast(&self, i: uint) -> N { (*mem::transmute::<&$t, &[N, ..$dim]>(self) .unsafe_ref(i)).clone() } /// Unsafe write access to a vector element by index. #[inline] pub unsafe fn set_fast(&mut self, i: uint, val: N) { (*mem::transmute::<&mut $t, &mut [N, ..$dim]>(self).unsafe_mut_ref(i)) = val } } ) ) // FIXME: N should be bounded by Ord instead of Float… // However, f32/f64 does not implement Ord… macro_rules! ord_impl( ($t: ident, $comp0: ident $(,$compN: ident)*) => ( impl PartialOrd for $t { #[inline] fn inf(a: &$t, b: &$t) -> $t { $t::new(a.$comp0.min(b.$comp0.clone()) $(, a.$compN.min(b.$compN))*) } #[inline] fn sup(a: &$t, b: &$t) -> $t { $t::new(a.$comp0.max(b.$comp0.clone()) $(, a.$compN.max(b.$compN.clone()))*) } #[inline] #[allow(unused_mut)] // otherwise there will be a warning for is_eq or Vec1. fn partial_cmp(a: &$t, b: &$t) -> PartialOrdering { let is_lt = a.$comp0 < b.$comp0; let mut is_eq = a.$comp0 == b.$comp0; if is_lt { // < $( if a.$compN > b.$compN { return NotComparable } )* PartialLess } else { // >= $( if a.$compN < b.$compN { return NotComparable } else if a.$compN > b.$compN { is_eq = false; } )* if is_eq { PartialEqual } else { PartialGreater } } } #[inline] fn partial_lt(a: &$t, b: &$t) -> bool { a.$comp0 < b.$comp0 $(&& a.$compN < b.$compN)* } #[inline] fn partial_le(a: &$t, b: &$t) -> bool { a.$comp0 <= b.$comp0 $(&& a.$compN <= b.$compN)* } #[inline] fn partial_gt(a: &$t, b: &$t) -> bool { a.$comp0 > b.$comp0 $(&& a.$compN > b.$compN)* } #[inline] fn partial_ge(a: &$t, b: &$t) -> bool { a.$comp0 >= b.$comp0 $(&& a.$compN >= b.$compN)* } } ) ) macro_rules! vec_axis_impl( ($t: ident, $comp0: ident $(,$compN: ident)*) => ( impl $t { /// Create a unit vector with its `$comp0` component equal to 1.0. #[inline] pub fn $comp0() -> $t { let mut res: $t = Zero::zero(); res.$comp0 = One::one(); res } $( /// Create a unit vector with its `$compN` component equal to 1.0. #[inline] pub fn $compN() -> $t { let mut res: $t = Zero::zero(); res.$compN = One::one(); res } )* } ) ) macro_rules! vec_cast_impl( ($t: ident, $tcast: ident, $comp0: ident $(,$compN: ident)*) => ( impl> $tcast for $t { #[inline] fn to(v: $t) -> $t { $t::new(Cast::from(v.$comp0.clone()) $(, Cast::from(v.$compN.clone()))*) } } ) ) macro_rules! indexable_impl( ($t: ident, $dim: expr) => ( impl Indexable for $t { #[inline] fn at(&self, i: uint) -> N { unsafe { mem::transmute::<&$t, &[N, ..$dim]>(self)[i].clone() } } #[inline] fn set(&mut self, i: uint, val: N) { unsafe { mem::transmute::<&mut $t, &mut [N, ..$dim]>(self)[i] = val } } #[inline] fn shape(&self) -> uint { $dim } #[inline] fn swap(&mut self, i1: uint, i2: uint) { unsafe { mem::transmute::<&mut $t, &mut [N, ..$dim]>(self).swap(i1, i2) } } #[inline] unsafe fn unsafe_at(&self, i: uint) -> N { (*mem::transmute::<&$t, &[N, ..$dim]>(self).unsafe_ref(i)).clone() } #[inline] unsafe fn unsafe_set(&mut self, i: uint, val: N) { (*mem::transmute::<&mut $t, &mut [N, ..$dim]>(self).unsafe_mut_ref(i)) = val } } ) ) macro_rules! new_repeat_impl( ($t: ident, $param: ident, $comp0: ident $(,$compN: ident)*) => ( impl $t { /// Creates a new vector with all its components equal to a given value. #[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 { #[inline] fn iter<'l>(&'l self) -> Items<'l, N> { unsafe { mem::transmute::<&'l $t, &'l [N, ..$dim]>(self).iter() } } } ) ) macro_rules! iterable_mut_impl( ($t: ident, $dim: expr) => ( impl IterableMut for $t { #[inline] fn mut_iter<'l>(&'l mut self) -> MutItems<'l, N> { unsafe { mem::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(_: Option<$t>) -> uint { $dim } } ) ) macro_rules! container_impl( ($t: ident) => ( impl Collection for $t { #[inline] fn len(&self) -> uint { Dim::dim(None::<$t>) } } ) ) macro_rules! basis_impl( ($t: ident, $trhs: ident, $dim: expr) => ( impl + $trhs>> Basis for $t { #[inline] fn canonical_basis(f: |$t| -> bool) { for i in range(0u, $dim) { let mut basis_element : $t = Zero::zero(); unsafe { basis_element.set_fast(i, One::one()); } if !f(basis_element) { return } } } #[inline] fn orthonormal_subspace_basis(n: &$t, f: |$t| -> bool) { // compute the basis of the orthogonal subspace using Gram-Schmidt // orthogonalization algorithm let mut basis: Vec<$t> = Vec::new(); for i in range(0u, $dim) { let mut basis_element : $t = Zero::zero(); unsafe { basis_element.set_fast(i, One::one()); } if basis.len() == $dim - 1 { break; } let mut elt = basis_element.clone(); elt = elt - *n * Dot::dot(&basis_element, n); for v in basis.iter() { elt = elt - v * Dot::dot(&elt, v) }; if !ApproxEq::approx_eq(&Norm::sqnorm(&elt), &Zero::zero()) { let new_element = Norm::normalize_cpy(&elt); if !f(new_element.clone()) { return }; basis.push(new_element); } } } } ) ) macro_rules! add_impl( ($t: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl> $trhs> for $t { #[inline] fn binop(left: &$t, right: &$t) -> $t { $t::new(left.$comp0 + right.$comp0 $(, left.$compN + right.$compN)*) } } ) ) macro_rules! sub_impl( ($t: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl> $trhs> for $t { #[inline] fn binop(left: &$t, right: &$t) -> $t { $t::new(left.$comp0 - right.$comp0 $(, left.$compN - right.$compN)*) } } ) ) macro_rules! mul_impl( ($t: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl> $trhs> for $t { #[inline] fn binop(left: &$t, right: &$t) -> $t { $t::new(left.$comp0 * right.$comp0 $(, left.$compN * right.$compN)*) } } ) ) macro_rules! div_impl( ($t: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl> $trhs> for $t { #[inline] fn binop(left: &$t, right: &$t) -> $t { $t::new(left.$comp0 / right.$comp0 $(, left.$compN / right.$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(a: &$t, b: &$t) -> N { a.$comp0 * b.$comp0 $(+ a.$compN * b.$compN )* } #[inline] fn sub_dot(a: &$t, b: &$t, c: &$t) -> N { (a.$comp0 - b.$comp0) * c.$comp0 $(+ (a.$compN - b.$compN) * c.$compN )* } } ) ) macro_rules! vec_mul_scalar_impl( ($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl $trhs<$n, $t<$n>> for $n { #[inline] fn binop(left: &$t<$n>, right: &$n) -> $t<$n> { $t::new(left.$comp0 * *right $(, left.$compN * *right)*) } } ) ) macro_rules! vec_div_scalar_impl( ($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl $trhs<$n, $t<$n>> for $n { #[inline] fn binop(left: &$t<$n>, right: &$n) -> $t<$n> { $t::new(left.$comp0 / *right $(, left.$compN / *right)*) } } ) ) macro_rules! vec_add_scalar_impl( ($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl $trhs<$n, $t<$n>> for $n { #[inline] fn binop(left: &$t<$n>, right: &$n) -> $t<$n> { $t::new(left.$comp0 + *right $(, left.$compN + *right)*) } } ) ) macro_rules! vec_sub_scalar_impl( ($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl $trhs<$n, $t<$n>> for $n { #[inline] fn binop(left: &$t<$n>, right: &$n) -> $t<$n> { $t::new(left.$comp0 - *right $(, left.$compN - *right)*) } } ) ) 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 append_translation(&mut self, t: &$t) { *self = *t + *self; } #[inline] fn append_translation_cpy(transform: &$t, t: &$t) -> $t { *t + *transform } #[inline] fn prepend_translation(&mut self, t: &$t) { *self = *self + *t; } #[inline] fn prepend_translation_cpy(transform: &$t, t: &$t) -> $t { transform + *t } #[inline] fn set_translation(&mut self, t: $t) { *self = t } } ) ) macro_rules! norm_impl( ($t: ident, $comp0: ident $(,$compN: ident)*) => ( impl Norm for $t { #[inline] fn sqnorm(v: &$t) -> N { Dot::dot(v, v) } #[inline] fn norm(v: &$t) -> N { Norm::sqnorm(v).sqrt() } #[inline] fn normalize_cpy(v: &$t) -> $t { let mut res : $t = v.clone(); let _ = res.normalize(); res } #[inline] fn normalize(&mut self) -> N { let l = Norm::norm(self); self.$comp0 = self.$comp0 / l; $(self.$compN = self.$compN / l;)* l } } ) ) macro_rules! approx_eq_impl( ($t: ident, $comp0: ident $(,$compN: ident)*) => ( impl> ApproxEq for $t { #[inline] fn approx_epsilon(_: Option<$t>) -> N { ApproxEq::approx_epsilon(None::) } #[inline] fn approx_eq(a: &$t, b: &$t) -> bool { ApproxEq::approx_eq(&a.$comp0, &b.$comp0) $(&& ApproxEq::approx_eq(&a.$compN, &b.$compN))* } #[inline] fn approx_eq_eps(a: &$t, b: &$t, eps: &N) -> bool { ApproxEq::approx_eq_eps(&a.$comp0, &b.$comp0, eps) $(&& ApproxEq::approx_eq_eps(&a.$compN, &b.$compN, eps))* } } ) ) macro_rules! one_impl( ($t: ident, $comp0: ident $(,$compN: ident)*) => ( impl One for $t { #[inline] fn one() -> $t { $t { $comp0: One::one() $(, $compN: One::one() )* } } } ) ) macro_rules! from_iterator_impl( ($t: ident, $param0: ident $(, $paramN: ident)*) => ( impl FromIterator for $t { #[inline] fn from_iter>(mut $param0: I) -> $t { $t::new($param0.next().unwrap() $(, $paramN.next().unwrap())*) } } ) ) macro_rules! bounded_impl( ($t: ident, $comp0: ident $(,$compN: ident)*) => ( impl Bounded for $t { #[inline] fn max_value() -> $t { $t { $comp0: Bounded::max_value() $(, $compN: Bounded::max_value() )* } } #[inline] fn min_value() -> $t { $t { $comp0: Bounded::min_value() $(, $compN: 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(v: &$t) -> $t2 { let mut res: $t2 = One::one(); res.$comp0 = v.$comp0.clone(); $( res.$compN = v.$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(v: &$t2) -> $t { let mut res: $t = Zero::zero(); res.$comp0 = v.$comp0.clone() / v.$extra; $( res.$compN = v.$compN.clone() / v.$extra; )* res } } ) ) macro_rules! translate_impl( ($t: ident) => ( impl + Sub> Translate<$t> for $t { fn translate(&self, other: &$t) -> $t { *other + *self } fn inv_translate(&self, other: &$t) -> $t { *other - *self } } ) ) macro_rules! rotate_impl( ($t: ident) => ( impl Rotate for $t { fn rotate(&self, other: &O) -> O { other.clone() } fn inv_rotate(&self, other: &O) -> O { other.clone() } } ) ) macro_rules! transform_impl( ($t: ident) => ( impl + Sub> Transform<$t> for $t { fn transform(&self, other: &$t) -> $t { self.translate(other) } fn inv_transform(&self, other: &$t) -> $t { self.inv_translate(other) } } ) )