Merge pull request #385 from Marckvdv/patch-1

Implement component wise number casting for the Point and Matrix types.
This commit is contained in:
Brendan Zabarauskas 2016-10-04 16:25:59 +11:00 committed by GitHub
commit 4e29dc1b2e
4 changed files with 58 additions and 6 deletions

View file

@ -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<S: BaseFloat> Transform3<S> for Matrix3<S> {}
impl<S: BaseFloat> Transform3<S> for Matrix4<S> {}
macro_rules! impl_operators {
macro_rules! impl_matrix {
($MatrixN:ident, $VectorN:ident { $($field:ident : $row_index:expr),+ }) => {
impl_operator!(<S: BaseFloat> Neg for $MatrixN<S> {
fn neg(matrix) -> $MatrixN<S> { $MatrixN { $($field: -matrix.$field),+ } }
@ -971,6 +971,15 @@ macro_rules! impl_operators {
impl_scalar_ops!($MatrixN<i64> { $($field),+ });
impl_scalar_ops!($MatrixN<f32> { $($field),+ });
impl_scalar_ops!($MatrixN<f64> { $($field),+ });
impl<S: NumCast + Copy> $MatrixN<S> {
/// Component-wise casting to another type
#[inline]
pub fn cast<T: NumCast>(&self) -> $MatrixN<T> {
$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!(<S: BaseFloat> Mul<Matrix2<S> > for Matrix2<S> {
fn mul(lhs, rhs) -> Matrix2<S> {

View file

@ -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<S: NumCast + Copy> $PointN<S> {
/// Component-wise casting to another type
#[inline]
pub fn cast<T: NumCast>(&self) -> $PointN<T> {
$PointN { $($field: NumCast::from(self.$field).unwrap()),+ }
}
}
impl<S: BaseFloat> MetricSpace for $PointN<S> {
type Metric = S;

View file

@ -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::*;

View file

@ -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));
}