Skip to content

Convert trait type parameters to associated types #246

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Nov 7, 2015
12 changes: 7 additions & 5 deletions src/angle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ pub trait Angle
>
: Clone + Zero
+ PartialEq + PartialOrd
+ ApproxEq<S>
+ ApproxEq<Epsilon = S>
+ Neg<Output=Self>
+ Into<Rad<S>>
+ Into<Deg<S>>
Expand Down Expand Up @@ -279,16 +279,18 @@ fmt::Debug for Deg<S> {
}
}

impl<S: BaseFloat>
ApproxEq<S> for Rad<S> {
impl<S: BaseFloat> ApproxEq for Rad<S> {
type Epsilon = S;

#[inline]
fn approx_eq_eps(&self, other: &Rad<S>, epsilon: &S) -> bool {
self.s.approx_eq_eps(&other.s, epsilon)
}
}

impl<S: BaseFloat>
ApproxEq<S> for Deg<S> {
impl<S: BaseFloat> ApproxEq for Deg<S> {
type Epsilon = S;

#[inline]
fn approx_eq_eps(&self, other: &Deg<S>, epsilon: &S) -> bool {
self.s.approx_eq_eps(&other.s, epsilon)
Expand Down
20 changes: 11 additions & 9 deletions src/approx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,26 @@
use rust_num::{Float, NumCast};
use rust_num::traits::cast;

pub trait ApproxEq<T: NumCast + Float>: Sized {
fn approx_epsilon(_hack: Option<Self>) -> T {
pub trait ApproxEq: Sized {
type Epsilon: NumCast + Float;

fn approx_epsilon() -> Self::Epsilon {
cast(1.0e-5f64).unwrap()
}

fn approx_eq(&self, other: &Self) -> bool {
let eps: T = ApproxEq::approx_epsilon(None::<Self>);
self.approx_eq_eps(other, &eps)
self.approx_eq_eps(other, &Self::approx_epsilon())
}

fn approx_eq_eps(&self, other: &Self, epsilon: &T) -> bool;
fn approx_eq_eps(&self, other: &Self, epsilon: &Self::Epsilon) -> bool;
}


macro_rules! approx_float(
($S:ident) => (
impl ApproxEq<$S> for $S {
impl ApproxEq for $S {
type Epsilon = $S;

#[inline]
fn approx_eq_eps(&self, other: &$S, epsilon: &$S) -> bool {
(*self - *other).abs() < *epsilon
Expand Down Expand Up @@ -62,9 +65,8 @@ macro_rules! assert_approx_eq(
($given: expr, $expected: expr) => ({
let (given_val, expected_val) = (&($given), &($expected));
if !given_val.approx_eq(expected_val) {
panic!("assertion failed: `left ≈ right` (left: `{:?}`, right: `{:?}`, tolerance: `{:?}`)",
*given_val, *expected_val,
ApproxEq::approx_epsilon(Some(*given_val))
panic!("assertion failed: `left ≈ right` (left: `{:?}`, right: `{:?}`)",
*given_val, *expected_val
);
}
})
Expand Down
33 changes: 23 additions & 10 deletions src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,20 @@ 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
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
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]
}

Expand All @@ -38,21 +44,28 @@ 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
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
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]
}

Expand All @@ -64,12 +77,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);
Expand Down
85 changes: 60 additions & 25 deletions src/matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,15 @@ impl<S: Copy + Neg<Output = S>> Matrix4<S> {
}
}

pub trait Matrix<S: BaseFloat, V: Vector<S> + 'static>: Array2<V, V, S> + ApproxEq<S> + Sized // where
pub trait Matrix where
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
Self: Array2<
Element = <<Self as Matrix>::ColumnRow as Vector>::Scalar,
Column = <Self as Matrix>::ColumnRow,
Row = <Self as Matrix>::ColumnRow,
>,
Self: ApproxEq<Epsilon = <<Self as Matrix>::ColumnRow as Vector>::Scalar> + Sized,
Self::Element: BaseFloat,
// FIXME: blocked by rust-lang/rust#20671
//
// for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>,
Expand All @@ -261,28 +269,31 @@ pub trait Matrix<S: BaseFloat, V: Vector<S> + 'static>: Array2<V, V, S> + Approx
// for<'a> &'a Self: Div<S, Output = Self>,
// for<'a> &'a Self: Rem<S, Output = Self>,
{
// FIXME: Will not be needed once equality constraints in where clauses is implemented
type ColumnRow: Vector;

/// Create a new diagonal matrix using the supplied value.
fn from_value(value: S) -> Self;
fn from_value(value: Self::Element) -> Self;
/// Create a matrix from a non-uniform scale
fn from_diagonal(value: &V) -> Self;
fn from_diagonal(diagonal: &Self::Column) -> Self;

/// Create a matrix with all elements equal to zero.
#[inline]
fn zero() -> Self { Self::from_value(S::zero()) }
fn zero() -> Self { Self::from_value(Self::Element::zero()) }
/// Create a matrix where the each element of the diagonal is equal to one.
#[inline]
fn one() -> Self { Self::from_value(S::one()) }
fn one() -> Self { Self::from_value(Self::Element::one()) }

/// Multiply this matrix by a scalar, returning the new matrix.
#[must_use]
fn mul_s(&self, s: S) -> Self;
fn mul_s(&self, s: Self::Element) -> Self;
/// Divide this matrix by a scalar, returning the new matrix.
#[must_use]
fn div_s(&self, s: S) -> Self;
fn div_s(&self, s: Self::Element) -> Self;
/// Take the remainder of this matrix by a scalar, returning the new
/// matrix.
#[must_use]
fn rem_s(&self, s: S) -> Self;
fn rem_s(&self, s: Self::Element) -> Self;

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

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

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

/// Multiply this matrix by a scalar, in-place.
fn mul_self_s(&mut self, s: S);
fn mul_self_s(&mut self, s: Self::Element);
/// Divide this matrix by a scalar, in-place.
fn div_self_s(&mut self, s: S);
fn div_self_s(&mut self, s: Self::Element);
/// Take the remainder of this matrix, in-place.
fn rem_self_s(&mut self, s: S);
fn rem_self_s(&mut self, s: Self::Element);

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

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

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

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

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

/// Test if this matrix is the identity matrix. That is, it is diagonal
/// and every element in the diagonal is one.
Expand All @@ -359,7 +370,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> 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],
Expand All @@ -373,7 +388,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> 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],
Expand All @@ -389,7 +408,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> 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],
Expand All @@ -407,7 +430,9 @@ impl<S: Copy + 'static> Array2<Vector4<S>, Vector4<S>, S> for Matrix4<S> {
}
}

impl<S: BaseFloat> Matrix<S, Vector2<S>> for Matrix2<S> {
impl<S: BaseFloat> Matrix for Matrix2<S> {
type ColumnRow = Vector2<S>;

#[inline]
fn from_value(value: S) -> Matrix2<S> {
Matrix2::new(value, S::zero(),
Expand Down Expand Up @@ -504,7 +529,9 @@ impl<S: BaseFloat> Matrix<S, Vector2<S>> for Matrix2<S> {
}
}

impl<S: BaseFloat> Matrix<S, Vector3<S>> for Matrix3<S> {
impl<S: BaseFloat> Matrix for Matrix3<S> {
type ColumnRow = Vector3<S>;

#[inline]
fn from_value(value: S) -> Matrix3<S> {
Matrix3::new(value, S::zero(), S::zero(),
Expand Down Expand Up @@ -620,7 +647,9 @@ impl<S: BaseFloat> Matrix<S, Vector3<S>> for Matrix3<S> {
}
}

impl<S: BaseFloat> Matrix<S, Vector4<S>> for Matrix4<S> {
impl<S: BaseFloat> Matrix for Matrix4<S> {
type ColumnRow = Vector4<S>;

#[inline]
fn from_value(value: S) -> Matrix4<S> {
Matrix4::new(value, S::zero(), S::zero(), S::zero(),
Expand Down Expand Up @@ -790,15 +819,19 @@ impl<S: BaseFloat> Matrix<S, Vector4<S>> for Matrix4<S> {
}
}

impl<S: BaseFloat> ApproxEq<S> for Matrix2<S> {
impl<S: BaseFloat> ApproxEq for Matrix2<S> {
type Epsilon = S;

#[inline]
fn approx_eq_eps(&self, other: &Matrix2<S>, epsilon: &S) -> bool {
self[0].approx_eq_eps(&other[0], epsilon) &&
self[1].approx_eq_eps(&other[1], epsilon)
}
}

impl<S: BaseFloat> ApproxEq<S> for Matrix3<S> {
impl<S: BaseFloat> ApproxEq for Matrix3<S> {
type Epsilon = S;

#[inline]
fn approx_eq_eps(&self, other: &Matrix3<S>, epsilon: &S) -> bool {
self[0].approx_eq_eps(&other[0], epsilon) &&
Expand All @@ -807,7 +840,9 @@ impl<S: BaseFloat> ApproxEq<S> for Matrix3<S> {
}
}

impl<S: BaseFloat> ApproxEq<S> for Matrix4<S> {
impl<S: BaseFloat> ApproxEq for Matrix4<S> {
type Epsilon = S;

#[inline]
fn approx_eq_eps(&self, other: &Matrix4<S>, epsilon: &S) -> bool {
self[0].approx_eq_eps(&other[0], epsilon) &&
Expand Down
2 changes: 1 addition & 1 deletion src/num.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ impl BaseInt for u64 {}
impl BaseInt for usize {}

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

impl BaseFloat for f32 {}
impl BaseFloat for f64 {}
Loading