Replace deprecated std::num traits

These traits are akin to the deprecated standard library traits (Zero, One,
Primitive) to keep everything running as before. However, for the long term a
better algebraic abstraction should be used/provided.
This commit is contained in:
Eduard Bopp 2014-11-20 16:28:02 +01:00
parent ce4ec62798
commit 9f8580eeca
13 changed files with 130 additions and 80 deletions

View file

@ -24,9 +24,9 @@ use point::{Point, Point2, Point3};
use vector::{Vector, Vector2, Vector3}; use vector::{Vector, Vector2, Vector3};
use ray::{Ray2}; use ray::{Ray2};
use intersect::Intersect; use intersect::Intersect;
use num::{BaseNum, BaseFloat}; use num::{zero, one, BaseNum, BaseFloat};
use std::fmt; use std::fmt;
use std::num::{zero, one, Float}; use std::num::Float;
pub trait Aabb<S: BaseNum, V: Vector<S>, P: Point<S, V>> { pub trait Aabb<S: BaseNum, V: Vector<S>, P: Point<S, V>> {
/// Create a new AABB using two points as opposing corners. /// Create a new AABB using two points as opposing corners.

View file

@ -16,10 +16,10 @@
//! Angle units for type-safe, self-documenting code. //! Angle units for type-safe, self-documenting code.
use std::fmt; use std::fmt;
use std::num::{One, one, Zero, zero, cast, Float}; use std::num::{cast, Float};
use approx::ApproxEq; use approx::ApproxEq;
use num::BaseFloat; use num::{BaseFloat, One, one, Zero, zero};
/// An angle, in radians /// An angle, in radians
#[deriving(Clone, PartialEq, PartialOrd, Hash, Encodable, Decodable, Rand)] #[deriving(Clone, PartialEq, PartialOrd, Hash, Encodable, Decodable, Rand)]

View file

@ -77,7 +77,7 @@ pub use obb::{Obb2, Obb3};
pub use sphere::Sphere; pub use sphere::Sphere;
pub use approx::ApproxEq; pub use approx::ApproxEq;
pub use num::{PartialOrd, BaseNum, BaseInt, BaseFloat}; pub use num::{BaseNum, BaseInt, BaseFloat, One, one, Zero, zero};
// Modules // Modules

View file

@ -15,9 +15,7 @@
//! Line segments //! Line segments
use std::num::{Zero, zero, One, one}; use num::{BaseNum, BaseFloat, Zero, zero, One, one};
use num::{BaseNum, BaseFloat};
use point::{Point, Point2, Point3}; use point::{Point, Point2, Point3};
use vector::{Vector, Vector2}; use vector::{Vector, Vector2};
use ray::{Ray2}; use ray::{Ray2};

View file

@ -17,12 +17,12 @@
use std::fmt; use std::fmt;
use std::mem; use std::mem;
use std::num::{Zero, zero, One, one, cast}; use std::num::cast;
use angle::{Rad, sin, cos, sin_cos}; use angle::{Rad, sin, cos, sin_cos};
use approx::ApproxEq; use approx::ApproxEq;
use array::{Array1, Array2, FixedArray}; use array::{Array1, Array2, FixedArray};
use num::{BaseFloat, BaseNum}; use num::{BaseFloat, BaseNum, Zero, zero, One, one};
use point::{Point, Point3}; use point::{Point, Point3};
use quaternion::{Quaternion, ToQuaternion}; use quaternion::{Quaternion, ToQuaternion};
use vector::{Vector, EuclideanVector}; use vector::{Vector, EuclideanVector};

View file

@ -17,7 +17,7 @@ use approx::ApproxEq;
use std::cmp; use std::cmp;
use std::fmt; use std::fmt;
use std::num::{FloatMath, Int, Primitive}; use std::num::{FloatMath, Int, NumCast, Float};
/// A trait providing a [partial ordering](http://mathworld.wolfram.com/PartialOrder.html). /// A trait providing a [partial ordering](http://mathworld.wolfram.com/PartialOrder.html).
pub trait PartialOrd { pub trait PartialOrd {
@ -57,21 +57,90 @@ macro_rules! partial_ord_float (
partial_ord_float!(f32) partial_ord_float!(f32)
partial_ord_float!(f64) partial_ord_float!(f64)
/// Base numeric types with partial ordering /// Additive neutral element
pub trait BaseNum: Primitive + PartialOrd + fmt::Show {} pub trait Zero {
fn zero() -> Self;
fn is_zero(&self) -> bool;
}
/// Multiplicative neutral element
pub trait One {
fn one() -> Self;
}
/// Base numeric types with partial ordering
pub trait BaseNum:
Copy + NumCast + Clone + Add<Self, Self> + Sub<Self, Self> +
Mul<Self, Self> + Div<Self, Self> + Rem<Self, Self> + Neg<Self> + PartialEq
+ PartialOrd + cmp::PartialOrd + fmt::Show + Zero + One
{}
macro_rules! impl_basenum_int (
($T: ident) => (
impl BaseNum for $T {}
impl Zero for $T {
fn zero() -> $T {
Int::zero()
}
fn is_zero(&self) -> bool {
*self == Int::zero()
}
}
impl One for $T {
fn one() -> $T {
Int::one()
}
}
)
)
impl_basenum_int!(i8)
impl_basenum_int!(i16)
impl_basenum_int!(i32)
impl_basenum_int!(i64)
impl_basenum_int!(u8)
impl_basenum_int!(u16)
impl_basenum_int!(u32)
impl_basenum_int!(u64)
impl_basenum_int!(int)
impl_basenum_int!(uint)
macro_rules! impl_basenum_float (
($T: ident) => (
impl BaseNum for $T {}
impl Zero for $T {
fn zero() -> $T {
Float::zero()
}
fn is_zero(&self) -> bool {
*self == Float::zero()
}
}
impl One for $T {
fn one() -> $T {
Float::one()
}
}
)
)
impl_basenum_float!(f32)
impl_basenum_float!(f64)
pub fn zero<T: Zero>() -> T {
Zero::zero()
}
pub fn one<T: One>() -> T {
One::one()
}
impl BaseNum for i8 {}
impl BaseNum for i16 {}
impl BaseNum for i32 {}
impl BaseNum for i64 {}
impl BaseNum for int {}
impl BaseNum for u8 {}
impl BaseNum for u16 {}
impl BaseNum for u32 {}
impl BaseNum for u64 {}
impl BaseNum for uint {}
impl BaseNum for f32 {}
impl BaseNum for f64 {}
/// Base integer types /// Base integer types
pub trait BaseInt : BaseNum + Int {} pub trait BaseInt : BaseNum + Int {}

View file

@ -14,11 +14,10 @@
// limitations under the License. // limitations under the License.
use std::fmt; use std::fmt;
use std::num::Zero;
use approx::ApproxEq; use approx::ApproxEq;
use intersect::Intersect; use intersect::Intersect;
use num::BaseFloat; use num::{BaseFloat, Zero, zero};
use point::{Point, Point3}; use point::{Point, Point3};
use ray::Ray3; use ray::Ray3;
use vector::{Vector3, Vector4}; use vector::{Vector3, Vector4};
@ -80,7 +79,7 @@ impl<S: BaseFloat> Plane<S> {
// find the normal vector that is perpendicular to v1 and v2 // find the normal vector that is perpendicular to v1 and v2
let mut n = v0.cross(&v1); let mut n = v0.cross(&v1);
if n.approx_eq(&Vector3::zero()) { None } if n.approx_eq(&zero()) { None }
else { else {
// compute the normal and the distance to the plane // compute the normal and the distance to the plane
n.normalize_self(); n.normalize_self();

View file

@ -19,11 +19,10 @@
use std::fmt; use std::fmt;
use std::mem; use std::mem;
use std::num::{one, zero};
use approx::ApproxEq; use approx::ApproxEq;
use array::{Array1, FixedArray}; use array::{Array1, FixedArray};
use num::{BaseNum, BaseFloat}; use num::{BaseNum, BaseFloat, one, zero};
use vector::*; use vector::*;
/// A point in 2-dimensional space. /// A point in 2-dimensional space.

View file

@ -13,12 +13,12 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::num::{zero, one, cast}; use std::num::cast;
use angle::{Angle, tan, cot}; use angle::{Angle, tan, cot};
use frustum::Frustum; use frustum::Frustum;
use matrix::{Matrix4, ToMatrix4}; use matrix::{Matrix4, ToMatrix4};
use num::BaseFloat; use num::{BaseFloat, zero, one};
use plane::Plane; use plane::Plane;
/// Create a perspective projection matrix. /// Create a perspective projection matrix.

View file

@ -15,13 +15,13 @@
use std::fmt; use std::fmt;
use std::mem; use std::mem;
use std::num::{zero, one, cast, Float}; use std::num::{cast, Float};
use angle::{Angle, Rad, acos, sin, sin_cos, rad}; use angle::{Angle, Rad, acos, sin, sin_cos, rad};
use approx::ApproxEq; use approx::ApproxEq;
use array::Array1; use array::Array1;
use matrix::{Matrix3, ToMatrix3, ToMatrix4, Matrix4}; use matrix::{Matrix3, ToMatrix3, ToMatrix4, Matrix4};
use num::BaseFloat; use num::{BaseFloat, one, zero};
use point::Point3; use point::Point3;
use rotation::{Rotation, Rotation3, Basis3, ToBasis3}; use rotation::{Rotation, Rotation3, Basis3, ToBasis3};
use vector::{Vector3, Vector, EuclideanVector}; use vector::{Vector3, Vector, EuclideanVector};
@ -87,7 +87,7 @@ impl<S: BaseFloat> Quaternion<S> {
/// The multiplicative identity, ie: `q = 1 + 0i + 0j + 0i` /// The multiplicative identity, ie: `q = 1 + 0i + 0j + 0i`
#[inline] #[inline]
pub fn identity() -> Quaternion<S> { pub fn identity() -> Quaternion<S> {
Quaternion::from_sv(one::<S>(), Vector3::zero()) Quaternion::from_sv(one::<S>(), zero())
} }
/// The result of multiplying the quaternion a scalar /// The result of multiplying the quaternion a scalar

View file

@ -16,13 +16,11 @@
//! Bounding sphere //! Bounding sphere
use intersect::Intersect; use intersect::Intersect;
use num::BaseFloat; use num::{BaseFloat, zero};
use point::{Point, Point3}; use point::{Point, Point3};
use ray::Ray3; use ray::Ray3;
use vector::Vector; use vector::Vector;
use std::num::zero;
#[deriving(Clone, PartialEq, Encodable, Decodable)] #[deriving(Clone, PartialEq, Encodable, Decodable)]
pub struct Sphere<S> { pub struct Sphere<S> {
pub center: Point3<S>, pub center: Point3<S>,

View file

@ -13,11 +13,11 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::{fmt, num}; use std::fmt;
use approx::ApproxEq; use approx::ApproxEq;
use matrix::{Matrix, Matrix4, ToMatrix4}; use matrix::{Matrix, Matrix4, ToMatrix4};
use num::{BaseNum, BaseFloat}; use num::{BaseNum, BaseFloat, zero, one};
use point::{Point, Point3}; use point::{Point, Point3};
use ray::Ray; use ray::Ray;
use rotation::{Rotation, Rotation3}; use rotation::{Rotation, Rotation3};
@ -87,9 +87,9 @@ impl<S: BaseFloat, V: Vector<S>, P: Point<S, V>, R: Rotation<S, V, P>> Transform
#[inline] #[inline]
fn identity() -> Decomposed<S, V, R> { fn identity() -> Decomposed<S, V, R> {
Decomposed { Decomposed {
scale: num::one(), scale: one(),
rot: Rotation::identity(), rot: Rotation::identity(),
disp: num::zero(), disp: zero(),
} }
} }
@ -99,7 +99,7 @@ impl<S: BaseFloat, V: Vector<S>, P: Point<S, V>, R: Rotation<S, V, P>> Transform
let rot: R = Rotation::look_at(&center.sub_p(eye), up); let rot: R = Rotation::look_at(&center.sub_p(eye), up);
let disp: V = rot.rotate_vector(&origin.sub_p(eye)); let disp: V = rot.rotate_vector(&origin.sub_p(eye));
Decomposed { Decomposed {
scale: num::one(), scale: one(),
rot: rot, rot: rot,
disp: disp, disp: disp,
} }
@ -124,10 +124,10 @@ impl<S: BaseFloat, V: Vector<S>, P: Point<S, V>, R: Rotation<S, V, P>> Transform
} }
fn invert(&self) -> Option<Decomposed<S, V, R>> { fn invert(&self) -> Option<Decomposed<S, V, R>> {
if self.scale.approx_eq(&num::zero()) { if self.scale.approx_eq(&zero()) {
None None
} else { } else {
let s = num::one::<S>() / self.scale; let s = one::<S>() / self.scale;
let r = self.rot.invert(); let r = self.rot.invert();
let d = r.rotate_vector(&self.disp).mul_s(-s); let d = r.rotate_vector(&self.disp).mul_s(-s);
Some(Decomposed { Some(Decomposed {
@ -144,7 +144,7 @@ pub trait Transform3<S>: Transform<S, Vector3<S>, Point3<S>>+ ToMatrix4<S> {}
impl<S: BaseFloat + 'static, R: Rotation3<S>> ToMatrix4<S> for Decomposed<S, Vector3<S>, R> { impl<S: BaseFloat + 'static, R: Rotation3<S>> ToMatrix4<S> for Decomposed<S, Vector3<S>, R> {
fn to_matrix4(&self) -> Matrix4<S> { fn to_matrix4(&self) -> Matrix4<S> {
let mut m = self.rot.to_matrix3().mul_s(self.scale.clone()).to_matrix4(); let mut m = self.rot.to_matrix3().mul_s(self.scale.clone()).to_matrix4();
m.w = self.disp.extend(num::one()); m.w = self.disp.extend(one());
m m
} }
} }
@ -177,7 +177,7 @@ impl<S: BaseFloat + 'static> Transform<S, Vector3<S>, Point3<S>> for AffineMatri
#[inline] #[inline]
fn transform_vector(&self, vec: &Vector3<S>) -> Vector3<S> { fn transform_vector(&self, vec: &Vector3<S>) -> Vector3<S> {
self.mat.mul_v(&vec.extend(num::zero())).truncate() self.mat.mul_v(&vec.extend(zero())).truncate()
} }
#[inline] #[inline]

View file

@ -22,29 +22,27 @@
//! vector are also provided: //! vector are also provided:
//! //!
//! ```rust //! ```rust
//! use cgmath::{Vector2, Vector3, Vector4}; //! use cgmath::{Vector2, Vector3, Vector4, one, zero};
//! //!
//! assert_eq!(Vector2::new(1.0f64, 0.0f64), Vector2::unit_x()); //! assert_eq!(Vector2::new(1.0f64, 0.0f64), Vector2::unit_x());
//! assert_eq!(Vector3::new(0.0f64, 0.0f64, 0.0f64), Vector3::zero()); //! assert_eq!(Vector3::new(0.0f64, 0.0f64, 0.0f64), zero());
//! assert_eq!(Vector4::from_value(1.0f64), Vector4::ident()); //! assert_eq!(Vector4::from_value(1.0f64), one());
//! ``` //! ```
//! //!
//! Vectors can be manipulated with typical mathematical operations (addition, //! Vectors can be manipulated with typical mathematical operations (addition,
//! subtraction, element-wise multiplication, element-wise division, negation) //! subtraction, element-wise multiplication, element-wise division, negation)
//! using the built-in operators. The additive and multiplicative inverses //! using the built-in operators. The additive and multiplicative neutral
//! (zero and one) provided by the standard library's `Zero` and `One` are also //! elements (zero and one) are also provided by this library
//! available:
//! //!
//! ```rust //! ```rust
//! use std::num::{Zero, One}; //! use cgmath::{Vector2, Vector3, Vector4, one, zero};
//! use cgmath::{Vector2, Vector3, Vector4};
//! //!
//! let a: Vector2<f64> = Vector2::new(3.0, 4.0); //! let a: Vector2<f64> = Vector2::new(3.0, 4.0);
//! let b: Vector2<f64> = Vector2::new(-3.0, -4.0); //! let b: Vector2<f64> = Vector2::new(-3.0, -4.0);
//! //!
//! assert_eq!(a + b, Zero::zero()); //! assert_eq!(a + b, zero());
//! assert_eq!(-(a * b), Vector2::new(9.0f64, 16.0f64)); //! assert_eq!(-(a * b), Vector2::new(9.0f64, 16.0f64));
//! assert_eq!(a / One::one(), a); //! assert_eq!(a / one(), a);
//! //!
//! // As with Rust's `int` and `f32` types, Vectors of different types cannot //! // As with Rust's `int` and `f32` types, Vectors of different types cannot
//! // be added and so on with impunity. The following will fail to compile: //! // be added and so on with impunity. The following will fail to compile:
@ -66,13 +64,12 @@
//! and [cross products](http://en.wikipedia.org/wiki/Cross_product). //! and [cross products](http://en.wikipedia.org/wiki/Cross_product).
//! //!
//! ```rust //! ```rust
//! use std::num::Zero; //! use cgmath::{Vector, Vector2, Vector3, Vector4, dot, zero};
//! use cgmath::{Vector, Vector2, Vector3, Vector4, dot};
//! //!
//! // All vectors implement the dot product as a method: //! // All vectors implement the dot product as a method:
//! let a: Vector2<f64> = Vector2::new(3.0, 6.0); //! let a: Vector2<f64> = Vector2::new(3.0, 6.0);
//! let b: Vector2<f64> = Vector2::new(-2.0, 1.0); //! let b: Vector2<f64> = Vector2::new(-2.0, 1.0);
//! assert_eq!(a.dot(&b), Zero::zero()); //! assert_eq!(a.dot(&b), zero());
//! //!
//! // But there is also a top-level function: //! // But there is also a top-level function:
//! assert_eq!(a.dot(&b), dot(a, b)); //! assert_eq!(a.dot(&b), dot(a, b));
@ -101,20 +98,16 @@
use std::fmt; use std::fmt;
use std::mem; use std::mem;
use std::num::{Zero, zero, One, one};
use angle::{Rad, atan2, acos}; use angle::{Rad, atan2, acos};
use approx::ApproxEq; use approx::ApproxEq;
use array::{Array1, FixedArray}; use array::{Array1, FixedArray};
use num::{BaseNum, BaseFloat}; use num::{BaseNum, BaseFloat, Zero, One, zero, one};
/// A trait that specifies a range of numeric operations for vectors. Not all /// 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 /// of these make sense from a linear algebra point of view, but are included
/// for pragmatic reasons. /// for pragmatic reasons.
pub trait Vector<S: BaseNum>: Array1<S> pub trait Vector<S: BaseNum>: Array1<S> + Zero + One + Neg<Self> {
+ Neg<Self>
+ Zero
+ One {
/// Add a scalar to this vector, returning a new vector. /// Add a scalar to this vector, returning a new vector.
fn add_s(&self, s: S) -> Self; fn add_s(&self, s: S) -> Self;
/// Subtract a scalar from this vector, returning a new vector. /// Subtract a scalar from this vector, returning a new vector.
@ -202,14 +195,17 @@ macro_rules! vec(
} }
} }
impl<$S: BaseNum> $Self<$S> { impl<$S: Zero> Zero for $Self<$S> {
/// The additive identity of the vector.
#[inline] #[inline]
pub fn zero() -> $Self<$S> { $Self::from_value(zero()) } fn zero() -> $Self<S> { $Self { $($field: zero()),+ } }
/// The multiplicative identity of the vector.
#[inline] #[inline]
pub fn ident() -> $Self<$S> { $Self::from_value(one()) } fn is_zero(&self) -> bool { $((self.$field.is_zero()) )&&+ }
}
impl<$S: One> One for $Self<$S> {
#[inline]
fn one() -> $Self<$S> { $Self { $($field: one()),+ } }
} }
impl<$S> FixedArray<[$S, ..$n]> for $Self<$S> { impl<$S> FixedArray<[$S, ..$n]> for $Self<$S> {
@ -307,11 +303,6 @@ macro_rules! vec(
#[inline] fn sub(&self, v: &$Self<S>) -> $Self<S> { self.sub_v(v) } #[inline] fn sub(&self, v: &$Self<S>) -> $Self<S> { self.sub_v(v) }
} }
impl<S: BaseNum> Zero for $Self<S> {
#[inline] fn zero() -> $Self<S> { $Self::from_value(zero()) }
#[inline] fn is_zero(&self) -> bool { *self == zero() }
}
impl<S: BaseNum> Neg<$Self<S>> for $Self<S> { impl<S: BaseNum> Neg<$Self<S>> for $Self<S> {
#[inline] fn neg(&self) -> $Self<S> { $Self::new($(-self.$field),+) } #[inline] fn neg(&self) -> $Self<S> { $Self::new($(-self.$field),+) }
} }
@ -328,10 +319,6 @@ macro_rules! vec(
#[inline] fn rem(&self, v: &$Self<S>) -> $Self<S> { self.rem_v(v) } #[inline] fn rem(&self, v: &$Self<S>) -> $Self<S> { self.rem_v(v) }
} }
impl<S: BaseNum> One for $Self<S> {
#[inline] fn one() -> $Self<S> { $Self::from_value(one()) }
}
impl<S: BaseFloat> ApproxEq<S> for $Self<S> { impl<S: BaseFloat> ApproxEq<S> for $Self<S> {
#[inline] #[inline]
fn approx_eq_eps(&self, other: &$Self<S>, epsilon: &S) -> bool { fn approx_eq_eps(&self, other: &$Self<S>, epsilon: &S) -> bool {