From a434f18ba4ccdeba0e096daf20f8a0ee082739d3 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Tue, 3 Nov 2015 14:15:11 +1100 Subject: [PATCH] Make array type parameters associated types --- src/array.rs | 31 +++++++++++++++++++++---------- src/matrix.rs | 22 ++++++++++++++++++---- src/point.rs | 10 +++++++--- src/quaternion.rs | 4 +++- src/vector.rs | 6 ++++-- 5 files changed, 53 insertions(+), 20 deletions(-) diff --git a/src/array.rs b/src/array.rs index f2e0e59..0bbfd32 100644 --- a/src/array.rs +++ b/src/array.rs @@ -18,14 +18,19 @@ use std::ptr; use std::ops::*; /// An array containing elements of type `Element` -pub trait Array1: Index + IndexMut { +pub trait Array1 where + Self: Index::Element>, + Self: IndexMut::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: Index + IndexMut 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+'static, Row: Array1, Element: Copy>: - Index + IndexMut { +pub trait Array2 where + Self: Index::Column>, + Self: IndexMut::Column>, +{ + type Element: Copy; + type Column: Array1; + type Row: Array1; + /// 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+'static, Row: Array1, 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); diff --git a/src/matrix.rs b/src/matrix.rs index 3fd337c..5b05ab8 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -249,7 +249,9 @@ impl> Matrix4 { } } -pub trait Matrix + 'static>: Array2 + ApproxEq + Sized // where +pub trait Matrix> where + Self: Array2, + Self: ApproxEq + 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 + 'static>: Array2 + Approx fn is_symmetric(&self) -> bool; } -impl Array2, Vector2, S> for Matrix2 { +impl Array2 for Matrix2 { + type Element = S; + type Column = Vector2; + type Row = Vector2; + #[inline] fn row(&self, r: usize) -> Vector2 { Vector2::new(self[0][r], @@ -373,7 +379,11 @@ impl Array2, Vector2, S> for Matrix2 { } } -impl Array2, Vector3, S> for Matrix3 { +impl Array2 for Matrix3 { + type Element = S; + type Column = Vector3; + type Row = Vector3; + #[inline] fn row(&self, r: usize) -> Vector3 { Vector3::new(self[0][r], @@ -389,7 +399,11 @@ impl Array2, Vector3, S> for Matrix3 { } } -impl Array2, Vector4, S> for Matrix4 { +impl Array2 for Matrix4 { + type Element = S; + type Column = Vector4; + type Row = Vector4; + #[inline] fn row(&self, r: usize) -> Vector4 { Vector4::new(self[0][r], diff --git a/src/point.rs b/src/point.rs index 1f917f1..809c94d 100644 --- a/src/point.rs +++ b/src/point.rs @@ -66,7 +66,7 @@ impl Point3 { } /// Specifies the numeric operations for point types. -pub trait Point: Array1 + Clone // where +pub trait Point: Array1 + 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: Array1 + Clone // where fn max(&self, p: &Self) -> Self; } -impl Array1 for Point2 {} +impl Array1 for Point2 { + type Element = S; +} impl Point for Point2 { type Vector = Vector2; @@ -200,7 +202,9 @@ impl ApproxEq for Point2 { } } -impl Array1 for Point3 {} +impl Array1 for Point3 { + type Element = S; +} impl Point for Point3 { type Vector = Vector3; diff --git a/src/quaternion.rs b/src/quaternion.rs index 51802e8..6c9635a 100644 --- a/src/quaternion.rs +++ b/src/quaternion.rs @@ -40,7 +40,9 @@ pub struct Quaternion { pub v: Vector3, } -impl Array1 for Quaternion {} +impl Array1 for Quaternion { + type Element = S; +} impl Quaternion { /// Construct a new quaternion from one scalar component and three diff --git a/src/vector.rs b/src/vector.rs index fa13ea5..77e63f1 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -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: Array1 + Clone // where +pub trait Vector: Array1 + 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 Array1 for $VectorN { + type Element = S; + } impl Vector for $VectorN { #[inline] fn from_value(s: S) -> $VectorN { $VectorN { $($field: s),+ } }