From 1103996b836de3c48c8059b62bdcccb3ad9b3990 Mon Sep 17 00:00:00 2001 From: Eduard Bopp Date: Sat, 10 Jan 2015 01:36:13 +0100 Subject: [PATCH] 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. --- Cargo.toml | 7 +++++ src/lib.rs | 3 ++ src/structs/dmat.rs | 12 +++++++ src/structs/dvec.rs | 9 ++++++ src/structs/dvec_macros.rs | 8 +++++ src/structs/iso.rs | 7 +++++ src/structs/iso_macros.rs | 14 +++++++++ src/structs/mat.rs | 30 ++++++++++++++++++ src/structs/ortho.rs | 32 +++++++++++++++++++ src/structs/persp.rs | 22 +++++++++++++ src/structs/pnt.rs | 8 +++++ src/structs/pnt_macros.rs | 14 +++++++++ src/structs/quat.rs | 14 +++++++++ src/structs/rot.rs | 22 +++++++++++-- src/structs/vec.rs | 9 ++++++ src/structs/vec_macros.rs | 12 +++++++ tests/arbitrary.rs | 64 ++++++++++++++++++++++++++++++++++++++ 17 files changed, 285 insertions(+), 2 deletions(-) create mode 100644 tests/arbitrary.rs diff --git a/Cargo.toml b/Cargo.toml index ebf35496..5ca8385d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,5 +15,12 @@ license = "BSD-3-Clause" name = "nalgebra" path = "src/lib.rs" +[features] +# Generate arbitrary instances of nalgebra types for testing with quickcheck +arbitrary = ["quickcheck"] + [dependencies] rustc-serialize = "*" + +[dependencies.quickcheck] +optional = true diff --git a/src/lib.rs b/src/lib.rs index fb1af57b..3177a4e4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; +#[cfg(feature="arbitrary")] +extern crate quickcheck; + #[cfg(test)] extern crate test; diff --git a/src/structs/dmat.rs b/src/structs/dmat.rs index 44d7dd2d..a6241ac7 100644 --- a/src/structs/dmat.rs +++ b/src/structs/dmat.rs @@ -13,6 +13,8 @@ use structs::dvec::DVec; use traits::operations::{Inv, Transpose, Mean, Cov}; use traits::structure::{Cast, ColSlice, RowSlice, Diag, Eye, Indexable, Shape, Zero, One, BaseNum}; use std::fmt::{Show, Formatter, Result, String}; +#[cfg(feature="arbitrary")] +use quickcheck::{Arbitrary, Gen}; /// Matrix with dimensions unknown at compile-time. @@ -703,3 +705,13 @@ impl> Sub for DMat { res } } + +#[cfg(feature="arbitrary")] +impl Arbitrary for DMat { + fn arbitrary(g: &mut G) -> DMat { + DMat::from_fn( + Arbitrary::arbitrary(g), Arbitrary::arbitrary(g), + |_, _| Arbitrary::arbitrary(g) + ) + } +} diff --git a/src/structs/dvec.rs b/src/structs/dvec.rs index 36b78317..e2deb970 100644 --- a/src/structs/dvec.rs +++ b/src/structs/dvec.rs @@ -11,6 +11,8 @@ use std::ops::{Add, Sub, Mul, Div, Neg, Index, IndexMut}; use traits::operations::{ApproxEq, Axpy}; use traits::geometry::{Dot, Norm}; use traits::structure::{Iterable, IterableMut, Indexable, Shape, BaseFloat, BaseNum, Zero, One}; +#[cfg(feature="arbitrary")] +use quickcheck::{Arbitrary, Gen}; /// Heap allocated, dynamically sized vector. #[derive(Eq, PartialEq, Show, Clone)] @@ -78,6 +80,13 @@ impl FromIterator for DVec { } } +#[cfg(feature="arbitrary")] +impl Arbitrary for DVec { + fn arbitrary(g: &mut G) -> DVec { + DVec { at: Arbitrary::arbitrary(g) } + } +} + dvec_impl!(DVec); diff --git a/src/structs/dvec_macros.rs b/src/structs/dvec_macros.rs index c64a8c4c..b43c66e1 100644 --- a/src/structs/dvec_macros.rs +++ b/src/structs/dvec_macros.rs @@ -520,5 +520,13 @@ macro_rules! small_dvec_from_impl ( } } } + + #[cfg(feature="arbitrary")] + impl Arbitrary for $dvec { + #[inline] + fn arbitrary(g: &mut G) -> $dvec { + $dvec::from_fn(g.gen_range(0, $dim), |_| Arbitrary::arbitrary(g)) + } + } ) ); diff --git a/src/structs/iso.rs b/src/structs/iso.rs index 1005cb96..0dbf768f 100644 --- a/src/structs/iso.rs +++ b/src/structs/iso.rs @@ -15,6 +15,9 @@ use structs::vec::{Vec1, Vec2, Vec3, Vec4}; use structs::pnt::{Pnt2, Pnt3, Pnt4}; use structs::rot::{Rot2, Rot3, Rot4}; +#[cfg(feature="arbitrary")] +use quickcheck::{Arbitrary, Gen}; + /// Two dimensional isometry. /// @@ -112,6 +115,7 @@ translate_impl!(Iso2, Pnt2); iso_mul_iso_impl!(Iso2); iso_mul_pnt_impl!(Iso2, Pnt2); pnt_mul_iso_impl!(Iso2, Pnt2); +arbitrary_iso_impl!(Iso2); iso_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_pnt_impl!(Iso3, Pnt3); pnt_mul_iso_impl!(Iso3, Pnt3); +arbitrary_iso_impl!(Iso3); // iso_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_pnt_impl!(Iso4, Pnt4); pnt_mul_iso_impl!(Iso4, Pnt4); +// FIXME: as soon as Rot4: Arbitrary +// arbitrary_iso_impl!(Iso4); diff --git a/src/structs/iso_macros.rs b/src/structs/iso_macros.rs index 0bdfd74e..dd0fe303 100644 --- a/src/structs/iso_macros.rs +++ b/src/structs/iso_macros.rs @@ -364,3 +364,17 @@ macro_rules! absolute_rotate_impl( } ) ); + +macro_rules! arbitrary_iso_impl( + ($t: ident) => ( + #[cfg(feature="arbitrary")] + impl Arbitrary for $t { + fn arbitrary(g: &mut G) -> $t { + $t::new_with_rotmat( + Arbitrary::arbitrary(g), + Arbitrary::arbitrary(g) + ) + } + } + ) +); diff --git a/src/structs/mat.rs b/src/structs/mat.rs index 64e4460e..5c106c7b 100644 --- a/src/structs/mat.rs +++ b/src/structs/mat.rs @@ -15,6 +15,8 @@ use traits::structure::{Cast, Row, Col, Iterable, IterableMut, Dim, Indexable, use traits::operations::{Absolute, Transpose, Inv, Outer, EigenQR}; use traits::geometry::{ToHomogeneous, FromHomogeneous, Orig}; use linalg; +#[cfg(feature="arbitrary")] +use quickcheck::{Arbitrary, Gen}; /// 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); outer_impl!(Vec1, Mat1); eigen_qr_impl!(Mat1, Vec1); +arbitrary_impl!(Mat1, m11); /// Square matrix of dimension 2. #[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); outer_impl!(Vec2, Mat2); eigen_qr_impl!(Mat2, Vec2); +arbitrary_impl!(Mat2, m11, m12, m21, m22); /// Square matrix of dimension 3. #[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); outer_impl!(Vec3, Mat3); eigen_qr_impl!(Mat3, Vec3); +arbitrary_impl!(Mat3, + m11, m12, m13, + m21, m22, m23, + m31, m32, m33 +); /// Square matrix of dimension 4. #[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); outer_impl!(Vec4, Mat4); 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. #[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); outer_impl!(Vec5, Mat5); 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. #[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); outer_impl!(Vec6, Mat6); 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 +); diff --git a/src/structs/ortho.rs b/src/structs/ortho.rs index fd030bec..238905e5 100644 --- a/src/structs/ortho.rs +++ b/src/structs/ortho.rs @@ -2,6 +2,10 @@ use std::num; use traits::structure::BaseFloat; use structs::{Pnt3, Vec3, Mat4}; +#[cfg(feature="arbitrary")] +use quickcheck::{Arbitrary, Gen}; + + /// A 3D orthographic projection stored without any matrix. /// /// Reading or modifying its individual properties is cheap but applying the transformation is costly. @@ -47,6 +51,17 @@ impl Ortho3 { } } +#[cfg(feature="arbitrary")] +impl Arbitrary for Ortho3 { + fn arbitrary(g: &mut G) -> Ortho3 { + 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 Ortho3 { /// The width of the view cuboid. #[inline] @@ -232,3 +247,20 @@ impl OrthoMat3 { self.mat.clone() } } + +#[cfg(feature="arbitrary")] +impl Arbitrary for OrthoMat3 { + fn arbitrary(g: &mut G) -> OrthoMat3 { + let x: Ortho3 = Arbitrary::arbitrary(g); + x.to_persp_mat() + } +} + + +/// Simple helper function for rejection sampling +#[cfg(feature="arbitrary")] +#[inline] +pub fn reject bool, T: Arbitrary>(g: &mut G, f: F) -> T { + use std::iter::repeat; + repeat(()).map(|_| Arbitrary::arbitrary(g)).filter(f).next().unwrap() +} diff --git a/src/structs/persp.rs b/src/structs/persp.rs index b4b98d70..2e03d69b 100644 --- a/src/structs/persp.rs +++ b/src/structs/persp.rs @@ -1,6 +1,10 @@ use traits::structure::BaseFloat; use structs::{Pnt3, Vec3, Mat4}; +#[cfg(feature="arbitrary")] +use quickcheck::{Arbitrary, Gen}; + + /// A 3D perspective projection stored without any matrix. /// /// Reading or modifying its individual properties is cheap but applying the transformation is costly. @@ -45,6 +49,16 @@ impl Persp3 { } } +#[cfg(feature="arbitrary")] +impl Arbitrary for Persp3 { + fn arbitrary(g: &mut G) -> Persp3 { + 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 Persp3 { /// Gets the `width / height` aspect ratio. #[inline] @@ -263,3 +277,11 @@ impl PerspMat3 { self.mat.clone() } } + +#[cfg(feature="arbitrary")] +impl Arbitrary for PerspMat3 { + fn arbitrary(g: &mut G) -> PerspMat3 { + let x: Persp3 = Arbitrary::arbitrary(g); + x.to_persp_mat() + } +} diff --git a/src/structs/pnt.rs b/src/structs/pnt.rs index cf9f2aee..8902554c 100644 --- a/src/structs/pnt.rs +++ b/src/structs/pnt.rs @@ -12,6 +12,8 @@ use traits::structure::{Cast, Dim, Indexable, Iterable, IterableMut, PntAsVec, S NumPnt, FloatPnt, BaseFloat, BaseNum, Zero, One, Bounded}; use traits::geometry::{Orig, FromHomogeneous, ToHomogeneous}; use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6}; +#[cfg(feature="arbitrary")] +use quickcheck::{Arbitrary, Gen}; /// Point of dimension 0. @@ -69,6 +71,7 @@ iterable_mut_impl!(Pnt1, 1); pnt_to_homogeneous_impl!(Pnt1, Pnt2, y, x); pnt_from_homogeneous_impl!(Pnt1, Pnt2, y, x); num_float_pnt_impl!(Pnt1, Vec1); +arbitrary_pnt_impl!(Pnt1, x); /// Point of dimension 2. #[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_from_homogeneous_impl!(Pnt2, Pnt3, z, x, y); num_float_pnt_impl!(Pnt2, Vec2); +arbitrary_pnt_impl!(Pnt2, x, y); /// Point of dimension 3. #[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_from_homogeneous_impl!(Pnt3, Pnt4, w, x, y, z); num_float_pnt_impl!(Pnt3, Vec3); +arbitrary_pnt_impl!(Pnt3, x, y, z); /// Point of dimension 4. #[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_from_homogeneous_impl!(Pnt4, Pnt5, a, x, y, z, w); num_float_pnt_impl!(Pnt4, Vec4); +arbitrary_pnt_impl!(Pnt4, x, y, z, w); /// Point of dimension 5. #[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_from_homogeneous_impl!(Pnt5, Pnt6, b, x, y, z, w, a); num_float_pnt_impl!(Pnt5, Vec5); +arbitrary_pnt_impl!(Pnt5, x, y, z, w, a); /// Point of dimension 6. #[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_mut_impl!(Pnt6, 6); num_float_pnt_impl!(Pnt6, Vec6); +arbitrary_pnt_impl!(Pnt6, x, y, z, w, a, b); diff --git a/src/structs/pnt_macros.rs b/src/structs/pnt_macros.rs index f026a246..acf891f8 100644 --- a/src/structs/pnt_macros.rs +++ b/src/structs/pnt_macros.rs @@ -141,3 +141,17 @@ macro_rules! num_float_pnt_impl( } ) ); + +macro_rules! arbitrary_pnt_impl( + ($t: ident, $($compN: ident),*) => ( + #[cfg(feature="arbitrary")] + impl Arbitrary for $t { + #[inline] + fn arbitrary(g: &mut G) -> $t { + $t { + $($compN: Arbitrary::arbitrary(g),)* + } + } + } + ) +); diff --git a/src/structs/quat.rs b/src/structs/quat.rs index 17a5090e..5fb4cb4c 100644 --- a/src/structs/quat.rs +++ b/src/structs/quat.rs @@ -15,6 +15,10 @@ use traits::structure::{Cast, Indexable, Iterable, IterableMut, Dim, Shape, Base One, Bounded}; use traits::geometry::{Norm, Rotation, Rotate, Transform}; +#[cfg(feature="arbitrary")] +use quickcheck::{Arbitrary, Gen}; + + /// A quaternion. #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Rand, Show, Copy)] pub struct Quat { @@ -146,6 +150,7 @@ impl + BaseFloat> Div> for Quat { } } + /// A unit quaternion that can represent a 3D rotation. #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Show, Copy)] pub struct UnitQuat { @@ -470,6 +475,14 @@ impl Transform> for UnitQuat { } } +#[cfg(feature="arbitrary")] +impl Arbitrary for UnitQuat { + fn arbitrary(g: &mut G) -> UnitQuat { + UnitQuat::new(Arbitrary::arbitrary(g)) + } +} + + ord_impl!(Quat, w, i, j, k); vec_axis_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); iterable_impl!(Quat, 4); iterable_mut_impl!(Quat, 4); +arbitrary_impl!(Quat, w, i, j, k); dim_impl!(UnitQuat, 3); diff --git a/src/structs/rot.rs b/src/structs/rot.rs index a87ce47c..34c38443 100644 --- a/src/structs/rot.rs +++ b/src/structs/rot.rs @@ -11,6 +11,8 @@ use traits::operations::{Absolute, Inv, Transpose, ApproxEq}; use structs::vec::{Vec1, Vec2, Vec3, Vec4}; use structs::pnt::{Pnt2, Pnt3, Pnt4}; use structs::mat::{Mat2, Mat3, Mat4, Mat5}; +#[cfg(feature="arbitrary")] +use quickcheck::{Arbitrary, Gen}; /// Two dimensional rotation matrix. @@ -19,13 +21,13 @@ pub struct Rot2 { submat: Mat2 } -impl + Copy> Rot2 { +impl> Rot2 { /// Builds a 2 dimensional rotation matrix from an angle in radian. pub fn new(angle: Vec1) -> Rot2 { let (sia, coa) = angle.x.sin_cos(); Rot2 { - submat: Mat2::new(coa.clone(), -sia, sia.clone(), coa) + submat: Mat2::new(coa.clone(), -sia, sia, coa) } } } @@ -87,6 +89,14 @@ impl AbsoluteRotate> for Rot2 { } } +#[cfg(feature="arbitrary")] +impl> Arbitrary for Rot2 { + fn arbitrary(g: &mut G) -> Rot2 { + Rot2::new(Arbitrary::arbitrary(g)) + } +} + + /* * 3d rotation */ @@ -287,6 +297,14 @@ impl AbsoluteRotate> for Rot3 { } } +#[cfg(feature="arbitrary")] +impl Arbitrary for Rot3 { + fn arbitrary(g: &mut G) -> Rot3 { + Rot3::new(Arbitrary::arbitrary(g)) + } +} + + /// Four dimensional rotation matrix. #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Show, Hash, Copy)] pub struct Rot4 { diff --git a/src/structs/vec.rs b/src/structs/vec.rs index 92181472..337c1f4d 100644 --- a/src/structs/vec.rs +++ b/src/structs/vec.rs @@ -14,6 +14,9 @@ use traits::structure::{Basis, Cast, Dim, Indexable, Iterable, IterableMut, VecA NumVec, FloatVec, BaseFloat, BaseNum, Zero, One, Bounded}; use structs::pnt::{Pnt1, Pnt2, Pnt3, Pnt4, Pnt5, Pnt6}; +#[cfg(feature="arbitrary")] +use quickcheck::{Arbitrary, Gen}; + /// Vector of dimension 0. #[derive(Eq, PartialEq, RustcDecodable, Clone, Rand, Show, Copy)] @@ -81,6 +84,7 @@ transform_impl!(Vec1, Pnt1); vec_as_pnt_impl!(Vec1, Pnt1, x); num_float_vec_impl!(Vec1); absolute_vec_impl!(Vec1, x); +arbitrary_impl!(Vec1, x); /// Vector of dimension 2. #[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); num_float_vec_impl!(Vec2); absolute_vec_impl!(Vec2, x, y); +arbitrary_impl!(Vec2, x, y); /// Vector of dimension 3. #[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); num_float_vec_impl!(Vec3); absolute_vec_impl!(Vec3, x, y, z); +arbitrary_impl!(Vec3, x, y, z); /// Vector of dimension 4. @@ -241,6 +247,7 @@ transform_impl!(Vec4, Pnt4); vec_as_pnt_impl!(Vec4, Pnt4, x, y, z, w); num_float_vec_impl!(Vec4); absolute_vec_impl!(Vec4, x, y, z, w); +arbitrary_impl!(Vec4, x, y, z, w); /// Vector of dimension 5. #[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); num_float_vec_impl!(Vec5); absolute_vec_impl!(Vec5, x, y, z, w, a); +arbitrary_impl!(Vec5, x, y, z, w, a); /// Vector of dimension 6. #[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); num_float_vec_impl!(Vec6); absolute_vec_impl!(Vec6, x, y, z, w, a, b); +arbitrary_impl!(Vec6, x, y, z, w, a, b); diff --git a/src/structs/vec_macros.rs b/src/structs/vec_macros.rs index 4f083b5b..a8ce93f7 100644 --- a/src/structs/vec_macros.rs +++ b/src/structs/vec_macros.rs @@ -844,3 +844,15 @@ macro_rules! absolute_vec_impl( } ) ); + +macro_rules! arbitrary_impl( + ($t: ident, $($compN: ident),*) => ( + #[cfg(feature="arbitrary")] + impl Arbitrary for $t { + #[inline] + fn arbitrary(g: &mut G) -> $t { + $t { $($compN: Arbitrary::arbitrary(g),)* } + } + } + ) +); diff --git a/tests/arbitrary.rs b/tests/arbitrary.rs new file mode 100644 index 00000000..4369ee78 --- /dev/null +++ b/tests/arbitrary.rs @@ -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, arb_vec1); +trivial_arb_test!(Vec2, arb_vec2); +trivial_arb_test!(Vec3, arb_vec3); +trivial_arb_test!(Vec4, arb_vec4); +trivial_arb_test!(Vec5, arb_vec5); +trivial_arb_test!(Vec6, arb_vec6); + +trivial_arb_test!(Pnt1, arb_pnt1); +trivial_arb_test!(Pnt2, arb_pnt2); +trivial_arb_test!(Pnt3, arb_pnt3); +trivial_arb_test!(Pnt4, arb_pnt4); +trivial_arb_test!(Pnt5, arb_pnt5); +trivial_arb_test!(Pnt6, arb_pnt6); + +trivial_arb_test!(Mat1, arb_mat1); +trivial_arb_test!(Mat2, arb_mat2); +trivial_arb_test!(Mat3, arb_mat3); +trivial_arb_test!(Mat4, arb_mat4); +trivial_arb_test!(Mat5, arb_mat5); +trivial_arb_test!(Mat6, arb_mat6); + +trivial_arb_test!(DVec1, arb_dvec1); +trivial_arb_test!(DVec2, arb_dvec2); +trivial_arb_test!(DVec3, arb_dvec3); +trivial_arb_test!(DVec4, arb_dvec4); +trivial_arb_test!(DVec5, arb_dvec5); +trivial_arb_test!(DVec6, arb_dvec6); + +trivial_arb_test!(DMat, arb_dmat); +trivial_arb_test!(DVec, arb_dvec); + +trivial_arb_test!(Quat, arb_quat); +trivial_arb_test!(UnitQuat, arb_unit_quat); + +trivial_arb_test!(Iso2, arb_iso2); +trivial_arb_test!(Iso3, arb_iso3); + +trivial_arb_test!(Rot2, arb_rot2); +trivial_arb_test!(Rot3, arb_rot3); + +trivial_arb_test!(Ortho3, arb_ortho3); +trivial_arb_test!(OrthoMat3, arb_ortho_mat3); +trivial_arb_test!(Persp3, arb_persp3); +trivial_arb_test!(PerspMat3, arb_persp_mat3);