nalgebra/src/structs/vec_macros.rs

662 lines
18 KiB
Rust
Raw Normal View History

#![macro_escape]
2013-07-22 16:26:20 +08:00
macro_rules! new_impl(
2013-08-05 15:44:56 +08:00
($t: ident, $comp0: ident $(,$compN: ident)*) => (
2013-08-05 16:13:44 +08:00
impl<N> $t<N> {
2013-08-05 15:44:56 +08:00
/// Creates a new vector.
#[inline]
2013-08-05 16:13:44 +08:00
pub fn new($comp0: N $( , $compN: N )*) -> $t<N> {
2013-08-05 15:44:56 +08:00
$t {
$comp0: $comp0
$(, $compN: $compN )*
}
}
2013-07-22 16:26:20 +08:00
}
2013-08-05 15:44:56 +08:00
)
2013-07-22 16:26:20 +08:00
)
macro_rules! as_slice_impl(
($t: ident, $dim: expr) => (
impl<N> $t<N> {
/// Slices this vector.
pub fn as_slice<'a>(&'a self) -> &'a [N] {
unsafe {
mem::transmute::<&$t<N>, &[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<N>, &mut [N, ..$dim]>(self).as_mut_slice()
}
}
}
)
)
macro_rules! at_fast_impl(
($t: ident, $dim: expr) => (
impl<N: Clone> $t<N> {
/// Unsafe read access to a vector element by index.
#[inline]
pub unsafe fn at_fast(&self, i: uint) -> N {
(*mem::transmute::<&$t<N>, &[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<N>, &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(
2013-08-05 15:44:56 +08:00
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: FloatMath + Clone> PartialOrd for $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
fn inf(a: &$t<N>, b: &$t<N>) -> $t<N> {
$t::new(a.$comp0.min(b.$comp0.clone())
$(, a.$compN.min(b.$compN))*)
2013-08-05 16:13:44 +08:00
}
2013-08-05 15:44:56 +08:00
#[inline]
fn sup(a: &$t<N>, b: &$t<N>) -> $t<N> {
$t::new(a.$comp0.max(b.$comp0.clone())
$(, a.$compN.max(b.$compN.clone()))*)
2013-08-05 16:13:44 +08:00
}
2013-08-05 15:44:56 +08:00
#[inline]
#[allow(unused_mut)] // otherwise there will be a warning for is_eq or Vec1.
fn partial_cmp(a: &$t<N>, b: &$t<N>) -> PartialOrdering {
let is_lt = a.$comp0 < b.$comp0;
let mut is_eq = a.$comp0 == b.$comp0;
2013-08-05 15:44:56 +08:00
if is_lt { // <
$(
if a.$compN > b.$compN {
return NotComparable
}
)*
2013-08-05 15:44:56 +08:00
PartialLess
}
else { // >=
$(
if a.$compN < b.$compN {
return NotComparable
}
else if a.$compN > b.$compN {
is_eq = false;
}
)*
if is_eq {
PartialEqual
}
else {
PartialGreater
}
}
2013-08-05 15:44:56 +08:00
}
#[inline]
fn partial_lt(a: &$t<N>, b: &$t<N>) -> bool {
a.$comp0 < b.$comp0 $(&& a.$compN < b.$compN)*
}
#[inline]
fn partial_le(a: &$t<N>, b: &$t<N>) -> bool {
a.$comp0 <= b.$comp0 $(&& a.$compN <= b.$compN)*
}
#[inline]
fn partial_gt(a: &$t<N>, b: &$t<N>) -> bool {
a.$comp0 > b.$comp0 $(&& a.$compN > b.$compN)*
}
#[inline]
fn partial_ge(a: &$t<N>, b: &$t<N>) -> bool {
a.$comp0 >= b.$comp0 $(&& a.$compN >= b.$compN)*
}
2013-08-05 15:44:56 +08:00
}
)
)
macro_rules! vec_axis_impl(
2013-08-05 15:44:56 +08:00
($t: ident, $comp0: ident $(,$compN: ident)*) => (
2013-08-05 16:13:44 +08:00
impl<N: Zero + One> $t<N> {
2013-08-05 15:44:56 +08:00
/// Create a unit vector with its `$comp0` component equal to 1.0.
#[inline]
2013-08-05 16:13:44 +08:00
pub fn $comp0() -> $t<N> {
2013-08-05 15:44:56 +08:00
let mut res: $t<N> = Zero::zero();
res.$comp0 = One::one();
2013-08-05 15:44:56 +08:00
res
}
2013-08-05 15:44:56 +08:00
$(
/// Create a unit vector with its `$compN` component equal to 1.0.
#[inline]
2013-08-05 16:13:44 +08:00
pub fn $compN() -> $t<N> {
2013-08-05 15:44:56 +08:00
let mut res: $t<N> = Zero::zero();
res.$compN = One::one();
res
}
)*
}
2013-08-05 15:44:56 +08:00
)
)
macro_rules! vec_cast_impl(
($t: ident, $tcast: ident, $comp0: ident $(,$compN: ident)*) => (
impl<Nin: Clone, Nout: Clone + Cast<Nin>> $tcast<Nout> for $t<Nin> {
2013-08-05 15:44:56 +08:00
#[inline]
fn to(v: $t<Nin>) -> $t<Nout> {
$t::new(Cast::from(v.$comp0.clone()) $(, Cast::from(v.$compN.clone()))*)
2013-08-05 16:13:44 +08:00
}
2013-08-05 15:44:56 +08:00
}
)
)
2013-07-22 16:26:20 +08:00
macro_rules! indexable_impl(
2013-08-05 15:44:56 +08:00
($t: ident, $dim: expr) => (
2013-08-05 16:13:44 +08:00
impl<N: Clone> Indexable<uint, N> for $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
fn at(&self, i: uint) -> N {
2013-08-05 16:13:44 +08:00
unsafe {
mem::transmute::<&$t<N>, &[N, ..$dim]>(self)[i].clone()
2013-08-05 16:13:44 +08:00
}
}
2013-08-05 15:44:56 +08:00
#[inline]
fn set(&mut self, i: uint, val: N) {
2013-08-05 16:13:44 +08:00
unsafe {
mem::transmute::<&mut $t<N>, &mut [N, ..$dim]>(self)[i] = val
2013-08-05 16:13:44 +08:00
}
}
2013-08-05 15:44:56 +08:00
#[inline]
fn shape(&self) -> uint {
$dim
}
2013-08-05 15:44:56 +08:00
#[inline]
fn swap(&mut self, i1: uint, i2: uint) {
2013-08-05 16:13:44 +08:00
unsafe {
mem::transmute::<&mut $t<N>, &mut [N, ..$dim]>(self).swap(i1, i2)
2013-08-05 16:13:44 +08:00
}
}
#[inline]
unsafe fn unsafe_at(&self, i: uint) -> N {
(*mem::transmute::<&$t<N>, &[N, ..$dim]>(self).unsafe_ref(i)).clone()
}
#[inline]
unsafe fn unsafe_set(&mut self, i: uint, val: N) {
(*mem::transmute::<&mut $t<N>, &mut [N, ..$dim]>(self).unsafe_mut_ref(i)) = val
}
2013-08-05 15:44:56 +08:00
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! new_repeat_impl(
2013-08-05 15:44:56 +08:00
($t: ident, $param: ident, $comp0: ident $(,$compN: ident)*) => (
2013-08-05 16:13:44 +08:00
impl<N: Clone> $t<N> {
2013-08-05 15:44:56 +08:00
/// Creates a new vector with all its components equal to a given value.
#[inline]
2013-08-05 16:13:44 +08:00
pub fn new_repeat($param: N) -> $t<N> {
2013-08-05 15:44:56 +08:00
$t{
$comp0: $param.clone()
$(, $compN: $param.clone() )*
}
}
2013-07-22 16:26:20 +08:00
}
2013-08-05 15:44:56 +08:00
)
2013-07-22 16:26:20 +08:00
)
macro_rules! iterable_impl(
2013-08-05 15:44:56 +08:00
($t: ident, $dim: expr) => (
2013-08-05 16:13:44 +08:00
impl<N> Iterable<N> for $t<N> {
2013-08-08 02:53:51 +08:00
#[inline]
fn iter<'l>(&'l self) -> Items<'l, N> {
2013-08-05 16:13:44 +08:00
unsafe {
mem::transmute::<&'l $t<N>, &'l [N, ..$dim]>(self).iter()
2013-08-05 16:13:44 +08:00
}
}
2013-08-05 15:44:56 +08:00
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! iterable_mut_impl(
2013-08-05 15:44:56 +08:00
($t: ident, $dim: expr) => (
2013-08-05 16:13:44 +08:00
impl<N> IterableMut<N> for $t<N> {
2013-08-08 02:53:51 +08:00
#[inline]
fn mut_iter<'l>(&'l mut self) -> MutItems<'l, N> {
2013-08-05 16:13:44 +08:00
unsafe {
mem::transmute::<&'l mut $t<N>, &'l mut [N, ..$dim]>(self).mut_iter()
2013-08-05 16:13:44 +08:00
}
}
2013-08-05 15:44:56 +08:00
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! dim_impl(
2013-08-05 15:44:56 +08:00
($t: ident, $dim: expr) => (
2013-08-05 16:13:44 +08:00
impl<N> Dim for $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
fn dim(_: Option<$t<N>>) -> uint {
2013-08-05 16:13:44 +08:00
$dim
}
2013-08-05 15:44:56 +08:00
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! container_impl(
($t: ident) => (
impl<N> Collection for $t<N> {
#[inline]
fn len(&self) -> uint {
Dim::dim(None::<$t<N>>)
}
}
)
)
2013-07-22 16:26:20 +08:00
macro_rules! basis_impl(
($t: ident, $trhs: ident, $dim: expr) => (
impl<N: Clone + Float + ApproxEq<N> + $trhs<N, $t<N>>> Basis for $t<N> {
2013-08-08 02:53:51 +08:00
#[inline]
2013-11-27 18:16:16 +08:00
fn canonical_basis(f: |$t<N>| -> bool) {
2013-08-05 16:13:44 +08:00
for i in range(0u, $dim) {
2013-08-05 15:44:56 +08:00
let mut basis_element : $t<N> = Zero::zero();
unsafe {
basis_element.set_fast(i, One::one());
}
2013-08-05 15:44:56 +08:00
if !f(basis_element) { return }
2013-08-05 15:44:56 +08:00
}
}
2013-08-08 02:53:51 +08:00
#[inline]
2013-11-27 18:16:16 +08:00
fn orthonormal_subspace_basis(n: &$t<N>, f: |$t<N>| -> bool) {
2013-08-05 15:44:56 +08:00
// compute the basis of the orthogonal subspace using Gram-Schmidt
// orthogonalization algorithm
let mut basis: Vec<$t<N>> = Vec::new();
2013-08-05 15:44:56 +08:00
2013-08-05 16:13:44 +08:00
for i in range(0u, $dim) {
2013-08-05 15:44:56 +08:00
let mut basis_element : $t<N> = Zero::zero();
unsafe {
basis_element.set_fast(i, One::one());
}
2013-08-05 15:44:56 +08:00
2013-08-05 16:13:44 +08:00
if basis.len() == $dim - 1 {
break;
}
2013-08-05 15:44:56 +08:00
let mut elt = basis_element.clone();
elt = elt - *n * Dot::dot(&basis_element, n);
2013-08-05 15:44:56 +08:00
2013-08-05 16:13:44 +08:00
for v in basis.iter() {
elt = elt - v * Dot::dot(&elt, v)
2013-08-05 16:13:44 +08:00
};
2013-08-05 15:44:56 +08:00
if !ApproxEq::approx_eq(&Norm::sqnorm(&elt), &Zero::zero()) {
Api change: deal with inplace/out of place methods. Before, it was too easy to use an out of place method instead of the inplace one since they name were pretty mutch the same. This kind of confusion may lead to silly bugs very hard to understand. Thus the following changes have been made when a method is available both inplace and out-of-place: * inplace version keep a short name. * out-of-place version are suffixed by `_cpy` (meaning `copy`), and are static methods. Methods applying transformations (rotation, translation or general transform) are now prefixed by `append`, and a `prepend` version is available too. Also, free functions doing in-place modifications dont really make sense. They have been removed. Here are the naming changes: * `invert` -> `inv` * `inverted` -> `Inv::inv_cpy` * `transpose` -> `transpose` * `transposed` -> `Transpose::transpose_cpy` * `transform_by` -> `append_transformation` * `transformed` -> `Transform::append_transformation_cpy` * `rotate_by` -> `apppend_rotation` * `rotated` -> `Rotation::append_rotation_cpy` * `translate_by` -> `apppend_translation` * `translate` -> `Translation::append_translation_cpy` * `normalized` -> `Norm::normalize_cpy` * `rotated_wrt_point` -> `RotationWithTranslation::append_rotation_wrt_point_cpy` * `rotated_wrt_center` -> `RotationWithTranslation::append_rotation_wrt_center_cpy` Note that using those static methods is very verbose, and using in-place methods require an explicit import of the related trait. This is a way to convince the user to use free functions most of the time.
2013-10-14 16:22:32 +08:00
let new_element = Norm::normalize_cpy(&elt);
2013-08-05 15:44:56 +08:00
if !f(new_element.clone()) { return };
2013-08-05 15:44:56 +08:00
basis.push(new_element);
}
}
}
2013-07-22 16:26:20 +08:00
}
2013-08-05 15:44:56 +08:00
)
2013-07-22 16:26:20 +08:00
)
macro_rules! add_impl(
($t: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Add<N, N>> $trhs<N, $t<N>> for $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
$t::new(left.$comp0 + right.$comp0 $(, left.$compN + right.$compN)*)
2013-08-05 16:13:44 +08:00
}
2013-08-05 15:44:56 +08:00
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! sub_impl(
($t: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Sub<N, N>> $trhs<N, $t<N>> for $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
$t::new(left.$comp0 - right.$comp0 $(, left.$compN - right.$compN)*)
2013-08-05 16:13:44 +08:00
}
2013-08-05 15:44:56 +08:00
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! mul_impl(
($t: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Mul<N, N>> $trhs<N, $t<N>> for $t<N> {
#[inline]
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
$t::new(left.$comp0 * right.$comp0 $(, left.$compN * right.$compN)*)
}
}
)
)
macro_rules! div_impl(
($t: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Div<N, N>> $trhs<N, $t<N>> for $t<N> {
#[inline]
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
$t::new(left.$comp0 / right.$comp0 $(, left.$compN / right.$compN)*)
}
}
)
)
2013-07-22 16:26:20 +08:00
macro_rules! neg_impl(
2013-08-05 15:44:56 +08:00
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Neg<N>> Neg<$t<N>> for $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
2013-08-05 16:13:44 +08:00
fn neg(&self) -> $t<N> {
$t::new(-self.$comp0 $(, -self.$compN )*)
}
2013-08-05 15:44:56 +08:00
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! dot_impl(
2013-08-05 15:44:56 +08:00
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Num> Dot<N> for $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
fn dot(a: &$t<N>, b: &$t<N>) -> N {
a.$comp0 * b.$comp0 $(+ a.$compN * b.$compN )*
2013-08-05 16:13:44 +08:00
}
2013-07-22 16:26:20 +08:00
2013-08-05 15:44:56 +08:00
#[inline]
fn sub_dot(a: &$t<N>, b: &$t<N>, c: &$t<N>) -> N {
(a.$comp0 - b.$comp0) * c.$comp0 $(+ (a.$compN - b.$compN) * c.$compN )*
2013-08-05 16:13:44 +08:00
}
2013-08-05 15:44:56 +08:00
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! vec_mul_scalar_impl(
($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
impl $trhs<$n, $t<$n>> for $n {
2013-08-05 15:44:56 +08:00
#[inline]
fn binop(left: &$t<$n>, right: &$n) -> $t<$n> {
$t::new(left.$comp0 * *right $(, left.$compN * *right)*)
2013-08-05 16:13:44 +08:00
}
2013-08-05 15:44:56 +08:00
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! vec_div_scalar_impl(
($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
impl $trhs<$n, $t<$n>> for $n {
2013-08-05 15:44:56 +08:00
#[inline]
fn binop(left: &$t<$n>, right: &$n) -> $t<$n> {
$t::new(left.$comp0 / *right $(, left.$compN / *right)*)
2013-08-05 16:13:44 +08:00
}
2013-08-05 15:44:56 +08:00
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! vec_add_scalar_impl(
($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
impl $trhs<$n, $t<$n>> for $n {
2013-08-05 15:44:56 +08:00
#[inline]
fn binop(left: &$t<$n>, right: &$n) -> $t<$n> {
$t::new(left.$comp0 + *right $(, left.$compN + *right)*)
2013-08-05 15:44:56 +08:00
}
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! vec_sub_scalar_impl(
($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
impl $trhs<$n, $t<$n>> for $n {
2013-08-05 15:44:56 +08:00
#[inline]
fn binop(left: &$t<$n>, right: &$n) -> $t<$n> {
$t::new(left.$comp0 - *right $(, left.$compN - *right)*)
2013-08-05 15:44:56 +08:00
}
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! translation_impl(
2013-08-05 15:44:56 +08:00
($t: ident) => (
2013-08-05 16:13:44 +08:00
impl<N: Clone + Add<N, N> + Neg<N>> Translation<$t<N>> for $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
2013-08-05 16:13:44 +08:00
fn translation(&self) -> $t<N> {
self.clone()
}
2013-08-05 15:44:56 +08:00
#[inline]
2013-08-05 16:13:44 +08:00
fn inv_translation(&self) -> $t<N> {
-self
}
2013-08-05 15:44:56 +08:00
#[inline]
Api change: deal with inplace/out of place methods. Before, it was too easy to use an out of place method instead of the inplace one since they name were pretty mutch the same. This kind of confusion may lead to silly bugs very hard to understand. Thus the following changes have been made when a method is available both inplace and out-of-place: * inplace version keep a short name. * out-of-place version are suffixed by `_cpy` (meaning `copy`), and are static methods. Methods applying transformations (rotation, translation or general transform) are now prefixed by `append`, and a `prepend` version is available too. Also, free functions doing in-place modifications dont really make sense. They have been removed. Here are the naming changes: * `invert` -> `inv` * `inverted` -> `Inv::inv_cpy` * `transpose` -> `transpose` * `transposed` -> `Transpose::transpose_cpy` * `transform_by` -> `append_transformation` * `transformed` -> `Transform::append_transformation_cpy` * `rotate_by` -> `apppend_rotation` * `rotated` -> `Rotation::append_rotation_cpy` * `translate_by` -> `apppend_translation` * `translate` -> `Translation::append_translation_cpy` * `normalized` -> `Norm::normalize_cpy` * `rotated_wrt_point` -> `RotationWithTranslation::append_rotation_wrt_point_cpy` * `rotated_wrt_center` -> `RotationWithTranslation::append_rotation_wrt_center_cpy` Note that using those static methods is very verbose, and using in-place methods require an explicit import of the related trait. This is a way to convince the user to use free functions most of the time.
2013-10-14 16:22:32 +08:00
fn append_translation(&mut self, t: &$t<N>) {
*self = *t + *self;
}
#[inline]
fn append_translation_cpy(transform: &$t<N>, t: &$t<N>) -> $t<N> {
*t + *transform
}
#[inline]
fn prepend_translation(&mut self, t: &$t<N>) {
2013-08-05 16:13:44 +08:00
*self = *self + *t;
}
2013-07-22 16:26:20 +08:00
2013-08-05 15:44:56 +08:00
#[inline]
Api change: deal with inplace/out of place methods. Before, it was too easy to use an out of place method instead of the inplace one since they name were pretty mutch the same. This kind of confusion may lead to silly bugs very hard to understand. Thus the following changes have been made when a method is available both inplace and out-of-place: * inplace version keep a short name. * out-of-place version are suffixed by `_cpy` (meaning `copy`), and are static methods. Methods applying transformations (rotation, translation or general transform) are now prefixed by `append`, and a `prepend` version is available too. Also, free functions doing in-place modifications dont really make sense. They have been removed. Here are the naming changes: * `invert` -> `inv` * `inverted` -> `Inv::inv_cpy` * `transpose` -> `transpose` * `transposed` -> `Transpose::transpose_cpy` * `transform_by` -> `append_transformation` * `transformed` -> `Transform::append_transformation_cpy` * `rotate_by` -> `apppend_rotation` * `rotated` -> `Rotation::append_rotation_cpy` * `translate_by` -> `apppend_translation` * `translate` -> `Translation::append_translation_cpy` * `normalized` -> `Norm::normalize_cpy` * `rotated_wrt_point` -> `RotationWithTranslation::append_rotation_wrt_point_cpy` * `rotated_wrt_center` -> `RotationWithTranslation::append_rotation_wrt_center_cpy` Note that using those static methods is very verbose, and using in-place methods require an explicit import of the related trait. This is a way to convince the user to use free functions most of the time.
2013-10-14 16:22:32 +08:00
fn prepend_translation_cpy(transform: &$t<N>, t: &$t<N>) -> $t<N> {
transform + *t
2013-08-05 16:13:44 +08:00
}
#[inline]
fn set_translation(&mut self, t: $t<N>) {
*self = t
}
2013-08-05 15:44:56 +08:00
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! norm_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + Float> Norm<N> for $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
fn sqnorm(v: &$t<N>) -> N {
Dot::dot(v, v)
2013-08-05 16:13:44 +08:00
}
2013-08-05 15:44:56 +08:00
#[inline]
fn norm(v: &$t<N>) -> N {
Norm::sqnorm(v).sqrt()
2013-08-05 16:13:44 +08:00
}
2013-08-05 15:44:56 +08:00
#[inline]
Api change: deal with inplace/out of place methods. Before, it was too easy to use an out of place method instead of the inplace one since they name were pretty mutch the same. This kind of confusion may lead to silly bugs very hard to understand. Thus the following changes have been made when a method is available both inplace and out-of-place: * inplace version keep a short name. * out-of-place version are suffixed by `_cpy` (meaning `copy`), and are static methods. Methods applying transformations (rotation, translation or general transform) are now prefixed by `append`, and a `prepend` version is available too. Also, free functions doing in-place modifications dont really make sense. They have been removed. Here are the naming changes: * `invert` -> `inv` * `inverted` -> `Inv::inv_cpy` * `transpose` -> `transpose` * `transposed` -> `Transpose::transpose_cpy` * `transform_by` -> `append_transformation` * `transformed` -> `Transform::append_transformation_cpy` * `rotate_by` -> `apppend_rotation` * `rotated` -> `Rotation::append_rotation_cpy` * `translate_by` -> `apppend_translation` * `translate` -> `Translation::append_translation_cpy` * `normalized` -> `Norm::normalize_cpy` * `rotated_wrt_point` -> `RotationWithTranslation::append_rotation_wrt_point_cpy` * `rotated_wrt_center` -> `RotationWithTranslation::append_rotation_wrt_center_cpy` Note that using those static methods is very verbose, and using in-place methods require an explicit import of the related trait. This is a way to convince the user to use free functions most of the time.
2013-10-14 16:22:32 +08:00
fn normalize_cpy(v: &$t<N>) -> $t<N> {
let mut res : $t<N> = v.clone();
2013-08-05 15:44:56 +08:00
2014-01-31 22:26:25 +08:00
let _ = res.normalize();
2013-08-05 15:44:56 +08:00
res
}
#[inline]
2013-08-05 16:13:44 +08:00
fn normalize(&mut self) -> N {
let l = Norm::norm(self);
2013-08-05 15:44:56 +08:00
self.$comp0 = self.$comp0 / l;
$(self.$compN = self.$compN / l;)*
2013-08-05 15:44:56 +08:00
l
}
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! approx_eq_impl(
2013-08-05 15:44:56 +08:00
($t: ident, $comp0: ident $(,$compN: ident)*) => (
2013-08-05 16:13:44 +08:00
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
fn approx_epsilon(_: Option<$t<N>>) -> N {
ApproxEq::approx_epsilon(None::<N>)
2013-08-05 16:13:44 +08:00
}
2013-08-05 15:44:56 +08:00
#[inline]
fn approx_eq(a: &$t<N>, b: &$t<N>) -> bool {
ApproxEq::approx_eq(&a.$comp0, &b.$comp0)
$(&& ApproxEq::approx_eq(&a.$compN, &b.$compN))*
2013-08-05 16:13:44 +08:00
}
2013-08-05 15:44:56 +08:00
#[inline]
fn approx_eq_eps(a: &$t<N>, b: &$t<N>, eps: &N) -> bool {
ApproxEq::approx_eq_eps(&a.$comp0, &b.$comp0, eps)
$(&& ApproxEq::approx_eq_eps(&a.$compN, &b.$compN, eps))*
2013-08-05 16:13:44 +08:00
}
2013-08-05 15:44:56 +08:00
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! one_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: One> One for $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
2013-08-05 16:13:44 +08:00
fn one() -> $t<N> {
$t {
$comp0: One::one()
$(, $compN: One::one() )*
}
2013-08-05 16:13:44 +08:00
}
2013-08-05 15:44:56 +08:00
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! from_iterator_impl(
2013-08-05 15:44:56 +08:00
($t: ident, $param0: ident $(, $paramN: ident)*) => (
impl<N> FromIterator<N> for $t<N> {
2013-08-08 02:53:51 +08:00
#[inline]
fn from_iter<I: Iterator<N>>(mut $param0: I) -> $t<N> {
2013-08-05 16:13:44 +08:00
$t::new($param0.next().unwrap() $(, $paramN.next().unwrap())*)
}
2013-08-05 15:44:56 +08:00
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! bounded_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Bounded> Bounded for $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
2013-08-05 16:13:44 +08:00
fn max_value() -> $t<N> {
$t {
$comp0: Bounded::max_value()
$(, $compN: Bounded::max_value() )*
}
2013-08-05 16:13:44 +08:00
}
2013-08-05 15:44:56 +08:00
#[inline]
2013-08-05 16:13:44 +08:00
fn min_value() -> $t<N> {
$t {
$comp0: Bounded::min_value()
$(, $compN: Bounded::min_value() )*
}
2013-08-05 16:13:44 +08:00
}
2013-08-05 15:44:56 +08:00
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! to_homogeneous_impl(
2013-08-05 15:44:56 +08:00
($t: ident, $t2: ident, $extra: ident, $comp0: ident $(,$compN: ident)*) => (
2013-08-05 16:13:44 +08:00
impl<N: Clone + One + Zero> ToHomogeneous<$t2<N>> for $t<N> {
fn to_homogeneous(v: &$t<N>) -> $t2<N> {
2013-08-05 15:44:56 +08:00
let mut res: $t2<N> = One::one();
res.$comp0 = v.$comp0.clone();
$( res.$compN = v.$compN.clone(); )*
2013-08-05 15:44:56 +08:00
res
}
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! from_homogeneous_impl(
2013-08-05 15:44:56 +08:00
($t: ident, $t2: ident, $extra: ident, $comp0: ident $(,$compN: ident)*) => (
2013-08-05 16:13:44 +08:00
impl<N: Clone + Div<N, N> + One + Zero> FromHomogeneous<$t2<N>> for $t<N> {
fn from(v: &$t2<N>) -> $t<N> {
2013-08-05 15:44:56 +08:00
let mut res: $t<N> = Zero::zero();
res.$comp0 = v.$comp0.clone() / v.$extra;
$( res.$compN = v.$compN.clone() / v.$extra; )*
2013-08-05 15:44:56 +08:00
res
}
}
)
2013-07-22 16:26:20 +08:00
)
macro_rules! translate_impl(
($t: ident) => (
impl<N: Add<N, N> + Sub<N, N>> Translate<$t<N>> for $t<N> {
fn translate(&self, other: &$t<N>) -> $t<N> {
*other + *self
}
fn inv_translate(&self, other: &$t<N>) -> $t<N> {
*other - *self
}
}
)
)
macro_rules! rotate_impl(
($t: ident) => (
impl<N, O: Clone> Rotate<O> for $t<N> {
fn rotate(&self, other: &O) -> O {
other.clone()
}
fn inv_rotate(&self, other: &O) -> O {
other.clone()
}
}
)
)
macro_rules! transform_impl(
($t: ident) => (
impl<N: Clone + Add<N, N> + Sub<N, N>> Transform<$t<N>> for $t<N> {
fn transform(&self, other: &$t<N>) -> $t<N> {
self.translate(other)
}
fn inv_transform(&self, other: &$t<N>) -> $t<N> {
self.inv_translate(other)
}
}
)
)