diff --git a/src/matrix.rs b/src/matrix.rs index 9d3acdf..6a1e2fd 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -14,7 +14,7 @@ // limitations under the License. use rand::{Rand, Rng}; -use num_traits::cast; +use num_traits::{cast, NumCast}; use std::fmt; use std::mem; use std::ops::*; @@ -917,7 +917,7 @@ impl Transform3 for Matrix3 {} impl Transform3 for Matrix4 {} -macro_rules! impl_operators { +macro_rules! impl_matrix { ($MatrixN:ident, $VectorN:ident { $($field:ident : $row_index:expr),+ }) => { impl_operator!( Neg for $MatrixN { fn neg(matrix) -> $MatrixN { $MatrixN { $($field: -matrix.$field),+ } } @@ -971,6 +971,15 @@ macro_rules! impl_operators { impl_scalar_ops!($MatrixN { $($field),+ }); impl_scalar_ops!($MatrixN { $($field),+ }); impl_scalar_ops!($MatrixN { $($field),+ }); + + + impl $MatrixN { + /// Component-wise casting to another type + #[inline] + pub fn cast(&self) -> $MatrixN { + $MatrixN { $($field: self.$field.cast() ),+ } + } + } } } @@ -988,9 +997,9 @@ macro_rules! impl_scalar_ops { }; } -impl_operators!(Matrix2, Vector2 { x: 0, y: 1 }); -impl_operators!(Matrix3, Vector3 { x: 0, y: 1, z: 2 }); -impl_operators!(Matrix4, Vector4 { x: 0, y: 1, z: 2, w: 3 }); +impl_matrix!(Matrix2, Vector2 { x: 0, y: 1 }); +impl_matrix!(Matrix3, Vector3 { x: 0, y: 1, z: 2 }); +impl_matrix!(Matrix4, Vector4 { x: 0, y: 1, z: 2, w: 3 }); impl_operator!( Mul > for Matrix2 { fn mul(lhs, rhs) -> Matrix2 { diff --git a/src/point.rs b/src/point.rs index a81312c..92ab046 100644 --- a/src/point.rs +++ b/src/point.rs @@ -17,6 +17,7 @@ //! disinguishes them from vectors, which have a length and direction, but do //! not have a fixed position. +use num_traits::NumCast; use std::fmt; use std::mem; use std::ops::*; @@ -128,6 +129,14 @@ macro_rules! impl_point { } } + impl $PointN { + /// Component-wise casting to another type + #[inline] + pub fn cast(&self) -> $PointN { + $PointN { $($field: NumCast::from(self.$field).unwrap()),+ } + } + } + impl MetricSpace for $PointN { type Metric = S; diff --git a/tests/matrix.rs b/tests/matrix.rs index f888f08..fc3cda3 100644 --- a/tests/matrix.rs +++ b/tests/matrix.rs @@ -704,6 +704,33 @@ pub mod matrix4 { assert_eq!(res, Vector4::new(1., 2., 3., 1.)); } + #[test] + fn test_cast() { + assert_ulps_eq!(Matrix2::new(0.2f64, 1.5, 4.7, 2.3).cast(), Matrix2::new(0.2f32, 1.5, 4.7, 2.3)); + assert_ulps_eq!(Matrix3::new( + 0.2f64, 1.5, 4.7, + 2.3, 5.7, 2.1, + 4.6, 5.2, 6.6, + ).cast(), Matrix3::new( + 0.2f32, 1.5, 4.7, + 2.3, 5.7, 2.1, + 4.6, 5.2, 6.6, + )); + + assert_ulps_eq!(Matrix4::new( + 0.2f64, 1.5, 4.7, 2.5, + 2.3, 5.7, 2.1, 1.1, + 4.6, 5.2, 6.6, 0.2, + 3.2, 1.8, 0.4, 2.9, + ).cast(), Matrix4::new( + 0.2f32, 1.5, 4.7, 2.5, + 2.3, 5.7, 2.1, 1.1, + 4.6, 5.2, 6.6, 0.2, + 3.2, 1.8, 0.4, 2.9, + )); + + } + mod from { use cgmath::*; diff --git a/tests/point.rs b/tests/point.rs index dc896d7..0078189 100644 --- a/tests/point.rs +++ b/tests/point.rs @@ -17,7 +17,7 @@ extern crate approx; extern crate cgmath; -use cgmath::{Point2, Point3}; +use cgmath::{Point1, Point2, Point3}; macro_rules! impl_test_mul { ($PointN:ident { $($field:ident),+ }, $s:expr, $v:expr) => ( @@ -74,3 +74,10 @@ fn test_rem() { impl_test_rem!(Point3 { x, y, z }, 2.0f32, Point3::new(2.0f32, 4.0, 6.0)); impl_test_rem!(Point2 { x, y }, 2.0f32, Point2::new(2.0f32, 4.0)); } + +#[test] +fn test_cast() { + assert_ulps_eq!(Point1::new(0.9f64).cast(), Point1::new(0.9f32)); + assert_ulps_eq!(Point2::new(0.9f64, 1.5).cast(), Point2::new(0.9f32, 1.5)); + assert_ulps_eq!(Point3::new(1.0f64, 2.4, -3.13).cast(), Point3::new(1.0f32, 2.4, -3.13)); +}