diff --git a/src/array.rs b/src/array.rs index e60234f..821cdc4 100644 --- a/src/array.rs +++ b/src/array.rs @@ -135,3 +135,14 @@ pub trait Array2, Row: Array1, Element: Copy>: /// Apply a function to each column. fn map(&mut self, op: |&Column| -> Column) -> Self; } + +/// Homogeneous arrays of elements that can be converted to and from `[T, ..N]` +/// arrays. +pub trait FixedArray { + fn into_fixed(self) -> V; + fn as_fixed<'a>(&'a self) -> &'a V; + fn as_mut_fixed<'a>(&'a mut self) -> &'a mut V; + fn from_fixed(v: V) -> Self; + fn from_fixed_ref<'a>(v: &'a V) -> &'a Self; + fn from_fixed_mut<'a>(v: &'a mut V) -> &'a mut Self; +} diff --git a/src/matrix.rs b/src/matrix.rs index 0e42821..5f62fcb 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -21,7 +21,7 @@ use std::num::{Zero, zero, One, one, cast}; use angle::{Rad, sin, cos, sin_cos}; use approx::ApproxEq; -use array::{Array1, Array2}; +use array::{Array1, Array2, FixedArray}; use num::{BaseFloat, BaseNum}; use point::{Point, Point3}; use quaternion::{Quaternion, ToQuaternion}; @@ -393,6 +393,63 @@ impl One for Matrix2 { #[inline] fn one() -> Matrix2 { Matri impl One for Matrix3 { #[inline] fn one() -> Matrix3 { Matrix3::identity() } } impl One for Matrix4 { #[inline] fn one() -> Matrix4 { Matrix4::identity() } } +impl FixedArray<[[S, ..2], ..2]> for Matrix2 { + #[inline] + fn into_fixed(self) -> [[S, ..2], ..2] { + match self { + Matrix2 { x, y } => [ + x.into_fixed(), + y.into_fixed(), + ], + } + } + + #[inline] + fn as_fixed<'a>(&'a self) -> &'a [[S, ..2], ..2] { + unsafe { mem::transmute(self) } + } + + #[inline] + fn as_mut_fixed<'a>(&'a mut self) -> &'a mut [[S, ..2], ..2] { + unsafe { mem::transmute(self) } + } + + #[inline] + fn from_fixed(_v: [[S, ..2], ..2]) -> Matrix2 { + // match v { + // [x, y] => Matrix2 { + // x: FixedArray::from_fixed(x), + // y: FixedArray::from_fixed(y), + // }, + // } + fail!("Unimplemented, pending a fix for rust-lang/rust#16418") + } + + #[inline] + fn from_fixed_ref<'a>(v: &'a [[S, ..2], ..2]) -> &'a Matrix2 { + unsafe { mem::transmute(v) } + } + + #[inline] + fn from_fixed_mut<'a>(v: &'a mut [[S, ..2], ..2]) -> &'a mut Matrix2 { + unsafe { mem::transmute(v) } + } +} + +impl Index> for Matrix2 { + #[inline] + fn index<'a>(&'a self, i: &uint) -> &'a Vector2 { + FixedArray::from_fixed_ref(&self.as_fixed()[*i]) + } +} + +impl IndexMut> for Matrix2 { + #[inline] + fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut Vector2 { + FixedArray::from_fixed_mut(&mut self.as_mut_fixed()[*i]) + } +} + impl Array2, Vector2, S> for Matrix2 { #[inline] fn row(&self, r: uint) -> Vector2 { @@ -414,19 +471,62 @@ impl Array2, Vector2, S> for Matrix2 { } } -impl Index> for Matrix2 { +impl FixedArray<[[S, ..3], ..3]> for Matrix3 { #[inline] - fn index<'a>(&'a self, c: &uint) -> &'a Vector2 { - let slice: &'a [Vector2, ..2] = unsafe { mem::transmute(self) }; - &slice[*c] + fn into_fixed(self) -> [[S, ..3], ..3] { + match self { + Matrix3 { x, y, z } => [ + x.into_fixed(), + y.into_fixed(), + z.into_fixed(), + ], + } + } + + #[inline] + fn as_fixed<'a>(&'a self) -> &'a [[S, ..3], ..3] { + unsafe { mem::transmute(self) } + } + + #[inline] + fn as_mut_fixed<'a>(&'a mut self) -> &'a mut [[S, ..3], ..3] { + unsafe { mem::transmute(self) } + } + + #[inline] + fn from_fixed(_v: [[S, ..3], ..3]) -> Matrix3 { + // match v { + // [x, y, z] => Matrix3 { + // x: FixedArray::from_fixed(x), + // y: FixedArray::from_fixed(y), + // z: FixedArray::from_fixed(z), + // }, + // } + fail!("Unimplemented, pending a fix for rust-lang/rust#16418") + } + + #[inline] + fn from_fixed_ref<'a>(v: &'a [[S, ..3], ..3]) -> &'a Matrix3 { + unsafe { mem::transmute(v) } + } + + #[inline] + fn from_fixed_mut<'a>(v: &'a mut [[S, ..3], ..3]) -> &'a mut Matrix3 { + unsafe { mem::transmute(v) } } } -impl IndexMut> for Matrix2 { +impl Index> for Matrix3 { #[inline] - fn index_mut<'a>(&'a mut self, c: &uint) -> &'a mut Vector2 { - let slice: &'a mut [Vector2, ..2] = unsafe { mem::transmute(self) }; - &mut slice[*c] + fn index<'a>(&'a self, i: &uint) -> &'a Vector3 { + FixedArray::from_fixed_ref(&self.as_fixed()[*i]) + } +} + +impl IndexMut> for Matrix3 { + #[inline] + fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut Vector3 { + FixedArray::from_fixed_mut(&mut self.as_mut_fixed()[*i]) } } @@ -454,19 +554,64 @@ impl Array2, Vector3, S> for Matrix3 { } } -impl Index> for Matrix3 { +impl FixedArray<[[S, ..4], ..4]> for Matrix4 { #[inline] - fn index<'a>(&'a self, c: &uint) -> &'a Vector3 { - let slice: &'a [Vector3, ..3] = unsafe { mem::transmute(self) }; - &slice[*c] + fn into_fixed(self) -> [[S, ..4], ..4] { + match self { + Matrix4 { x, y, z, w } => [ + x.into_fixed(), + y.into_fixed(), + z.into_fixed(), + w.into_fixed(), + ], + } + } + + #[inline] + fn as_fixed<'a>(&'a self) -> &'a [[S, ..4], ..4] { + unsafe { mem::transmute(self) } + } + + #[inline] + fn as_mut_fixed<'a>(&'a mut self) -> &'a mut [[S, ..4], ..4] { + unsafe { mem::transmute(self) } + } + + #[inline] + fn from_fixed(_v: [[S, ..4], ..4]) -> Matrix4 { + // match v { + // [x, y, z, w] => Matrix4 { + // x: FixedArray::from_fixed(x), + // y: FixedArray::from_fixed(y), + // z: FixedArray::from_fixed(z), + // w: FixedArray::from_fixed(w), + // }, + // } + fail!("Unimplemented, pending a fix for rust-lang/rust#16418") + } + + #[inline] + fn from_fixed_ref<'a>(v: &'a [[S, ..4], ..4]) -> &'a Matrix4 { + unsafe { mem::transmute(v) } + } + + #[inline] + fn from_fixed_mut<'a>(v: &'a mut [[S, ..4], ..4]) -> &'a mut Matrix4 { + unsafe { mem::transmute(v) } } } -impl IndexMut> for Matrix3 { +impl Index> for Matrix4 { #[inline] - fn index_mut<'a>(&'a mut self, c: &uint) -> &'a mut Vector3 { - let slice: &'a mut [Vector3, ..3] = unsafe { mem::transmute(self) }; - &mut slice[*c] + fn index<'a>(&'a self, i: &uint) -> &'a Vector4 { + FixedArray::from_fixed_ref(&self.as_fixed()[*i]) + } +} + +impl IndexMut> for Matrix4 { + #[inline] + fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut Vector4 { + FixedArray::from_fixed_mut(&mut self.as_mut_fixed()[*i]) } } @@ -497,22 +642,6 @@ impl Array2, Vector4, S> for Matrix4 { } } -impl Index> for Matrix4 { - #[inline] - fn index<'a>(&'a self, c: &uint) -> &'a Vector4 { - let slice: &'a [Vector4, ..4] = unsafe { mem::transmute(self) }; - &slice[*c] - } -} - -impl IndexMut> for Matrix4 { - #[inline] - fn index_mut<'a>(&'a mut self, c: &uint) -> &'a mut Vector4 { - let slice: &'a mut [Vector4, ..4] = unsafe { mem::transmute(self) }; - &mut slice[*c] - } -} - impl Matrix> for Matrix2 { #[inline] fn mul_s(&self, s: S) -> Matrix2 { diff --git a/src/point.rs b/src/point.rs index 16ec84d..cb7390c 100644 --- a/src/point.rs +++ b/src/point.rs @@ -22,7 +22,7 @@ use std::mem; use std::num::{one, zero}; use approx::ApproxEq; -use array::Array1; +use array::{Array1, FixedArray}; use num::{BaseNum, BaseFloat}; use vector::*; @@ -102,28 +102,59 @@ pub trait Point>: Array1 + Clone { fn max(&self, p: &Self) -> Self; } -impl Array1 for Point2 { +impl FixedArray<[S, ..2]> for Point2 { #[inline] - fn map(&mut self, op: |S| -> S) -> Point2 { - self.x = op(self.x); - self.y = op(self.y); - *self + fn into_fixed(self) -> [S, ..2] { + match self { Point2 { x, y } => [x, y] } + } + + #[inline] + fn as_fixed<'a>(&'a self) -> &'a [S, ..2] { + unsafe { mem::transmute(self) } + } + + #[inline] + fn as_mut_fixed<'a>(&'a mut self) -> &'a mut [S, ..2] { + unsafe { mem::transmute(self) } + } + + #[inline] + fn from_fixed(_v: [S, ..2]) -> Point2 { + // match v { [x, y] => Point2 { x: x, y: y } } + fail!("Unimplemented, pending a fix for rust-lang/rust#16418") + } + + #[inline] + fn from_fixed_ref<'a>(v: &'a [S, ..2]) -> &'a Point2 { + unsafe { mem::transmute(v) } + } + + #[inline] + fn from_fixed_mut<'a>(v: &'a mut [S, ..2]) -> &'a mut Point2 { + unsafe { mem::transmute(v) } } } impl Index for Point2 { #[inline] fn index<'a>(&'a self, i: &uint) -> &'a S { - let slice: &[S, ..2] = unsafe { mem::transmute(self) }; - &slice[*i] + &self.as_fixed()[*i] } } impl IndexMut for Point2 { #[inline] fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut S { - let slice: &'a mut [S, ..2] = unsafe { mem::transmute(self) }; - &mut slice[*i] + &mut self.as_mut_fixed()[*i] + } +} + +impl Array1 for Point2 { + #[inline] + fn map(&mut self, op: |S| -> S) -> Point2 { + self.x = op(self.x); + self.y = op(self.y); + *self } } @@ -225,6 +256,53 @@ impl ApproxEq for Point2 { } } +impl FixedArray<[S, ..3]> for Point3 { + #[inline] + fn into_fixed(self) -> [S, ..3] { + match self { Point3 { x, y, z } => [x, y, z] } + } + + #[inline] + fn as_fixed<'a>(&'a self) -> &'a [S, ..3] { + unsafe { mem::transmute(self) } + } + + #[inline] + fn as_mut_fixed<'a>(&'a mut self) -> &'a mut [S, ..3] { + unsafe { mem::transmute(self) } + } + + #[inline] + fn from_fixed(_v: [S, ..3]) -> Point3 { + // match v { [x, y, z] => Point3 { x: x, y: y, z: z } } + fail!("Unimplemented, pending a fix for rust-lang/rust#16418") + } + + #[inline] + fn from_fixed_ref<'a>(v: &'a [S, ..3]) -> &'a Point3 { + unsafe { mem::transmute(v) } + } + + #[inline] + fn from_fixed_mut<'a>(v: &'a mut [S, ..3]) -> &'a mut Point3 { + unsafe { mem::transmute(v) } + } +} + +impl Index for Point3 { + #[inline] + fn index<'a>(&'a self, i: &uint) -> &'a S { + &self.as_fixed()[*i] + } +} + +impl IndexMut for Point3 { + #[inline] + fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut S { + &mut self.as_mut_fixed()[*i] + } +} + impl Array1 for Point3 { #[inline] fn map(&mut self, op: |S| -> S) -> Point3 { @@ -235,22 +313,6 @@ impl Array1 for Point3 { } } -impl Index for Point3 { - #[inline] - fn index<'a>(&'a self, i: &uint) -> &'a S { - let slice: &[S, ..3] = unsafe { mem::transmute(self) }; - &slice[*i] - } -} - -impl IndexMut for Point3 { - #[inline] - fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut S { - let slice: &'a mut [S, ..3] = unsafe { mem::transmute(self) }; - &mut slice[*i] - } -} - impl Point> for Point3 { #[inline] fn origin() -> Point3 { diff --git a/src/vector.rs b/src/vector.rs index 8d9fda8..5834462 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -105,7 +105,7 @@ use std::num::{Zero, zero, One, one}; use angle::{Rad, atan2, acos}; use approx::ApproxEq; -use array::Array1; +use array::{Array1, FixedArray}; use num::{BaseNum, BaseFloat}; /// A trait that specifies a range of numeric operations for vectors. Not all @@ -212,9 +212,56 @@ macro_rules! vec( pub fn ident() -> $Self<$S> { $Self::from_value(one()) } } - impl Array1 for $Self { + impl<$S> FixedArray<[$S, ..$n]> for $Self<$S> { #[inline] - fn map(&mut self, op: |S| -> S) -> $Self { + fn into_fixed(self) -> [$S, ..$n] { + match self { $Self { $($field),+ } => [$($field),+] } + } + + #[inline] + fn as_fixed<'a>(&'a self) -> &'a [$S, ..$n] { + unsafe { mem::transmute(self) } + } + + #[inline] + fn as_mut_fixed<'a>(&'a mut self) -> &'a mut [$S, ..$n] { + unsafe { mem::transmute(self) } + } + + #[inline] + fn from_fixed(_v: [$S, ..$n]) -> $Self<$S> { + // match v { [$($field),+] => $Self { $($field: $field),+ } } + fail!("Unimplemented, pending a fix for rust-lang/rust#16418") + } + + #[inline] + fn from_fixed_ref<'a>(v: &'a [$S, ..$n]) -> &'a $Self<$S> { + unsafe { mem::transmute(v) } + } + + #[inline] + fn from_fixed_mut<'a>(v: &'a mut [$S, ..$n]) -> &'a mut $Self<$S> { + unsafe { mem::transmute(v) } + } + } + + impl<$S: Copy> Index for $Self<$S> { + #[inline] + fn index<'a>(&'a self, i: &uint) -> &'a $S { + &self.as_fixed()[*i] + } + } + + impl<$S: Copy> IndexMut for $Self<$S> { + #[inline] + fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut $S { + &mut self.as_mut_fixed()[*i] + } + } + + impl<$S: Copy> Array1<$S> for $Self<$S> { + #[inline] + fn map(&mut self, op: |$S| -> $S) -> $Self<$S> { $(self.$field = op(self.$field);)+ *self } } @@ -285,22 +332,6 @@ macro_rules! vec( #[inline] fn one() -> $Self { $Self::from_value(one()) } } - impl Index for $Self { - #[inline] - fn index<'a>(&'a self, i: &uint) -> &'a S { - let slice: &[S, ..$n] = unsafe { mem::transmute(self) }; - &slice[*i] - } - } - - impl IndexMut for $Self { - #[inline] - fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut S { - let slice: &'a mut [S, ..$n] = unsafe { mem::transmute(self) }; - &mut slice[*i] - } - } - impl ApproxEq for $Self { #[inline] fn approx_eq_eps(&self, other: &$Self, epsilon: &S) -> bool {