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: One>() -> T {
 //
 //
 
+/// Returns the trivial origin of an affine space.
+#[inline(always)]
+pub fn orig<T: Orig>() -> T {
+    Orig::orig()
+}
+
+/*
+ * FloatPnt
+ */
+/// Returns the distance between two points.
+#[inline(always)]
+pub fn dist<N: Float, P: FloatPnt<N, V>, V: Norm<N>>(a: &P, b: &P) -> N {
+    FloatPnt::<N, V>::dist(a, b)
+}
+
+/// Returns the squared distance between two points.
+#[inline(always)]
+pub fn sqdist<N: Float, P: FloatPnt<N, V>, V: Norm<N>>(a: &P, b: &P) -> N {
+    FloatPnt::<N, V>::sqdist(a, b)
+}
+
 /*
  * Perspective
  */
@@ -405,46 +435,46 @@ pub fn append_translation<V, M: Translation<V>>(m: &M, v: &V) -> M {
 }
 
 /*
- * Translate<V>
+ * Translate<P>
  */
 
-/// 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<V, M: Translate<V>>(m: &M, v: &V) -> V {
-    m.translate(v)
+pub fn translate<P, M: Translate<P>>(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<V, M: Translate<V>>(m: &M, v: &V) -> V {
-    m.inv_translate(v)
+pub fn inv_translate<P, M: Translate<P>>(m: &M, p: &P) -> P {
+    m.inv_translate(p)
 }
 
 /*
@@ -666,12 +696,6 @@ pub fn dot<V: Dot<N>, N>(a: &V, b: &V) -> N {
     Dot::dot(a, b)
 }
 
-/// Computes a subtraction followed by a dot product.
-#[inline(always)]
-pub fn sub_dot<V: Dot<N>, N>(a: &V, b: &V, c: &V) -> N {
-    Dot::sub_dot(a, b, c)
-}
-
 /*
  * Norm<N>
  */
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<V: Dot<N>, 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<V: Dot<N>, N>(a: &V, b: &V, c: &V) -> N {
-    super::sub_dot(a, b, c)
-}
-
 /*
  * Norm<N>
  */
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<N>, b: &$dvec<N>, c: &$dvec<N>) -> 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<N: Float + Clone> Norm<N> for $dvec<N> {
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<N: Num + Clone> $tmul<N, $tv<N>> for $tv<N> {
             #[inline]
             fn binop(left: &$t<N>, right: &$tv<N>) -> $tv<N> {
-                left.translation + left.rotation * *right
+                left.rotation * *right
             }
         }
     )
 )
 
 macro_rules! vec_mul_iso_impl(
+    ($t: ident, $tv: ident, $tmul: ident) => (
+        impl<N: Clone + Num> $tmul<N, $tv<N>> for $t<N> {
+            #[inline]
+            fn binop(left: &$tv<N>, right: &$t<N>) -> $tv<N> {
+                left * right.rotation
+            }
+        }
+    )
+)
+
+macro_rules! iso_mul_pnt_impl(
+    ($t: ident, $tv: ident, $tmul: ident) => (
+        impl<N: Num + Clone> $tmul<N, $tv<N>> for $tv<N> {
+            #[inline]
+            fn binop(left: &$t<N>, right: &$tv<N>) -> $tv<N> {
+                left.rotation * *right + left.translation
+            }
+        }
+    )
+)
+
+macro_rules! pnt_mul_iso_impl(
     ($t: ident, $tv: ident, $tmul: ident) => (
         impl<N: Clone + Num> $tmul<N, $tv<N>> for $t<N> {
             #[inline]
@@ -254,16 +276,49 @@ macro_rules! transformation_impl(
 )
 
 macro_rules! transform_impl(
-    ($t: ident, $tv: ident) => (
-        impl<N: Num + Clone> Transform<$tv<N>> for $t<N> {
+    ($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<N> {
+            fn transform(left: &$t<N>, right: &Self) -> Self;
+            fn inv_transform(left: &$t<N>, right: &Self) -> Self;
+        }
+
+        impl<N, V: $trhs<N>> Transform<V> for $t<N> {
+            #[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<N: Num + Clone> $trhs<N> for $tv<N> {
             #[inline]
-            fn transform(&self, v: &$tv<N>) -> $tv<N> {
-                self.rotation.transform(v) + self.translation
+            fn transform(t: &$t<N>, v: &$tv<N>) -> $tv<N> {
+                t.rotation.transform(v)
             }
 
             #[inline]
-            fn inv_transform(&self, v: &$tv<N>) -> $tv<N> {
-                self.rotation.inv_transform(&(v - self.translation))
+            fn inv_transform(t: &$t<N>, v: &$tv<N>) -> $tv<N> {
+                t.rotation.inv_transform(v)
+            }
+        }
+
+        impl<N: Num + Clone> $trhs<N> for $tp<N> {
+            #[inline]
+            fn transform(t: &$t<N>, p: &$tp<N>) -> $tp<N> {
+                t.rotation.transform(p) + t.translation
+            }
+
+            #[inline]
+            fn inv_transform(t: &$t<N>, p: &$tp<N>) -> $tp<N> {
+                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<N: Clone + Num> $trhs<N, $v<N>> for $t<N> {
         #[inline]
         fn binop(left: &$v<N>, right: &$t<N>) -> $v<N> {
-            let mut res : $v<N> = Zero::zero();
+            let mut res : $v<N> = $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<N: Clone + Num> $trhs<N, $v<N>> for $v<N> {
         #[inline]
         fn binop(left: &$t<N>, right: &$v<N>) -> $v<N> {
-            let mut res : $v<N> = Zero::zero();
+            let mut res : $v<N> = $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<N: Clone + Num>
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<N>;
+
+impl<N> Pnt0<N> {
+    /// Creates a new vector.
+    #[inline]
+    pub fn new() -> Pnt0<N> {
+        Pnt0
+    }
+
+    /// Creates a new vector. The parameter is not taken in account.
+    #[inline]
+    pub fn new_repeat(_: N) -> Pnt0<N> {
+        Pnt0
+    }
+}
+
+/// Point of dimension 1.
+#[deriving(Eq, PartialEq, Encodable, Decodable, Clone, Hash, Rand, Show)]
+pub struct Pnt1<N> {
+    /// 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<N> {
+    /// 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<N> {
+    /// 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<N> {
+    /// 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<N> {
+    /// 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<N> {
+    /// 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<N: Zero> Orig for $t<N> {
+            #[inline]
+            fn orig() -> $t<N> {
+                $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<N: Sub<N, N>> $trhs<N, $tv<N>> for $t<N> {
+            #[inline]
+            fn binop(left: &$t<N>, right: &$t<N>) -> $tv<N> {
+                *left.as_vec() - *right.as_vec()
+            }
+        }
+    )
+)
+
+macro_rules! pnt_add_vec_impl(
+    ($t: ident, $tv: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
+        impl<N: Add<N, N>> $trhs<N, $t<N>> for $tv<N> {
+            #[inline]
+            fn binop(left: &$t<N>, right: &$tv<N>) -> $t<N> {
+                $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<N: Sub<N, N>> $trhs<N, $t<N>> for $tv<N> {
+            #[inline]
+            fn binop(left: &$t<N>, right: &$tv<N>) -> $t<N> {
+                $t::new(left.$comp0 - right.$comp0 $(, left.$compN - right.$compN)*)
+            }
+        }
+    )
+)
+
+macro_rules! pnt_as_vec_impl(
+    ($t: ident, $tv: ident) => (
+        impl<N> $t<N> {
+            #[inline]
+            pub fn as_vec<'a>(&'a self) -> &'a $tv<N> {
+                unsafe {
+                    mem::transmute(self)
+                }
+            }
+        }
+
+        impl<N> PntAsVec<$tv<N>> for $t<N> {
+            #[inline]
+            fn as_vec<'a>(&'a self) -> &'a $tv<N> {
+                self.as_vec()
+            }
+        }
+    )
+)
+
+macro_rules! pnt_to_homogeneous_impl(
+    ($t: ident, $t2: ident, $extra: ident, $comp0: ident $(,$compN: ident)*) => (
+        impl<N: Clone + One + Zero> ToHomogeneous<$t2<N>> for $t<N> {
+            fn to_homogeneous(v: &$t<N>) -> $t2<N> {
+                let mut res: $t2<N> = 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<N: Clone + Div<N, N> + One + Zero> FromHomogeneous<$t2<N>> for $t<N> {
+            fn from(v: &$t2<N>) -> $t<N> {
+                let mut res: $t<N> = 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<N: Clone + FloatMath + Neg<N>> Rot2<N> {
     }
 }
 
-impl<N: FloatMath + Clone>
-Rotation<Vec1<N>> for Rot2<N> {
+impl<N: FloatMath + Clone> Rotation<Vec1<N>> for Rot2<N> {
     #[inline]
     fn rotation(&self) -> Vec1<N> {
         Vec1::new((-self.submat.m12).atan2(self.submat.m11.clone()))
@@ -353,12 +353,14 @@ Rotation<Vec4<N>> for Rot4<N> {
 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<N: Num + Clone> Rotate<$tv<N>> for $t<N> {
+    ($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<N> {
+            fn rotate(left: &$t<N>, right: &Self) -> Self;
+            fn inv_rotate(left: &$t<N>, right: &Self) -> Self;
+        }
+
+        impl<N, V: $trhs<N>> Rotate<V> for $t<N> {
+            #[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<N: Num + Clone> $trhs<N> for $tv<N> {
             #[inline]
-            fn rotate(&self, v: &$tv<N>) -> $tv<N> {
-                self * *v
+            fn rotate(t: &$t<N>, v: &$tv<N>) -> $tv<N> {
+                t * *v
             }
 
             #[inline]
-            fn inv_rotate(&self, v: &$tv<N>) -> $tv<N> {
-                v * *self
+            fn inv_rotate(t: &$t<N>, v: &$tv<N>) -> $tv<N> {
+                v * *t
+            }
+        }
+
+        impl<N: Num + Clone> $trhs<N> for $tp<N> {
+            #[inline]
+            fn rotate(t: &$t<N>, p: &$tp<N>) -> $tp<N> {
+                t * *p
+            }
+
+            #[inline]
+            fn inv_rotate(t: &$t<N>, p: &$tp<N>) -> $tp<N> {
+                p * *t
             }
         }
     )
 )
 
 macro_rules! transform_impl(
-    ($t: ident, $tv: ident) => (
-        impl<N: Num + Clone> Transform<$tv<N>> for $t<N> {
+    ($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<N> {
+            fn transform(left: &$t<N>, right: &Self) -> Self;
+            fn inv_transform(left: &$t<N>, right: &Self) -> Self;
+        }
+
+        impl<N, V: $trhs<N>> Transform<V> for $t<N> {
+            #[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<N: Num + Clone> $trhs<N> for $tv<N> {
             #[inline]
-            fn transform(&self, v: &$tv<N>) -> $tv<N> {
-                self.rotate(v)
+            fn transform(t: &$t<N>, v: &$tv<N>) -> $tv<N> {
+                t.rotate(v)
             }
 
             #[inline]
-            fn inv_transform(&self, v: &$tv<N>) -> $tv<N> {
-                self.inv_rotate(v)
+            fn inv_transform(t: &$t<N>, v: &$tv<N>) -> $tv<N> {
+                t.inv_rotate(v)
+            }
+        }
+
+        impl<N: Num + Clone> $trhs<N> for $tp<N> {
+            #[inline]
+            fn transform(t: &$t<N>, p: &$tp<N>) -> $tp<N> {
+                t.rotate(p)
+            }
+
+            #[inline]
+            fn inv_transform(t: &$t<N>, p: &$tp<N>) -> $tp<N> {
+                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<N: Num + Clone> $mulrhs<N, $tv<N>> for $t<N> {
@@ -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<N: Clone> Inv for $t<N> {
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<N: Mul<N, N> + Add<N, N>> Mat2MulRhs<N, Vec2<N>> for Vec2<N> {
         )
     }
 }
+
+impl<N: Mul<N, N> + Add<N, N>> Mat3MulRhs<N, Pnt3<N>> for Pnt3<N> {
+    #[inline(always)]
+    fn binop(left: &Mat3<N>, right: &Pnt3<N>) -> Pnt3<N> {
+        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<N: Mul<N, N> + Add<N, N>> Pnt3MulRhs<N, Pnt3<N>> for Mat3<N> {
+    #[inline(always)]
+    fn binop(left: &Pnt3<N>, right: &Mat3<N>) -> Pnt3<N> {
+        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<N: Mul<N, N> + Add<N, N>> Pnt2MulRhs<N, Pnt2<N>> for Mat2<N> {
+    #[inline(always)]
+    fn binop(left: &Pnt2<N>, right: &Mat2<N>) -> Pnt2<N> {
+        Pnt2::new(
+            left.x * right.m11 + left.y * right.m21,
+            left.x * right.m12 + left.y * right.m22
+        )
+    }
+}
+
+impl<N: Mul<N, N> + Add<N, N>> Mat2MulRhs<N, Pnt2<N>> for Pnt2<N> {
+    #[inline(always)]
+    fn binop(left: &Mat2<N>, right: &Pnt2<N>) -> Pnt2<N> {
+        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<N: Num> Dot<N> for vec::Vec0<N> {
     fn dot(_: &vec::Vec0<N>, _: &vec::Vec0<N>) -> N {
         Zero::zero()
     }
-
-    #[inline]
-    fn sub_dot(_: &vec::Vec0<N>, _: &vec::Vec0<N>, _: &vec::Vec0<N>) -> N {
-        Zero::zero()
-    }
 }
 
 impl<N, T> Mul<T, vec::Vec0<N>> for vec::Vec0<N> {
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<N>, b: &$t<N>) -> N {
                 a.$comp0 * b.$comp0 $(+ a.$compN * b.$compN )*
             }
-
-            #[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 )*
-            }
         }
     )
 )
@@ -608,7 +603,7 @@ macro_rules! to_homogeneous_impl(
     ($t: ident, $t2: ident, $extra: ident, $comp0: ident $(,$compN: ident)*) => (
         impl<N: Clone + One + Zero> ToHomogeneous<$t2<N>> for $t<N> {
             fn to_homogeneous(v: &$t<N>) -> $t2<N> {
-                let mut res: $t2<N> = One::one();
+                let mut res: $t2<N> = 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<N>) -> $t<N> {
                 let mut res: $t<N> = 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<N: Add<N, N> + Sub<N, N>> Translate<$t<N>> for $t<N> {
+    ($tv: ident, $t: ident) => (
+        impl<N: Add<N, N> + Sub<N, N>> Translate<$t<N>> for $tv<N> {
             fn translate(&self, other: &$t<N>) -> $t<N> {
                 *other + *self
             }
@@ -663,8 +658,8 @@ macro_rules! rotate_impl(
 )
 
 macro_rules! transform_impl(
-    ($t: ident) => (
-        impl<N: Clone + Add<N, N> + Sub<N, N>> Transform<$t<N>> for $t<N> {
+    ($tv: ident, $t: ident) => (
+        impl<N: Clone + Add<N, N> + Sub<N, N>> Transform<$t<N>> for $tv<N> {
             fn transform(&self, other: &$t<N>) -> $t<N> {
                 self.translate(other)
             }
@@ -673,5 +668,35 @@ macro_rules! transform_impl(
                 self.inv_translate(other)
             }
         }
+
+        impl<N: Clone> Transform<$tv<N>> for $tv<N> {
+            fn transform(&self, other: &$tv<N>) -> $tv<N> {
+                other.clone()
+            }
+
+            fn inv_transform(&self, other: &$tv<N>) -> $tv<N> {
+                other.clone()
+            }
+        }
+    )
+)
+
+macro_rules! vec_as_pnt_impl(
+    ($tv: ident, $t: ident) => (
+        impl<N> $tv<N> {
+            #[inline]
+            pub fn as_pnt<'a>(&'a self) -> &'a $t<N> {
+                unsafe {
+                    mem::transmute(self)
+                }
+            }
+        }
+
+        impl<N> VecAsPnt<$t<N>> for $tv<N> {
+            #[inline]
+            fn as_pnt<'a>(&'a self) -> &'a $t<N> {
+                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<N> {
     /// 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<Vin, Vout> {
+    /// 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<T> {
@@ -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<N>: Dim + Sub<Self, Self> + Add<Self, Self> + Neg<Self> + Zero + PartialEq + Mul<N, Self>
-                     + Div<N, Self> + Dot<N> {
-}
-
-/// Trait of vector with components implementing the `Float` trait.
-pub trait FloatVec<N: Float>: AnyVec<N> + Norm<N> {
-}
-
-/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
-/// operations on vectors.
-pub trait VecExt<N>: AnyVec<N> + Indexable<uint, N> + Iterable<N> +
-                     UniformSphereSample + ScalarAdd<N> + ScalarSub<N> + Bounded
-{ }
-
-/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
-/// operations on vectors.
-pub trait FloatVecExt<N: Float>: FloatVec<N> + VecExt<N> + Basis { }
-
-impl<N, V: Dim + Sub<V, V> + Add<V, V> + Neg<V> + Zero + PartialEq + Mul<N, V> + Div<N, V> + Dot<N>>
-AnyVec<N> for V { }
-
-impl<N: Float, V: AnyVec<N> + Norm<N>> FloatVec<N> for V { }
-
-impl<N,
-     V: AnyVec<N> + Indexable<uint, N> + Iterable<N> +
-        UniformSphereSample + ScalarAdd<N> + ScalarSub<N> + Bounded>
-VecExt<N> for V { }
-
-impl<N: Float, V: FloatVec<N> + VecExt<N> + Basis> FloatVecExt<N> 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<N> {
     /// 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<P> {
+    /// 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<N>: Dim + Sub<Self, Self> + Add<Self, Self> + Neg<Self> + Zero + PartialEq + Mul<N, Self>
+                     + Div<N, Self> + Dot<N> {
+}
+
+/// Trait of vector with components implementing the `Float` trait.
+pub trait FloatVec<N: Float>: AnyVec<N> + Norm<N> {
+}
+
+/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
+/// operations on vectors.
+pub trait VecExt<N>: AnyVec<N> + Indexable<uint, N> + Iterable<N> +
+                     UniformSphereSample + ScalarAdd<N> + ScalarSub<N> + Bounded
+{ }
+
+/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
+/// operations on vectors.
+pub trait FloatVecExt<N: Float>: FloatVec<N> + VecExt<N> + Basis { }
+
+impl<N, V: Dim + Sub<V, V> + Add<V, V> + Neg<V> + Zero + PartialEq + Mul<N, V> + Div<N, V> + Dot<N>>
+AnyVec<N> for V { }
+
+impl<N: Float, V: AnyVec<N> + Norm<N>> FloatVec<N> for V { }
+
+impl<N,
+     V: AnyVec<N> + Indexable<uint, N> + Iterable<N> +
+        UniformSphereSample + ScalarAdd<N> + ScalarSub<N> + Bounded>
+VecExt<N> for V { }
+
+impl<N: Float, V: FloatVec<N> + VecExt<N> + Basis> FloatVecExt<N> 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<V> {
+    /// 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<N, V>:
+          PntAsVec<V> + Dim + Sub<Self, V> + Orig + Neg<Self> + PartialEq + Mul<N, Self> + Div<N, Self> {
+}
+
+/// Trait of points with components implementing the `Float` trait.
+pub trait FloatPnt<N: Float, V: Norm<N>>: AnyPnt<N, V> {
+    /// 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<N, V>: AnyPnt<N, V> + Indexable<uint, N> + Iterable<N> +
+                        ScalarAdd<N> + ScalarSub<N> + Bounded
+{ }
+
+/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
+/// operations on points.
+pub trait FloatPntExt<N: Float, V: Norm<N>> : FloatPnt<N, V> + PntExt<N, V> { }
+
+
+impl<N, V, P: PntAsVec<V> + Dim + Sub<P, V> + Orig + Neg<P> + PartialEq + Mul<N, P> + Div<N, P>>
+AnyPnt<N, V> for P { }
+impl<N: Float, V: Norm<N>, P: AnyPnt<N, V>> FloatPnt<N, V> for P { }
+impl<N, V, P: AnyPnt<N, V> + Indexable<uint, N> + Iterable<N> + ScalarAdd<N> + ScalarSub<N> + Bounded>
+PntExt<N, V> for P { }
+impl<N: Float, V: Norm<N>, P: FloatPnt<N, V> + PntExt<N, V>> FloatPntExt<N, V> for P { }