Add fixed-length array conversions

Closes #111

`FixedArray::from_fixed` cannot yet be implemented due to  rust-lang/rust#16418
This commit is contained in:
Brendan Zabarauskas 2014-08-11 21:10:38 +10:00
parent f93963919a
commit 3ff1eb583f
4 changed files with 311 additions and 78 deletions

View file

@ -135,3 +135,14 @@ pub trait Array2<Column: Array1<Element>, Row: Array1<Element>, 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<V> {
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;
}

View file

@ -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<S: BaseFloat> One for Matrix2<S> { #[inline] fn one() -> Matrix2<S> { Matri
impl<S: BaseFloat> One for Matrix3<S> { #[inline] fn one() -> Matrix3<S> { Matrix3::identity() } }
impl<S: BaseFloat> One for Matrix4<S> { #[inline] fn one() -> Matrix4<S> { Matrix4::identity() } }
impl<S> FixedArray<[[S, ..2], ..2]> for Matrix2<S> {
#[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<S> {
// 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<S> {
unsafe { mem::transmute(v) }
}
#[inline]
fn from_fixed_mut<'a>(v: &'a mut [[S, ..2], ..2]) -> &'a mut Matrix2<S> {
unsafe { mem::transmute(v) }
}
}
impl<S> Index<uint, Vector2<S>> for Matrix2<S> {
#[inline]
fn index<'a>(&'a self, i: &uint) -> &'a Vector2<S> {
FixedArray::from_fixed_ref(&self.as_fixed()[*i])
}
}
impl<S> IndexMut<uint, Vector2<S>> for Matrix2<S> {
#[inline]
fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut Vector2<S> {
FixedArray::from_fixed_mut(&mut self.as_mut_fixed()[*i])
}
}
impl<S: Copy> Array2<Vector2<S>, Vector2<S>, S> for Matrix2<S> {
#[inline]
fn row(&self, r: uint) -> Vector2<S> {
@ -414,19 +471,62 @@ impl<S: Copy> Array2<Vector2<S>, Vector2<S>, S> for Matrix2<S> {
}
}
impl<S: Copy> Index<uint, Vector2<S>> for Matrix2<S> {
impl<S> FixedArray<[[S, ..3], ..3]> for Matrix3<S> {
#[inline]
fn index<'a>(&'a self, c: &uint) -> &'a Vector2<S> {
let slice: &'a [Vector2<S>, ..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<S> {
// 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<S> {
unsafe { mem::transmute(v) }
}
#[inline]
fn from_fixed_mut<'a>(v: &'a mut [[S, ..3], ..3]) -> &'a mut Matrix3<S> {
unsafe { mem::transmute(v) }
}
}
impl<S: Copy> IndexMut<uint, Vector2<S>> for Matrix2<S> {
impl<S> Index<uint, Vector3<S>> for Matrix3<S> {
#[inline]
fn index_mut<'a>(&'a mut self, c: &uint) -> &'a mut Vector2<S> {
let slice: &'a mut [Vector2<S>, ..2] = unsafe { mem::transmute(self) };
&mut slice[*c]
fn index<'a>(&'a self, i: &uint) -> &'a Vector3<S> {
FixedArray::from_fixed_ref(&self.as_fixed()[*i])
}
}
impl<S> IndexMut<uint, Vector3<S>> for Matrix3<S> {
#[inline]
fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut Vector3<S> {
FixedArray::from_fixed_mut(&mut self.as_mut_fixed()[*i])
}
}
@ -454,19 +554,64 @@ impl<S: Copy> Array2<Vector3<S>, Vector3<S>, S> for Matrix3<S> {
}
}
impl<S: Copy> Index<uint, Vector3<S>> for Matrix3<S> {
impl<S> FixedArray<[[S, ..4], ..4]> for Matrix4<S> {
#[inline]
fn index<'a>(&'a self, c: &uint) -> &'a Vector3<S> {
let slice: &'a [Vector3<S>, ..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<S> {
// 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<S> {
unsafe { mem::transmute(v) }
}
#[inline]
fn from_fixed_mut<'a>(v: &'a mut [[S, ..4], ..4]) -> &'a mut Matrix4<S> {
unsafe { mem::transmute(v) }
}
}
impl<S: Copy> IndexMut<uint, Vector3<S>> for Matrix3<S> {
impl<S> Index<uint, Vector4<S>> for Matrix4<S> {
#[inline]
fn index_mut<'a>(&'a mut self, c: &uint) -> &'a mut Vector3<S> {
let slice: &'a mut [Vector3<S>, ..3] = unsafe { mem::transmute(self) };
&mut slice[*c]
fn index<'a>(&'a self, i: &uint) -> &'a Vector4<S> {
FixedArray::from_fixed_ref(&self.as_fixed()[*i])
}
}
impl<S> IndexMut<uint, Vector4<S>> for Matrix4<S> {
#[inline]
fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut Vector4<S> {
FixedArray::from_fixed_mut(&mut self.as_mut_fixed()[*i])
}
}
@ -497,22 +642,6 @@ impl<S: Copy> Array2<Vector4<S>, Vector4<S>, S> for Matrix4<S> {
}
}
impl<S: Copy> Index<uint, Vector4<S>> for Matrix4<S> {
#[inline]
fn index<'a>(&'a self, c: &uint) -> &'a Vector4<S> {
let slice: &'a [Vector4<S>, ..4] = unsafe { mem::transmute(self) };
&slice[*c]
}
}
impl<S: Copy> IndexMut<uint, Vector4<S>> for Matrix4<S> {
#[inline]
fn index_mut<'a>(&'a mut self, c: &uint) -> &'a mut Vector4<S> {
let slice: &'a mut [Vector4<S>, ..4] = unsafe { mem::transmute(self) };
&mut slice[*c]
}
}
impl<S: BaseFloat> Matrix<S, Vector2<S>> for Matrix2<S> {
#[inline]
fn mul_s(&self, s: S) -> Matrix2<S> {

View file

@ -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<S: BaseNum, V: Vector<S>>: Array1<S> + Clone {
fn max(&self, p: &Self) -> Self;
}
impl<S: BaseNum> Array1<S> for Point2<S> {
impl<S> FixedArray<[S, ..2]> for Point2<S> {
#[inline]
fn map(&mut self, op: |S| -> S) -> Point2<S> {
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<S> {
// 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<S> {
unsafe { mem::transmute(v) }
}
#[inline]
fn from_fixed_mut<'a>(v: &'a mut [S, ..2]) -> &'a mut Point2<S> {
unsafe { mem::transmute(v) }
}
}
impl<S: BaseNum> Index<uint, S> for Point2<S> {
#[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<S: BaseNum> IndexMut<uint, S> for Point2<S> {
#[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<S: BaseNum> Array1<S> for Point2<S> {
#[inline]
fn map(&mut self, op: |S| -> S) -> Point2<S> {
self.x = op(self.x);
self.y = op(self.y);
*self
}
}
@ -225,6 +256,53 @@ impl<S: BaseFloat> ApproxEq<S> for Point2<S> {
}
}
impl<S> FixedArray<[S, ..3]> for Point3<S> {
#[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<S> {
// 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<S> {
unsafe { mem::transmute(v) }
}
#[inline]
fn from_fixed_mut<'a>(v: &'a mut [S, ..3]) -> &'a mut Point3<S> {
unsafe { mem::transmute(v) }
}
}
impl<S: BaseNum> Index<uint, S> for Point3<S> {
#[inline]
fn index<'a>(&'a self, i: &uint) -> &'a S {
&self.as_fixed()[*i]
}
}
impl<S: BaseNum> IndexMut<uint, S> for Point3<S> {
#[inline]
fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut S {
&mut self.as_mut_fixed()[*i]
}
}
impl<S: BaseNum> Array1<S> for Point3<S> {
#[inline]
fn map(&mut self, op: |S| -> S) -> Point3<S> {
@ -235,22 +313,6 @@ impl<S: BaseNum> Array1<S> for Point3<S> {
}
}
impl<S: BaseNum> Index<uint, S> for Point3<S> {
#[inline]
fn index<'a>(&'a self, i: &uint) -> &'a S {
let slice: &[S, ..3] = unsafe { mem::transmute(self) };
&slice[*i]
}
}
impl<S: BaseNum> IndexMut<uint, S> for Point3<S> {
#[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<S: BaseNum> Point<S, Vector3<S>> for Point3<S> {
#[inline]
fn origin() -> Point3<S> {

View file

@ -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<S: Copy> Array1<S> for $Self<S> {
impl<$S> FixedArray<[$S, ..$n]> for $Self<$S> {
#[inline]
fn map(&mut self, op: |S| -> S) -> $Self<S> {
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<uint, S> for $Self<$S> {
#[inline]
fn index<'a>(&'a self, i: &uint) -> &'a $S {
&self.as_fixed()[*i]
}
}
impl<$S: Copy> IndexMut<uint, S> 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<S> { $Self::from_value(one()) }
}
impl<S: Copy> Index<uint, S> for $Self<S> {
#[inline]
fn index<'a>(&'a self, i: &uint) -> &'a S {
let slice: &[S, ..$n] = unsafe { mem::transmute(self) };
&slice[*i]
}
}
impl<S: Copy> IndexMut<uint, S> for $Self<S> {
#[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<S: BaseFloat> ApproxEq<S> for $Self<S> {
#[inline]
fn approx_eq_eps(&self, other: &$Self<S>, epsilon: &S) -> bool {