diff --git a/.gitignore b/.gitignore index a3b337ba..1dcd336f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ doc lib TODO target/ +Cargo.lock diff --git a/src/lib.rs b/src/lib.rs index 9d618f31..f93d40bc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -115,6 +115,7 @@ pub use traits::{ Absolute, AbsoluteRotate, AnyVec, + AnyPnt, ApproxEq, Basis, Cast, @@ -128,6 +129,8 @@ pub use traits::{ Dim, Dot, Eye, + FloatPnt, + FloatPntExt, FloatVec, FloatVecExt, FromHomogeneous, @@ -139,9 +142,13 @@ pub use traits::{ Mat, Mean, Norm, + Orig, Outer, PartialOrd, PartialOrdering, + PntAsVec, + PntExt, + Projector, RMul, Rotate, Rotation, RotationMatrix, RotationWithTranslation, Row, @@ -152,6 +159,7 @@ pub use traits::{ Translate, Translation, Transpose, UniformSphereSample, + VecAsPnt, VecExt }; @@ -163,7 +171,8 @@ pub use structs::{ Mat1, Mat2, Mat3, Mat4, Mat5, Mat6, Rot2, Rot3, Rot4, - Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6 + Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6, + Pnt0, Pnt1, Pnt2, Pnt3, Pnt4, Pnt5, Pnt6 }; pub use linalg::{ @@ -337,6 +346,27 @@ pub fn one() -> T { // // +/// Returns the trivial origin of an affine space. +#[inline(always)] +pub fn orig() -> T { + Orig::orig() +} + +/* + * FloatPnt + */ +/// Returns the distance between two points. +#[inline(always)] +pub fn dist, V: Norm>(a: &P, b: &P) -> N { + FloatPnt::::dist(a, b) +} + +/// Returns the squared distance between two points. +#[inline(always)] +pub fn sqdist, V: Norm>(a: &P, b: &P) -> N { + FloatPnt::::sqdist(a, b) +} + /* * Perspective */ @@ -405,46 +435,46 @@ pub fn append_translation>(m: &M, v: &V) -> M { } /* - * Translate + * Translate

*/ -/// Applies a translation to a vector. +/// Applies a translation to a point. /// /// ```rust /// extern crate "nalgebra" as na; -/// use na::{Vec3, Iso3}; +/// use na::{Pnt3, Vec3, Iso3}; /// /// fn main() { /// let t = Iso3::new(Vec3::new(1.0f64, 1.0, 1.0), na::zero()); -/// let v = Vec3::new(2.0, 2.0, 2.0); +/// let p = Pnt3::new(2.0, 2.0, 2.0); /// -/// let tv = na::translate(&t, &v); +/// let tp = na::translate(&t, &p); /// -/// assert!(tv == Vec3::new(3.0, 3.0, 3.0)) +/// assert!(tp == Pnt3::new(3.0, 3.0, 3.0)) /// } /// ``` #[inline(always)] -pub fn translate>(m: &M, v: &V) -> V { - m.translate(v) +pub fn translate>(m: &M, p: &P) -> P { + m.translate(p) } -/// Applies an inverse translation to a vector. +/// Applies an inverse translation to a point. /// /// ```rust /// extern crate "nalgebra" as na; -/// use na::{Vec3, Iso3}; +/// use na::{Pnt3, Vec3, Iso3}; /// /// fn main() { /// let t = Iso3::new(Vec3::new(1.0f64, 1.0, 1.0), na::zero()); -/// let v = Vec3::new(2.0, 2.0, 2.0); +/// let p = Pnt3::new(2.0, 2.0, 2.0); /// -/// let tv = na::inv_translate(&t, &v); +/// let tp = na::inv_translate(&t, &p); /// -/// assert!(na::approx_eq(&tv, &Vec3::new(1.0, 1.0, 1.0))) +/// assert!(na::approx_eq(&tp, &Pnt3::new(1.0, 1.0, 1.0))) /// } #[inline(always)] -pub fn inv_translate>(m: &M, v: &V) -> V { - m.inv_translate(v) +pub fn inv_translate>(m: &M, p: &P) -> P { + m.inv_translate(p) } /* @@ -666,12 +696,6 @@ pub fn dot, N>(a: &V, b: &V) -> N { Dot::dot(a, b) } -/// Computes a subtraction followed by a dot product. -#[inline(always)] -pub fn sub_dot, N>(a: &V, b: &V, c: &V) -> N { - Dot::sub_dot(a, b, c) -} - /* * Norm */ diff --git a/src/na.rs b/src/na.rs index c5298494..1a2fa4c9 100644 --- a/src/na.rs +++ b/src/na.rs @@ -431,13 +431,6 @@ pub fn dot, N>(a: &V, b: &V) -> N { super::dot(a, b) } -/// Computes a subtraction followed by a dot product. -#[inline(always)] -#[deprecated = "use the root module `nalgebra::` directly instead of the `nalgebra::na::` module (you may create an alias `extern crate \"nalgebra\" as na;` when importing the crate)"] -pub fn sub_dot, N>(a: &V, b: &V, c: &V) -> N { - super::sub_dot(a, b, c) -} - /* * Norm */ diff --git a/src/structs/dvec_macros.rs b/src/structs/dvec_macros.rs index 5469d97a..bba4d156 100644 --- a/src/structs/dvec_macros.rs +++ b/src/structs/dvec_macros.rs @@ -220,17 +220,6 @@ macro_rules! dvec_impl( res } - - #[inline] - fn sub_dot(a: &$dvec, b: &$dvec, c: &$dvec) -> N { - let mut res: N = Zero::zero(); - - for i in range(0u, a.len()) { - res = res + unsafe { (a.unsafe_at(i) - b.unsafe_at(i)) * c.unsafe_at(i) }; - } - - res - } } impl Norm for $dvec { diff --git a/src/structs/iso.rs b/src/structs/iso.rs index 942ea053..1b45b44b 100644 --- a/src/structs/iso.rs +++ b/src/structs/iso.rs @@ -11,6 +11,7 @@ use traits::geometry::{RotationMatrix, Rotation, Rotate, AbsoluteRotate, Transfo Translate, Translation, ToHomogeneous}; use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec2MulRhs, Vec3MulRhs, Vec4MulRhs}; +use structs::pnt::{Pnt2, Pnt3, Pnt4, Pnt2MulRhs, Pnt3MulRhs, Pnt4MulRhs}; use structs::rot::{Rot2, Rot3, Rot4}; @@ -104,14 +105,16 @@ rand_impl!(Iso2) approx_eq_impl!(Iso2) to_homogeneous_impl!(Iso2, Mat3) inv_impl!(Iso2) -transform_impl!(Iso2, Vec2) +transform_impl!(Iso2TransformRhs, Iso2, Vec2, Pnt2) transformation_impl!(Iso2) rotate_impl!(Iso2, Vec2) translation_impl!(Iso2, Vec2) -translate_impl!(Iso2, Vec2) +translate_impl!(Iso2, Pnt2) iso_mul_iso_impl!(Iso2, Iso2MulRhs) iso_mul_vec_impl!(Iso2, Vec2, Iso2MulRhs) vec_mul_iso_impl!(Iso2, Vec2, Vec2MulRhs) +iso_mul_pnt_impl!(Iso2, Pnt2, Iso2MulRhs) +pnt_mul_iso_impl!(Iso2, Pnt2, Pnt2MulRhs) iso_impl!(Iso3, Rot3, Vec3, Vec3) double_dispatch_binop_decl_trait!(Iso3, Iso3MulRhs) @@ -125,14 +128,16 @@ rand_impl!(Iso3) approx_eq_impl!(Iso3) to_homogeneous_impl!(Iso3, Mat4) inv_impl!(Iso3) -transform_impl!(Iso3, Vec3) +transform_impl!(Iso3TransformRhs, Iso3, Vec3, Pnt3) transformation_impl!(Iso3) rotate_impl!(Iso3, Vec3) translation_impl!(Iso3, Vec3) -translate_impl!(Iso3, Vec3) +translate_impl!(Iso3, Pnt3) iso_mul_iso_impl!(Iso3, Iso3MulRhs) iso_mul_vec_impl!(Iso3, Vec3, Iso3MulRhs) vec_mul_iso_impl!(Iso3, Vec3, Vec3MulRhs) +iso_mul_pnt_impl!(Iso3, Pnt3, Iso3MulRhs) +pnt_mul_iso_impl!(Iso3, Pnt3, Pnt3MulRhs) // iso_impl!(Iso4, Rot4, Vec4, Vec4) double_dispatch_binop_decl_trait!(Iso4, Iso4MulRhs) @@ -146,11 +151,13 @@ absolute_rotate_impl!(Iso4, Vec4) approx_eq_impl!(Iso4) to_homogeneous_impl!(Iso4, Mat5) inv_impl!(Iso4) -transform_impl!(Iso4, Vec4) +transform_impl!(Iso4TransformRhs, Iso4, Vec4, Pnt4) transformation_impl!(Iso4) rotate_impl!(Iso4, Vec4) translation_impl!(Iso4, Vec4) -translate_impl!(Iso4, Vec4) +translate_impl!(Iso4, Pnt4) iso_mul_iso_impl!(Iso4, Iso4MulRhs) iso_mul_vec_impl!(Iso4, Vec4, Iso4MulRhs) vec_mul_iso_impl!(Iso4, Vec4, Vec4MulRhs) +iso_mul_pnt_impl!(Iso4, Pnt4, Iso4MulRhs) +pnt_mul_iso_impl!(Iso4, Pnt4, Pnt4MulRhs) diff --git a/src/structs/iso_macros.rs b/src/structs/iso_macros.rs index 1c618df4..58972174 100644 --- a/src/structs/iso_macros.rs +++ b/src/structs/iso_macros.rs @@ -77,13 +77,35 @@ macro_rules! iso_mul_vec_impl( impl $tmul> for $tv { #[inline] fn binop(left: &$t, right: &$tv) -> $tv { - left.translation + left.rotation * *right + left.rotation * *right } } ) ) macro_rules! vec_mul_iso_impl( + ($t: ident, $tv: ident, $tmul: ident) => ( + impl $tmul> for $t { + #[inline] + fn binop(left: &$tv, right: &$t) -> $tv { + left * right.rotation + } + } + ) +) + +macro_rules! iso_mul_pnt_impl( + ($t: ident, $tv: ident, $tmul: ident) => ( + impl $tmul> for $tv { + #[inline] + fn binop(left: &$t, right: &$tv) -> $tv { + left.rotation * *right + left.translation + } + } + ) +) + +macro_rules! pnt_mul_iso_impl( ($t: ident, $tv: ident, $tmul: ident) => ( impl $tmul> for $t { #[inline] @@ -254,16 +276,49 @@ macro_rules! transformation_impl( ) macro_rules! transform_impl( - ($t: ident, $tv: ident) => ( - impl Transform<$tv> for $t { + ($trhs: ident, $t: ident, $tv: ident, $tp: ident) => ( + /* + * FIXME: we use the double dispatch trick here so that we can transform vectors _and_ + * points. Remove this as soon as rust supports multidispatch. + */ + pub trait $trhs { + fn transform(left: &$t, right: &Self) -> Self; + fn inv_transform(left: &$t, right: &Self) -> Self; + } + + impl> Transform for $t { + #[inline(always)] + fn transform(&self, other: &V) -> V { + $trhs::transform(self, other) + } + + #[inline(always)] + fn inv_transform(&self, other: &V) -> V { + $trhs::inv_transform(self, other) + } + } + + impl $trhs for $tv { #[inline] - fn transform(&self, v: &$tv) -> $tv { - self.rotation.transform(v) + self.translation + fn transform(t: &$t, v: &$tv) -> $tv { + t.rotation.transform(v) } #[inline] - fn inv_transform(&self, v: &$tv) -> $tv { - self.rotation.inv_transform(&(v - self.translation)) + fn inv_transform(t: &$t, v: &$tv) -> $tv { + t.rotation.inv_transform(v) + } + } + + impl $trhs for $tp { + #[inline] + fn transform(t: &$t, p: &$tp) -> $tp { + t.rotation.transform(p) + t.translation + } + + #[inline] + fn inv_transform(t: &$t, p: &$tp) -> $tp { + t.rotation.inv_transform(&(p - t.translation)) } } ) diff --git a/src/structs/mat.rs b/src/structs/mat.rs index 25845468..6c022823 100644 --- a/src/structs/mat.rs +++ b/src/structs/mat.rs @@ -8,12 +8,13 @@ use traits::operations::ApproxEq; use std::slice::{Items, MutItems}; use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6, Vec1MulRhs, Vec4MulRhs, Vec5MulRhs, Vec6MulRhs}; +use structs::pnt::{Pnt1, Pnt4, Pnt5, Pnt6, Pnt1MulRhs, Pnt4MulRhs, Pnt5MulRhs, Pnt6MulRhs}; use structs::dvec::{DVec1, DVec2, DVec3, DVec4, DVec5, DVec6}; use traits::structure::{Cast, Row, Col, Iterable, IterableMut, Dim, Indexable, Eye, ColSlice, RowSlice, Diag}; use traits::operations::{Absolute, Transpose, Inv, Outer}; -use traits::geometry::{ToHomogeneous, FromHomogeneous}; +use traits::geometry::{ToHomogeneous, FromHomogeneous, Orig}; /// Special identity matrix. All its operation are no-ops. @@ -112,8 +113,10 @@ dim_impl!(Mat1, 1) indexable_impl!(Mat1, 1) index_impl!(Mat1, Vec1, 1) mat_mul_mat_impl!(Mat1, Mat1MulRhs, 1) -mat_mul_vec_impl!(Mat1, Vec1, Mat1MulRhs, 1) -vec_mul_mat_impl!(Mat1, Vec1, Vec1MulRhs, 1) +mat_mul_vec_impl!(Mat1, Vec1, Mat1MulRhs, 1, Zero::zero) +vec_mul_mat_impl!(Mat1, Vec1, Vec1MulRhs, 1, Zero::zero) +mat_mul_pnt_impl!(Mat1, Pnt1, Mat1MulRhs, 1, Orig::orig) +pnt_mul_mat_impl!(Mat1, Pnt1, Pnt1MulRhs, 1, Orig::orig) // (specialized) inv_impl!(Mat1, 1) transpose_impl!(Mat1, 1) approx_eq_impl!(Mat1) @@ -501,8 +504,10 @@ indexable_impl!(Mat4, 4) index_impl!(Mat4, Vec4, 4) at_fast_impl!(Mat4, 4) mat_mul_mat_impl!(Mat4, Mat4MulRhs, 4) -mat_mul_vec_impl!(Mat4, Vec4, Mat4MulRhs, 4) -vec_mul_mat_impl!(Mat4, Vec4, Vec4MulRhs, 4) +mat_mul_vec_impl!(Mat4, Vec4, Mat4MulRhs, 4, Zero::zero) +vec_mul_mat_impl!(Mat4, Vec4, Vec4MulRhs, 4, Zero::zero) +mat_mul_pnt_impl!(Mat4, Pnt4, Mat4MulRhs, 4, Orig::orig) +pnt_mul_mat_impl!(Mat4, Pnt4, Pnt4MulRhs, 4, Orig::orig) inv_impl!(Mat4, 4) transpose_impl!(Mat4, 4) approx_eq_impl!(Mat4) @@ -686,8 +691,10 @@ indexable_impl!(Mat5, 5) index_impl!(Mat5, Vec5, 5) at_fast_impl!(Mat5, 5) mat_mul_mat_impl!(Mat5, Mat5MulRhs, 5) -mat_mul_vec_impl!(Mat5, Vec5, Mat5MulRhs, 5) -vec_mul_mat_impl!(Mat5, Vec5, Vec5MulRhs, 5) +mat_mul_vec_impl!(Mat5, Vec5, Mat5MulRhs, 5, Zero::zero) +vec_mul_mat_impl!(Mat5, Vec5, Vec5MulRhs, 5, Zero::zero) +mat_mul_pnt_impl!(Mat5, Pnt5, Mat5MulRhs, 5, Orig::orig) +pnt_mul_mat_impl!(Mat5, Pnt5, Pnt5MulRhs, 5, Orig::orig) inv_impl!(Mat5, 5) transpose_impl!(Mat5, 5) approx_eq_impl!(Mat5) @@ -923,8 +930,10 @@ indexable_impl!(Mat6, 6) index_impl!(Mat6, Vec6, 6) at_fast_impl!(Mat6, 6) mat_mul_mat_impl!(Mat6, Mat6MulRhs, 6) -mat_mul_vec_impl!(Mat6, Vec6, Mat6MulRhs, 6) -vec_mul_mat_impl!(Mat6, Vec6, Vec6MulRhs, 6) +mat_mul_vec_impl!(Mat6, Vec6, Mat6MulRhs, 6, Zero::zero) +vec_mul_mat_impl!(Mat6, Vec6, Vec6MulRhs, 6, Zero::zero) +mat_mul_pnt_impl!(Mat6, Pnt6, Mat6MulRhs, 6, Orig::orig) +pnt_mul_mat_impl!(Mat6, Pnt6, Pnt6MulRhs, 6, Orig::orig) inv_impl!(Mat6, 6) transpose_impl!(Mat6, 6) approx_eq_impl!(Mat6) diff --git a/src/structs/mat_macros.rs b/src/structs/mat_macros.rs index 3978ed60..c09a6b7a 100644 --- a/src/structs/mat_macros.rs +++ b/src/structs/mat_macros.rs @@ -381,11 +381,11 @@ macro_rules! mat_mul_mat_impl( ) macro_rules! vec_mul_mat_impl( - ($t: ident, $v: ident, $trhs: ident, $dim: expr) => ( + ($t: ident, $v: ident, $trhs: ident, $dim: expr, $zero: expr) => ( impl $trhs> for $t { #[inline] fn binop(left: &$v, right: &$t) -> $v { - let mut res : $v = Zero::zero(); + let mut res : $v = $zero(); for i in range(0u, $dim) { for j in range(0u, $dim) { @@ -403,11 +403,11 @@ macro_rules! vec_mul_mat_impl( ) macro_rules! mat_mul_vec_impl( - ($t: ident, $v: ident, $trhs: ident, $dim: expr) => ( + ($t: ident, $v: ident, $trhs: ident, $dim: expr, $zero: expr) => ( impl $trhs> for $v { #[inline] fn binop(left: &$t, right: &$v) -> $v { - let mut res : $v = Zero::zero(); + let mut res : $v = $zero(); for i in range(0u, $dim) { for j in range(0u, $dim) { @@ -424,6 +424,18 @@ macro_rules! mat_mul_vec_impl( ) ) +macro_rules! pnt_mul_mat_impl( + ($t: ident, $v: ident, $trhs: ident, $dim: expr, $zero: expr) => ( + vec_mul_mat_impl!($t, $v, $trhs, $dim, $zero) + ) +) + +macro_rules! mat_mul_pnt_impl( + ($t: ident, $v: ident, $trhs: ident, $dim: expr, $zero: expr) => ( + mat_mul_vec_impl!($t, $v, $trhs, $dim, $zero) + ) +) + macro_rules! inv_impl( ($t: ident, $dim: expr) => ( impl diff --git a/src/structs/mod.rs b/src/structs/mod.rs index 0aef1e8c..be5f335f 100644 --- a/src/structs/mod.rs +++ b/src/structs/mod.rs @@ -3,6 +3,7 @@ pub use self::dmat::DMat; pub use self::dvec::{DVec, DVec1, DVec2, DVec3, DVec4, DVec5, DVec6}; pub use self::vec::{Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6}; +pub use self::pnt::{Pnt0, Pnt1, Pnt2, Pnt3, Pnt4, Pnt5, Pnt6}; pub use self::mat::{Identity, Mat1, Mat2, Mat3, Mat4, Mat5, Mat6}; pub use self::rot::{Rot2, Rot3, Rot4}; pub use self::iso::{Iso2, Iso3, Iso4}; @@ -22,6 +23,8 @@ mod dvec_macros; mod dvec; mod vec_macros; mod vec; +mod pnt_macros; +mod pnt; mod mat_macros; mod mat; mod rot_macros; diff --git a/src/structs/pnt.rs b/src/structs/pnt.rs new file mode 100644 index 00000000..4a861744 --- /dev/null +++ b/src/structs/pnt.rs @@ -0,0 +1,593 @@ +//! Points with dimensions known at compile-time. + +#![allow(missing_doc)] // we allow missing to avoid having to document the vector components. + +use std::mem; +use std::num::{Zero, One, Bounded}; +use std::slice::{Items, MutItems}; +use std::iter::{Iterator, FromIterator}; +use traits::operations::{ApproxEq, PartialOrd, PartialOrdering, PartialLess, PartialEqual, + PartialGreater, NotComparable}; +use traits::structure::{Cast, Dim, Indexable, Iterable, IterableMut, PntAsVec}; +use traits::geometry::{Orig, FromHomogeneous, ToHomogeneous}; +use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6}; + + +/// Point of dimension 0. +#[deriving(Eq, PartialEq, Decodable, Clone, Rand, Show)] +pub struct Pnt0; + +impl Pnt0 { + /// Creates a new vector. + #[inline] + pub fn new() -> Pnt0 { + Pnt0 + } + + /// Creates a new vector. The parameter is not taken in account. + #[inline] + pub fn new_repeat(_: N) -> Pnt0 { + Pnt0 + } +} + +/// Point of dimension 1. +#[deriving(Eq, PartialEq, Encodable, Decodable, Clone, Hash, Rand, Show)] +pub struct Pnt1 { + /// First component of the vector. + pub x: N +} + +double_dispatch_binop_decl_trait!(Pnt1, Pnt1MulRhs) +double_dispatch_binop_decl_trait!(Pnt1, Pnt1DivRhs) +double_dispatch_binop_decl_trait!(Pnt1, Pnt1AddRhs) +double_dispatch_binop_decl_trait!(Pnt1, Pnt1SubRhs) +double_dispatch_cast_decl_trait!(Pnt1, Pnt1Cast) +mul_redispatch_impl!(Pnt1, Pnt1MulRhs) +div_redispatch_impl!(Pnt1, Pnt1DivRhs) +add_redispatch_impl!(Pnt1, Pnt1AddRhs) +sub_redispatch_impl!(Pnt1, Pnt1SubRhs) +cast_redispatch_impl!(Pnt1, Pnt1Cast) +new_impl!(Pnt1, x) +orig_impl!(Pnt1, x) +ord_impl!(Pnt1, x) +vec_cast_impl!(Pnt1, Pnt1Cast, x) +as_slice_impl!(Pnt1, 1) +index_impl!(Pnt1) +indexable_impl!(Pnt1, 1) +at_fast_impl!(Pnt1, 1) +new_repeat_impl!(Pnt1, val, x) +dim_impl!(Pnt1, 1) +container_impl!(Pnt1) +pnt_as_vec_impl!(Pnt1, Vec1) +pnt_sub_impl!(Pnt1, Vec1, Pnt1SubRhs) +neg_impl!(Pnt1, x) +pnt_add_vec_impl!(Pnt1, Vec1, Pnt1AddRhs, x) +pnt_sub_vec_impl!(Pnt1, Vec1, Pnt1SubRhs, x) +vec_mul_scalar_impl!(Pnt1, f64, Pnt1MulRhs, x) +vec_mul_scalar_impl!(Pnt1, f32, Pnt1MulRhs, x) +vec_mul_scalar_impl!(Pnt1, u64, Pnt1MulRhs, x) +vec_mul_scalar_impl!(Pnt1, u32, Pnt1MulRhs, x) +vec_mul_scalar_impl!(Pnt1, u16, Pnt1MulRhs, x) +vec_mul_scalar_impl!(Pnt1, u8, Pnt1MulRhs, x) +vec_mul_scalar_impl!(Pnt1, i64, Pnt1MulRhs, x) +vec_mul_scalar_impl!(Pnt1, i32, Pnt1MulRhs, x) +vec_mul_scalar_impl!(Pnt1, i16, Pnt1MulRhs, x) +vec_mul_scalar_impl!(Pnt1, i8, Pnt1MulRhs, x) +vec_mul_scalar_impl!(Pnt1, uint, Pnt1MulRhs, x) +vec_mul_scalar_impl!(Pnt1, int, Pnt1MulRhs, x) +vec_div_scalar_impl!(Pnt1, f64, Pnt1DivRhs, x) +vec_div_scalar_impl!(Pnt1, f32, Pnt1DivRhs, x) +vec_div_scalar_impl!(Pnt1, u64, Pnt1DivRhs, x) +vec_div_scalar_impl!(Pnt1, u32, Pnt1DivRhs, x) +vec_div_scalar_impl!(Pnt1, u16, Pnt1DivRhs, x) +vec_div_scalar_impl!(Pnt1, u8, Pnt1DivRhs, x) +vec_div_scalar_impl!(Pnt1, i64, Pnt1DivRhs, x) +vec_div_scalar_impl!(Pnt1, i32, Pnt1DivRhs, x) +vec_div_scalar_impl!(Pnt1, i16, Pnt1DivRhs, x) +vec_div_scalar_impl!(Pnt1, i8, Pnt1DivRhs, x) +vec_div_scalar_impl!(Pnt1, uint, Pnt1DivRhs, x) +vec_div_scalar_impl!(Pnt1, int, Pnt1DivRhs, x) +vec_add_scalar_impl!(Pnt1, f64, Pnt1AddRhs, x) +vec_add_scalar_impl!(Pnt1, f32, Pnt1AddRhs, x) +vec_add_scalar_impl!(Pnt1, u64, Pnt1AddRhs, x) +vec_add_scalar_impl!(Pnt1, u32, Pnt1AddRhs, x) +vec_add_scalar_impl!(Pnt1, u16, Pnt1AddRhs, x) +vec_add_scalar_impl!(Pnt1, u8, Pnt1AddRhs, x) +vec_add_scalar_impl!(Pnt1, i64, Pnt1AddRhs, x) +vec_add_scalar_impl!(Pnt1, i32, Pnt1AddRhs, x) +vec_add_scalar_impl!(Pnt1, i16, Pnt1AddRhs, x) +vec_add_scalar_impl!(Pnt1, i8, Pnt1AddRhs, x) +vec_add_scalar_impl!(Pnt1, uint, Pnt1AddRhs, x) +vec_add_scalar_impl!(Pnt1, int, Pnt1AddRhs, x) +vec_sub_scalar_impl!(Pnt1, f64, Pnt1SubRhs, x) +vec_sub_scalar_impl!(Pnt1, f32, Pnt1SubRhs, x) +vec_sub_scalar_impl!(Pnt1, u64, Pnt1SubRhs, x) +vec_sub_scalar_impl!(Pnt1, u32, Pnt1SubRhs, x) +vec_sub_scalar_impl!(Pnt1, u16, Pnt1SubRhs, x) +vec_sub_scalar_impl!(Pnt1, u8, Pnt1SubRhs, x) +vec_sub_scalar_impl!(Pnt1, i64, Pnt1SubRhs, x) +vec_sub_scalar_impl!(Pnt1, i32, Pnt1SubRhs, x) +vec_sub_scalar_impl!(Pnt1, i16, Pnt1SubRhs, x) +vec_sub_scalar_impl!(Pnt1, i8, Pnt1SubRhs, x) +vec_sub_scalar_impl!(Pnt1, uint, Pnt1SubRhs, x) +vec_sub_scalar_impl!(Pnt1, int, Pnt1SubRhs, x) +approx_eq_impl!(Pnt1, x) +from_iterator_impl!(Pnt1, iterator) +bounded_impl!(Pnt1, x) +iterable_impl!(Pnt1, 1) +iterable_mut_impl!(Pnt1, 1) +pnt_to_homogeneous_impl!(Pnt1, Pnt2, y, x) +pnt_from_homogeneous_impl!(Pnt1, Pnt2, y, x) + +/// Point of dimension 2. +#[deriving(Eq, PartialEq, Encodable, Decodable, Clone, Hash, Rand, Show)] +pub struct Pnt2 { + /// First component of the vector. + pub x: N, + /// Second component of the vector. + pub y: N +} + +double_dispatch_binop_decl_trait!(Pnt2, Pnt2MulRhs) +double_dispatch_binop_decl_trait!(Pnt2, Pnt2DivRhs) +double_dispatch_binop_decl_trait!(Pnt2, Pnt2AddRhs) +double_dispatch_binop_decl_trait!(Pnt2, Pnt2SubRhs) +double_dispatch_cast_decl_trait!(Pnt2, Pnt2Cast) +mul_redispatch_impl!(Pnt2, Pnt2MulRhs) +div_redispatch_impl!(Pnt2, Pnt2DivRhs) +add_redispatch_impl!(Pnt2, Pnt2AddRhs) +sub_redispatch_impl!(Pnt2, Pnt2SubRhs) +cast_redispatch_impl!(Pnt2, Pnt2Cast) +new_impl!(Pnt2, x, y) +orig_impl!(Pnt2, x, y) +ord_impl!(Pnt2, x, y) +vec_cast_impl!(Pnt2, Pnt2Cast, x, y) +as_slice_impl!(Pnt2, 2) +index_impl!(Pnt2) +indexable_impl!(Pnt2, 2) +at_fast_impl!(Pnt2, 2) +new_repeat_impl!(Pnt2, val, x, y) +dim_impl!(Pnt2, 2) +container_impl!(Pnt2) +pnt_as_vec_impl!(Pnt2, Vec2) +pnt_sub_impl!(Pnt2, Vec2, Pnt2SubRhs) +neg_impl!(Pnt2, x, y) +pnt_add_vec_impl!(Pnt2, Vec2, Pnt2AddRhs, x, y) +pnt_sub_vec_impl!(Pnt2, Vec2, Pnt2SubRhs, x, y) +vec_mul_scalar_impl!(Pnt2, f64, Pnt2MulRhs, x, y) +vec_mul_scalar_impl!(Pnt2, f32, Pnt2MulRhs, x, y) +vec_mul_scalar_impl!(Pnt2, u64, Pnt2MulRhs, x, y) +vec_mul_scalar_impl!(Pnt2, u32, Pnt2MulRhs, x, y) +vec_mul_scalar_impl!(Pnt2, u16, Pnt2MulRhs, x, y) +vec_mul_scalar_impl!(Pnt2, u8, Pnt2MulRhs, x, y) +vec_mul_scalar_impl!(Pnt2, i64, Pnt2MulRhs, x, y) +vec_mul_scalar_impl!(Pnt2, i32, Pnt2MulRhs, x, y) +vec_mul_scalar_impl!(Pnt2, i16, Pnt2MulRhs, x, y) +vec_mul_scalar_impl!(Pnt2, i8, Pnt2MulRhs, x, y) +vec_mul_scalar_impl!(Pnt2, uint, Pnt2MulRhs, x, y) +vec_mul_scalar_impl!(Pnt2, int, Pnt2MulRhs, x, y) +vec_div_scalar_impl!(Pnt2, f64, Pnt2DivRhs, x, y) +vec_div_scalar_impl!(Pnt2, f32, Pnt2DivRhs, x, y) +vec_div_scalar_impl!(Pnt2, u64, Pnt2DivRhs, x, y) +vec_div_scalar_impl!(Pnt2, u32, Pnt2DivRhs, x, y) +vec_div_scalar_impl!(Pnt2, u16, Pnt2DivRhs, x, y) +vec_div_scalar_impl!(Pnt2, u8, Pnt2DivRhs, x, y) +vec_div_scalar_impl!(Pnt2, i64, Pnt2DivRhs, x, y) +vec_div_scalar_impl!(Pnt2, i32, Pnt2DivRhs, x, y) +vec_div_scalar_impl!(Pnt2, i16, Pnt2DivRhs, x, y) +vec_div_scalar_impl!(Pnt2, i8, Pnt2DivRhs, x, y) +vec_div_scalar_impl!(Pnt2, uint, Pnt2DivRhs, x, y) +vec_div_scalar_impl!(Pnt2, int, Pnt2DivRhs, x, y) +vec_add_scalar_impl!(Pnt2, f64, Pnt2AddRhs, x, y) +vec_add_scalar_impl!(Pnt2, f32, Pnt2AddRhs, x, y) +vec_add_scalar_impl!(Pnt2, u64, Pnt2AddRhs, x, y) +vec_add_scalar_impl!(Pnt2, u32, Pnt2AddRhs, x, y) +vec_add_scalar_impl!(Pnt2, u16, Pnt2AddRhs, x, y) +vec_add_scalar_impl!(Pnt2, u8, Pnt2AddRhs, x, y) +vec_add_scalar_impl!(Pnt2, i64, Pnt2AddRhs, x, y) +vec_add_scalar_impl!(Pnt2, i32, Pnt2AddRhs, x, y) +vec_add_scalar_impl!(Pnt2, i16, Pnt2AddRhs, x, y) +vec_add_scalar_impl!(Pnt2, i8, Pnt2AddRhs, x, y) +vec_add_scalar_impl!(Pnt2, uint, Pnt2AddRhs, x, y) +vec_add_scalar_impl!(Pnt2, int, Pnt2AddRhs, x, y) +vec_sub_scalar_impl!(Pnt2, f64, Pnt2SubRhs, x, y) +vec_sub_scalar_impl!(Pnt2, f32, Pnt2SubRhs, x, y) +vec_sub_scalar_impl!(Pnt2, u64, Pnt2SubRhs, x, y) +vec_sub_scalar_impl!(Pnt2, u32, Pnt2SubRhs, x, y) +vec_sub_scalar_impl!(Pnt2, u16, Pnt2SubRhs, x, y) +vec_sub_scalar_impl!(Pnt2, u8, Pnt2SubRhs, x, y) +vec_sub_scalar_impl!(Pnt2, i64, Pnt2SubRhs, x, y) +vec_sub_scalar_impl!(Pnt2, i32, Pnt2SubRhs, x, y) +vec_sub_scalar_impl!(Pnt2, i16, Pnt2SubRhs, x, y) +vec_sub_scalar_impl!(Pnt2, i8, Pnt2SubRhs, x, y) +vec_sub_scalar_impl!(Pnt2, uint, Pnt2SubRhs, x, y) +vec_sub_scalar_impl!(Pnt2, int, Pnt2SubRhs, x, y) +approx_eq_impl!(Pnt2, x, y) +from_iterator_impl!(Pnt2, iterator, iterator) +bounded_impl!(Pnt2, x, y) +iterable_impl!(Pnt2, 2) +iterable_mut_impl!(Pnt2, 2) +pnt_to_homogeneous_impl!(Pnt2, Pnt3, z, x, y) +pnt_from_homogeneous_impl!(Pnt2, Pnt3, z, x, y) + +/// Point of dimension 3. +#[deriving(Eq, PartialEq, Encodable, Decodable, Clone, Hash, Rand, Show)] +pub struct Pnt3 { + /// First component of the vector. + pub x: N, + /// Second component of the vector. + pub y: N, + /// Third component of the vector. + pub z: N +} + +double_dispatch_binop_decl_trait!(Pnt3, Pnt3MulRhs) +double_dispatch_binop_decl_trait!(Pnt3, Pnt3DivRhs) +double_dispatch_binop_decl_trait!(Pnt3, Pnt3AddRhs) +double_dispatch_binop_decl_trait!(Pnt3, Pnt3SubRhs) +double_dispatch_cast_decl_trait!(Pnt3, Pnt3Cast) +mul_redispatch_impl!(Pnt3, Pnt3MulRhs) +div_redispatch_impl!(Pnt3, Pnt3DivRhs) +add_redispatch_impl!(Pnt3, Pnt3AddRhs) +sub_redispatch_impl!(Pnt3, Pnt3SubRhs) +cast_redispatch_impl!(Pnt3, Pnt3Cast) +new_impl!(Pnt3, x, y, z) +orig_impl!(Pnt3, x, y, z) +ord_impl!(Pnt3, x, y, z) +vec_cast_impl!(Pnt3, Pnt3Cast, x, y, z) +as_slice_impl!(Pnt3, 3) +index_impl!(Pnt3) +indexable_impl!(Pnt3, 3) +at_fast_impl!(Pnt3, 3) +new_repeat_impl!(Pnt3, val, x, y, z) +dim_impl!(Pnt3, 3) +container_impl!(Pnt3) +pnt_as_vec_impl!(Pnt3, Vec3) +pnt_sub_impl!(Pnt3, Vec3, Pnt3SubRhs) +neg_impl!(Pnt3, x, y, z) +pnt_add_vec_impl!(Pnt3, Vec3, Pnt3AddRhs, x, y, z) +pnt_sub_vec_impl!(Pnt3, Vec3, Pnt3SubRhs, x, y, z) +vec_mul_scalar_impl!(Pnt3, f64, Pnt3MulRhs, x, y, z) +vec_mul_scalar_impl!(Pnt3, f32, Pnt3MulRhs, x, y, z) +vec_mul_scalar_impl!(Pnt3, u64, Pnt3MulRhs, x, y, z) +vec_mul_scalar_impl!(Pnt3, u32, Pnt3MulRhs, x, y, z) +vec_mul_scalar_impl!(Pnt3, u16, Pnt3MulRhs, x, y, z) +vec_mul_scalar_impl!(Pnt3, u8, Pnt3MulRhs, x, y, z) +vec_mul_scalar_impl!(Pnt3, i64, Pnt3MulRhs, x, y, z) +vec_mul_scalar_impl!(Pnt3, i32, Pnt3MulRhs, x, y, z) +vec_mul_scalar_impl!(Pnt3, i16, Pnt3MulRhs, x, y, z) +vec_mul_scalar_impl!(Pnt3, i8, Pnt3MulRhs, x, y, z) +vec_mul_scalar_impl!(Pnt3, uint, Pnt3MulRhs, x, y, z) +vec_mul_scalar_impl!(Pnt3, int, Pnt3MulRhs, x, y, z) +vec_div_scalar_impl!(Pnt3, f64, Pnt3DivRhs, x, y, z) +vec_div_scalar_impl!(Pnt3, f32, Pnt3DivRhs, x, y, z) +vec_div_scalar_impl!(Pnt3, u64, Pnt3DivRhs, x, y, z) +vec_div_scalar_impl!(Pnt3, u32, Pnt3DivRhs, x, y, z) +vec_div_scalar_impl!(Pnt3, u16, Pnt3DivRhs, x, y, z) +vec_div_scalar_impl!(Pnt3, u8, Pnt3DivRhs, x, y, z) +vec_div_scalar_impl!(Pnt3, i64, Pnt3DivRhs, x, y, z) +vec_div_scalar_impl!(Pnt3, i32, Pnt3DivRhs, x, y, z) +vec_div_scalar_impl!(Pnt3, i16, Pnt3DivRhs, x, y, z) +vec_div_scalar_impl!(Pnt3, i8, Pnt3DivRhs, x, y, z) +vec_div_scalar_impl!(Pnt3, uint, Pnt3DivRhs, x, y, z) +vec_div_scalar_impl!(Pnt3, int, Pnt3DivRhs, x, y, z) +vec_add_scalar_impl!(Pnt3, f64, Pnt3AddRhs, x, y, z) +vec_add_scalar_impl!(Pnt3, f32, Pnt3AddRhs, x, y, z) +vec_add_scalar_impl!(Pnt3, u64, Pnt3AddRhs, x, y, z) +vec_add_scalar_impl!(Pnt3, u32, Pnt3AddRhs, x, y, z) +vec_add_scalar_impl!(Pnt3, u16, Pnt3AddRhs, x, y, z) +vec_add_scalar_impl!(Pnt3, u8, Pnt3AddRhs, x, y, z) +vec_add_scalar_impl!(Pnt3, i64, Pnt3AddRhs, x, y, z) +vec_add_scalar_impl!(Pnt3, i32, Pnt3AddRhs, x, y, z) +vec_add_scalar_impl!(Pnt3, i16, Pnt3AddRhs, x, y, z) +vec_add_scalar_impl!(Pnt3, i8, Pnt3AddRhs, x, y, z) +vec_add_scalar_impl!(Pnt3, uint, Pnt3AddRhs, x, y, z) +vec_add_scalar_impl!(Pnt3, int, Pnt3AddRhs, x, y, z) +vec_sub_scalar_impl!(Pnt3, f64, Pnt3SubRhs, x, y, z) +vec_sub_scalar_impl!(Pnt3, f32, Pnt3SubRhs, x, y, z) +vec_sub_scalar_impl!(Pnt3, u64, Pnt3SubRhs, x, y, z) +vec_sub_scalar_impl!(Pnt3, u32, Pnt3SubRhs, x, y, z) +vec_sub_scalar_impl!(Pnt3, u16, Pnt3SubRhs, x, y, z) +vec_sub_scalar_impl!(Pnt3, u8, Pnt3SubRhs, x, y, z) +vec_sub_scalar_impl!(Pnt3, i64, Pnt3SubRhs, x, y, z) +vec_sub_scalar_impl!(Pnt3, i32, Pnt3SubRhs, x, y, z) +vec_sub_scalar_impl!(Pnt3, i16, Pnt3SubRhs, x, y, z) +vec_sub_scalar_impl!(Pnt3, i8, Pnt3SubRhs, x, y, z) +vec_sub_scalar_impl!(Pnt3, uint, Pnt3SubRhs, x, y, z) +vec_sub_scalar_impl!(Pnt3, int, Pnt3SubRhs, x, y, z) +approx_eq_impl!(Pnt3, x, y, z) +from_iterator_impl!(Pnt3, iterator, iterator, iterator) +bounded_impl!(Pnt3, x, y, z) +iterable_impl!(Pnt3, 3) +iterable_mut_impl!(Pnt3, 3) +pnt_to_homogeneous_impl!(Pnt3, Pnt4, w, x, y, z) +pnt_from_homogeneous_impl!(Pnt3, Pnt4, w, x, y, z) + +/// Point of dimension 4. +#[deriving(Eq, PartialEq, Encodable, Decodable, Clone, Hash, Rand, Show)] +pub struct Pnt4 { + /// First component of the vector. + pub x: N, + /// Second component of the vector. + pub y: N, + /// Third component of the vector. + pub z: N, + /// Fourth component of the vector. + pub w: N +} + +double_dispatch_binop_decl_trait!(Pnt4, Pnt4MulRhs) +double_dispatch_binop_decl_trait!(Pnt4, Pnt4DivRhs) +double_dispatch_binop_decl_trait!(Pnt4, Pnt4AddRhs) +double_dispatch_binop_decl_trait!(Pnt4, Pnt4SubRhs) +double_dispatch_cast_decl_trait!(Pnt4, Pnt4Cast) +mul_redispatch_impl!(Pnt4, Pnt4MulRhs) +div_redispatch_impl!(Pnt4, Pnt4DivRhs) +add_redispatch_impl!(Pnt4, Pnt4AddRhs) +sub_redispatch_impl!(Pnt4, Pnt4SubRhs) +cast_redispatch_impl!(Pnt4, Pnt4Cast) +new_impl!(Pnt4, x, y, z, w) +orig_impl!(Pnt4, x, y, z, w) +ord_impl!(Pnt4, x, y, z, w) +vec_cast_impl!(Pnt4, Pnt4Cast, x, y, z, w) +as_slice_impl!(Pnt4, 4) +index_impl!(Pnt4) +indexable_impl!(Pnt4, 4) +at_fast_impl!(Pnt4, 4) +new_repeat_impl!(Pnt4, val, x, y, z, w) +dim_impl!(Pnt4, 4) +container_impl!(Pnt4) +pnt_as_vec_impl!(Pnt4, Vec4) +pnt_sub_impl!(Pnt4, Vec4, Pnt4SubRhs) +neg_impl!(Pnt4, x, y, z, w) +pnt_add_vec_impl!(Pnt4, Vec4, Pnt4AddRhs, x, y, z, w) +pnt_sub_vec_impl!(Pnt4, Vec4, Pnt4SubRhs, x, y, z, w) +vec_mul_scalar_impl!(Pnt4, f64, Pnt4MulRhs, x, y, z, w) +vec_mul_scalar_impl!(Pnt4, f32, Pnt4MulRhs, x, y, z, w) +vec_mul_scalar_impl!(Pnt4, u64, Pnt4MulRhs, x, y, z, w) +vec_mul_scalar_impl!(Pnt4, u32, Pnt4MulRhs, x, y, z, w) +vec_mul_scalar_impl!(Pnt4, u16, Pnt4MulRhs, x, y, z, w) +vec_mul_scalar_impl!(Pnt4, u8, Pnt4MulRhs, x, y, z, w) +vec_mul_scalar_impl!(Pnt4, i64, Pnt4MulRhs, x, y, z, w) +vec_mul_scalar_impl!(Pnt4, i32, Pnt4MulRhs, x, y, z, w) +vec_mul_scalar_impl!(Pnt4, i16, Pnt4MulRhs, x, y, z, w) +vec_mul_scalar_impl!(Pnt4, i8, Pnt4MulRhs, x, y, z, w) +vec_mul_scalar_impl!(Pnt4, uint, Pnt4MulRhs, x, y, z, w) +vec_mul_scalar_impl!(Pnt4, int, Pnt4MulRhs, x, y, z, w) +vec_div_scalar_impl!(Pnt4, f64, Pnt4DivRhs, x, y, z, w) +vec_div_scalar_impl!(Pnt4, f32, Pnt4DivRhs, x, y, z, w) +vec_div_scalar_impl!(Pnt4, u64, Pnt4DivRhs, x, y, z, w) +vec_div_scalar_impl!(Pnt4, u32, Pnt4DivRhs, x, y, z, w) +vec_div_scalar_impl!(Pnt4, u16, Pnt4DivRhs, x, y, z, w) +vec_div_scalar_impl!(Pnt4, u8, Pnt4DivRhs, x, y, z, w) +vec_div_scalar_impl!(Pnt4, i64, Pnt4DivRhs, x, y, z, w) +vec_div_scalar_impl!(Pnt4, i32, Pnt4DivRhs, x, y, z, w) +vec_div_scalar_impl!(Pnt4, i16, Pnt4DivRhs, x, y, z, w) +vec_div_scalar_impl!(Pnt4, i8, Pnt4DivRhs, x, y, z, w) +vec_div_scalar_impl!(Pnt4, uint, Pnt4DivRhs, x, y, z, w) +vec_div_scalar_impl!(Pnt4, int, Pnt4DivRhs, x, y, z, w) +vec_add_scalar_impl!(Pnt4, f64, Pnt4AddRhs, x, y, z, w) +vec_add_scalar_impl!(Pnt4, f32, Pnt4AddRhs, x, y, z, w) +vec_add_scalar_impl!(Pnt4, u64, Pnt4AddRhs, x, y, z, w) +vec_add_scalar_impl!(Pnt4, u32, Pnt4AddRhs, x, y, z, w) +vec_add_scalar_impl!(Pnt4, u16, Pnt4AddRhs, x, y, z, w) +vec_add_scalar_impl!(Pnt4, u8, Pnt4AddRhs, x, y, z, w) +vec_add_scalar_impl!(Pnt4, i64, Pnt4AddRhs, x, y, z, w) +vec_add_scalar_impl!(Pnt4, i32, Pnt4AddRhs, x, y, z, w) +vec_add_scalar_impl!(Pnt4, i16, Pnt4AddRhs, x, y, z, w) +vec_add_scalar_impl!(Pnt4, i8, Pnt4AddRhs, x, y, z, w) +vec_add_scalar_impl!(Pnt4, uint, Pnt4AddRhs, x, y, z, w) +vec_add_scalar_impl!(Pnt4, int, Pnt4AddRhs, x, y, z, w) +vec_sub_scalar_impl!(Pnt4, f64, Pnt4SubRhs, x, y, z, w) +vec_sub_scalar_impl!(Pnt4, f32, Pnt4SubRhs, x, y, z, w) +vec_sub_scalar_impl!(Pnt4, u64, Pnt4SubRhs, x, y, z, w) +vec_sub_scalar_impl!(Pnt4, u32, Pnt4SubRhs, x, y, z, w) +vec_sub_scalar_impl!(Pnt4, u16, Pnt4SubRhs, x, y, z, w) +vec_sub_scalar_impl!(Pnt4, u8, Pnt4SubRhs, x, y, z, w) +vec_sub_scalar_impl!(Pnt4, i64, Pnt4SubRhs, x, y, z, w) +vec_sub_scalar_impl!(Pnt4, i32, Pnt4SubRhs, x, y, z, w) +vec_sub_scalar_impl!(Pnt4, i16, Pnt4SubRhs, x, y, z, w) +vec_sub_scalar_impl!(Pnt4, i8, Pnt4SubRhs, x, y, z, w) +vec_sub_scalar_impl!(Pnt4, uint, Pnt4SubRhs, x, y, z, w) +vec_sub_scalar_impl!(Pnt4, int, Pnt4SubRhs, x, y, z, w) +approx_eq_impl!(Pnt4, x, y, z, w) +from_iterator_impl!(Pnt4, iterator, iterator, iterator, iterator) +bounded_impl!(Pnt4, x, y, z, w) +iterable_impl!(Pnt4, 4) +iterable_mut_impl!(Pnt4, 4) +pnt_to_homogeneous_impl!(Pnt4, Pnt5, a, x, y, z, w) +pnt_from_homogeneous_impl!(Pnt4, Pnt5, a, x, y, z, w) + +/// Point of dimension 5. +#[deriving(Eq, PartialEq, Encodable, Decodable, Clone, Hash, Rand, Show)] +pub struct Pnt5 { + /// First component of the vector. + pub x: N, + /// Second component of the vector. + pub y: N, + /// Third component of the vector. + pub z: N, + /// Fourth component of the vector. + pub w: N, + /// Fifth of the vector. + pub a: N +} + +double_dispatch_binop_decl_trait!(Pnt5, Pnt5MulRhs) +double_dispatch_binop_decl_trait!(Pnt5, Pnt5DivRhs) +double_dispatch_binop_decl_trait!(Pnt5, Pnt5AddRhs) +double_dispatch_binop_decl_trait!(Pnt5, Pnt5SubRhs) +double_dispatch_cast_decl_trait!(Pnt5, Pnt5Cast) +mul_redispatch_impl!(Pnt5, Pnt5MulRhs) +div_redispatch_impl!(Pnt5, Pnt5DivRhs) +add_redispatch_impl!(Pnt5, Pnt5AddRhs) +sub_redispatch_impl!(Pnt5, Pnt5SubRhs) +cast_redispatch_impl!(Pnt5, Pnt5Cast) +new_impl!(Pnt5, x, y, z, w, a) +orig_impl!(Pnt5, x, y, z, w, a) +ord_impl!(Pnt5, x, y, z, w, a) +vec_cast_impl!(Pnt5, Pnt5Cast, x, y, z, w, a) +as_slice_impl!(Pnt5, 5) +index_impl!(Pnt5) +indexable_impl!(Pnt5, 5) +at_fast_impl!(Pnt5, 5) +new_repeat_impl!(Pnt5, val, x, y, z, w, a) +dim_impl!(Pnt5, 5) +container_impl!(Pnt5) +pnt_as_vec_impl!(Pnt5, Vec5) +pnt_sub_impl!(Pnt5, Vec5, Pnt5SubRhs) +neg_impl!(Pnt5, x, y, z, w, a) +pnt_add_vec_impl!(Pnt5, Vec5, Pnt5AddRhs, x, y, z, w, a) +pnt_sub_vec_impl!(Pnt5, Vec5, Pnt5SubRhs, x, y, z, w, a) +vec_mul_scalar_impl!(Pnt5, f64, Pnt5MulRhs, x, y, z, w, a) +vec_mul_scalar_impl!(Pnt5, f32, Pnt5MulRhs, x, y, z, w, a) +vec_mul_scalar_impl!(Pnt5, u64, Pnt5MulRhs, x, y, z, w, a) +vec_mul_scalar_impl!(Pnt5, u32, Pnt5MulRhs, x, y, z, w, a) +vec_mul_scalar_impl!(Pnt5, u16, Pnt5MulRhs, x, y, z, w, a) +vec_mul_scalar_impl!(Pnt5, u8, Pnt5MulRhs, x, y, z, w, a) +vec_mul_scalar_impl!(Pnt5, i64, Pnt5MulRhs, x, y, z, w, a) +vec_mul_scalar_impl!(Pnt5, i32, Pnt5MulRhs, x, y, z, w, a) +vec_mul_scalar_impl!(Pnt5, i16, Pnt5MulRhs, x, y, z, w, a) +vec_mul_scalar_impl!(Pnt5, i8, Pnt5MulRhs, x, y, z, w, a) +vec_mul_scalar_impl!(Pnt5, uint, Pnt5MulRhs, x, y, z, w, a) +vec_mul_scalar_impl!(Pnt5, int, Pnt5MulRhs, x, y, z, w, a) +vec_div_scalar_impl!(Pnt5, f64, Pnt5DivRhs, x, y, z, w, a) +vec_div_scalar_impl!(Pnt5, f32, Pnt5DivRhs, x, y, z, w, a) +vec_div_scalar_impl!(Pnt5, u64, Pnt5DivRhs, x, y, z, w, a) +vec_div_scalar_impl!(Pnt5, u32, Pnt5DivRhs, x, y, z, w, a) +vec_div_scalar_impl!(Pnt5, u16, Pnt5DivRhs, x, y, z, w, a) +vec_div_scalar_impl!(Pnt5, u8, Pnt5DivRhs, x, y, z, w, a) +vec_div_scalar_impl!(Pnt5, i64, Pnt5DivRhs, x, y, z, w, a) +vec_div_scalar_impl!(Pnt5, i32, Pnt5DivRhs, x, y, z, w, a) +vec_div_scalar_impl!(Pnt5, i16, Pnt5DivRhs, x, y, z, w, a) +vec_div_scalar_impl!(Pnt5, i8, Pnt5DivRhs, x, y, z, w, a) +vec_div_scalar_impl!(Pnt5, uint, Pnt5DivRhs, x, y, z, w, a) +vec_div_scalar_impl!(Pnt5, int, Pnt5DivRhs, x, y, z, w, a) +vec_add_scalar_impl!(Pnt5, f64, Pnt5AddRhs, x, y, z, w, a) +vec_add_scalar_impl!(Pnt5, f32, Pnt5AddRhs, x, y, z, w, a) +vec_add_scalar_impl!(Pnt5, u64, Pnt5AddRhs, x, y, z, w, a) +vec_add_scalar_impl!(Pnt5, u32, Pnt5AddRhs, x, y, z, w, a) +vec_add_scalar_impl!(Pnt5, u16, Pnt5AddRhs, x, y, z, w, a) +vec_add_scalar_impl!(Pnt5, u8, Pnt5AddRhs, x, y, z, w, a) +vec_add_scalar_impl!(Pnt5, i64, Pnt5AddRhs, x, y, z, w, a) +vec_add_scalar_impl!(Pnt5, i32, Pnt5AddRhs, x, y, z, w, a) +vec_add_scalar_impl!(Pnt5, i16, Pnt5AddRhs, x, y, z, w, a) +vec_add_scalar_impl!(Pnt5, i8, Pnt5AddRhs, x, y, z, w, a) +vec_add_scalar_impl!(Pnt5, uint, Pnt5AddRhs, x, y, z, w, a) +vec_add_scalar_impl!(Pnt5, int, Pnt5AddRhs, x, y, z, w, a) +vec_sub_scalar_impl!(Pnt5, f64, Pnt5SubRhs, x, y, z, w, a) +vec_sub_scalar_impl!(Pnt5, f32, Pnt5SubRhs, x, y, z, w, a) +vec_sub_scalar_impl!(Pnt5, u64, Pnt5SubRhs, x, y, z, w, a) +vec_sub_scalar_impl!(Pnt5, u32, Pnt5SubRhs, x, y, z, w, a) +vec_sub_scalar_impl!(Pnt5, u16, Pnt5SubRhs, x, y, z, w, a) +vec_sub_scalar_impl!(Pnt5, u8, Pnt5SubRhs, x, y, z, w, a) +vec_sub_scalar_impl!(Pnt5, i64, Pnt5SubRhs, x, y, z, w, a) +vec_sub_scalar_impl!(Pnt5, i32, Pnt5SubRhs, x, y, z, w, a) +vec_sub_scalar_impl!(Pnt5, i16, Pnt5SubRhs, x, y, z, w, a) +vec_sub_scalar_impl!(Pnt5, i8, Pnt5SubRhs, x, y, z, w, a) +vec_sub_scalar_impl!(Pnt5, uint, Pnt5SubRhs, x, y, z, w, a) +vec_sub_scalar_impl!(Pnt5, int, Pnt5SubRhs, x, y, z, w, a) +approx_eq_impl!(Pnt5, x, y, z, w, a) +from_iterator_impl!(Pnt5, iterator, iterator, iterator, iterator, iterator) +bounded_impl!(Pnt5, x, y, z, w, a) +iterable_impl!(Pnt5, 5) +iterable_mut_impl!(Pnt5, 5) +pnt_to_homogeneous_impl!(Pnt5, Pnt6, b, x, y, z, w, a) +pnt_from_homogeneous_impl!(Pnt5, Pnt6, b, x, y, z, w, a) + +/// Point of dimension 6. +#[deriving(Eq, PartialEq, Encodable, Decodable, Clone, Hash, Rand, Show)] +pub struct Pnt6 { + /// First component of the vector. + pub x: N, + /// Second component of the vector. + pub y: N, + /// Third component of the vector. + pub z: N, + /// Fourth component of the vector. + pub w: N, + /// Fifth of the vector. + pub a: N, + /// Sixth component of the vector. + pub b: N +} + +double_dispatch_binop_decl_trait!(Pnt6, Pnt6MulRhs) +double_dispatch_binop_decl_trait!(Pnt6, Pnt6DivRhs) +double_dispatch_binop_decl_trait!(Pnt6, Pnt6AddRhs) +double_dispatch_binop_decl_trait!(Pnt6, Pnt6SubRhs) +double_dispatch_cast_decl_trait!(Pnt6, Pnt6Cast) +mul_redispatch_impl!(Pnt6, Pnt6MulRhs) +div_redispatch_impl!(Pnt6, Pnt6DivRhs) +add_redispatch_impl!(Pnt6, Pnt6AddRhs) +sub_redispatch_impl!(Pnt6, Pnt6SubRhs) +cast_redispatch_impl!(Pnt6, Pnt6Cast) +new_impl!(Pnt6, x, y, z, w, a, b) +orig_impl!(Pnt6, x, y, z, w, a, b) +ord_impl!(Pnt6, x, y, z, w, a, b) +vec_cast_impl!(Pnt6, Pnt6Cast, x, y, z, w, a, b) +as_slice_impl!(Pnt6, 6) +index_impl!(Pnt6) +indexable_impl!(Pnt6, 6) +at_fast_impl!(Pnt6, 6) +new_repeat_impl!(Pnt6, val, x, y, z, w, a, b) +dim_impl!(Pnt6, 6) +container_impl!(Pnt6) +pnt_as_vec_impl!(Pnt6, Vec6) +pnt_sub_impl!(Pnt6, Vec6, Pnt6SubRhs) +neg_impl!(Pnt6, x, y, z, w, a, b) +pnt_add_vec_impl!(Pnt6, Vec6, Pnt6AddRhs, x, y, z, w, a, b) +pnt_sub_vec_impl!(Pnt6, Vec6, Pnt6SubRhs, x, y, z, w, a, b) +vec_mul_scalar_impl!(Pnt6, f64, Pnt6MulRhs, x, y, z, w, a, b) +vec_mul_scalar_impl!(Pnt6, f32, Pnt6MulRhs, x, y, z, w, a, b) +vec_mul_scalar_impl!(Pnt6, u64, Pnt6MulRhs, x, y, z, w, a, b) +vec_mul_scalar_impl!(Pnt6, u32, Pnt6MulRhs, x, y, z, w, a, b) +vec_mul_scalar_impl!(Pnt6, u16, Pnt6MulRhs, x, y, z, w, a, b) +vec_mul_scalar_impl!(Pnt6, u8, Pnt6MulRhs, x, y, z, w, a, b) +vec_mul_scalar_impl!(Pnt6, i64, Pnt6MulRhs, x, y, z, w, a, b) +vec_mul_scalar_impl!(Pnt6, i32, Pnt6MulRhs, x, y, z, w, a, b) +vec_mul_scalar_impl!(Pnt6, i16, Pnt6MulRhs, x, y, z, w, a, b) +vec_mul_scalar_impl!(Pnt6, i8, Pnt6MulRhs, x, y, z, w, a, b) +vec_mul_scalar_impl!(Pnt6, uint, Pnt6MulRhs, x, y, z, w, a, b) +vec_mul_scalar_impl!(Pnt6, int, Pnt6MulRhs, x, y, z, w, a, b) +vec_div_scalar_impl!(Pnt6, f64, Pnt6DivRhs, x, y, z, w, a, b) +vec_div_scalar_impl!(Pnt6, f32, Pnt6DivRhs, x, y, z, w, a, b) +vec_div_scalar_impl!(Pnt6, u64, Pnt6DivRhs, x, y, z, w, a, b) +vec_div_scalar_impl!(Pnt6, u32, Pnt6DivRhs, x, y, z, w, a, b) +vec_div_scalar_impl!(Pnt6, u16, Pnt6DivRhs, x, y, z, w, a, b) +vec_div_scalar_impl!(Pnt6, u8, Pnt6DivRhs, x, y, z, w, a, b) +vec_div_scalar_impl!(Pnt6, i64, Pnt6DivRhs, x, y, z, w, a, b) +vec_div_scalar_impl!(Pnt6, i32, Pnt6DivRhs, x, y, z, w, a, b) +vec_div_scalar_impl!(Pnt6, i16, Pnt6DivRhs, x, y, z, w, a, b) +vec_div_scalar_impl!(Pnt6, i8, Pnt6DivRhs, x, y, z, w, a, b) +vec_div_scalar_impl!(Pnt6, uint, Pnt6DivRhs, x, y, z, w, a, b) +vec_div_scalar_impl!(Pnt6, int, Pnt6DivRhs, x, y, z, w, a, b) +vec_add_scalar_impl!(Pnt6, f64, Pnt6AddRhs, x, y, z, w, a, b) +vec_add_scalar_impl!(Pnt6, f32, Pnt6AddRhs, x, y, z, w, a, b) +vec_add_scalar_impl!(Pnt6, u64, Pnt6AddRhs, x, y, z, w, a, b) +vec_add_scalar_impl!(Pnt6, u32, Pnt6AddRhs, x, y, z, w, a, b) +vec_add_scalar_impl!(Pnt6, u16, Pnt6AddRhs, x, y, z, w, a, b) +vec_add_scalar_impl!(Pnt6, u8, Pnt6AddRhs, x, y, z, w, a, b) +vec_add_scalar_impl!(Pnt6, i64, Pnt6AddRhs, x, y, z, w, a, b) +vec_add_scalar_impl!(Pnt6, i32, Pnt6AddRhs, x, y, z, w, a, b) +vec_add_scalar_impl!(Pnt6, i16, Pnt6AddRhs, x, y, z, w, a, b) +vec_add_scalar_impl!(Pnt6, i8, Pnt6AddRhs, x, y, z, w, a, b) +vec_add_scalar_impl!(Pnt6, uint, Pnt6AddRhs, x, y, z, w, a, b) +vec_add_scalar_impl!(Pnt6, int, Pnt6AddRhs, x, y, z, w, a, b) +vec_sub_scalar_impl!(Pnt6, f64, Pnt6SubRhs, x, y, z, w, a, b) +vec_sub_scalar_impl!(Pnt6, f32, Pnt6SubRhs, x, y, z, w, a, b) +vec_sub_scalar_impl!(Pnt6, u64, Pnt6SubRhs, x, y, z, w, a, b) +vec_sub_scalar_impl!(Pnt6, u32, Pnt6SubRhs, x, y, z, w, a, b) +vec_sub_scalar_impl!(Pnt6, u16, Pnt6SubRhs, x, y, z, w, a, b) +vec_sub_scalar_impl!(Pnt6, u8, Pnt6SubRhs, x, y, z, w, a, b) +vec_sub_scalar_impl!(Pnt6, i64, Pnt6SubRhs, x, y, z, w, a, b) +vec_sub_scalar_impl!(Pnt6, i32, Pnt6SubRhs, x, y, z, w, a, b) +vec_sub_scalar_impl!(Pnt6, i16, Pnt6SubRhs, x, y, z, w, a, b) +vec_sub_scalar_impl!(Pnt6, i8, Pnt6SubRhs, x, y, z, w, a, b) +vec_sub_scalar_impl!(Pnt6, uint, Pnt6SubRhs, x, y, z, w, a, b) +vec_sub_scalar_impl!(Pnt6, int, Pnt6SubRhs, x, y, z, w, a, b) +approx_eq_impl!(Pnt6, x, y, z, w, a, b) +from_iterator_impl!(Pnt6, iterator, iterator, iterator, iterator, iterator, iterator) +iterable_impl!(Pnt6, 6) +iterable_mut_impl!(Pnt6, 6) diff --git a/src/structs/pnt_macros.rs b/src/structs/pnt_macros.rs new file mode 100644 index 00000000..bbfd100b --- /dev/null +++ b/src/structs/pnt_macros.rs @@ -0,0 +1,104 @@ +#![macro_escape] + +macro_rules! orig_impl( + ($t: ident, $comp0: ident $(,$compN: ident)*) => ( + impl Orig for $t { + #[inline] + fn orig() -> $t { + $t { + $comp0: Zero::zero() + $(, $compN: Zero::zero() )* + } + } + + #[inline] + fn is_orig(&self) -> bool { + self.$comp0.is_zero() $(&& self.$compN.is_zero() )* + } + } + ) +) + +macro_rules! pnt_sub_impl( + ($t: ident, $tv: ident, $trhs: ident) => ( + impl> $trhs> for $t { + #[inline] + fn binop(left: &$t, right: &$t) -> $tv { + *left.as_vec() - *right.as_vec() + } + } + ) +) + +macro_rules! pnt_add_vec_impl( + ($t: ident, $tv: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( + impl> $trhs> for $tv { + #[inline] + fn binop(left: &$t, right: &$tv) -> $t { + $t::new(left.$comp0 + right.$comp0 $(, left.$compN + right.$compN)*) + } + } + ) +) + +macro_rules! pnt_sub_vec_impl( + ($t: ident, $tv: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( + impl> $trhs> for $tv { + #[inline] + fn binop(left: &$t, right: &$tv) -> $t { + $t::new(left.$comp0 - right.$comp0 $(, left.$compN - right.$compN)*) + } + } + ) +) + +macro_rules! pnt_as_vec_impl( + ($t: ident, $tv: ident) => ( + impl $t { + #[inline] + pub fn as_vec<'a>(&'a self) -> &'a $tv { + unsafe { + mem::transmute(self) + } + } + } + + impl PntAsVec<$tv> for $t { + #[inline] + fn as_vec<'a>(&'a self) -> &'a $tv { + self.as_vec() + } + } + ) +) + +macro_rules! pnt_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 = Orig::orig(); + + res.$comp0 = v.$comp0.clone(); + $( res.$compN = v.$compN.clone(); )* + res.$extra = One::one(); + + res + } + } + ) +) + +macro_rules! pnt_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 = Orig::orig(); + + res.$comp0 = v.$comp0.clone() / v.$extra; + $( res.$compN = v.$compN.clone() / v.$extra; )* + + res + } + } + ) +) diff --git a/src/structs/rot.rs b/src/structs/rot.rs index d84f49f5..4468f0a0 100644 --- a/src/structs/rot.rs +++ b/src/structs/rot.rs @@ -9,6 +9,7 @@ use traits::geometry::{Rotate, Rotation, AbsoluteRotate, RotationMatrix, Transfo use traits::structure::{Cast, Dim, Row, Col}; use traits::operations::{Absolute, Inv, Transpose, ApproxEq}; use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec2MulRhs, Vec3MulRhs, Vec4MulRhs}; +use structs::pnt::{Pnt2, Pnt3, Pnt4, Pnt2MulRhs, Pnt3MulRhs, Pnt4MulRhs}; use structs::mat::{Mat2, Mat3, Mat4, Mat5}; @@ -29,8 +30,7 @@ impl> Rot2 { } } -impl -Rotation> for Rot2 { +impl Rotation> for Rot2 { #[inline] fn rotation(&self) -> Vec1 { Vec1::new((-self.submat.m12).atan2(self.submat.m11.clone())) @@ -353,12 +353,14 @@ Rotation> for Rot4 { double_dispatch_binop_decl_trait!(Rot2, Rot2MulRhs) mul_redispatch_impl!(Rot2, Rot2MulRhs) submat_impl!(Rot2, Mat2) -rotate_impl!(Rot2, Vec2) -transform_impl!(Rot2, Vec2) +rotate_impl!(Rot2RotateRhs, Rot2, Vec2, Pnt2) +transform_impl!(Rot2TransformRhs, Rot2, Vec2, Pnt2) dim_impl!(Rot2, 2) rot_mul_rot_impl!(Rot2, Rot2MulRhs) rot_mul_vec_impl!(Rot2, Vec2, Rot2MulRhs) vec_mul_rot_impl!(Rot2, Vec2, Vec2MulRhs) +rot_mul_pnt_impl!(Rot2, Pnt2, Rot2MulRhs) +pnt_mul_rot_impl!(Rot2, Pnt2, Pnt2MulRhs) one_impl!(Rot2) rotation_matrix_impl!(Rot2, Vec2, Vec1) col_impl!(Rot2, Vec2) @@ -373,12 +375,14 @@ approx_eq_impl!(Rot2) double_dispatch_binop_decl_trait!(Rot3, Rot3MulRhs) mul_redispatch_impl!(Rot3, Rot3MulRhs) submat_impl!(Rot3, Mat3) -rotate_impl!(Rot3, Vec3) -transform_impl!(Rot3, Vec3) +rotate_impl!(Rot3RotateRhs, Rot3, Vec3, Pnt3) +transform_impl!(Rot3TransformRhs, Rot3, Vec3, Pnt3) dim_impl!(Rot3, 3) rot_mul_rot_impl!(Rot3, Rot3MulRhs) rot_mul_vec_impl!(Rot3, Vec3, Rot3MulRhs) vec_mul_rot_impl!(Rot3, Vec3, Vec3MulRhs) +rot_mul_pnt_impl!(Rot3, Pnt3, Rot3MulRhs) +pnt_mul_rot_impl!(Rot3, Pnt3, Pnt3MulRhs) one_impl!(Rot3) rotation_matrix_impl!(Rot3, Vec3, Vec3) col_impl!(Rot3, Vec3) @@ -393,12 +397,14 @@ approx_eq_impl!(Rot3) double_dispatch_binop_decl_trait!(Rot4, Rot4MulRhs) mul_redispatch_impl!(Rot4, Rot4MulRhs) submat_impl!(Rot4, Mat4) -rotate_impl!(Rot4, Vec4) -transform_impl!(Rot4, Vec4) +rotate_impl!(Rot4RotateRhs, Rot4, Vec4, Pnt4) +transform_impl!(Rot4TransformRhs, Rot4, Vec4, Pnt4) dim_impl!(Rot4, 4) rot_mul_rot_impl!(Rot4, Rot4MulRhs) rot_mul_vec_impl!(Rot4, Vec4, Rot4MulRhs) vec_mul_rot_impl!(Rot4, Vec4, Vec4MulRhs) +rot_mul_pnt_impl!(Rot4, Pnt4, Rot4MulRhs) +pnt_mul_rot_impl!(Rot4, Pnt4, Pnt4MulRhs) one_impl!(Rot4) rotation_matrix_impl!(Rot4, Vec4, Vec4) col_impl!(Rot4, Vec4) diff --git a/src/structs/rot_macros.rs b/src/structs/rot_macros.rs index a6caa497..a184b4fe 100644 --- a/src/structs/rot_macros.rs +++ b/src/structs/rot_macros.rs @@ -12,32 +12,98 @@ macro_rules! submat_impl( ) macro_rules! rotate_impl( - ($t: ident, $tv: ident) => ( - impl Rotate<$tv> for $t { + ($trhs: ident, $t: ident, $tv: ident, $tp: ident) => ( + /* + * FIXME: we use the double dispatch trick here so that we can rotate vectors _and_ + * points. Remove this as soon as rust supports multidispatch. + */ + pub trait $trhs { + fn rotate(left: &$t, right: &Self) -> Self; + fn inv_rotate(left: &$t, right: &Self) -> Self; + } + + impl> Rotate for $t { + #[inline(always)] + fn rotate(&self, other: &V) -> V { + $trhs::rotate(self, other) + } + + #[inline(always)] + fn inv_rotate(&self, other: &V) -> V { + $trhs::inv_rotate(self, other) + } + } + + impl $trhs for $tv { #[inline] - fn rotate(&self, v: &$tv) -> $tv { - self * *v + fn rotate(t: &$t, v: &$tv) -> $tv { + t * *v } #[inline] - fn inv_rotate(&self, v: &$tv) -> $tv { - v * *self + fn inv_rotate(t: &$t, v: &$tv) -> $tv { + v * *t + } + } + + impl $trhs for $tp { + #[inline] + fn rotate(t: &$t, p: &$tp) -> $tp { + t * *p + } + + #[inline] + fn inv_rotate(t: &$t, p: &$tp) -> $tp { + p * *t } } ) ) macro_rules! transform_impl( - ($t: ident, $tv: ident) => ( - impl Transform<$tv> for $t { + ($trhs: ident, $t: ident, $tv: ident, $tp: ident) => ( + /* + * FIXME: we use the double dispatch trick here so that we can transform vectors _and_ + * points. Remove this as soon as rust supports multidispatch. + */ + pub trait $trhs { + fn transform(left: &$t, right: &Self) -> Self; + fn inv_transform(left: &$t, right: &Self) -> Self; + } + + impl> Transform for $t { + #[inline(always)] + fn transform(&self, other: &V) -> V { + $trhs::transform(self, other) + } + + #[inline(always)] + fn inv_transform(&self, other: &V) -> V { + $trhs::inv_transform(self, other) + } + } + + impl $trhs for $tv { #[inline] - fn transform(&self, v: &$tv) -> $tv { - self.rotate(v) + fn transform(t: &$t, v: &$tv) -> $tv { + t.rotate(v) } #[inline] - fn inv_transform(&self, v: &$tv) -> $tv { - self.inv_rotate(v) + fn inv_transform(t: &$t, v: &$tv) -> $tv { + t.inv_rotate(v) + } + } + + impl $trhs for $tp { + #[inline] + fn transform(t: &$t, p: &$tp) -> $tp { + t.rotate(p) + } + + #[inline] + fn inv_transform(t: &$t, p: &$tp) -> $tp { + t.inv_rotate(p) } } ) @@ -99,6 +165,12 @@ macro_rules! rot_mul_vec_impl( ) ) +macro_rules! rot_mul_pnt_impl( + ($t: ident, $tv: ident, $mulrhs: ident) => ( + rot_mul_vec_impl!($t, $tv, $mulrhs) + ) +) + macro_rules! vec_mul_rot_impl( ($t: ident, $tv: ident, $mulrhs: ident) => ( impl $mulrhs> for $t { @@ -110,6 +182,12 @@ macro_rules! vec_mul_rot_impl( ) ) +macro_rules! pnt_mul_rot_impl( + ($t: ident, $tv: ident, $mulrhs: ident) => ( + vec_mul_rot_impl!($t, $tv, $mulrhs) + ) +) + macro_rules! inv_impl( ($t: ident) => ( impl Inv for $t { diff --git a/src/structs/spec/mat.rs b/src/structs/spec/mat.rs index 5ff57d42..58789510 100644 --- a/src/structs/spec/mat.rs +++ b/src/structs/spec/mat.rs @@ -1,5 +1,6 @@ use std::num::{Zero, One}; use structs::vec::{Vec2, Vec3, Vec2MulRhs, Vec3MulRhs}; +use structs::pnt::{Pnt2, Pnt3, Pnt2MulRhs, Pnt3MulRhs}; use structs::mat::{Mat1, Mat2, Mat3, Mat3MulRhs, Mat2MulRhs}; use traits::operations::{Inv, Det, ApproxEq}; use traits::structure::{Row, Col}; @@ -284,3 +285,45 @@ impl + Add> Mat2MulRhs> for Vec2 { ) } } + +impl + Add> Mat3MulRhs> for Pnt3 { + #[inline(always)] + fn binop(left: &Mat3, right: &Pnt3) -> Pnt3 { + Pnt3::new( + left.m11 * right.x + left.m12 * right.y + left.m13 * right.z, + left.m21 * right.x + left.m22 * right.y + left.m23 * right.z, + left.m31 * right.x + left.m32 * right.y + left.m33 * right.z + ) + } +} + +impl + Add> Pnt3MulRhs> for Mat3 { + #[inline(always)] + fn binop(left: &Pnt3, right: &Mat3) -> Pnt3 { + Pnt3::new( + left.x * right.m11 + left.y * right.m21 + left.z * right.m31, + left.x * right.m12 + left.y * right.m22 + left.z * right.m32, + left.x * right.m13 + left.y * right.m23 + left.z * right.m33 + ) + } +} + +impl + Add> Pnt2MulRhs> for Mat2 { + #[inline(always)] + fn binop(left: &Pnt2, right: &Mat2) -> Pnt2 { + Pnt2::new( + left.x * right.m11 + left.y * right.m21, + left.x * right.m12 + left.y * right.m22 + ) + } +} + +impl + Add> Mat2MulRhs> for Pnt2 { + #[inline(always)] + fn binop(left: &Mat2, right: &Pnt2) -> Pnt2 { + Pnt2::new( + left.m11 * right.x + left.m12 * right.y, + left.m21 * right.x + left.m22 * right.y + ) + } +} diff --git a/src/structs/spec/vec0.rs b/src/structs/spec/vec0.rs index e3fbcc32..4a3ea40d 100644 --- a/src/structs/spec/vec0.rs +++ b/src/structs/spec/vec0.rs @@ -91,11 +91,6 @@ impl Dot for vec::Vec0 { fn dot(_: &vec::Vec0, _: &vec::Vec0) -> N { Zero::zero() } - - #[inline] - fn sub_dot(_: &vec::Vec0, _: &vec::Vec0, _: &vec::Vec0) -> N { - Zero::zero() - } } impl Mul> for vec::Vec0 { diff --git a/src/structs/vec.rs b/src/structs/vec.rs index d9bef290..81f31752 100644 --- a/src/structs/vec.rs +++ b/src/structs/vec.rs @@ -10,7 +10,8 @@ use traits::operations::{ApproxEq, PartialOrd, PartialOrdering, PartialLess, Par PartialGreater, NotComparable}; use traits::geometry::{Transform, Rotate, FromHomogeneous, ToHomogeneous, Dot, Norm, Translation, Translate}; -use traits::structure::{Basis, Cast, Dim, Indexable, Iterable, IterableMut}; +use traits::structure::{Basis, Cast, Dim, Indexable, Iterable, IterableMut, VecAsPnt}; +use structs::pnt::{Pnt1, Pnt2, Pnt3, Pnt4, Pnt5, Pnt6}; /// Vector of dimension 0. @@ -124,9 +125,11 @@ iterable_impl!(Vec1, 1) iterable_mut_impl!(Vec1, 1) to_homogeneous_impl!(Vec1, Vec2, y, x) from_homogeneous_impl!(Vec1, Vec2, y, x) -translate_impl!(Vec1) +translate_impl!(Vec1, Pnt1) rotate_impl!(Vec1) -transform_impl!(Vec1) +rotate_impl!(Pnt1) +transform_impl!(Vec1, Pnt1) +vec_as_pnt_impl!(Vec1, Pnt1) /// Vector of dimension 2. #[deriving(Eq, PartialEq, Encodable, Decodable, Clone, Hash, Rand, Zero, Show)] @@ -223,9 +226,11 @@ 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) -translate_impl!(Vec2) +translate_impl!(Vec2, Pnt2) rotate_impl!(Vec2) -transform_impl!(Vec2) +rotate_impl!(Pnt2) +transform_impl!(Vec2, Pnt2) +vec_as_pnt_impl!(Vec2, Pnt2) /// Vector of dimension 3. #[deriving(Eq, PartialEq, Encodable, Decodable, Clone, Hash, Rand, Zero, Show)] @@ -327,9 +332,11 @@ 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) -translate_impl!(Vec3) +translate_impl!(Vec3, Pnt3) rotate_impl!(Vec3) -transform_impl!(Vec3) +rotate_impl!(Pnt3) +transform_impl!(Vec3, Pnt3) +vec_as_pnt_impl!(Vec3, Pnt3) /// Vector of dimension 4. @@ -431,9 +438,11 @@ 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) -translate_impl!(Vec4) +translate_impl!(Vec4, Pnt4) rotate_impl!(Vec4) -transform_impl!(Vec4) +rotate_impl!(Pnt4) +transform_impl!(Vec4, Pnt4) +vec_as_pnt_impl!(Vec4, Pnt4) /// Vector of dimension 5. #[deriving(Eq, PartialEq, Encodable, Decodable, Clone, Hash, Rand, Zero, Show)] @@ -536,9 +545,11 @@ 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) -translate_impl!(Vec5) +translate_impl!(Vec5, Pnt5) rotate_impl!(Vec5) -transform_impl!(Vec5) +rotate_impl!(Pnt5) +transform_impl!(Vec5, Pnt5) +vec_as_pnt_impl!(Vec5, Pnt5) /// Vector of dimension 6. #[deriving(Eq, PartialEq, Encodable, Decodable, Clone, Hash, Rand, Zero, Show)] @@ -641,6 +652,8 @@ from_iterator_impl!(Vec6, iterator, iterator, iterator, iterator, iterator, iter bounded_impl!(Vec6, x, y, z, w, a, b) iterable_impl!(Vec6, 6) iterable_mut_impl!(Vec6, 6) -translate_impl!(Vec6) +translate_impl!(Vec6, Pnt6) rotate_impl!(Vec6) -transform_impl!(Vec6) +rotate_impl!(Pnt6) +transform_impl!(Vec6, Pnt6) +vec_as_pnt_impl!(Vec6, Pnt6) diff --git a/src/structs/vec_macros.rs b/src/structs/vec_macros.rs index d6f71d21..b4aa58fd 100644 --- a/src/structs/vec_macros.rs +++ b/src/structs/vec_macros.rs @@ -405,11 +405,6 @@ macro_rules! dot_impl( 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 )* - } } ) ) @@ -608,7 +603,7 @@ 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(); + let mut res: $t2 = Zero::zero(); res.$comp0 = v.$comp0.clone(); $( res.$compN = v.$compN.clone(); )* @@ -625,8 +620,8 @@ macro_rules! from_homogeneous_impl( 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.$comp0 = v.$comp0.clone(); + $( res.$compN = v.$compN.clone(); )* res } @@ -635,8 +630,8 @@ macro_rules! from_homogeneous_impl( ) macro_rules! translate_impl( - ($t: ident) => ( - impl + Sub> Translate<$t> for $t { + ($tv: ident, $t: ident) => ( + impl + Sub> Translate<$t> for $tv { fn translate(&self, other: &$t) -> $t { *other + *self } @@ -663,8 +658,8 @@ macro_rules! rotate_impl( ) macro_rules! transform_impl( - ($t: ident) => ( - impl + Sub> Transform<$t> for $t { + ($tv: ident, $t: ident) => ( + impl + Sub> Transform<$t> for $tv { fn transform(&self, other: &$t) -> $t { self.translate(other) } @@ -673,5 +668,35 @@ macro_rules! transform_impl( self.inv_translate(other) } } + + impl Transform<$tv> for $tv { + fn transform(&self, other: &$tv) -> $tv { + other.clone() + } + + fn inv_transform(&self, other: &$tv) -> $tv { + other.clone() + } + } + ) +) + +macro_rules! vec_as_pnt_impl( + ($tv: ident, $t: ident) => ( + impl $tv { + #[inline] + pub fn as_pnt<'a>(&'a self) -> &'a $t { + unsafe { + mem::transmute(self) + } + } + } + + impl VecAsPnt<$t> for $tv { + #[inline] + fn as_pnt<'a>(&'a self) -> &'a $t { + self.as_pnt() + } + } ) ) diff --git a/src/traits/geometry.rs b/src/traits/geometry.rs index cd65382b..c8c6a214 100644 --- a/src/traits/geometry.rs +++ b/src/traits/geometry.rs @@ -202,19 +202,6 @@ pub trait Dot { /// Computes the dot (inner) product of two vectors. #[inline] fn dot(&Self, &Self) -> N; - - /** - * Short-cut to compute the projection of a point on a vector, but without - * computing intermediate vectors. - * The following equation must be verified: - * - * ```.ignore - * a.sub_dot(b, c) == (a - b).dot(c) - * ``` - * - */ - #[inline] - fn sub_dot(a: &Self, b: &Self, c: &Self) -> N; } /// Traits of objects having an euclidian norm. @@ -280,3 +267,21 @@ pub trait UniformSphereSample { /// Iterate through the samples. fn sample(|Self| -> ()); } + +/// The zero element of a vector space, seen as an element of its embeding affine space. +// XXX: once associated types are suported, move this to the `AnyPnt` trait. +pub trait Orig { + /// The trivial origin. + fn orig() -> Self; + /// Returns true if this points is exactly the trivial origin. + fn is_orig(&self) -> bool; +} + +/// Trait implemented by projectors. +// XXX: Vout should be an associated type instead of a type parameter. +pub trait Projector { + /// Projects an element of a vector or affine space to a subspace. + /// + /// This must be an indempotent operaton. + fn project(&self, &Vin) -> Vout; +} diff --git a/src/traits/mod.rs b/src/traits/mod.rs index 5fe3c9fa..2fefef1e 100644 --- a/src/traits/mod.rs +++ b/src/traits/mod.rs @@ -1,12 +1,13 @@ //! Mathematical traits. -pub use self::geometry::{AbsoluteRotate, Cross, CrossMatrix, Dot, FromHomogeneous, Norm, Rotate, - Rotation, RotationMatrix, RotationWithTranslation, ToHomogeneous, - Transform, Transformation, Translate, Translation, UniformSphereSample}; +pub use self::geometry::{AbsoluteRotate, Cross, CrossMatrix, Dot, FromHomogeneous, Norm, Orig, + Projector, Rotate, Rotation, RotationMatrix, RotationWithTranslation, + ToHomogeneous, Transform, Transformation, Translate, Translation, + UniformSphereSample}; -pub use self::structure::{FloatVec, FloatVecExt, Basis, Cast, Col, Dim, Indexable, - Iterable, IterableMut, Mat, Row, AnyVec, VecExt, - ColSlice, RowSlice, Diag, Eye}; +pub use self::structure::{FloatVec, FloatVecExt, FloatPnt, FloatPntExt, Basis, Cast, Col, Dim, + Indexable, Iterable, IterableMut, Mat, Row, AnyVec, VecExt, AnyPnt, + PntExt, PntAsVec, VecAsPnt, ColSlice, RowSlice, Diag, Eye}; pub use self::operations::{Absolute, ApproxEq, Cov, Det, Inv, LMul, Mean, Outer, PartialOrd, RMul, ScalarAdd, ScalarSub, ScalarMul, ScalarDiv, Transpose}; diff --git a/src/traits/structure.rs b/src/traits/structure.rs index 94d16aae..679b1b02 100644 --- a/src/traits/structure.rs +++ b/src/traits/structure.rs @@ -3,7 +3,7 @@ use std::num::{Zero, Bounded}; use std::slice::{Items, MutItems}; use traits::operations::{RMul, LMul, ScalarAdd, ScalarSub}; -use traits::geometry::{Dot, Norm, UniformSphereSample}; +use traits::geometry::{Dot, Norm, UniformSphereSample, Orig}; /// Traits of objects which can be created from an object of type `T`. pub trait Cast { @@ -28,37 +28,6 @@ pub trait Eye { // XXX: we keep ScalarAdd and ScalarSub here to avoid trait impl conflict (overriding) between the // different Add/Sub traits. This is _so_ unfortunateā€¦ -/// Trait grouping most common operations on vectors. -pub trait AnyVec: Dim + Sub + Add + Neg + Zero + PartialEq + Mul - + Div + Dot { -} - -/// Trait of vector with components implementing the `Float` trait. -pub trait FloatVec: AnyVec + Norm { -} - -/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view) -/// operations on vectors. -pub trait VecExt: AnyVec + Indexable + Iterable + - UniformSphereSample + ScalarAdd + ScalarSub + Bounded -{ } - -/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view) -/// operations on vectors. -pub trait FloatVecExt: FloatVec + VecExt + Basis { } - -impl + Add + Neg + Zero + PartialEq + Mul + Div + Dot> -AnyVec for V { } - -impl + Norm> FloatVec for V { } - -impl + Indexable + Iterable + - UniformSphereSample + ScalarAdd + ScalarSub + Bounded> -VecExt for V { } - -impl + VecExt + Basis> FloatVecExt for V { } - // FIXME: return an iterator instead /// Traits of objects which can form a basis (typically vectors). pub trait Basis { @@ -172,3 +141,92 @@ pub trait IterableMut { /// Gets a vector-like read-write iterator. fn mut_iter<'l>(&'l mut self) -> MutItems<'l, N>; } + +/* + * Vec related traits. + */ +/// Trait that relates a point of an affine space to a vector of the associated vector space. +pub trait VecAsPnt

{ + /// Converts a reference to this point to a reference to its associated vector. + fn as_pnt<'a>(&'a self) -> &'a P; +} + +/// Trait grouping most common operations on vectors. +pub trait AnyVec: Dim + Sub + Add + Neg + Zero + PartialEq + Mul + + Div + Dot { +} + +/// Trait of vector with components implementing the `Float` trait. +pub trait FloatVec: AnyVec + Norm { +} + +/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view) +/// operations on vectors. +pub trait VecExt: AnyVec + Indexable + Iterable + + UniformSphereSample + ScalarAdd + ScalarSub + Bounded +{ } + +/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view) +/// operations on vectors. +pub trait FloatVecExt: FloatVec + VecExt + Basis { } + +impl + Add + Neg + Zero + PartialEq + Mul + Div + Dot> +AnyVec for V { } + +impl + Norm> FloatVec for V { } + +impl + Indexable + Iterable + + UniformSphereSample + ScalarAdd + ScalarSub + Bounded> +VecExt for V { } + +impl + VecExt + Basis> FloatVecExt for V { } + +/* + * Pnt related traits. + */ +/// Trait that relates a point of an affine space to a vector of the associated vector space. +pub trait PntAsVec { + /// Converts a reference to this point to a reference to its associated vector. + fn as_vec<'a>(&'a self) -> &'a V; +} + +/// Trait grouping most common operations on points. +// XXX: the vector space element `V` should be an associated type. Though this would prevent V from +// having bounds (they are not supported yet). So, for now, we will just use a type parameter. +pub trait AnyPnt: + PntAsVec + Dim + Sub + Orig + Neg + PartialEq + Mul + Div { +} + +/// Trait of points with components implementing the `Float` trait. +pub trait FloatPnt>: AnyPnt { + /// Computes the square distance between two points. + #[inline] + fn sqdist(a: &Self, b: &Self) -> N { + Norm::sqnorm(&(*a - *b)) + } + + /// Computes the distance between two points. + #[inline] + fn dist(a: &Self, b: &Self) -> N { + Norm::norm(&(*a - *b)) + } +} + +/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view) +/// operations on points. +pub trait PntExt: AnyPnt + Indexable + Iterable + + ScalarAdd + ScalarSub + Bounded +{ } + +/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view) +/// operations on points. +pub trait FloatPntExt> : FloatPnt + PntExt { } + + +impl + Dim + Sub + Orig + Neg

+ PartialEq + Mul + Div> +AnyPnt for P { } +impl, P: AnyPnt> FloatPnt for P { } +impl + Indexable + Iterable + ScalarAdd + ScalarSub + Bounded> +PntExt for P { } +impl, P: FloatPnt + PntExt> FloatPntExt for P { }