Inherit Zero and One for core structural traits

This commit is contained in:
Brendan Zabarauskas 2016-04-25 15:10:53 +10:00
parent 54adacc2a8
commit 6b48236cb6
5 changed files with 131 additions and 73 deletions

View file

@ -71,19 +71,22 @@ macro_rules! impl_angle {
}
}
impl<S: BaseFloat> Angle for $Angle<S> {
type Unitless = S;
impl<S: BaseFloat> Zero for $Angle<S> {
#[inline]
fn zero() -> $Angle<S> {
$Angle::new(S::zero())
}
#[inline]
fn is_zero(&self) -> bool {
$Angle::approx_eq(self, &$Angle::zero())
}
}
impl<S: BaseFloat> Angle for $Angle<S> {
type Unitless = S;
#[inline] fn full_turn() -> $Angle<S> { $Angle::new(cast($full_turn).unwrap()) }
#[inline] fn turn_div_2() -> $Angle<S> { let factor: S = cast(2).unwrap(); $Angle::full_turn() / factor }
#[inline] fn turn_div_3() -> $Angle<S> { let factor: S = cast(3).unwrap(); $Angle::full_turn() / factor }
#[inline] fn turn_div_4() -> $Angle<S> { let factor: S = cast(4).unwrap(); $Angle::full_turn() / factor }
#[inline] fn turn_div_6() -> $Angle<S> { let factor: S = cast(6).unwrap(); $Angle::full_turn() / factor }
#[inline] fn sin(self) -> S { Rad::from(self).s.sin() }
#[inline] fn cos(self) -> S { Rad::from(self).s.cos() }

View file

@ -266,30 +266,34 @@ impl<S: BaseFloat> Matrix4<S> {
}
}
impl<S: BaseFloat> VectorSpace for Matrix2<S> {
type Scalar = S;
impl<S: BaseFloat> Zero for Matrix2<S> {
#[inline]
fn zero() -> Matrix2<S> {
Matrix2::new(S::zero(), S::zero(),
S::zero(), S::zero())
}
#[inline]
fn is_zero(&self) -> bool {
Matrix2::approx_eq(self, &Matrix2::zero())
}
}
impl<S: BaseFloat> VectorSpace for Matrix3<S> {
type Scalar = S;
impl<S: BaseFloat> Zero for Matrix3<S> {
#[inline]
fn zero() -> Matrix3<S> {
Matrix3::new(S::zero(), S::zero(), S::zero(),
S::zero(), S::zero(), S::zero(),
S::zero(), S::zero(), S::zero())
}
#[inline]
fn is_zero(&self) -> bool {
Matrix3::approx_eq(self, &Matrix3::zero())
}
}
impl<S: BaseFloat> VectorSpace for Matrix4<S> {
type Scalar = S;
impl<S: BaseFloat> Zero for Matrix4<S> {
#[inline]
fn zero() -> Matrix4<S> {
Matrix4::new(S::zero(), S::zero(), S::zero(), S::zero(),
@ -297,6 +301,44 @@ impl<S: BaseFloat> VectorSpace for Matrix4<S> {
S::zero(), S::zero(), S::zero(), S::zero(),
S::zero(), S::zero(), S::zero(), S::zero())
}
#[inline]
fn is_zero(&self) -> bool {
Matrix4::approx_eq(self, &Matrix4::zero())
}
}
impl<S: BaseFloat> One for Matrix2<S> {
#[inline]
fn one() -> Matrix2<S> {
Matrix2::from_value(S::one())
}
}
impl<S: BaseFloat> One for Matrix3<S> {
#[inline]
fn one() -> Matrix3<S> {
Matrix3::from_value(S::one())
}
}
impl<S: BaseFloat> One for Matrix4<S> {
#[inline]
fn one() -> Matrix4<S> {
Matrix4::from_value(S::one())
}
}
impl<S: BaseFloat> VectorSpace for Matrix2<S> {
type Scalar = S;
}
impl<S: BaseFloat> VectorSpace for Matrix3<S> {
type Scalar = S;
}
impl<S: BaseFloat> VectorSpace for Matrix4<S> {
type Scalar = S;
}
impl<S: BaseFloat> Matrix for Matrix2<S> {
@ -349,11 +391,6 @@ impl<S: BaseFloat> SquareMatrix for Matrix2<S> {
S::zero(), value.y)
}
#[inline]
fn identity() -> Matrix2<S> {
Matrix2::from_value(S::one())
}
#[inline]
fn transpose_self(&mut self) {
self.swap_elements((0, 1), (1, 0));
@ -450,11 +487,6 @@ impl<S: BaseFloat> SquareMatrix for Matrix3<S> {
S::zero(), S::zero(), value.z)
}
#[inline]
fn identity() -> Matrix3<S> {
Matrix3::from_value(S::one())
}
#[inline]
fn transpose_self(&mut self) {
self.swap_elements((0, 1), (1, 0));
@ -567,11 +599,6 @@ impl<S: BaseFloat> SquareMatrix for Matrix4<S> {
S::zero(), S::zero(), S::zero(), value.w)
}
#[inline]
fn identity() -> Matrix4<S> {
Matrix4::from_value(S::one())
}
fn transpose_self(&mut self) {
self.swap_elements((0, 1), (1, 0));
self.swap_elements((0, 2), (2, 0));

View file

@ -120,13 +120,20 @@ impl<S: BaseFloat> Quaternion<S> {
}
}
impl<S: BaseFloat> VectorSpace for Quaternion<S> {
type Scalar = S;
impl<S: BaseFloat> Zero for Quaternion<S> {
#[inline]
fn zero() -> Quaternion<S> {
Quaternion::from_sv(S::zero(), Vector3::zero())
}
#[inline]
fn is_zero(&self) -> bool {
Quaternion::approx_eq(self, &Quaternion::zero())
}
}
impl<S: BaseFloat> VectorSpace for Quaternion<S> {
type Scalar = S;
}
impl<S: BaseFloat> MetricSpace for Quaternion<S> {

View file

@ -122,6 +122,17 @@ pub trait ElementWise<Rhs = Self> {
/// let reversed_velocity0 = -velocity0;
/// ```
///
/// Vector spaces are also required to implement the additive identity trait,
/// `Zero`. Adding this to another vector should have no effect:
///
/// ```rust
/// use cgmath::prelude::*;
/// use cgmath::Vector2;
///
/// let v = Vector2::new(1, 2);
/// assert_eq!(v + Vector2::zero(), v);
/// ```
///
/// ## Scalar multiplication
///
/// Vectors can be multiplied or divided by their associated scalars via the
@ -141,6 +152,8 @@ pub trait ElementWise<Rhs = Self> {
/// let downscaled_translation = translation / scale_factor;
/// ```
pub trait VectorSpace: Copy + Clone where
Self: Zero,
Self: Add<Self, Output = Self>,
Self: Sub<Self, Output = Self>,
@ -151,19 +164,6 @@ pub trait VectorSpace: Copy + Clone where
{
/// The associated scalar.
type Scalar: BaseNum;
/// The additive identity.
///
/// Adding this to another `Self` value has no effect.
///
/// ```rust
/// use cgmath::prelude::*;
/// use cgmath::Vector2;
///
/// let v = Vector2::new(1, 2);
/// assert_eq!(v + Vector2::zero(), v);
/// ```
fn zero() -> Self;
}
/// A type with a distance function between values.
@ -454,6 +454,8 @@ pub trait Matrix: VectorSpace where
pub trait SquareMatrix where
Self::Scalar: BaseFloat,
Self: One,
Self: Matrix<
// FIXME: Can be cleaned up once equality constraints in where clauses are implemented
Column = <Self as SquareMatrix>::ColumnRow,
@ -476,9 +478,18 @@ pub trait SquareMatrix where
/// Create a matrix from a non-uniform scale
fn from_diagonal(diagonal: Self::ColumnRow) -> Self;
/// The [identity matrix](https://en.wikipedia.org/wiki/Identity_matrix). Multiplying this
/// matrix with another has no effect.
fn identity() -> Self;
/// The [identity matrix]. Multiplying this matrix with another should have
/// no effect.
///
/// Note that this is exactly the same as `One::one`. The term 'identity
/// matrix' is more common though, so we provide this method as an
/// alternative.
///
/// [identity matrix]: https://en.wikipedia.org/wiki/Identity_matrix
#[inline]
fn identity() -> Self {
Self::one()
}
/// Transpose this matrix in-place.
fn transpose_self(&mut self);
@ -534,6 +545,8 @@ pub trait Angle where
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
Self: ApproxEq<Epsilon = <Self as Angle>::Unitless>,
Self: Zero,
Self: Neg<Output = Self>,
Self: Add<Self, Output = Self>,
Self: Sub<Self, Output = Self>,
@ -564,35 +577,36 @@ pub trait Angle where
Self::normalize((self - other) * half + self)
}
/// The additive identity.
///
/// Adding this to another angle has no affect.
///
/// For example:
///
/// ```rust
/// use cgmath::prelude::*;
/// use cgmath::Deg;
///
/// let v = Deg::new(180.0);
/// assert_eq!(v + Deg::zero(), v);
/// ```
fn zero() -> Self;
/// A full rotation.
fn full_turn() -> Self;
/// Half of a full rotation.
fn turn_div_2() -> Self;
#[inline]
fn turn_div_2() -> Self {
let factor: Self::Unitless = cast(2).unwrap();
Self::full_turn() / factor
}
/// A third of a full rotation.
fn turn_div_3() -> Self;
#[inline]
fn turn_div_3() -> Self {
let factor: Self::Unitless = cast(3).unwrap();
Self::full_turn() / factor
}
/// A quarter of a full rotation.
fn turn_div_4() -> Self;
#[inline]
fn turn_div_4() -> Self {
let factor: Self::Unitless = cast(4).unwrap();
Self::full_turn() / factor
}
/// A sixth of a full rotation.
fn turn_div_6() -> Self;
#[inline]
fn turn_div_6() -> Self {
let factor: Self::Unitless = cast(6).unwrap();
Self::full_turn() / factor
}
/// Compute the sine of the angle, returning a unitless ratio.
///

View file

@ -140,15 +140,22 @@ macro_rules! impl_vector {
}
}
impl<S: BaseNum> VectorSpace for $VectorN<S> {
type Scalar = S;
impl<S: BaseNum> Zero for $VectorN<S> {
#[inline]
fn zero() -> $VectorN<S> {
$VectorN::from_value(S::zero())
}
#[inline]
fn zero() -> Self {
Self::from_value(Self::Scalar::zero())
fn is_zero(&self) -> bool {
*self == $VectorN::zero()
}
}
impl<S: BaseNum> VectorSpace for $VectorN<S> {
type Scalar = S;
}
impl<S: Neg<Output = S>> Neg for $VectorN<S> {
type Output = $VectorN<S>;