diff --git a/src/angle.rs b/src/angle.rs index 0526017..900ac67 100644 --- a/src/angle.rs +++ b/src/angle.rs @@ -71,19 +71,22 @@ macro_rules! impl_angle { } } - impl Angle for $Angle { - type Unitless = S; - + impl Zero for $Angle { #[inline] fn zero() -> $Angle { $Angle::new(S::zero()) } + #[inline] + fn is_zero(&self) -> bool { + $Angle::approx_eq(self, &$Angle::zero()) + } + } + + impl Angle for $Angle { + type Unitless = S; + #[inline] fn full_turn() -> $Angle { $Angle::new(cast($full_turn).unwrap()) } - #[inline] fn turn_div_2() -> $Angle { let factor: S = cast(2).unwrap(); $Angle::full_turn() / factor } - #[inline] fn turn_div_3() -> $Angle { let factor: S = cast(3).unwrap(); $Angle::full_turn() / factor } - #[inline] fn turn_div_4() -> $Angle { let factor: S = cast(4).unwrap(); $Angle::full_turn() / factor } - #[inline] fn turn_div_6() -> $Angle { 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() } diff --git a/src/matrix.rs b/src/matrix.rs index 9d444b9..d405847 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -266,30 +266,34 @@ impl Matrix4 { } } -impl VectorSpace for Matrix2 { - type Scalar = S; - +impl Zero for Matrix2 { #[inline] fn zero() -> Matrix2 { Matrix2::new(S::zero(), S::zero(), S::zero(), S::zero()) } + + #[inline] + fn is_zero(&self) -> bool { + Matrix2::approx_eq(self, &Matrix2::zero()) + } } -impl VectorSpace for Matrix3 { - type Scalar = S; - +impl Zero for Matrix3 { #[inline] fn zero() -> Matrix3 { 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 VectorSpace for Matrix4 { - type Scalar = S; - +impl Zero for Matrix4 { #[inline] fn zero() -> Matrix4 { Matrix4::new(S::zero(), S::zero(), S::zero(), S::zero(), @@ -297,6 +301,44 @@ impl VectorSpace for Matrix4 { 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 One for Matrix2 { + #[inline] + fn one() -> Matrix2 { + Matrix2::from_value(S::one()) + } +} + +impl One for Matrix3 { + #[inline] + fn one() -> Matrix3 { + Matrix3::from_value(S::one()) + } +} + +impl One for Matrix4 { + #[inline] + fn one() -> Matrix4 { + Matrix4::from_value(S::one()) + } +} + +impl VectorSpace for Matrix2 { + type Scalar = S; +} + +impl VectorSpace for Matrix3 { + type Scalar = S; +} + +impl VectorSpace for Matrix4 { + type Scalar = S; } impl Matrix for Matrix2 { @@ -349,11 +391,6 @@ impl SquareMatrix for Matrix2 { S::zero(), value.y) } - #[inline] - fn identity() -> Matrix2 { - Matrix2::from_value(S::one()) - } - #[inline] fn transpose_self(&mut self) { self.swap_elements((0, 1), (1, 0)); @@ -450,11 +487,6 @@ impl SquareMatrix for Matrix3 { S::zero(), S::zero(), value.z) } - #[inline] - fn identity() -> Matrix3 { - Matrix3::from_value(S::one()) - } - #[inline] fn transpose_self(&mut self) { self.swap_elements((0, 1), (1, 0)); @@ -567,11 +599,6 @@ impl SquareMatrix for Matrix4 { S::zero(), S::zero(), S::zero(), value.w) } - #[inline] - fn identity() -> Matrix4 { - Matrix4::from_value(S::one()) - } - fn transpose_self(&mut self) { self.swap_elements((0, 1), (1, 0)); self.swap_elements((0, 2), (2, 0)); diff --git a/src/quaternion.rs b/src/quaternion.rs index a630934..4bd39a6 100644 --- a/src/quaternion.rs +++ b/src/quaternion.rs @@ -120,13 +120,20 @@ impl Quaternion { } } -impl VectorSpace for Quaternion { - type Scalar = S; - +impl Zero for Quaternion { #[inline] fn zero() -> Quaternion { Quaternion::from_sv(S::zero(), Vector3::zero()) } + + #[inline] + fn is_zero(&self) -> bool { + Quaternion::approx_eq(self, &Quaternion::zero()) + } +} + +impl VectorSpace for Quaternion { + type Scalar = S; } impl MetricSpace for Quaternion { diff --git a/src/structure.rs b/src/structure.rs index d4771f2..c1130de 100644 --- a/src/structure.rs +++ b/src/structure.rs @@ -122,6 +122,17 @@ pub trait ElementWise { /// 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 { /// let downscaled_translation = translation / scale_factor; /// ``` pub trait VectorSpace: Copy + Clone where + Self: Zero, + Self: Add, Self: Sub, @@ -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 = ::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::Unitless>, + Self: Zero, + Self: Neg, Self: Add, Self: Sub, @@ -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. /// diff --git a/src/vector.rs b/src/vector.rs index d5d0650..b5ecf03 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -140,15 +140,22 @@ macro_rules! impl_vector { } } - impl VectorSpace for $VectorN { - type Scalar = S; + impl Zero for $VectorN { + #[inline] + fn zero() -> $VectorN { + $VectorN::from_value(S::zero()) + } #[inline] - fn zero() -> Self { - Self::from_value(Self::Scalar::zero()) + fn is_zero(&self) -> bool { + *self == $VectorN::zero() } } + impl VectorSpace for $VectorN { + type Scalar = S; + } + impl> Neg for $VectorN { type Output = $VectorN;