Make array type parameters associated types

This commit is contained in:
Brendan Zabarauskas 2015-11-03 14:15:11 +11:00
parent 0584bcac64
commit a434f18ba4
5 changed files with 53 additions and 20 deletions

View file

@ -18,14 +18,19 @@ use std::ptr;
use std::ops::*; use std::ops::*;
/// An array containing elements of type `Element` /// An array containing elements of type `Element`
pub trait Array1<Element: Copy>: Index<usize, Output=Element> + IndexMut<usize, Output=Element> { pub trait Array1 where
Self: Index<usize, Output = <Self as Array1>::Element>,
Self: IndexMut<usize, Output = <Self as Array1>::Element>,
{
type Element: Copy;
/// Get the pointer to the first element of the array. /// Get the pointer to the first element of the array.
fn ptr<'a>(&'a self) -> &'a Element { fn ptr<'a>(&'a self) -> &'a Self::Element {
&self[0] &self[0]
} }
/// Get a mutable pointer to the first element of the array. /// Get a mutable pointer to the first element of the array.
fn mut_ptr<'a>(&'a mut self) -> &'a mut Element { fn mut_ptr<'a>(&'a mut self) -> &'a mut Self::Element {
&mut self[0] &mut self[0]
} }
@ -38,21 +43,27 @@ pub trait Array1<Element: Copy>: Index<usize, Output=Element> + IndexMut<usize,
/// Replace an element in the array. /// Replace an element in the array.
#[inline] #[inline]
fn replace_elem(&mut self, i: usize, src: Element) -> Element { fn replace_elem(&mut self, i: usize, src: Self::Element) -> Self::Element {
mem::replace(&mut self[i], src) mem::replace(&mut self[i], src)
} }
} }
/// A column-major array /// A column-major array
pub trait Array2<Column: Array1<Element>+'static, Row: Array1<Element>, Element: Copy>: pub trait Array2 where
Index<usize, Output=Column> + IndexMut<usize, Output=Column> { Self: Index<usize, Output = <Self as Array2>::Column>,
Self: IndexMut<usize, Output = <Self as Array2>::Column>,
{
type Element: Copy;
type Column: Array1<Element = Self::Element>;
type Row: Array1<Element = Self::Element>;
/// Get the pointer to the first element of the array. /// Get the pointer to the first element of the array.
fn ptr<'a>(&'a self) -> &'a Element { fn ptr<'a>(&'a self) -> &'a Self::Element {
&self[0][0] &self[0][0]
} }
/// Get a mutable pointer to the first element of the array. /// Get a mutable pointer to the first element of the array.
fn mut_ptr<'a>(&'a mut self) -> &'a mut Element { fn mut_ptr<'a>(&'a mut self) -> &'a mut Self::Element {
&mut self[0][0] &mut self[0][0]
} }
@ -64,12 +75,12 @@ pub trait Array2<Column: Array1<Element>+'static, Row: Array1<Element>, Element:
/// Replace a column in the array. /// Replace a column in the array.
#[inline] #[inline]
fn replace_col(&mut self, c: usize, src: Column) -> Column { fn replace_col(&mut self, c: usize, src: Self::Column) -> Self::Column {
mem::replace(&mut self[c], src) mem::replace(&mut self[c], src)
} }
/// Get a row from this array by-value. /// Get a row from this array by-value.
fn row(&self, r: usize) -> Row; fn row(&self, r: usize) -> Self::Row;
/// Swap two rows of this array. /// Swap two rows of this array.
fn swap_rows(&mut self, a: usize, b: usize); fn swap_rows(&mut self, a: usize, b: usize);

View file

@ -249,7 +249,9 @@ impl<S: Copy + Neg<Output = S>> Matrix4<S> {
} }
} }
pub trait Matrix<S: BaseFloat, V: Vector<S> + 'static>: Array2<V, V, S> + ApproxEq<Epsilon = S> + Sized // where pub trait Matrix<S: BaseFloat, V: Vector<S>> where
Self: Array2<Element = S, Column = V, Row = V>,
Self: ApproxEq<Epsilon = S> + Sized,
// FIXME: blocked by rust-lang/rust#20671 // FIXME: blocked by rust-lang/rust#20671
// //
// for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>, // for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>,
@ -359,7 +361,11 @@ pub trait Matrix<S: BaseFloat, V: Vector<S> + 'static>: Array2<V, V, S> + Approx
fn is_symmetric(&self) -> bool; fn is_symmetric(&self) -> bool;
} }
impl<S: Copy + 'static> Array2<Vector2<S>, Vector2<S>, S> for Matrix2<S> { impl<S: Copy + 'static> Array2 for Matrix2<S> {
type Element = S;
type Column = Vector2<S>;
type Row = Vector2<S>;
#[inline] #[inline]
fn row(&self, r: usize) -> Vector2<S> { fn row(&self, r: usize) -> Vector2<S> {
Vector2::new(self[0][r], Vector2::new(self[0][r],
@ -373,7 +379,11 @@ impl<S: Copy + 'static> Array2<Vector2<S>, Vector2<S>, S> for Matrix2<S> {
} }
} }
impl<S: Copy + 'static> Array2<Vector3<S>, Vector3<S>, S> for Matrix3<S> { impl<S: Copy + 'static> Array2 for Matrix3<S> {
type Element = S;
type Column = Vector3<S>;
type Row = Vector3<S>;
#[inline] #[inline]
fn row(&self, r: usize) -> Vector3<S> { fn row(&self, r: usize) -> Vector3<S> {
Vector3::new(self[0][r], Vector3::new(self[0][r],
@ -389,7 +399,11 @@ impl<S: Copy + 'static> Array2<Vector3<S>, Vector3<S>, S> for Matrix3<S> {
} }
} }
impl<S: Copy + 'static> Array2<Vector4<S>, Vector4<S>, S> for Matrix4<S> { impl<S: Copy + 'static> Array2 for Matrix4<S> {
type Element = S;
type Column = Vector4<S>;
type Row = Vector4<S>;
#[inline] #[inline]
fn row(&self, r: usize) -> Vector4<S> { fn row(&self, r: usize) -> Vector4<S> {
Vector4::new(self[0][r], Vector4::new(self[0][r],

View file

@ -66,7 +66,7 @@ impl<S: BaseNum> Point3<S> {
} }
/// Specifies the numeric operations for point types. /// Specifies the numeric operations for point types.
pub trait Point<S: BaseNum>: Array1<S> + Clone // where pub trait Point<S: BaseNum>: Array1<Element = S> + Clone // where
// FIXME: blocked by rust-lang/rust#20671 // FIXME: blocked by rust-lang/rust#20671
// //
// for<'a, 'b> &'a Self: Add<&'b V, Output = Self>, // for<'a, 'b> &'a Self: Add<&'b V, Output = Self>,
@ -123,7 +123,9 @@ pub trait Point<S: BaseNum>: Array1<S> + Clone // where
fn max(&self, p: &Self) -> Self; fn max(&self, p: &Self) -> Self;
} }
impl<S: BaseNum> Array1<S> for Point2<S> {} impl<S: BaseNum> Array1 for Point2<S> {
type Element = S;
}
impl<S: BaseNum> Point<S> for Point2<S> { impl<S: BaseNum> Point<S> for Point2<S> {
type Vector = Vector2<S>; type Vector = Vector2<S>;
@ -200,7 +202,9 @@ impl<S: BaseFloat> ApproxEq for Point2<S> {
} }
} }
impl<S: BaseNum> Array1<S> for Point3<S> {} impl<S: BaseNum> Array1 for Point3<S> {
type Element = S;
}
impl<S: BaseNum> Point<S> for Point3<S> { impl<S: BaseNum> Point<S> for Point3<S> {
type Vector = Vector3<S>; type Vector = Vector3<S>;

View file

@ -40,7 +40,9 @@ pub struct Quaternion<S> {
pub v: Vector3<S>, pub v: Vector3<S>,
} }
impl<S: Copy + BaseFloat> Array1<S> for Quaternion<S> {} impl<S: Copy + BaseFloat> Array1 for Quaternion<S> {
type Element = S;
}
impl<S: BaseFloat> Quaternion<S> { impl<S: BaseFloat> Quaternion<S> {
/// Construct a new quaternion from one scalar component and three /// Construct a new quaternion from one scalar component and three

View file

@ -111,7 +111,7 @@ use num::{BaseNum, BaseFloat};
/// A trait that specifies a range of numeric operations for vectors. Not all /// A trait that specifies a range of numeric operations for vectors. Not all
/// of these make sense from a linear algebra point of view, but are included /// of these make sense from a linear algebra point of view, but are included
/// for pragmatic reasons. /// for pragmatic reasons.
pub trait Vector<S: BaseNum>: Array1<S> + Clone // where pub trait Vector<S: BaseNum>: Array1<Element = S> + Clone // where
// FIXME: blocked by rust-lang/rust#20671 // FIXME: blocked by rust-lang/rust#20671
// //
// for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>, // for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>,
@ -245,7 +245,9 @@ macro_rules! vec {
} }
} }
impl<$S: Copy> Array1<$S> for $VectorN<$S> {} impl<S: Copy> Array1 for $VectorN<S> {
type Element = S;
}
impl<S: BaseNum> Vector<S> for $VectorN<S> { impl<S: BaseNum> Vector<S> for $VectorN<S> {
#[inline] fn from_value(s: S) -> $VectorN<S> { $VectorN { $($field: s),+ } } #[inline] fn from_value(s: S) -> $VectorN<S> { $VectorN { $($field: s),+ } }