Skip to content

Commit d784e4e

Browse files
committed
Merge pull request #246 from bjz/associated-types
Convert trait type parameters to associated types
2 parents 28ea564 + 490997c commit d784e4e

11 files changed

+331
-259
lines changed

src/angle.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ pub trait Angle
8080
>
8181
: Clone + Zero
8282
+ PartialEq + PartialOrd
83-
+ ApproxEq<S>
83+
+ ApproxEq<Epsilon = S>
8484
+ Neg<Output=Self>
8585
+ Into<Rad<S>>
8686
+ Into<Deg<S>>
@@ -279,16 +279,18 @@ fmt::Debug for Deg<S> {
279279
}
280280
}
281281

282-
impl<S: BaseFloat>
283-
ApproxEq<S> for Rad<S> {
282+
impl<S: BaseFloat> ApproxEq for Rad<S> {
283+
type Epsilon = S;
284+
284285
#[inline]
285286
fn approx_eq_eps(&self, other: &Rad<S>, epsilon: &S) -> bool {
286287
self.s.approx_eq_eps(&other.s, epsilon)
287288
}
288289
}
289290

290-
impl<S: BaseFloat>
291-
ApproxEq<S> for Deg<S> {
291+
impl<S: BaseFloat> ApproxEq for Deg<S> {
292+
type Epsilon = S;
293+
292294
#[inline]
293295
fn approx_eq_eps(&self, other: &Deg<S>, epsilon: &S) -> bool {
294296
self.s.approx_eq_eps(&other.s, epsilon)

src/approx.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,26 @@
1616
use rust_num::{Float, NumCast};
1717
use rust_num::traits::cast;
1818

19-
pub trait ApproxEq<T: NumCast + Float>: Sized {
20-
fn approx_epsilon(_hack: Option<Self>) -> T {
19+
pub trait ApproxEq: Sized {
20+
type Epsilon: NumCast + Float;
21+
22+
fn approx_epsilon() -> Self::Epsilon {
2123
cast(1.0e-5f64).unwrap()
2224
}
2325

2426
fn approx_eq(&self, other: &Self) -> bool {
25-
let eps: T = ApproxEq::approx_epsilon(None::<Self>);
26-
self.approx_eq_eps(other, &eps)
27+
self.approx_eq_eps(other, &Self::approx_epsilon())
2728
}
2829

29-
fn approx_eq_eps(&self, other: &Self, epsilon: &T) -> bool;
30+
fn approx_eq_eps(&self, other: &Self, epsilon: &Self::Epsilon) -> bool;
3031
}
3132

3233

3334
macro_rules! approx_float(
3435
($S:ident) => (
35-
impl ApproxEq<$S> for $S {
36+
impl ApproxEq for $S {
37+
type Epsilon = $S;
38+
3639
#[inline]
3740
fn approx_eq_eps(&self, other: &$S, epsilon: &$S) -> bool {
3841
(*self - *other).abs() < *epsilon
@@ -62,9 +65,8 @@ macro_rules! assert_approx_eq(
6265
($given: expr, $expected: expr) => ({
6366
let (given_val, expected_val) = (&($given), &($expected));
6467
if !given_val.approx_eq(expected_val) {
65-
panic!("assertion failed: `left ≈ right` (left: `{:?}`, right: `{:?}`, tolerance: `{:?}`)",
66-
*given_val, *expected_val,
67-
ApproxEq::approx_epsilon(Some(*given_val))
68+
panic!("assertion failed: `left ≈ right` (left: `{:?}`, right: `{:?}`)",
69+
*given_val, *expected_val
6870
);
6971
}
7072
})

src/array.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,20 @@ use std::ptr;
1818
use std::ops::*;
1919

2020
/// An array containing elements of type `Element`
21-
pub trait Array1<Element: Copy>: Index<usize, Output=Element> + IndexMut<usize, Output=Element> {
21+
pub trait Array1 where
22+
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
23+
Self: Index<usize, Output = <Self as Array1>::Element>,
24+
Self: IndexMut<usize, Output = <Self as Array1>::Element>,
25+
{
26+
type Element: Copy;
27+
2228
/// Get the pointer to the first element of the array.
23-
fn ptr<'a>(&'a self) -> &'a Element {
29+
fn ptr<'a>(&'a self) -> &'a Self::Element {
2430
&self[0]
2531
}
2632

2733
/// Get a mutable pointer to the first element of the array.
28-
fn mut_ptr<'a>(&'a mut self) -> &'a mut Element {
34+
fn mut_ptr<'a>(&'a mut self) -> &'a mut Self::Element {
2935
&mut self[0]
3036
}
3137

@@ -38,21 +44,28 @@ pub trait Array1<Element: Copy>: Index<usize, Output=Element> + IndexMut<usize,
3844

3945
/// Replace an element in the array.
4046
#[inline]
41-
fn replace_elem(&mut self, i: usize, src: Element) -> Element {
47+
fn replace_elem(&mut self, i: usize, src: Self::Element) -> Self::Element {
4248
mem::replace(&mut self[i], src)
4349
}
4450
}
4551

4652
/// A column-major array
47-
pub trait Array2<Column: Array1<Element>+'static, Row: Array1<Element>, Element: Copy>:
48-
Index<usize, Output=Column> + IndexMut<usize, Output=Column> {
53+
pub trait Array2 where
54+
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
55+
Self: Index<usize, Output = <Self as Array2>::Column>,
56+
Self: IndexMut<usize, Output = <Self as Array2>::Column>,
57+
{
58+
type Element: Copy;
59+
type Column: Array1<Element = Self::Element>;
60+
type Row: Array1<Element = Self::Element>;
61+
4962
/// Get the pointer to the first element of the array.
50-
fn ptr<'a>(&'a self) -> &'a Element {
63+
fn ptr<'a>(&'a self) -> &'a Self::Element {
5164
&self[0][0]
5265
}
5366

5467
/// Get a mutable pointer to the first element of the array.
55-
fn mut_ptr<'a>(&'a mut self) -> &'a mut Element {
68+
fn mut_ptr<'a>(&'a mut self) -> &'a mut Self::Element {
5669
&mut self[0][0]
5770
}
5871

@@ -64,12 +77,12 @@ pub trait Array2<Column: Array1<Element>+'static, Row: Array1<Element>, Element:
6477

6578
/// Replace a column in the array.
6679
#[inline]
67-
fn replace_col(&mut self, c: usize, src: Column) -> Column {
80+
fn replace_col(&mut self, c: usize, src: Self::Column) -> Self::Column {
6881
mem::replace(&mut self[c], src)
6982
}
7083

7184
/// Get a row from this array by-value.
72-
fn row(&self, r: usize) -> Row;
85+
fn row(&self, r: usize) -> Self::Row;
7386

7487
/// Swap two rows of this array.
7588
fn swap_rows(&mut self, a: usize, b: usize);

src/matrix.rs

Lines changed: 60 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,15 @@ impl<S: Copy + Neg<Output = S>> Matrix4<S> {
249249
}
250250
}
251251

252-
pub trait Matrix<S: BaseFloat, V: Vector<S> + 'static>: Array2<V, V, S> + ApproxEq<S> + Sized // where
252+
pub trait Matrix where
253+
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
254+
Self: Array2<
255+
Element = <<Self as Matrix>::ColumnRow as Vector>::Scalar,
256+
Column = <Self as Matrix>::ColumnRow,
257+
Row = <Self as Matrix>::ColumnRow,
258+
>,
259+
Self: ApproxEq<Epsilon = <<Self as Matrix>::ColumnRow as Vector>::Scalar> + Sized,
260+
Self::Element: BaseFloat,
253261
// FIXME: blocked by rust-lang/rust#20671
254262
//
255263
// for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>,
@@ -261,28 +269,31 @@ pub trait Matrix<S: BaseFloat, V: Vector<S> + 'static>: Array2<V, V, S> + Approx
261269
// for<'a> &'a Self: Div<S, Output = Self>,
262270
// for<'a> &'a Self: Rem<S, Output = Self>,
263271
{
272+
// FIXME: Will not be needed once equality constraints in where clauses is implemented
273+
type ColumnRow: Vector;
274+
264275
/// Create a new diagonal matrix using the supplied value.
265-
fn from_value(value: S) -> Self;
276+
fn from_value(value: Self::Element) -> Self;
266277
/// Create a matrix from a non-uniform scale
267-
fn from_diagonal(value: &V) -> Self;
278+
fn from_diagonal(diagonal: &Self::Column) -> Self;
268279

269280
/// Create a matrix with all elements equal to zero.
270281
#[inline]
271-
fn zero() -> Self { Self::from_value(S::zero()) }
282+
fn zero() -> Self { Self::from_value(Self::Element::zero()) }
272283
/// Create a matrix where the each element of the diagonal is equal to one.
273284
#[inline]
274-
fn one() -> Self { Self::from_value(S::one()) }
285+
fn one() -> Self { Self::from_value(Self::Element::one()) }
275286

276287
/// Multiply this matrix by a scalar, returning the new matrix.
277288
#[must_use]
278-
fn mul_s(&self, s: S) -> Self;
289+
fn mul_s(&self, s: Self::Element) -> Self;
279290
/// Divide this matrix by a scalar, returning the new matrix.
280291
#[must_use]
281-
fn div_s(&self, s: S) -> Self;
292+
fn div_s(&self, s: Self::Element) -> Self;
282293
/// Take the remainder of this matrix by a scalar, returning the new
283294
/// matrix.
284295
#[must_use]
285-
fn rem_s(&self, s: S) -> Self;
296+
fn rem_s(&self, s: Self::Element) -> Self;
286297

287298
/// Add this matrix with another matrix, returning the new metrix.
288299
#[must_use]
@@ -292,18 +303,18 @@ pub trait Matrix<S: BaseFloat, V: Vector<S> + 'static>: Array2<V, V, S> + Approx
292303
fn sub_m(&self, m: &Self) -> Self;
293304

294305
/// Multiplay a vector by this matrix, returning a new vector.
295-
fn mul_v(&self, v: &V) -> V;
306+
fn mul_v(&self, v: &Self::Column) -> Self::Column;
296307

297308
/// Multiply this matrix by another matrix, returning the new matrix.
298309
#[must_use]
299310
fn mul_m(&self, m: &Self) -> Self;
300311

301312
/// Multiply this matrix by a scalar, in-place.
302-
fn mul_self_s(&mut self, s: S);
313+
fn mul_self_s(&mut self, s: Self::Element);
303314
/// Divide this matrix by a scalar, in-place.
304-
fn div_self_s(&mut self, s: S);
315+
fn div_self_s(&mut self, s: Self::Element);
305316
/// Take the remainder of this matrix, in-place.
306-
fn rem_self_s(&mut self, s: S);
317+
fn rem_self_s(&mut self, s: Self::Element);
307318

308319
/// Add this matrix with another matrix, in-place.
309320
fn add_self_m(&mut self, m: &Self);
@@ -320,14 +331,14 @@ pub trait Matrix<S: BaseFloat, V: Vector<S> + 'static>: Array2<V, V, S> + Approx
320331
/// Transpose this matrix in-place.
321332
fn transpose_self(&mut self);
322333
/// Take the determinant of this matrix.
323-
fn determinant(&self) -> S;
334+
fn determinant(&self) -> Self::Element;
324335

325336
/// Return a vector containing the diagonal of this matrix.
326-
fn diagonal(&self) -> V;
337+
fn diagonal(&self) -> Self::Column;
327338

328339
/// Return the trace of this matrix. That is, the sum of the diagonal.
329340
#[inline]
330-
fn trace(&self) -> S { self.diagonal().sum() }
341+
fn trace(&self) -> Self::Element { self.diagonal().sum() }
331342

332343
/// Invert this matrix, returning a new matrix. `m.mul_m(m.invert())` is
333344
/// the identity matrix. Returns `None` if this matrix is not invertible
@@ -343,7 +354,7 @@ pub trait Matrix<S: BaseFloat, V: Vector<S> + 'static>: Array2<V, V, S> + Approx
343354

344355
/// Test if this matrix is invertible.
345356
#[inline]
346-
fn is_invertible(&self) -> bool { !self.determinant().approx_eq(&S::zero()) }
357+
fn is_invertible(&self) -> bool { !self.determinant().approx_eq(&Self::Element::zero()) }
347358

348359
/// Test if this matrix is the identity matrix. That is, it is diagonal
349360
/// and every element in the diagonal is one.
@@ -359,7 +370,11 @@ pub trait Matrix<S: BaseFloat, V: Vector<S> + 'static>: Array2<V, V, S> + Approx
359370
fn is_symmetric(&self) -> bool;
360371
}
361372

362-
impl<S: Copy + 'static> Array2<Vector2<S>, Vector2<S>, S> for Matrix2<S> {
373+
impl<S: Copy> Array2 for Matrix2<S> {
374+
type Element = S;
375+
type Column = Vector2<S>;
376+
type Row = Vector2<S>;
377+
363378
#[inline]
364379
fn row(&self, r: usize) -> Vector2<S> {
365380
Vector2::new(self[0][r],
@@ -373,7 +388,11 @@ impl<S: Copy + 'static> Array2<Vector2<S>, Vector2<S>, S> for Matrix2<S> {
373388
}
374389
}
375390

376-
impl<S: Copy + 'static> Array2<Vector3<S>, Vector3<S>, S> for Matrix3<S> {
391+
impl<S: Copy> Array2 for Matrix3<S> {
392+
type Element = S;
393+
type Column = Vector3<S>;
394+
type Row = Vector3<S>;
395+
377396
#[inline]
378397
fn row(&self, r: usize) -> Vector3<S> {
379398
Vector3::new(self[0][r],
@@ -389,7 +408,11 @@ impl<S: Copy + 'static> Array2<Vector3<S>, Vector3<S>, S> for Matrix3<S> {
389408
}
390409
}
391410

392-
impl<S: Copy + 'static> Array2<Vector4<S>, Vector4<S>, S> for Matrix4<S> {
411+
impl<S: Copy> Array2 for Matrix4<S> {
412+
type Element = S;
413+
type Column = Vector4<S>;
414+
type Row = Vector4<S>;
415+
393416
#[inline]
394417
fn row(&self, r: usize) -> Vector4<S> {
395418
Vector4::new(self[0][r],
@@ -407,7 +430,9 @@ impl<S: Copy + 'static> Array2<Vector4<S>, Vector4<S>, S> for Matrix4<S> {
407430
}
408431
}
409432

410-
impl<S: BaseFloat> Matrix<S, Vector2<S>> for Matrix2<S> {
433+
impl<S: BaseFloat> Matrix for Matrix2<S> {
434+
type ColumnRow = Vector2<S>;
435+
411436
#[inline]
412437
fn from_value(value: S) -> Matrix2<S> {
413438
Matrix2::new(value, S::zero(),
@@ -504,7 +529,9 @@ impl<S: BaseFloat> Matrix<S, Vector2<S>> for Matrix2<S> {
504529
}
505530
}
506531

507-
impl<S: BaseFloat> Matrix<S, Vector3<S>> for Matrix3<S> {
532+
impl<S: BaseFloat> Matrix for Matrix3<S> {
533+
type ColumnRow = Vector3<S>;
534+
508535
#[inline]
509536
fn from_value(value: S) -> Matrix3<S> {
510537
Matrix3::new(value, S::zero(), S::zero(),
@@ -620,7 +647,9 @@ impl<S: BaseFloat> Matrix<S, Vector3<S>> for Matrix3<S> {
620647
}
621648
}
622649

623-
impl<S: BaseFloat> Matrix<S, Vector4<S>> for Matrix4<S> {
650+
impl<S: BaseFloat> Matrix for Matrix4<S> {
651+
type ColumnRow = Vector4<S>;
652+
624653
#[inline]
625654
fn from_value(value: S) -> Matrix4<S> {
626655
Matrix4::new(value, S::zero(), S::zero(), S::zero(),
@@ -790,15 +819,19 @@ impl<S: BaseFloat> Matrix<S, Vector4<S>> for Matrix4<S> {
790819
}
791820
}
792821

793-
impl<S: BaseFloat> ApproxEq<S> for Matrix2<S> {
822+
impl<S: BaseFloat> ApproxEq for Matrix2<S> {
823+
type Epsilon = S;
824+
794825
#[inline]
795826
fn approx_eq_eps(&self, other: &Matrix2<S>, epsilon: &S) -> bool {
796827
self[0].approx_eq_eps(&other[0], epsilon) &&
797828
self[1].approx_eq_eps(&other[1], epsilon)
798829
}
799830
}
800831

801-
impl<S: BaseFloat> ApproxEq<S> for Matrix3<S> {
832+
impl<S: BaseFloat> ApproxEq for Matrix3<S> {
833+
type Epsilon = S;
834+
802835
#[inline]
803836
fn approx_eq_eps(&self, other: &Matrix3<S>, epsilon: &S) -> bool {
804837
self[0].approx_eq_eps(&other[0], epsilon) &&
@@ -807,7 +840,9 @@ impl<S: BaseFloat> ApproxEq<S> for Matrix3<S> {
807840
}
808841
}
809842

810-
impl<S: BaseFloat> ApproxEq<S> for Matrix4<S> {
843+
impl<S: BaseFloat> ApproxEq for Matrix4<S> {
844+
type Epsilon = S;
845+
811846
#[inline]
812847
fn approx_eq_eps(&self, other: &Matrix4<S>, epsilon: &S) -> bool {
813848
self[0].approx_eq_eps(&other[0], epsilon) &&

src/num.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ impl BaseInt for u64 {}
110110
impl BaseInt for usize {}
111111

112112
/// Base floating point types
113-
pub trait BaseFloat : BaseNum + Float + ApproxEq<Self> {}
113+
pub trait BaseFloat : BaseNum + Float + ApproxEq<Epsilon = Self> {}
114114

115115
impl BaseFloat for f32 {}
116116
impl BaseFloat for f64 {}

0 commit comments

Comments
 (0)