Implement Arbitrary for (almost) all types

Rot4 and Iso4 had to be left out, since Rot4 apparently lacks a working
constructor.

Thereby (almost) all types in nalgebra can now be used for quickcheck-style
testing.

"arbitrary" is now a conditionally compiled feature that contains these impls
adding a dependency on quickcheck.
This commit is contained in:
Eduard Bopp 2015-01-10 01:36:13 +01:00
parent dc7a85ccde
commit 1103996b83
17 changed files with 285 additions and 2 deletions

View File

@ -15,5 +15,12 @@ license = "BSD-3-Clause"
name = "nalgebra" name = "nalgebra"
path = "src/lib.rs" path = "src/lib.rs"
[features]
# Generate arbitrary instances of nalgebra types for testing with quickcheck
arbitrary = ["quickcheck"]
[dependencies] [dependencies]
rustc-serialize = "*" rustc-serialize = "*"
[dependencies.quickcheck]
optional = true

View File

@ -89,6 +89,9 @@ Feel free to add your project to this list if you happen to use **nalgebra**!
extern crate "rustc-serialize" as rustc_serialize; extern crate "rustc-serialize" as rustc_serialize;
#[cfg(feature="arbitrary")]
extern crate quickcheck;
#[cfg(test)] #[cfg(test)]
extern crate test; extern crate test;

View File

@ -13,6 +13,8 @@ use structs::dvec::DVec;
use traits::operations::{Inv, Transpose, Mean, Cov}; use traits::operations::{Inv, Transpose, Mean, Cov};
use traits::structure::{Cast, ColSlice, RowSlice, Diag, Eye, Indexable, Shape, Zero, One, BaseNum}; use traits::structure::{Cast, ColSlice, RowSlice, Diag, Eye, Indexable, Shape, Zero, One, BaseNum};
use std::fmt::{Show, Formatter, Result, String}; use std::fmt::{Show, Formatter, Result, String};
#[cfg(feature="arbitrary")]
use quickcheck::{Arbitrary, Gen};
/// Matrix with dimensions unknown at compile-time. /// Matrix with dimensions unknown at compile-time.
@ -703,3 +705,13 @@ impl<N: Copy + Sub<N, Output = N>> Sub<N> for DMat<N> {
res res
} }
} }
#[cfg(feature="arbitrary")]
impl<N: Arbitrary> Arbitrary for DMat<N> {
fn arbitrary<G: Gen>(g: &mut G) -> DMat<N> {
DMat::from_fn(
Arbitrary::arbitrary(g), Arbitrary::arbitrary(g),
|_, _| Arbitrary::arbitrary(g)
)
}
}

View File

@ -11,6 +11,8 @@ use std::ops::{Add, Sub, Mul, Div, Neg, Index, IndexMut};
use traits::operations::{ApproxEq, Axpy}; use traits::operations::{ApproxEq, Axpy};
use traits::geometry::{Dot, Norm}; use traits::geometry::{Dot, Norm};
use traits::structure::{Iterable, IterableMut, Indexable, Shape, BaseFloat, BaseNum, Zero, One}; use traits::structure::{Iterable, IterableMut, Indexable, Shape, BaseFloat, BaseNum, Zero, One};
#[cfg(feature="arbitrary")]
use quickcheck::{Arbitrary, Gen};
/// Heap allocated, dynamically sized vector. /// Heap allocated, dynamically sized vector.
#[derive(Eq, PartialEq, Show, Clone)] #[derive(Eq, PartialEq, Show, Clone)]
@ -78,6 +80,13 @@ impl<N> FromIterator<N> for DVec<N> {
} }
} }
#[cfg(feature="arbitrary")]
impl<N: Arbitrary> Arbitrary for DVec<N> {
fn arbitrary<G: Gen>(g: &mut G) -> DVec<N> {
DVec { at: Arbitrary::arbitrary(g) }
}
}
dvec_impl!(DVec); dvec_impl!(DVec);

View File

@ -520,5 +520,13 @@ macro_rules! small_dvec_from_impl (
} }
} }
} }
#[cfg(feature="arbitrary")]
impl<N: Arbitrary + Zero> Arbitrary for $dvec<N> {
#[inline]
fn arbitrary<G: Gen>(g: &mut G) -> $dvec<N> {
$dvec::from_fn(g.gen_range(0, $dim), |_| Arbitrary::arbitrary(g))
}
}
) )
); );

View File

@ -15,6 +15,9 @@ use structs::vec::{Vec1, Vec2, Vec3, Vec4};
use structs::pnt::{Pnt2, Pnt3, Pnt4}; use structs::pnt::{Pnt2, Pnt3, Pnt4};
use structs::rot::{Rot2, Rot3, Rot4}; use structs::rot::{Rot2, Rot3, Rot4};
#[cfg(feature="arbitrary")]
use quickcheck::{Arbitrary, Gen};
/// Two dimensional isometry. /// Two dimensional isometry.
/// ///
@ -112,6 +115,7 @@ translate_impl!(Iso2, Pnt2);
iso_mul_iso_impl!(Iso2); iso_mul_iso_impl!(Iso2);
iso_mul_pnt_impl!(Iso2, Pnt2); iso_mul_pnt_impl!(Iso2, Pnt2);
pnt_mul_iso_impl!(Iso2, Pnt2); pnt_mul_iso_impl!(Iso2, Pnt2);
arbitrary_iso_impl!(Iso2);
iso_impl!(Iso3, Rot3, Vec3, Vec3); iso_impl!(Iso3, Rot3, Vec3, Vec3);
rotation_matrix_impl!(Iso3, Rot3, Vec3, Vec3); rotation_matrix_impl!(Iso3, Rot3, Vec3, Vec3);
@ -131,6 +135,7 @@ translate_impl!(Iso3, Pnt3);
iso_mul_iso_impl!(Iso3); iso_mul_iso_impl!(Iso3);
iso_mul_pnt_impl!(Iso3, Pnt3); iso_mul_pnt_impl!(Iso3, Pnt3);
pnt_mul_iso_impl!(Iso3, Pnt3); pnt_mul_iso_impl!(Iso3, Pnt3);
arbitrary_iso_impl!(Iso3);
// iso_impl!(Iso4, Rot4, Vec4, Vec4); // iso_impl!(Iso4, Rot4, Vec4, Vec4);
// rotation_matrix_impl!(Iso4, Rot4, Vec4, Vec4); // rotation_matrix_impl!(Iso4, Rot4, Vec4, Vec4);
@ -150,3 +155,5 @@ translate_impl!(Iso4, Pnt4);
iso_mul_iso_impl!(Iso4); iso_mul_iso_impl!(Iso4);
iso_mul_pnt_impl!(Iso4, Pnt4); iso_mul_pnt_impl!(Iso4, Pnt4);
pnt_mul_iso_impl!(Iso4, Pnt4); pnt_mul_iso_impl!(Iso4, Pnt4);
// FIXME: as soon as Rot4<N>: Arbitrary
// arbitrary_iso_impl!(Iso4);

View File

@ -364,3 +364,17 @@ macro_rules! absolute_rotate_impl(
} }
) )
); );
macro_rules! arbitrary_iso_impl(
($t: ident) => (
#[cfg(feature="arbitrary")]
impl<N: Arbitrary + BaseFloat> Arbitrary for $t<N> {
fn arbitrary<G: Gen>(g: &mut G) -> $t<N> {
$t::new_with_rotmat(
Arbitrary::arbitrary(g),
Arbitrary::arbitrary(g)
)
}
}
)
);

View File

@ -15,6 +15,8 @@ use traits::structure::{Cast, Row, Col, Iterable, IterableMut, Dim, Indexable,
use traits::operations::{Absolute, Transpose, Inv, Outer, EigenQR}; use traits::operations::{Absolute, Transpose, Inv, Outer, EigenQR};
use traits::geometry::{ToHomogeneous, FromHomogeneous, Orig}; use traits::geometry::{ToHomogeneous, FromHomogeneous, Orig};
use linalg; use linalg;
#[cfg(feature="arbitrary")]
use quickcheck::{Arbitrary, Gen};
/// Special identity matrix. All its operation are no-ops. /// Special identity matrix. All its operation are no-ops.
@ -72,6 +74,7 @@ to_homogeneous_impl!(Mat1, Mat2, 1, 2);
from_homogeneous_impl!(Mat1, Mat2, 1, 2); from_homogeneous_impl!(Mat1, Mat2, 1, 2);
outer_impl!(Vec1, Mat1); outer_impl!(Vec1, Mat1);
eigen_qr_impl!(Mat1, Vec1); eigen_qr_impl!(Mat1, Vec1);
arbitrary_impl!(Mat1, m11);
/// Square matrix of dimension 2. /// Square matrix of dimension 2.
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)]
@ -120,6 +123,7 @@ to_homogeneous_impl!(Mat2, Mat3, 2, 3);
from_homogeneous_impl!(Mat2, Mat3, 2, 3); from_homogeneous_impl!(Mat2, Mat3, 2, 3);
outer_impl!(Vec2, Mat2); outer_impl!(Vec2, Mat2);
eigen_qr_impl!(Mat2, Vec2); eigen_qr_impl!(Mat2, Vec2);
arbitrary_impl!(Mat2, m11, m12, m21, m22);
/// Square matrix of dimension 3. /// Square matrix of dimension 3.
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)]
@ -202,6 +206,11 @@ to_homogeneous_impl!(Mat3, Mat4, 3, 4);
from_homogeneous_impl!(Mat3, Mat4, 3, 4); from_homogeneous_impl!(Mat3, Mat4, 3, 4);
outer_impl!(Vec3, Mat3); outer_impl!(Vec3, Mat3);
eigen_qr_impl!(Mat3, Vec3); eigen_qr_impl!(Mat3, Vec3);
arbitrary_impl!(Mat3,
m11, m12, m13,
m21, m22, m23,
m31, m32, m33
);
/// Square matrix of dimension 4. /// Square matrix of dimension 4.
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)]
@ -302,6 +311,12 @@ to_homogeneous_impl!(Mat4, Mat5, 4, 5);
from_homogeneous_impl!(Mat4, Mat5, 4, 5); from_homogeneous_impl!(Mat4, Mat5, 4, 5);
outer_impl!(Vec4, Mat4); outer_impl!(Vec4, Mat4);
eigen_qr_impl!(Mat4, Vec4); eigen_qr_impl!(Mat4, Vec4);
arbitrary_impl!(Mat4,
m11, m12, m13, m14,
m21, m22, m23, m24,
m31, m32, m33, m34,
m41, m42, m43, m44
);
/// Square matrix of dimension 5. /// Square matrix of dimension 5.
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)]
@ -416,6 +431,13 @@ to_homogeneous_impl!(Mat5, Mat6, 5, 6);
from_homogeneous_impl!(Mat5, Mat6, 5, 6); from_homogeneous_impl!(Mat5, Mat6, 5, 6);
outer_impl!(Vec5, Mat5); outer_impl!(Vec5, Mat5);
eigen_qr_impl!(Mat5, Vec5); eigen_qr_impl!(Mat5, Vec5);
arbitrary_impl!(Mat5,
m11, m12, m13, m14, m15,
m21, m22, m23, m24, m25,
m31, m32, m33, m34, m35,
m41, m42, m43, m44, m45,
m51, m52, m53, m54, m55
);
/// Square matrix of dimension 6. /// Square matrix of dimension 6.
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)]
@ -532,3 +554,11 @@ row_slice_impl!(Mat6, Vec6, DVec6, 6);
diag_impl!(Mat6, Vec6, 6); diag_impl!(Mat6, Vec6, 6);
outer_impl!(Vec6, Mat6); outer_impl!(Vec6, Mat6);
eigen_qr_impl!(Mat6, Vec6); eigen_qr_impl!(Mat6, Vec6);
arbitrary_impl!(Mat6,
m11, m12, m13, m14, m15, m16,
m21, m22, m23, m24, m25, m26,
m31, m32, m33, m34, m35, m36,
m41, m42, m43, m44, m45, m46,
m51, m52, m53, m54, m55, m56,
m61, m62, m63, m64, m65, m66
);

View File

@ -2,6 +2,10 @@ use std::num;
use traits::structure::BaseFloat; use traits::structure::BaseFloat;
use structs::{Pnt3, Vec3, Mat4}; use structs::{Pnt3, Vec3, Mat4};
#[cfg(feature="arbitrary")]
use quickcheck::{Arbitrary, Gen};
/// A 3D orthographic projection stored without any matrix. /// A 3D orthographic projection stored without any matrix.
/// ///
/// Reading or modifying its individual properties is cheap but applying the transformation is costly. /// Reading or modifying its individual properties is cheap but applying the transformation is costly.
@ -47,6 +51,17 @@ impl<N: BaseFloat> Ortho3<N> {
} }
} }
#[cfg(feature="arbitrary")]
impl<N: Arbitrary + BaseFloat> Arbitrary for Ortho3<N> {
fn arbitrary<G: Gen>(g: &mut G) -> Ortho3<N> {
let width = reject(g, |x| !::is_zero(x));
let height = reject(g, |x| !::is_zero(x));
let znear = Arbitrary::arbitrary(g);
let zfar = reject(g, |&x: &N| !::is_zero(&(x - znear)));
Ortho3::new(width, height, znear, zfar)
}
}
impl<N: BaseFloat + Clone> Ortho3<N> { impl<N: BaseFloat + Clone> Ortho3<N> {
/// The width of the view cuboid. /// The width of the view cuboid.
#[inline] #[inline]
@ -232,3 +247,20 @@ impl<N: BaseFloat + Clone> OrthoMat3<N> {
self.mat.clone() self.mat.clone()
} }
} }
#[cfg(feature="arbitrary")]
impl<N: Arbitrary + BaseFloat> Arbitrary for OrthoMat3<N> {
fn arbitrary<G: Gen>(g: &mut G) -> OrthoMat3<N> {
let x: Ortho3<N> = Arbitrary::arbitrary(g);
x.to_persp_mat()
}
}
/// Simple helper function for rejection sampling
#[cfg(feature="arbitrary")]
#[inline]
pub fn reject<G: Gen, F: FnMut(&T) -> bool, T: Arbitrary>(g: &mut G, f: F) -> T {
use std::iter::repeat;
repeat(()).map(|_| Arbitrary::arbitrary(g)).filter(f).next().unwrap()
}

View File

@ -1,6 +1,10 @@
use traits::structure::BaseFloat; use traits::structure::BaseFloat;
use structs::{Pnt3, Vec3, Mat4}; use structs::{Pnt3, Vec3, Mat4};
#[cfg(feature="arbitrary")]
use quickcheck::{Arbitrary, Gen};
/// A 3D perspective projection stored without any matrix. /// A 3D perspective projection stored without any matrix.
/// ///
/// Reading or modifying its individual properties is cheap but applying the transformation is costly. /// Reading or modifying its individual properties is cheap but applying the transformation is costly.
@ -45,6 +49,16 @@ impl<N: BaseFloat> Persp3<N> {
} }
} }
#[cfg(feature="arbitrary")]
impl<N: Arbitrary + BaseFloat> Arbitrary for Persp3<N> {
fn arbitrary<G: Gen>(g: &mut G) -> Persp3<N> {
use structs::ortho::reject;
let znear = Arbitrary::arbitrary(g);
let zfar = reject(g, |&x: &N| !::is_zero(&(x - znear)));
Persp3::new(Arbitrary::arbitrary(g), Arbitrary::arbitrary(g), znear, zfar)
}
}
impl<N: BaseFloat + Clone> Persp3<N> { impl<N: BaseFloat + Clone> Persp3<N> {
/// Gets the `width / height` aspect ratio. /// Gets the `width / height` aspect ratio.
#[inline] #[inline]
@ -263,3 +277,11 @@ impl<N: BaseFloat + Clone> PerspMat3<N> {
self.mat.clone() self.mat.clone()
} }
} }
#[cfg(feature="arbitrary")]
impl<N: Arbitrary + BaseFloat> Arbitrary for PerspMat3<N> {
fn arbitrary<G: Gen>(g: &mut G) -> PerspMat3<N> {
let x: Persp3<N> = Arbitrary::arbitrary(g);
x.to_persp_mat()
}
}

View File

@ -12,6 +12,8 @@ use traits::structure::{Cast, Dim, Indexable, Iterable, IterableMut, PntAsVec, S
NumPnt, FloatPnt, BaseFloat, BaseNum, Zero, One, Bounded}; NumPnt, FloatPnt, BaseFloat, BaseNum, Zero, One, Bounded};
use traits::geometry::{Orig, FromHomogeneous, ToHomogeneous}; use traits::geometry::{Orig, FromHomogeneous, ToHomogeneous};
use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6}; use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6};
#[cfg(feature="arbitrary")]
use quickcheck::{Arbitrary, Gen};
/// Point of dimension 0. /// Point of dimension 0.
@ -69,6 +71,7 @@ iterable_mut_impl!(Pnt1, 1);
pnt_to_homogeneous_impl!(Pnt1, Pnt2, y, x); pnt_to_homogeneous_impl!(Pnt1, Pnt2, y, x);
pnt_from_homogeneous_impl!(Pnt1, Pnt2, y, x); pnt_from_homogeneous_impl!(Pnt1, Pnt2, y, x);
num_float_pnt_impl!(Pnt1, Vec1); num_float_pnt_impl!(Pnt1, Vec1);
arbitrary_pnt_impl!(Pnt1, x);
/// Point of dimension 2. /// Point of dimension 2.
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)]
@ -109,6 +112,7 @@ iterable_mut_impl!(Pnt2, 2);
pnt_to_homogeneous_impl!(Pnt2, Pnt3, z, x, y); pnt_to_homogeneous_impl!(Pnt2, Pnt3, z, x, y);
pnt_from_homogeneous_impl!(Pnt2, Pnt3, z, x, y); pnt_from_homogeneous_impl!(Pnt2, Pnt3, z, x, y);
num_float_pnt_impl!(Pnt2, Vec2); num_float_pnt_impl!(Pnt2, Vec2);
arbitrary_pnt_impl!(Pnt2, x, y);
/// Point of dimension 3. /// Point of dimension 3.
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)]
@ -151,6 +155,7 @@ iterable_mut_impl!(Pnt3, 3);
pnt_to_homogeneous_impl!(Pnt3, Pnt4, w, x, y, z); pnt_to_homogeneous_impl!(Pnt3, Pnt4, w, x, y, z);
pnt_from_homogeneous_impl!(Pnt3, Pnt4, w, x, y, z); pnt_from_homogeneous_impl!(Pnt3, Pnt4, w, x, y, z);
num_float_pnt_impl!(Pnt3, Vec3); num_float_pnt_impl!(Pnt3, Vec3);
arbitrary_pnt_impl!(Pnt3, x, y, z);
/// Point of dimension 4. /// Point of dimension 4.
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)]
@ -195,6 +200,7 @@ iterable_mut_impl!(Pnt4, 4);
pnt_to_homogeneous_impl!(Pnt4, Pnt5, a, x, y, z, w); pnt_to_homogeneous_impl!(Pnt4, Pnt5, a, x, y, z, w);
pnt_from_homogeneous_impl!(Pnt4, Pnt5, a, x, y, z, w); pnt_from_homogeneous_impl!(Pnt4, Pnt5, a, x, y, z, w);
num_float_pnt_impl!(Pnt4, Vec4); num_float_pnt_impl!(Pnt4, Vec4);
arbitrary_pnt_impl!(Pnt4, x, y, z, w);
/// Point of dimension 5. /// Point of dimension 5.
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)]
@ -241,6 +247,7 @@ iterable_mut_impl!(Pnt5, 5);
pnt_to_homogeneous_impl!(Pnt5, Pnt6, b, x, y, z, w, a); pnt_to_homogeneous_impl!(Pnt5, Pnt6, b, x, y, z, w, a);
pnt_from_homogeneous_impl!(Pnt5, Pnt6, b, x, y, z, w, a); pnt_from_homogeneous_impl!(Pnt5, Pnt6, b, x, y, z, w, a);
num_float_pnt_impl!(Pnt5, Vec5); num_float_pnt_impl!(Pnt5, Vec5);
arbitrary_pnt_impl!(Pnt5, x, y, z, w, a);
/// Point of dimension 6. /// Point of dimension 6.
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)]
@ -287,3 +294,4 @@ axpy_impl!(Pnt6, x, y, z, w, a, b);
iterable_impl!(Pnt6, 6); iterable_impl!(Pnt6, 6);
iterable_mut_impl!(Pnt6, 6); iterable_mut_impl!(Pnt6, 6);
num_float_pnt_impl!(Pnt6, Vec6); num_float_pnt_impl!(Pnt6, Vec6);
arbitrary_pnt_impl!(Pnt6, x, y, z, w, a, b);

View File

@ -141,3 +141,17 @@ macro_rules! num_float_pnt_impl(
} }
) )
); );
macro_rules! arbitrary_pnt_impl(
($t: ident, $($compN: ident),*) => (
#[cfg(feature="arbitrary")]
impl<N: Arbitrary> Arbitrary for $t<N> {
#[inline]
fn arbitrary<G: Gen>(g: &mut G) -> $t<N> {
$t {
$($compN: Arbitrary::arbitrary(g),)*
}
}
}
)
);

View File

@ -15,6 +15,10 @@ use traits::structure::{Cast, Indexable, Iterable, IterableMut, Dim, Shape, Base
One, Bounded}; One, Bounded};
use traits::geometry::{Norm, Rotation, Rotate, Transform}; use traits::geometry::{Norm, Rotation, Rotate, Transform};
#[cfg(feature="arbitrary")]
use quickcheck::{Arbitrary, Gen};
/// A quaternion. /// A quaternion.
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)]
pub struct Quat<N> { pub struct Quat<N> {
@ -146,6 +150,7 @@ impl<N: ApproxEq<N> + BaseFloat> Div<Quat<N>> for Quat<N> {
} }
} }
/// A unit quaternion that can represent a 3D rotation. /// A unit quaternion that can represent a 3D rotation.
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Show, Copy)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Show, Copy)]
pub struct UnitQuat<N> { pub struct UnitQuat<N> {
@ -470,6 +475,14 @@ impl<N: BaseNum> Transform<Pnt3<N>> for UnitQuat<N> {
} }
} }
#[cfg(feature="arbitrary")]
impl<N: Arbitrary + BaseFloat> Arbitrary for UnitQuat<N> {
fn arbitrary<G: Gen>(g: &mut G) -> UnitQuat<N> {
UnitQuat::new(Arbitrary::arbitrary(g))
}
}
ord_impl!(Quat, w, i, j, k); ord_impl!(Quat, w, i, j, k);
vec_axis_impl!(Quat, w, i, j, k); vec_axis_impl!(Quat, w, i, j, k);
vec_cast_impl!(Quat, w, i, j, k); vec_cast_impl!(Quat, w, i, j, k);
@ -495,5 +508,6 @@ bounded_impl!(Quat, w, i, j, k);
axpy_impl!(Quat, w, i, j, k); axpy_impl!(Quat, w, i, j, k);
iterable_impl!(Quat, 4); iterable_impl!(Quat, 4);
iterable_mut_impl!(Quat, 4); iterable_mut_impl!(Quat, 4);
arbitrary_impl!(Quat, w, i, j, k);
dim_impl!(UnitQuat, 3); dim_impl!(UnitQuat, 3);

View File

@ -11,6 +11,8 @@ use traits::operations::{Absolute, Inv, Transpose, ApproxEq};
use structs::vec::{Vec1, Vec2, Vec3, Vec4}; use structs::vec::{Vec1, Vec2, Vec3, Vec4};
use structs::pnt::{Pnt2, Pnt3, Pnt4}; use structs::pnt::{Pnt2, Pnt3, Pnt4};
use structs::mat::{Mat2, Mat3, Mat4, Mat5}; use structs::mat::{Mat2, Mat3, Mat4, Mat5};
#[cfg(feature="arbitrary")]
use quickcheck::{Arbitrary, Gen};
/// Two dimensional rotation matrix. /// Two dimensional rotation matrix.
@ -19,13 +21,13 @@ pub struct Rot2<N> {
submat: Mat2<N> submat: Mat2<N>
} }
impl<N: Clone + BaseFloat + Neg<Output = N> + Copy> Rot2<N> { impl<N: Clone + BaseFloat + Neg<Output = N>> Rot2<N> {
/// Builds a 2 dimensional rotation matrix from an angle in radian. /// Builds a 2 dimensional rotation matrix from an angle in radian.
pub fn new(angle: Vec1<N>) -> Rot2<N> { pub fn new(angle: Vec1<N>) -> Rot2<N> {
let (sia, coa) = angle.x.sin_cos(); let (sia, coa) = angle.x.sin_cos();
Rot2 { Rot2 {
submat: Mat2::new(coa.clone(), -sia, sia.clone(), coa) submat: Mat2::new(coa.clone(), -sia, sia, coa)
} }
} }
} }
@ -87,6 +89,14 @@ impl<N: BaseFloat> AbsoluteRotate<Vec2<N>> for Rot2<N> {
} }
} }
#[cfg(feature="arbitrary")]
impl<N: Arbitrary + Clone + BaseFloat + Neg<Output = N>> Arbitrary for Rot2<N> {
fn arbitrary<G: Gen>(g: &mut G) -> Rot2<N> {
Rot2::new(Arbitrary::arbitrary(g))
}
}
/* /*
* 3d rotation * 3d rotation
*/ */
@ -287,6 +297,14 @@ impl<N: BaseFloat> AbsoluteRotate<Vec3<N>> for Rot3<N> {
} }
} }
#[cfg(feature="arbitrary")]
impl<N: Arbitrary + Clone + BaseFloat> Arbitrary for Rot3<N> {
fn arbitrary<G: Gen>(g: &mut G) -> Rot3<N> {
Rot3::new(Arbitrary::arbitrary(g))
}
}
/// Four dimensional rotation matrix. /// Four dimensional rotation matrix.
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Show, Hash, Copy)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Show, Hash, Copy)]
pub struct Rot4<N> { pub struct Rot4<N> {

View File

@ -14,6 +14,9 @@ use traits::structure::{Basis, Cast, Dim, Indexable, Iterable, IterableMut, VecA
NumVec, FloatVec, BaseFloat, BaseNum, Zero, One, Bounded}; NumVec, FloatVec, BaseFloat, BaseNum, Zero, One, Bounded};
use structs::pnt::{Pnt1, Pnt2, Pnt3, Pnt4, Pnt5, Pnt6}; use structs::pnt::{Pnt1, Pnt2, Pnt3, Pnt4, Pnt5, Pnt6};
#[cfg(feature="arbitrary")]
use quickcheck::{Arbitrary, Gen};
/// Vector of dimension 0. /// Vector of dimension 0.
#[derive(Eq, PartialEq, RustcDecodable, Clone, Rand, Show, Copy)] #[derive(Eq, PartialEq, RustcDecodable, Clone, Rand, Show, Copy)]
@ -81,6 +84,7 @@ transform_impl!(Vec1, Pnt1);
vec_as_pnt_impl!(Vec1, Pnt1, x); vec_as_pnt_impl!(Vec1, Pnt1, x);
num_float_vec_impl!(Vec1); num_float_vec_impl!(Vec1);
absolute_vec_impl!(Vec1, x); absolute_vec_impl!(Vec1, x);
arbitrary_impl!(Vec1, x);
/// Vector of dimension 2. /// Vector of dimension 2.
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)]
@ -132,6 +136,7 @@ transform_impl!(Vec2, Pnt2);
vec_as_pnt_impl!(Vec2, Pnt2, x, y); vec_as_pnt_impl!(Vec2, Pnt2, x, y);
num_float_vec_impl!(Vec2); num_float_vec_impl!(Vec2);
absolute_vec_impl!(Vec2, x, y); absolute_vec_impl!(Vec2, x, y);
arbitrary_impl!(Vec2, x, y);
/// Vector of dimension 3. /// Vector of dimension 3.
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)]
@ -185,6 +190,7 @@ transform_impl!(Vec3, Pnt3);
vec_as_pnt_impl!(Vec3, Pnt3, x, y, z); vec_as_pnt_impl!(Vec3, Pnt3, x, y, z);
num_float_vec_impl!(Vec3); num_float_vec_impl!(Vec3);
absolute_vec_impl!(Vec3, x, y, z); absolute_vec_impl!(Vec3, x, y, z);
arbitrary_impl!(Vec3, x, y, z);
/// Vector of dimension 4. /// Vector of dimension 4.
@ -241,6 +247,7 @@ transform_impl!(Vec4, Pnt4);
vec_as_pnt_impl!(Vec4, Pnt4, x, y, z, w); vec_as_pnt_impl!(Vec4, Pnt4, x, y, z, w);
num_float_vec_impl!(Vec4); num_float_vec_impl!(Vec4);
absolute_vec_impl!(Vec4, x, y, z, w); absolute_vec_impl!(Vec4, x, y, z, w);
arbitrary_impl!(Vec4, x, y, z, w);
/// Vector of dimension 5. /// Vector of dimension 5.
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)]
@ -298,6 +305,7 @@ transform_impl!(Vec5, Pnt5);
vec_as_pnt_impl!(Vec5, Pnt5, x, y, z, w, a); vec_as_pnt_impl!(Vec5, Pnt5, x, y, z, w, a);
num_float_vec_impl!(Vec5); num_float_vec_impl!(Vec5);
absolute_vec_impl!(Vec5, x, y, z, w, a); absolute_vec_impl!(Vec5, x, y, z, w, a);
arbitrary_impl!(Vec5, x, y, z, w, a);
/// Vector of dimension 6. /// Vector of dimension 6.
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)]
@ -355,3 +363,4 @@ transform_impl!(Vec6, Pnt6);
vec_as_pnt_impl!(Vec6, Pnt6, x, y, z, w, a, b); vec_as_pnt_impl!(Vec6, Pnt6, x, y, z, w, a, b);
num_float_vec_impl!(Vec6); num_float_vec_impl!(Vec6);
absolute_vec_impl!(Vec6, x, y, z, w, a, b); absolute_vec_impl!(Vec6, x, y, z, w, a, b);
arbitrary_impl!(Vec6, x, y, z, w, a, b);

View File

@ -844,3 +844,15 @@ macro_rules! absolute_vec_impl(
} }
) )
); );
macro_rules! arbitrary_impl(
($t: ident, $($compN: ident),*) => (
#[cfg(feature="arbitrary")]
impl<N: Arbitrary> Arbitrary for $t<N> {
#[inline]
fn arbitrary<G: Gen>(g: &mut G) -> $t<N> {
$t { $($compN: Arbitrary::arbitrary(g),)* }
}
}
)
);

64
tests/arbitrary.rs Normal file
View File

@ -0,0 +1,64 @@
#![cfg(feature="arbitrary")]
extern crate "nalgebra" as na;
extern crate quickcheck;
use std::rand;
use quickcheck::{Arbitrary, StdGen};
use na::*;
macro_rules! trivial_arb_test(
($t: ty, $name: ident) => (
#[test]
fn $name() {
let mut g = StdGen::new(rand::thread_rng(), 100);
let _: $t = Arbitrary::arbitrary(&mut g);
}
)
);
trivial_arb_test!(Vec1<f64>, arb_vec1);
trivial_arb_test!(Vec2<f64>, arb_vec2);
trivial_arb_test!(Vec3<f64>, arb_vec3);
trivial_arb_test!(Vec4<f64>, arb_vec4);
trivial_arb_test!(Vec5<f64>, arb_vec5);
trivial_arb_test!(Vec6<f64>, arb_vec6);
trivial_arb_test!(Pnt1<f64>, arb_pnt1);
trivial_arb_test!(Pnt2<f64>, arb_pnt2);
trivial_arb_test!(Pnt3<f64>, arb_pnt3);
trivial_arb_test!(Pnt4<f64>, arb_pnt4);
trivial_arb_test!(Pnt5<f64>, arb_pnt5);
trivial_arb_test!(Pnt6<f64>, arb_pnt6);
trivial_arb_test!(Mat1<f64>, arb_mat1);
trivial_arb_test!(Mat2<f64>, arb_mat2);
trivial_arb_test!(Mat3<f64>, arb_mat3);
trivial_arb_test!(Mat4<f64>, arb_mat4);
trivial_arb_test!(Mat5<f64>, arb_mat5);
trivial_arb_test!(Mat6<f64>, arb_mat6);
trivial_arb_test!(DVec1<f64>, arb_dvec1);
trivial_arb_test!(DVec2<f64>, arb_dvec2);
trivial_arb_test!(DVec3<f64>, arb_dvec3);
trivial_arb_test!(DVec4<f64>, arb_dvec4);
trivial_arb_test!(DVec5<f64>, arb_dvec5);
trivial_arb_test!(DVec6<f64>, arb_dvec6);
trivial_arb_test!(DMat<f64>, arb_dmat);
trivial_arb_test!(DVec<f64>, arb_dvec);
trivial_arb_test!(Quat<f64>, arb_quat);
trivial_arb_test!(UnitQuat<f64>, arb_unit_quat);
trivial_arb_test!(Iso2<f64>, arb_iso2);
trivial_arb_test!(Iso3<f64>, arb_iso3);
trivial_arb_test!(Rot2<f64>, arb_rot2);
trivial_arb_test!(Rot3<f64>, arb_rot3);
trivial_arb_test!(Ortho3<f64>, arb_ortho3);
trivial_arb_test!(OrthoMat3<f64>, arb_ortho_mat3);
trivial_arb_test!(Persp3<f64>, arb_persp3);
trivial_arb_test!(PerspMat3<f64>, arb_persp_mat3);