Add a double-trait-dispatch-trick based cast trait

The Cast trait replaces both MatCast and VecCast.
This commit is contained in:
Sébastien Crozet 2013-10-09 22:59:44 +02:00
parent 2a4807262a
commit 7667d8f19a
17 changed files with 358 additions and 98 deletions

View File

@ -7,6 +7,7 @@ pub use traits::{
AlgebraicVec,
AlgebraicVecExt,
Basis,
Cast,
Col,
Cov,
Cross,
@ -20,7 +21,6 @@ pub use traits::{
IterableMut,
LMul,
Mat,
MatCast,
Mean,
Norm,
Outer,
@ -34,7 +34,6 @@ pub use traits::{
Transpose,
UniformSphereSample,
Vec,
VecCast,
VecExt
};
@ -709,26 +708,6 @@ pub fn mean<N, M: Mean<N>>(observations: &M) -> N {
//
//
/*
* MatCast<M>
*/
/// Converts a matrix to a matrix with different value type.
#[inline(always)]
pub fn cast_mat<M: MatCast<Res>, Res>(m: M) -> Res {
MatCast::from(m)
}
/*
* VecCast<M>
*/
/// Converts a matrix to a matrix with different value type.
#[inline(always)]
pub fn cast_vec<V: VecCast<Res>, Res>(v: V) -> Res {
VecCast::from(v)
}
/*
* Basis
*/
@ -764,6 +743,28 @@ pub fn dim<V: Dim>() -> uint {
Dim::dim(None::<V>)
}
/*
* Cast<T>
*/
/// Converts an object from one type to another.
///
/// For primitive types, this is the same as the `as` keywords.
/// Those properties are preserved by a cast:
/// * Type-level geometric invariants cannot be broken (eg. a cast from Rot3<f64> to Rot3<i64>
/// is not possible)
/// * A cast to a type with more type-level invariants cannot be done (eg. a cast from
/// Mat<f64> to Rot3<f64> is not possible)
/// * For primitive types an unbounded cast is done using the `as` keyword (this is different
/// from the standard library which makes bound-checking to ensure eg. that a i64 is not out of
/// the range of an i32 when a cast from i64 to i32 is done).
/// * A cast does not affect the dimension of an algebraic object. Note that this prevents an
/// isometric transform to be cast to a raw matrix. Use `to_homogeneous` for that special
/// purpose.
#[inline(always)]
pub fn cast<T, U: Cast<T>>(t: T) -> U {
Cast::from(t)
}
/*
* Indexable
*/

View File

@ -4,12 +4,13 @@
use std::rand::Rand;
use std::rand;
use std::num::{One, Zero, from_f32, from_uint};
use std::num::{One, Zero};
use std::vec;
use std::cmp::ApproxEq;
use std::util;
use structs::dvec::{DVec, DVecMulRhs};
use traits::operations::{Inv, Transpose, Mean, Cov};
use traits::structure::Cast;
#[doc(hidden)]
mod metal;
@ -409,10 +410,10 @@ impl<N: Clone> Transpose for DMat<N> {
}
}
impl<N: Num + FromPrimitive + Clone> Mean<DVec<N>> for DMat<N> {
impl<N: Num + Cast<f32> + Clone> Mean<DVec<N>> for DMat<N> {
fn mean(&self) -> DVec<N> {
let mut res: DVec<N> = DVec::new_zeros(self.ncols);
let normalizer: N = from_f32(1.0f32 / from_uint(self.nrows).unwrap()).unwrap();
let normalizer: N = Cast::from(1.0f32 / Cast::from(self.nrows));
for i in range(0u, self.nrows) {
for j in range(0u, self.ncols) {
@ -427,7 +428,7 @@ impl<N: Num + FromPrimitive + Clone> Mean<DVec<N>> for DMat<N> {
}
}
impl<N: Clone + Num + FromPrimitive + DMatDivRhs<N, DMat<N>> + ToStr > Cov<DMat<N>> for DMat<N> {
impl<N: Clone + Num + Cast<f32> + DMatDivRhs<N, DMat<N>> + ToStr > Cov<DMat<N>> for DMat<N> {
// FIXME: this could be heavily optimized, removing all temporaries by merging loops.
fn cov(&self) -> DMat<N> {
assert!(self.nrows > 1);
@ -445,7 +446,8 @@ impl<N: Clone + Num + FromPrimitive + DMatDivRhs<N, DMat<N>> + ToStr > Cov<DMat<
}
// FIXME: return a triangular matrix?
let normalizer: N = from_uint(self.nrows() - 1).unwrap();
let fnormalizer: f32 = Cast::from(self.nrows() - 1);
let normalizer: N = Cast::from(fnormalizer);
// FIXME: this will do 2 allocations for temporaries!
(centered.transposed() * centered) / normalizer
}

View File

@ -5,7 +5,7 @@
use std::num::{Zero, One};
use std::rand::{Rand, Rng};
use structs::mat::{Mat3, Mat4, Mat5};
use traits::structure::{Dim, Col};
use traits::structure::{Cast, Dim, Col};
use traits::operations::{Inv};
use traits::geometry::{RotationMatrix, Rotation, Rotate, AbsoluteRotate, Transform, Transformation,
Translate, Translation, ToHomogeneous};

View File

@ -17,7 +17,7 @@ macro_rules! iso_impl(
macro_rules! rotation_matrix_impl(
($t: ident, $trot: ident, $tlv: ident, $tav: ident) => (
impl<N: FromPrimitive + Algebraic + Trigonometric + Num + Clone>
impl<N: Cast<f32> + Algebraic + Trigonometric + Num + Clone>
RotationMatrix<$tlv<N>, $tav<N>, $trot<N>> for $t<N> {
#[inline]
fn to_rot_mat(&self) -> $trot<N> {
@ -132,7 +132,7 @@ macro_rules! translate_impl(
macro_rules! rotation_impl(
($t: ident, $trot: ident, $tav: ident) => (
impl<N: Num + Trigonometric + Algebraic + FromPrimitive + Clone> Rotation<$tav<N>> for $t<N> {
impl<N: Cast<f32> + Num + Trigonometric + Algebraic + Clone> Rotation<$tav<N>> for $t<N> {
#[inline]
fn rotation(&self) -> $tav<N> {
self.rotation.rotation()

View File

@ -9,7 +9,7 @@ use std::vec::{VecIterator, VecMutIterator};
use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6, Vec1MulRhs, Vec4MulRhs,
Vec5MulRhs, Vec6MulRhs};
use traits::structure::{MatCast, Row, Col, Iterable, IterableMut, Dim, Indexable};
use traits::structure::{Cast, Row, Col, Iterable, IterableMut, Dim, Indexable};
use traits::operations::{Absolute, Transpose, Inv, Outer};
use traits::geometry::{ToHomogeneous, FromHomogeneous};
@ -42,12 +42,14 @@ double_dispatch_binop_decl_trait!(Mat1, Mat1MulRhs)
double_dispatch_binop_decl_trait!(Mat1, Mat1DivRhs)
double_dispatch_binop_decl_trait!(Mat1, Mat1AddRhs)
double_dispatch_binop_decl_trait!(Mat1, Mat1SubRhs)
double_dispatch_cast_decl_trait!(Mat1, Mat1Cast)
mul_redispatch_impl!(Mat1, Mat1MulRhs)
div_redispatch_impl!(Mat1, Mat1DivRhs)
add_redispatch_impl!(Mat1, Mat1AddRhs)
sub_redispatch_impl!(Mat1, Mat1SubRhs)
cast_redispatch_impl!(Mat1, Mat1Cast)
mat_impl!(Mat1, m11)
mat_cast_impl!(Mat1, m11)
mat_cast_impl!(Mat1, Mat1Cast, m11)
add_impl!(Mat1, Mat1AddRhs, m11)
sub_impl!(Mat1, Mat1SubRhs, m11)
@ -133,13 +135,15 @@ double_dispatch_binop_decl_trait!(Mat2, Mat2MulRhs)
double_dispatch_binop_decl_trait!(Mat2, Mat2DivRhs)
double_dispatch_binop_decl_trait!(Mat2, Mat2AddRhs)
double_dispatch_binop_decl_trait!(Mat2, Mat2SubRhs)
double_dispatch_cast_decl_trait!(Mat2, Mat2Cast)
mul_redispatch_impl!(Mat2, Mat2MulRhs)
div_redispatch_impl!(Mat2, Mat2DivRhs)
add_redispatch_impl!(Mat2, Mat2AddRhs)
sub_redispatch_impl!(Mat2, Mat2SubRhs)
cast_redispatch_impl!(Mat2, Mat2Cast)
mat_impl!(Mat2, m11, m12,
m21, m22)
mat_cast_impl!(Mat2, m11, m12,
mat_cast_impl!(Mat2, Mat2Cast, m11, m12,
m21, m22)
add_impl!(Mat2, Mat2AddRhs, m11, m12, m21, m22)
sub_impl!(Mat2, Mat2SubRhs, m11, m12, m21, m22)
@ -229,14 +233,16 @@ double_dispatch_binop_decl_trait!(Mat3, Mat3MulRhs)
double_dispatch_binop_decl_trait!(Mat3, Mat3DivRhs)
double_dispatch_binop_decl_trait!(Mat3, Mat3AddRhs)
double_dispatch_binop_decl_trait!(Mat3, Mat3SubRhs)
double_dispatch_cast_decl_trait!(Mat3, Mat3Cast)
mul_redispatch_impl!(Mat3, Mat3MulRhs)
div_redispatch_impl!(Mat3, Mat3DivRhs)
add_redispatch_impl!(Mat3, Mat3AddRhs)
sub_redispatch_impl!(Mat3, Mat3SubRhs)
cast_redispatch_impl!(Mat3, Mat3Cast)
mat_impl!(Mat3, m11, m12, m13,
m21, m22, m23,
m31, m32, m33)
mat_cast_impl!(Mat3, m11, m12, m13,
mat_cast_impl!(Mat3, Mat3Cast, m11, m12, m13,
m21, m22, m23,
m31, m32, m33)
add_impl!(Mat3, Mat3AddRhs,
@ -339,17 +345,19 @@ double_dispatch_binop_decl_trait!(Mat4, Mat4MulRhs)
double_dispatch_binop_decl_trait!(Mat4, Mat4DivRhs)
double_dispatch_binop_decl_trait!(Mat4, Mat4AddRhs)
double_dispatch_binop_decl_trait!(Mat4, Mat4SubRhs)
double_dispatch_cast_decl_trait!(Mat4, Mat4Cast)
mul_redispatch_impl!(Mat4, Mat4MulRhs)
div_redispatch_impl!(Mat4, Mat4DivRhs)
add_redispatch_impl!(Mat4, Mat4AddRhs)
sub_redispatch_impl!(Mat4, Mat4SubRhs)
cast_redispatch_impl!(Mat4, Mat4Cast)
mat_impl!(Mat4,
m11, m12, m13, m14,
m21, m22, m23, m24,
m31, m32, m33, m34,
m41, m42, m43, m44
)
mat_cast_impl!(Mat4,
mat_cast_impl!(Mat4, Mat4Cast,
m11, m12, m13, m14,
m21, m22, m23, m24,
m31, m32, m33, m34,
@ -501,10 +509,12 @@ double_dispatch_binop_decl_trait!(Mat5, Mat5MulRhs)
double_dispatch_binop_decl_trait!(Mat5, Mat5DivRhs)
double_dispatch_binop_decl_trait!(Mat5, Mat5AddRhs)
double_dispatch_binop_decl_trait!(Mat5, Mat5SubRhs)
double_dispatch_cast_decl_trait!(Mat5, Mat5Cast)
mul_redispatch_impl!(Mat5, Mat5MulRhs)
div_redispatch_impl!(Mat5, Mat5DivRhs)
add_redispatch_impl!(Mat5, Mat5AddRhs)
sub_redispatch_impl!(Mat5, Mat5SubRhs)
cast_redispatch_impl!(Mat5, Mat5Cast)
mat_impl!(Mat5,
m11, m12, m13, m14, m15,
m21, m22, m23, m24, m25,
@ -512,7 +522,7 @@ mat_impl!(Mat5,
m41, m42, m43, m44, m45,
m51, m52, m53, m54, m55
)
mat_cast_impl!(Mat5,
mat_cast_impl!(Mat5, Mat5Cast,
m11, m12, m13, m14, m15,
m21, m22, m23, m24, m25,
m31, m32, m33, m34, m35,
@ -679,10 +689,12 @@ double_dispatch_binop_decl_trait!(Mat6, Mat6MulRhs)
double_dispatch_binop_decl_trait!(Mat6, Mat6DivRhs)
double_dispatch_binop_decl_trait!(Mat6, Mat6AddRhs)
double_dispatch_binop_decl_trait!(Mat6, Mat6SubRhs)
double_dispatch_cast_decl_trait!(Mat6, Mat6Cast)
mul_redispatch_impl!(Mat6, Mat6MulRhs)
div_redispatch_impl!(Mat6, Mat6DivRhs)
add_redispatch_impl!(Mat6, Mat6AddRhs)
sub_redispatch_impl!(Mat6, Mat6SubRhs)
cast_redispatch_impl!(Mat6, Mat6Cast)
mat_impl!(Mat6,
m11, m12, m13, m14, m15, m16,
m21, m22, m23, m24, m25, m26,
@ -691,7 +703,7 @@ mat_impl!(Mat6,
m51, m52, m53, m54, m55, m56,
m61, m62, m63, m64, m65, m66
)
mat_cast_impl!(Mat6,
mat_cast_impl!(Mat6, Mat6Cast,
m11, m12, m13, m14, m15, m16,
m21, m22, m23, m24, m25, m26,
m31, m32, m33, m34, m35, m36,

View File

@ -33,11 +33,11 @@ macro_rules! at_fast_impl(
)
macro_rules! mat_cast_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<Nin: NumCast + Clone, Nout: NumCast> MatCast<$t<Nout>> for $t<Nin> {
($t: ident, $tcast: ident, $comp0: ident $(,$compN: ident)*) => (
impl<Nin: Clone, Nout: Clone + Cast<Nin>> $tcast<Nout> for $t<Nin> {
#[inline]
fn from(m: $t<Nin>) -> $t<Nout> {
$t::new(NumCast::from(m.$comp0.clone()).unwrap() $(, NumCast::from(m.$compN.clone()).unwrap() )*)
fn to(v: $t<Nin>) -> $t<Nout> {
$t::new(Cast::from(v.$comp0.clone()) $(, Cast::from(v.$compN.clone()))*)
}
}
)

View File

@ -62,3 +62,23 @@ macro_rules! sub_redispatch_impl(
}
)
)
// Double dispatch traits to drive the Cast method for structured types with one type parameter.
macro_rules! double_dispatch_cast_decl_trait(
($t: ident, $tcast: ident) => (
pub trait $tcast<N> {
fn to(Self) -> $t<N>;
}
)
)
macro_rules! cast_redispatch_impl(
($t:ident, $tcast: ident) => (
impl<T: $tcast<N>, N> Cast<T> for $t<N> {
#[inline(always)]
fn from(t: T) -> $t<N> {
$tcast::to(t)
}
}
)
)

View File

@ -21,5 +21,6 @@ mod spec {
mod mat;
mod vec0;
mod vec;
mod primitives;
// mod complex;
}

View File

@ -2,11 +2,11 @@
#[allow(missing_doc)];
use std::num::{Zero, One, from_f32};
use std::num::{Zero, One};
use std::rand::{Rand, Rng};
use traits::geometry::{Rotate, Rotation, AbsoluteRotate, RotationMatrix, Transform, ToHomogeneous,
Norm, Cross};
use traits::structure::{Dim, Indexable, Row, Col};
use traits::structure::{Cast, Dim, Indexable, Row, Col};
use traits::operations::{Absolute, Inv, Transpose};
use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec2MulRhs, Vec3MulRhs, Vec4MulRhs};
use structs::mat::{Mat2, Mat3, Mat4, Mat5};
@ -168,11 +168,11 @@ impl<N: Clone + Num + Algebraic> Rot3<N> {
}
}
impl<N: Clone + Trigonometric + Num + Algebraic + FromPrimitive>
impl<N: Clone + Trigonometric + Num + Algebraic + Cast<f32>>
Rotation<Vec3<N>> for Rot3<N> {
#[inline]
fn rotation(&self) -> Vec3<N> {
let angle = ((self.submat.m11 + self.submat.m22 + self.submat.m33 - One::one()) / from_f32(2.0).unwrap()).acos();
let angle = ((self.submat.m11 + self.submat.m22 + self.submat.m33 - One::one()) / Cast::from(2.0)).acos();
if angle != angle {
// FIXME: handle that correctly

View File

@ -56,7 +56,7 @@ macro_rules! dim_impl(
macro_rules! rotation_matrix_impl(
($t: ident, $tlv: ident, $tav: ident) => (
impl<N: FromPrimitive + Algebraic + Trigonometric + Num + Clone>
impl<N: Cast<f32> + Algebraic + Trigonometric + Num + Clone>
RotationMatrix<$tlv<N>, $tav<N>, $t<N>> for $t<N> {
#[inline]
fn to_rot_mat(&self) -> $t<N> {

View File

@ -1,9 +1,9 @@
use std::num::{Zero, One, from_f32};
use std::num::{Zero, One};
use structs::vec::{Vec2, Vec3, Vec2MulRhs, Vec3MulRhs};
use structs::mat::{Mat1, Mat2, Mat3, Mat3MulRhs, Mat2MulRhs};
use structs::mat;
use traits::operations::{Inv};
use traits::structure::{Row, Col};
use traits::structure::{Cast, Row, Col};
// some specializations:
impl<N: Num + Clone>
@ -266,17 +266,17 @@ impl<N: Mul<N, N> + Add<N, N>> Mat2MulRhs<N, Vec2<N>> for Vec2<N> {
}
// FIXME: move this to another file?
impl<N: Real + FromPrimitive + Zero + One> mat::Mat4<N> {
impl<N: Real + Cast<f32> + Zero + One> mat::Mat4<N> {
/// Computes a projection matrix given the frustrum near plane width, height, the field of
/// view, and the distance to the clipping planes (`znear` and `zfar`).
pub fn new_perspective(width: N, height: N, fov: N, znear: N, zfar: N) -> mat::Mat4<N> {
let aspect = width / height;
let _1: N = One::one();
let sy = _1 / (fov * from_f32(0.5).unwrap()).tan();
let sy = _1 / (fov * Cast::from(0.5)).tan();
let sx = -sy / aspect;
let sz = -(zfar + znear) / (znear - zfar);
let tz = zfar * znear * from_f32(2.0).unwrap() / (znear - zfar);
let tz = zfar * znear * Cast::from(2.0) / (znear - zfar);
mat::Mat4::new(
sx, Zero::zero(), Zero::zero(), Zero::zero(),

View File

@ -0,0 +1,219 @@
//! nalgebra trait implementation for primitive types.
#[allow(missing_doc)];
#[allow(non_camel_case_types)];
use traits::structure::Cast;
// Double dispatch traits to drive the Cast method for primitive types.
macro_rules! primitive_double_dispatch_cast_decl_trait(
($t: ident, $tcast: ident) => (
pub trait $tcast {
fn to(Self) -> $t;
}
)
)
macro_rules! primitive_double_dispatch_cast_impl(
($ttarget: ident, $tself: ident, $tcast: ident) => (
impl $tcast for $tself{
#[inline(always)]
fn to(v: $tself) -> $ttarget {
v as $ttarget
}
}
)
)
macro_rules! primitive_cast_redispatch_impl(
($t:ident, $tcast: ident) => (
impl<T: $tcast> Cast<T> for $t {
#[inline(always)]
fn from(t: T) -> $t {
$tcast::to(t)
}
}
)
)
primitive_double_dispatch_cast_decl_trait!(f64, f64Cast)
primitive_double_dispatch_cast_decl_trait!(f32, f32Cast)
primitive_double_dispatch_cast_decl_trait!(i64, i64Cast)
primitive_double_dispatch_cast_decl_trait!(i32, i32Cast)
primitive_double_dispatch_cast_decl_trait!(i16, i16Cast)
primitive_double_dispatch_cast_decl_trait!(i8, i8Cast)
primitive_double_dispatch_cast_decl_trait!(u64, u64Cast)
primitive_double_dispatch_cast_decl_trait!(u32, u32Cast)
primitive_double_dispatch_cast_decl_trait!(u16, u16Cast)
primitive_double_dispatch_cast_decl_trait!(u8, u8Cast)
primitive_double_dispatch_cast_decl_trait!(int, intCast)
primitive_double_dispatch_cast_decl_trait!(uint, uintCast)
primitive_cast_redispatch_impl!(f64, f64Cast)
primitive_cast_redispatch_impl!(f32, f32Cast)
primitive_cast_redispatch_impl!(i64, i64Cast)
primitive_cast_redispatch_impl!(i32, i32Cast)
primitive_cast_redispatch_impl!(i16, i16Cast)
primitive_cast_redispatch_impl!(i8, i8Cast)
primitive_cast_redispatch_impl!(u64, u64Cast)
primitive_cast_redispatch_impl!(u32, u32Cast)
primitive_cast_redispatch_impl!(u16, u16Cast)
primitive_cast_redispatch_impl!(u8, u8Cast)
primitive_cast_redispatch_impl!(int, intCast)
primitive_cast_redispatch_impl!(uint, uintCast)
primitive_double_dispatch_cast_impl!(f64, f64, f64Cast)
primitive_double_dispatch_cast_impl!(f64, f32, f64Cast)
primitive_double_dispatch_cast_impl!(f64, i64, f64Cast)
primitive_double_dispatch_cast_impl!(f64, i32, f64Cast)
primitive_double_dispatch_cast_impl!(f64, i16, f64Cast)
primitive_double_dispatch_cast_impl!(f64, i8, f64Cast)
primitive_double_dispatch_cast_impl!(f64, u64, f64Cast)
primitive_double_dispatch_cast_impl!(f64, u32, f64Cast)
primitive_double_dispatch_cast_impl!(f64, u16, f64Cast)
primitive_double_dispatch_cast_impl!(f64, u8, f64Cast)
primitive_double_dispatch_cast_impl!(f64, int, f64Cast)
primitive_double_dispatch_cast_impl!(f64, uint, f64Cast)
primitive_double_dispatch_cast_impl!(f32, f64, f32Cast)
primitive_double_dispatch_cast_impl!(f32, f32, f32Cast)
primitive_double_dispatch_cast_impl!(f32, i64, f32Cast)
primitive_double_dispatch_cast_impl!(f32, i32, f32Cast)
primitive_double_dispatch_cast_impl!(f32, i16, f32Cast)
primitive_double_dispatch_cast_impl!(f32, i8, f32Cast)
primitive_double_dispatch_cast_impl!(f32, u64, f32Cast)
primitive_double_dispatch_cast_impl!(f32, u32, f32Cast)
primitive_double_dispatch_cast_impl!(f32, u16, f32Cast)
primitive_double_dispatch_cast_impl!(f32, u8, f32Cast)
primitive_double_dispatch_cast_impl!(f32, int, f32Cast)
primitive_double_dispatch_cast_impl!(f32, uint, f32Cast)
primitive_double_dispatch_cast_impl!(i64, f64, i64Cast)
primitive_double_dispatch_cast_impl!(i64, f32, i64Cast)
primitive_double_dispatch_cast_impl!(i64, i64, i64Cast)
primitive_double_dispatch_cast_impl!(i64, i32, i64Cast)
primitive_double_dispatch_cast_impl!(i64, i16, i64Cast)
primitive_double_dispatch_cast_impl!(i64, i8, i64Cast)
primitive_double_dispatch_cast_impl!(i64, u64, i64Cast)
primitive_double_dispatch_cast_impl!(i64, u32, i64Cast)
primitive_double_dispatch_cast_impl!(i64, u16, i64Cast)
primitive_double_dispatch_cast_impl!(i64, u8, i64Cast)
primitive_double_dispatch_cast_impl!(i64, int, i64Cast)
primitive_double_dispatch_cast_impl!(i64, uint, i64Cast)
primitive_double_dispatch_cast_impl!(i32, f64, i32Cast)
primitive_double_dispatch_cast_impl!(i32, f32, i32Cast)
primitive_double_dispatch_cast_impl!(i32, i64, i32Cast)
primitive_double_dispatch_cast_impl!(i32, i32, i32Cast)
primitive_double_dispatch_cast_impl!(i32, i16, i32Cast)
primitive_double_dispatch_cast_impl!(i32, i8, i32Cast)
primitive_double_dispatch_cast_impl!(i32, u64, i32Cast)
primitive_double_dispatch_cast_impl!(i32, u32, i32Cast)
primitive_double_dispatch_cast_impl!(i32, u16, i32Cast)
primitive_double_dispatch_cast_impl!(i32, u8, i32Cast)
primitive_double_dispatch_cast_impl!(i32, int, i32Cast)
primitive_double_dispatch_cast_impl!(i32, uint, i32Cast)
primitive_double_dispatch_cast_impl!(i16, f64, i16Cast)
primitive_double_dispatch_cast_impl!(i16, f32, i16Cast)
primitive_double_dispatch_cast_impl!(i16, i64, i16Cast)
primitive_double_dispatch_cast_impl!(i16, i32, i16Cast)
primitive_double_dispatch_cast_impl!(i16, i16, i16Cast)
primitive_double_dispatch_cast_impl!(i16, i8, i16Cast)
primitive_double_dispatch_cast_impl!(i16, u64, i16Cast)
primitive_double_dispatch_cast_impl!(i16, u32, i16Cast)
primitive_double_dispatch_cast_impl!(i16, u16, i16Cast)
primitive_double_dispatch_cast_impl!(i16, u8, i16Cast)
primitive_double_dispatch_cast_impl!(i16, int, i16Cast)
primitive_double_dispatch_cast_impl!(i16, uint, i16Cast)
primitive_double_dispatch_cast_impl!(i8, f64, i8Cast)
primitive_double_dispatch_cast_impl!(i8, f32, i8Cast)
primitive_double_dispatch_cast_impl!(i8, i64, i8Cast)
primitive_double_dispatch_cast_impl!(i8, i32, i8Cast)
primitive_double_dispatch_cast_impl!(i8, i16, i8Cast)
primitive_double_dispatch_cast_impl!(i8, i8, i8Cast)
primitive_double_dispatch_cast_impl!(i8, u64, i8Cast)
primitive_double_dispatch_cast_impl!(i8, u32, i8Cast)
primitive_double_dispatch_cast_impl!(i8, u16, i8Cast)
primitive_double_dispatch_cast_impl!(i8, u8, i8Cast)
primitive_double_dispatch_cast_impl!(i8, int, i8Cast)
primitive_double_dispatch_cast_impl!(i8, uint, i8Cast)
primitive_double_dispatch_cast_impl!(u64, f64, u64Cast)
primitive_double_dispatch_cast_impl!(u64, f32, u64Cast)
primitive_double_dispatch_cast_impl!(u64, i64, u64Cast)
primitive_double_dispatch_cast_impl!(u64, i32, u64Cast)
primitive_double_dispatch_cast_impl!(u64, i16, u64Cast)
primitive_double_dispatch_cast_impl!(u64, i8, u64Cast)
primitive_double_dispatch_cast_impl!(u64, u64, u64Cast)
primitive_double_dispatch_cast_impl!(u64, u32, u64Cast)
primitive_double_dispatch_cast_impl!(u64, u16, u64Cast)
primitive_double_dispatch_cast_impl!(u64, u8, u64Cast)
primitive_double_dispatch_cast_impl!(u64, int, u64Cast)
primitive_double_dispatch_cast_impl!(u64, uint, u64Cast)
primitive_double_dispatch_cast_impl!(u32, f64, u32Cast)
primitive_double_dispatch_cast_impl!(u32, f32, u32Cast)
primitive_double_dispatch_cast_impl!(u32, i64, u32Cast)
primitive_double_dispatch_cast_impl!(u32, i32, u32Cast)
primitive_double_dispatch_cast_impl!(u32, i16, u32Cast)
primitive_double_dispatch_cast_impl!(u32, i8, u32Cast)
primitive_double_dispatch_cast_impl!(u32, u64, u32Cast)
primitive_double_dispatch_cast_impl!(u32, u32, u32Cast)
primitive_double_dispatch_cast_impl!(u32, u16, u32Cast)
primitive_double_dispatch_cast_impl!(u32, u8, u32Cast)
primitive_double_dispatch_cast_impl!(u32, int, u32Cast)
primitive_double_dispatch_cast_impl!(u32, uint, u32Cast)
primitive_double_dispatch_cast_impl!(u16, f64, u16Cast)
primitive_double_dispatch_cast_impl!(u16, f32, u16Cast)
primitive_double_dispatch_cast_impl!(u16, i64, u16Cast)
primitive_double_dispatch_cast_impl!(u16, i32, u16Cast)
primitive_double_dispatch_cast_impl!(u16, i16, u16Cast)
primitive_double_dispatch_cast_impl!(u16, i8, u16Cast)
primitive_double_dispatch_cast_impl!(u16, u64, u16Cast)
primitive_double_dispatch_cast_impl!(u16, u32, u16Cast)
primitive_double_dispatch_cast_impl!(u16, u16, u16Cast)
primitive_double_dispatch_cast_impl!(u16, u8, u16Cast)
primitive_double_dispatch_cast_impl!(u16, int, u16Cast)
primitive_double_dispatch_cast_impl!(u16, uint, u16Cast)
primitive_double_dispatch_cast_impl!(u8, f64, u8Cast)
primitive_double_dispatch_cast_impl!(u8, f32, u8Cast)
primitive_double_dispatch_cast_impl!(u8, i64, u8Cast)
primitive_double_dispatch_cast_impl!(u8, i32, u8Cast)
primitive_double_dispatch_cast_impl!(u8, i16, u8Cast)
primitive_double_dispatch_cast_impl!(u8, i8, u8Cast)
primitive_double_dispatch_cast_impl!(u8, u64, u8Cast)
primitive_double_dispatch_cast_impl!(u8, u32, u8Cast)
primitive_double_dispatch_cast_impl!(u8, u16, u8Cast)
primitive_double_dispatch_cast_impl!(u8, u8, u8Cast)
primitive_double_dispatch_cast_impl!(u8, int, u8Cast)
primitive_double_dispatch_cast_impl!(u8, uint, u8Cast)
primitive_double_dispatch_cast_impl!(uint, f64, uintCast)
primitive_double_dispatch_cast_impl!(uint, f32, uintCast)
primitive_double_dispatch_cast_impl!(uint, i64, uintCast)
primitive_double_dispatch_cast_impl!(uint, i32, uintCast)
primitive_double_dispatch_cast_impl!(uint, i16, uintCast)
primitive_double_dispatch_cast_impl!(uint, i8, uintCast)
primitive_double_dispatch_cast_impl!(uint, u64, uintCast)
primitive_double_dispatch_cast_impl!(uint, u32, uintCast)
primitive_double_dispatch_cast_impl!(uint, u16, uintCast)
primitive_double_dispatch_cast_impl!(uint, u8, uintCast)
primitive_double_dispatch_cast_impl!(uint, int, uintCast)
primitive_double_dispatch_cast_impl!(uint, uint, uintCast)
primitive_double_dispatch_cast_impl!(int, f64, intCast)
primitive_double_dispatch_cast_impl!(int, f32, intCast)
primitive_double_dispatch_cast_impl!(int, i64, intCast)
primitive_double_dispatch_cast_impl!(int, i32, intCast)
primitive_double_dispatch_cast_impl!(int, i16, intCast)
primitive_double_dispatch_cast_impl!(int, i8, intCast)
primitive_double_dispatch_cast_impl!(int, u64, intCast)
primitive_double_dispatch_cast_impl!(int, u32, intCast)
primitive_double_dispatch_cast_impl!(int, u16, intCast)
primitive_double_dispatch_cast_impl!(int, u8, intCast)
primitive_double_dispatch_cast_impl!(int, int, intCast)
primitive_double_dispatch_cast_impl!(int, uint, intCast)

View File

@ -1,5 +1,5 @@
use std::num::{Zero, One};
use traits::structure::{VecCast, Row, Basis};
use traits::structure::{Cast, Row, Basis};
use traits::geometry::{Norm, Cross, CrossMatrix, UniformSphereSample};
use structs::vec::{Vec1, Vec2, Vec3, Vec4};
use structs::mat::Mat3;
@ -115,7 +115,7 @@ impl<N: Clone + Ord + Algebraic + Signed> Basis for Vec3<N> {
}
// FIXME: this bad: this fixes definitly the number of samples…
static SAMPLES_2_F64: [Vec2<f64>, ..21] = [
static SAMPLES_2_F32: [Vec2<f32>, ..21] = [
Vec2 { x: 1.0, y: 0.0 },
Vec2 { x: 0.95557281, y: 0.29475517 },
Vec2 { x: 0.82623877, y: 0.56332006 },
@ -140,7 +140,7 @@ static SAMPLES_2_F64: [Vec2<f64>, ..21] = [
];
// Those vectors come from bullet 3d
static SAMPLES_3_F64: [Vec3<f64>, ..42] = [
static SAMPLES_3_F32: [Vec3<f32>, ..42] = [
Vec3 { x: 0.000000 , y: -0.000000, z: -1.000000 },
Vec3 { x: 0.723608 , y: -0.525725, z: -0.447219 },
Vec3 { x: -0.276388, y: -0.850649, z: -0.447219 },
@ -192,30 +192,30 @@ impl<N: One + Clone> UniformSphereSample for Vec1<N> {
}
}
impl<N: NumCast + Clone> UniformSphereSample for Vec2<N> {
impl<N: Cast<f32> + Clone> UniformSphereSample for Vec2<N> {
#[inline(always)]
fn sample(f: &fn(Vec2<N>)) {
for sample in SAMPLES_2_F64.iter() {
f(VecCast::from(*sample))
for sample in SAMPLES_2_F32.iter() {
f(Cast::from(*sample))
}
}
}
impl<N: NumCast + Clone> UniformSphereSample for Vec3<N> {
impl<N: Cast<f32> + Clone> UniformSphereSample for Vec3<N> {
#[inline(always)]
fn sample(f: &fn(Vec3<N>)) {
for sample in SAMPLES_3_F64.iter() {
f(VecCast::from(*sample))
for sample in SAMPLES_3_F32.iter() {
f(Cast::from(*sample))
}
}
}
impl<N: NumCast + Clone> UniformSphereSample for Vec4<N> {
impl<N: Cast<f32> + Clone> UniformSphereSample for Vec4<N> {
#[inline(always)]
fn sample(_: &fn(Vec4<N>)) {
fail!("UniformSphereSample::<Vec4<N>>::sample : Not yet implemented.")
// for sample in SAMPLES_3_F64.iter() {
// f(VecCast::from(*sample))
// for sample in SAMPLES_3_F32.iter() {
// f(Cast::from(*sample))
// }
}
}

View File

@ -11,7 +11,7 @@ use std::cmp::ApproxEq;
use traits::geometry::{Transform, Rotate, FromHomogeneous, ToHomogeneous, Dot, Norm,
Translation, Translate};
use traits::structure::{VecCast, Basis, Dim, Indexable, Iterable, IterableMut};
use traits::structure::{Basis, Cast, Dim, Indexable, Iterable, IterableMut};
mod metal;
mod vec_macros;
@ -31,15 +31,17 @@ double_dispatch_binop_decl_trait!(Vec1, Vec1MulRhs)
double_dispatch_binop_decl_trait!(Vec1, Vec1DivRhs)
double_dispatch_binop_decl_trait!(Vec1, Vec1AddRhs)
double_dispatch_binop_decl_trait!(Vec1, Vec1SubRhs)
double_dispatch_cast_decl_trait!(Vec1, Vec1Cast)
mul_redispatch_impl!(Vec1, Vec1MulRhs)
div_redispatch_impl!(Vec1, Vec1DivRhs)
add_redispatch_impl!(Vec1, Vec1AddRhs)
sub_redispatch_impl!(Vec1, Vec1SubRhs)
cast_redispatch_impl!(Vec1, Vec1Cast)
new_impl!(Vec1, x)
ord_impl!(Vec1, x)
orderable_impl!(Vec1, x)
vec_axis_impl!(Vec1, x)
vec_cast_impl!(Vec1, x)
vec_cast_impl!(Vec1, Vec1Cast, x)
indexable_impl!(Vec1, 1)
at_fast_impl!(Vec1, 1)
new_repeat_impl!(Vec1, val, x)
@ -128,15 +130,17 @@ double_dispatch_binop_decl_trait!(Vec2, Vec2MulRhs)
double_dispatch_binop_decl_trait!(Vec2, Vec2DivRhs)
double_dispatch_binop_decl_trait!(Vec2, Vec2AddRhs)
double_dispatch_binop_decl_trait!(Vec2, Vec2SubRhs)
double_dispatch_cast_decl_trait!(Vec2, Vec2Cast)
mul_redispatch_impl!(Vec2, Vec2MulRhs)
div_redispatch_impl!(Vec2, Vec2DivRhs)
add_redispatch_impl!(Vec2, Vec2AddRhs)
sub_redispatch_impl!(Vec2, Vec2SubRhs)
cast_redispatch_impl!(Vec2, Vec2Cast)
new_impl!(Vec2, x, y)
ord_impl!(Vec2, x, y)
orderable_impl!(Vec2, x, y)
vec_axis_impl!(Vec2, x, y)
vec_cast_impl!(Vec2, x, y)
vec_cast_impl!(Vec2, Vec2Cast, x, y)
indexable_impl!(Vec2, 2)
at_fast_impl!(Vec2, 2)
new_repeat_impl!(Vec2, val, x, y)
@ -227,15 +231,17 @@ double_dispatch_binop_decl_trait!(Vec3, Vec3MulRhs)
double_dispatch_binop_decl_trait!(Vec3, Vec3DivRhs)
double_dispatch_binop_decl_trait!(Vec3, Vec3AddRhs)
double_dispatch_binop_decl_trait!(Vec3, Vec3SubRhs)
double_dispatch_cast_decl_trait!(Vec3, Vec3Cast)
mul_redispatch_impl!(Vec3, Vec3MulRhs)
div_redispatch_impl!(Vec3, Vec3DivRhs)
add_redispatch_impl!(Vec3, Vec3AddRhs)
sub_redispatch_impl!(Vec3, Vec3SubRhs)
cast_redispatch_impl!(Vec3, Vec3Cast)
new_impl!(Vec3, x, y, z)
ord_impl!(Vec3, x, y, z)
orderable_impl!(Vec3, x, y, z)
vec_axis_impl!(Vec3, x, y, z)
vec_cast_impl!(Vec3, x, y, z)
vec_cast_impl!(Vec3, Vec3Cast, x, y, z)
indexable_impl!(Vec3, 3)
at_fast_impl!(Vec3, 3)
new_repeat_impl!(Vec3, val, x, y, z)
@ -339,14 +345,16 @@ double_dispatch_binop_decl_trait!(PVec3, PVec3MulRhs)
double_dispatch_binop_decl_trait!(PVec3, PVec3DivRhs)
double_dispatch_binop_decl_trait!(PVec3, PVec3AddRhs)
double_dispatch_binop_decl_trait!(PVec3, PVec3SubRhs)
double_dispatch_cast_decl_trait!(PVec3, PVec3Cast)
mul_redispatch_impl!(PVec3, PVec3MulRhs)
div_redispatch_impl!(PVec3, PVec3DivRhs)
add_redispatch_impl!(PVec3, PVec3AddRhs)
sub_redispatch_impl!(PVec3, PVec3SubRhs)
cast_redispatch_impl!(PVec3, PVec3Cast)
ord_impl!(PVec3, x, y, z)
orderable_impl!(PVec3, x, y, z)
vec_axis_impl!(PVec3, x, y, z)
vec_cast_impl!(PVec3, x, y, z)
vec_cast_impl!(PVec3, PVec3Cast, x, y, z)
indexable_impl!(PVec3, 3)
at_fast_impl!(PVec3, 3)
new_repeat_impl!(PVec3, val, x, y, z, _unused)
@ -441,15 +449,17 @@ double_dispatch_binop_decl_trait!(Vec4, Vec4MulRhs)
double_dispatch_binop_decl_trait!(Vec4, Vec4DivRhs)
double_dispatch_binop_decl_trait!(Vec4, Vec4AddRhs)
double_dispatch_binop_decl_trait!(Vec4, Vec4SubRhs)
double_dispatch_cast_decl_trait!(Vec4, Vec4Cast)
mul_redispatch_impl!(Vec4, Vec4MulRhs)
div_redispatch_impl!(Vec4, Vec4DivRhs)
add_redispatch_impl!(Vec4, Vec4AddRhs)
sub_redispatch_impl!(Vec4, Vec4SubRhs)
cast_redispatch_impl!(Vec4, Vec4Cast)
new_impl!(Vec4, x, y, z, w)
ord_impl!(Vec4, x, y, z, w)
orderable_impl!(Vec4, x, y, z, w)
vec_axis_impl!(Vec4, x, y, z, w)
vec_cast_impl!(Vec4, x, y, z, w)
vec_cast_impl!(Vec4, Vec4Cast, x, y, z, w)
indexable_impl!(Vec4, 4)
at_fast_impl!(Vec4, 4)
new_repeat_impl!(Vec4, val, x, y, z, w)
@ -544,15 +554,17 @@ double_dispatch_binop_decl_trait!(Vec5, Vec5MulRhs)
double_dispatch_binop_decl_trait!(Vec5, Vec5DivRhs)
double_dispatch_binop_decl_trait!(Vec5, Vec5AddRhs)
double_dispatch_binop_decl_trait!(Vec5, Vec5SubRhs)
double_dispatch_cast_decl_trait!(Vec5, Vec5Cast)
mul_redispatch_impl!(Vec5, Vec5MulRhs)
div_redispatch_impl!(Vec5, Vec5DivRhs)
add_redispatch_impl!(Vec5, Vec5AddRhs)
sub_redispatch_impl!(Vec5, Vec5SubRhs)
cast_redispatch_impl!(Vec5, Vec5Cast)
new_impl!(Vec5, x, y, z, w, a)
ord_impl!(Vec5, x, y, z, w, a)
orderable_impl!(Vec5, x, y, z, w, a)
vec_axis_impl!(Vec5, x, y, z, w, a)
vec_cast_impl!(Vec5, x, y, z, w, a)
vec_cast_impl!(Vec5, Vec5Cast, x, y, z, w, a)
indexable_impl!(Vec5, 5)
at_fast_impl!(Vec5, 5)
new_repeat_impl!(Vec5, val, x, y, z, w, a)
@ -649,15 +661,17 @@ double_dispatch_binop_decl_trait!(Vec6, Vec6MulRhs)
double_dispatch_binop_decl_trait!(Vec6, Vec6DivRhs)
double_dispatch_binop_decl_trait!(Vec6, Vec6AddRhs)
double_dispatch_binop_decl_trait!(Vec6, Vec6SubRhs)
double_dispatch_cast_decl_trait!(Vec6, Vec6Cast)
mul_redispatch_impl!(Vec6, Vec6MulRhs)
div_redispatch_impl!(Vec6, Vec6DivRhs)
add_redispatch_impl!(Vec6, Vec6AddRhs)
sub_redispatch_impl!(Vec6, Vec6SubRhs)
cast_redispatch_impl!(Vec6, Vec6Cast)
new_impl!(Vec6, x, y, z, w, a, b)
ord_impl!(Vec6, x, y, z, w, a, b)
orderable_impl!(Vec6, x, y, z, w, a, b)
vec_axis_impl!(Vec6, x, y, z, w, a, b)
vec_cast_impl!(Vec6, x, y, z, w, a, b)
vec_cast_impl!(Vec6, Vec6Cast, x, y, z, w, a, b)
indexable_impl!(Vec6, 6)
at_fast_impl!(Vec6, 6)
new_repeat_impl!(Vec6, val, x, y, z, w, a, b)

View File

@ -111,11 +111,11 @@ macro_rules! vec_axis_impl(
)
macro_rules! vec_cast_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<Nin: NumCast + Clone, Nout: Clone + NumCast> VecCast<$t<Nout>> for $t<Nin> {
($t: ident, $tcast: ident, $comp0: ident $(,$compN: ident)*) => (
impl<Nin: Clone, Nout: Clone + Cast<Nin>> $tcast<Nout> for $t<Nin> {
#[inline]
fn from(v: $t<Nin>) -> $t<Nout> {
$t::new(NumCast::from(v.$comp0.clone()).unwrap() $(, NumCast::from(v.$compN.clone()).unwrap())*)
fn to(v: $t<Nin>) -> $t<Nout> {
$t::new(Cast::from(v.$comp0.clone()) $(, Cast::from(v.$compN.clone()))*)
}
}
)

View File

@ -4,8 +4,8 @@ pub use self::geometry::{AbsoluteRotate, Cross, CrossMatrix, Dot, FromHomogeneou
Rotation, RotationMatrix, RotationWithTranslation, ToHomogeneous,
Transform, Transformation, Translate, Translation, UniformSphereSample};
pub use self::structure::{AlgebraicVec, AlgebraicVecExt, Basis, Col, Dim, Indexable, Iterable,
IterableMut, Mat, MatCast, Row, Vec, VecCast, VecExt};
pub use self::structure::{AlgebraicVec, AlgebraicVecExt, Basis, Cast, Col, Dim, Indexable,
Iterable, IterableMut, Mat, Row, Vec, VecExt};
pub use self::operations::{Absolute, Cov, Inv, LMul, Mean, Outer, RMul, ScalarAdd, ScalarSub,
Transpose};

View File

@ -5,6 +5,12 @@ use std::vec::{VecIterator, VecMutIterator};
use traits::operations::{RMul, LMul, ScalarAdd, ScalarSub};
use traits::geometry::{Dot, Norm, UniformSphereSample};
/// Traits of objects which can be created from an object of type `T`.
pub trait Cast<T> {
/// Converts an element of type `T` to an element of type `Self`.
fn from(t: T) -> Self;
}
/// Trait of matrices.
///
/// A matrix has rows and columns and are able to multiply them.
@ -13,14 +19,6 @@ pub trait Mat<R, C> : Row<R> + Col<C> + RMul<R> + LMul<C> { }
impl<M: Row<R> + Col<C> + RMul<R> + LMul<C>, R, C> Mat<R, C> for M {
}
/// Trait of matrices which can be converted to another matrix.
///
/// Use this to change easily the type of a matrix components.
pub trait MatCast<M> {
/// Converts `m` to have the type `M`.
fn from(m: Self) -> M;
}
// XXX: we keep ScalarAdd and ScalarSub here to avoid trait impl conflict (overriding) between the
// different Add/Sub traits. This is _so_ unfortunate…
@ -55,13 +53,6 @@ VecExt<N> for V { }
impl<N: Algebraic, V: AlgebraicVec<N> + VecExt<N> + Basis + Round> AlgebraicVecExt<N> for V { }
/// Trait of vectors which can be converted to another vector. Used to change the type of a vector
/// components.
pub trait VecCast<V> {
/// Converts `v` to have the type `V`.
fn from(v: Self) -> V;
}
// FIXME: return an iterator instead
/// Traits of objects which can form a basis (typically vectors).
pub trait Basis {