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::*;
/// 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.
fn ptr<'a>(&'a self) -> &'a Element {
fn ptr<'a>(&'a self) -> &'a Self::Element {
&self[0]
}
/// 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]
}
@ -38,21 +43,27 @@ pub trait Array1<Element: Copy>: Index<usize, Output=Element> + IndexMut<usize,
/// Replace an element in the array.
#[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)
}
}
/// A column-major array
pub trait Array2<Column: Array1<Element>+'static, Row: Array1<Element>, Element: Copy>:
Index<usize, Output=Column> + IndexMut<usize, Output=Column> {
pub trait Array2 where
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.
fn ptr<'a>(&'a self) -> &'a Element {
fn ptr<'a>(&'a self) -> &'a Self::Element {
&self[0][0]
}
/// 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]
}
@ -64,12 +75,12 @@ pub trait Array2<Column: Array1<Element>+'static, Row: Array1<Element>, Element:
/// Replace a column in the array.
#[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)
}
/// 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.
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
//
// 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;
}
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]
fn row(&self, r: usize) -> Vector2<S> {
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]
fn row(&self, r: usize) -> Vector3<S> {
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]
fn row(&self, r: usize) -> Vector4<S> {
Vector4::new(self[0][r],

View file

@ -66,7 +66,7 @@ impl<S: BaseNum> Point3<S> {
}
/// 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
//
// 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;
}
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> {
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> {
type Vector = Vector3<S>;

View file

@ -40,7 +40,9 @@ pub struct Quaternion<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> {
/// 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
/// of these make sense from a linear algebra point of view, but are included
/// 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
//
// 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> {
#[inline] fn from_value(s: S) -> $VectorN<S> { $VectorN { $($field: s),+ } }