nalgebra/tests/vec.rs

375 lines
8.2 KiB
Rust
Raw Permalink Normal View History

extern crate rand;
#[cfg(feature="generic_sizes")]
extern crate typenum;
extern crate nalgebra as na;
use rand::random;
use na::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6, Mat3, Rot2, Rot3, Iterable, IterableMut};
#[cfg(feature="generic_sizes")]
use typenum::U10;
#[cfg(feature="generic_sizes")]
use na::VecN;
2013-05-19 05:56:03 +08:00
macro_rules! test_iterator_impl(
2013-08-05 16:13:44 +08:00
($t: ty, $n: ty) => (
for _ in 0usize .. 10000 {
2013-08-05 16:13:44 +08:00
let v: $t = random();
let mut mv: $t = v.clone();
let n: $n = random();
let nv: $t = v.iter().map(|e| *e * n).collect();
2014-10-22 19:35:17 +08:00
for e in mv.iter_mut() {
2013-08-05 16:13:44 +08:00
*e = *e * n
}
assert!(nv == mv && nv == v * n);
}
2013-08-05 16:13:44 +08:00
)
);
2013-05-22 07:15:03 +08:00
macro_rules! test_commut_dot_impl(
2013-08-05 16:13:44 +08:00
($t: ty) => (
for _ in 0usize .. 10000 {
2013-08-05 16:13:44 +08:00
let v1 : $t = random();
let v2 : $t = random();
2014-10-22 19:35:17 +08:00
assert!(na::approx_eq(&na::dot(&v1, &v2), &na::dot(&v2, &v1)));
}
2013-08-05 16:13:44 +08:00
);
);
2013-05-22 07:15:03 +08:00
macro_rules! test_scalar_op_impl(
2013-08-05 16:13:44 +08:00
($t: ty, $n: ty) => (
for _ in 0usize .. 10000 {
2013-08-05 16:13:44 +08:00
let v1 : $t = random();
let n : $n = random();
2014-10-22 19:35:17 +08:00
assert!(na::approx_eq(&((v1 * n) / n), &v1));
assert!(na::approx_eq(&((v1 / n) * n), &v1));
assert!(na::approx_eq(&((v1 - n) + n), &v1));
assert!(na::approx_eq(&((v1 + n) - n), &v1));
2013-08-05 16:13:44 +08:00
let mut v1 : $t = random();
let v0 : $t = v1.clone();
let n : $n = random();
v1 = v1 * n;
v1 = v1 / n;
2014-10-22 19:35:17 +08:00
assert!(na::approx_eq(&v1, &v0));
}
2013-08-05 16:13:44 +08:00
);
);
2013-05-22 07:15:03 +08:00
macro_rules! test_basis_impl(
2013-08-05 16:13:44 +08:00
($t: ty) => (
for _ in 0usize .. 10000 {
2013-11-27 18:16:16 +08:00
na::canonical_basis(|e1: $t| {
na::canonical_basis(|e2: $t| {
assert!(e1 == e2 || na::approx_eq(&na::dot(&e1, &e2), &na::zero()));
true
2013-11-27 18:16:16 +08:00
});
2013-08-05 16:13:44 +08:00
assert!(na::approx_eq(&na::norm(&e1), &na::one()));
true
2013-11-27 18:16:16 +08:00
})
}
2013-08-05 16:13:44 +08:00
);
);
2013-05-22 07:15:03 +08:00
macro_rules! test_subspace_basis_impl(
2013-08-05 16:13:44 +08:00
($t: ty) => (
for _ in 0usize .. 10000 {
2013-08-05 16:13:44 +08:00
let v : $t = random();
Api change: deal with inplace/out of place methods. Before, it was too easy to use an out of place method instead of the inplace one since they name were pretty mutch the same. This kind of confusion may lead to silly bugs very hard to understand. Thus the following changes have been made when a method is available both inplace and out-of-place: * inplace version keep a short name. * out-of-place version are suffixed by `_cpy` (meaning `copy`), and are static methods. Methods applying transformations (rotation, translation or general transform) are now prefixed by `append`, and a `prepend` version is available too. Also, free functions doing in-place modifications dont really make sense. They have been removed. Here are the naming changes: * `invert` -> `inv` * `inverted` -> `Inv::inv_cpy` * `transpose` -> `transpose` * `transposed` -> `Transpose::transpose_cpy` * `transform_by` -> `append_transformation` * `transformed` -> `Transform::append_transformation_cpy` * `rotate_by` -> `apppend_rotation` * `rotated` -> `Rotation::append_rotation_cpy` * `translate_by` -> `apppend_translation` * `translate` -> `Translation::append_translation_cpy` * `normalized` -> `Norm::normalize_cpy` * `rotated_wrt_point` -> `RotationWithTranslation::append_rotation_wrt_point_cpy` * `rotated_wrt_center` -> `RotationWithTranslation::append_rotation_wrt_center_cpy` Note that using those static methods is very verbose, and using in-place methods require an explicit import of the related trait. This is a way to convince the user to use free functions most of the time.
2013-10-14 16:22:32 +08:00
let v1 = na::normalize(&v);
2013-08-05 16:13:44 +08:00
2013-11-27 18:16:16 +08:00
na::orthonormal_subspace_basis(&v1, |e1| {
2013-08-05 16:13:44 +08:00
// check vectors are orthogonal to v1
assert!(na::approx_eq(&na::dot(&v1, &e1), &na::zero()));
2013-08-05 16:13:44 +08:00
// check vectors form an orthonormal basis
assert!(na::approx_eq(&na::norm(&e1), &na::one()));
2013-08-05 16:13:44 +08:00
// check vectors form an ortogonal basis
2013-11-27 18:16:16 +08:00
na::orthonormal_subspace_basis(&v1, |e2| {
assert!(e1 == e2 || na::approx_eq(&na::dot(&e1, &e2), &na::zero()));
true
2013-11-27 18:16:16 +08:00
});
true
2013-11-27 18:16:16 +08:00
})
}
2013-08-05 16:13:44 +08:00
);
);
2013-05-19 01:04:03 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_cross_vec3() {
for _ in 0usize .. 10000 {
2013-08-05 16:13:44 +08:00
let v1 : Vec3<f64> = random();
let v2 : Vec3<f64> = random();
let v3 : Vec3<f64> = na::cross(&v1, &v2);
2013-05-19 01:04:03 +08:00
assert!(na::approx_eq(&na::dot(&v3, &v2), &na::zero()));
assert!(na::approx_eq(&na::dot(&v3, &v1), &na::zero()));
}
2013-05-19 01:04:03 +08:00
}
#[test]
2013-08-05 16:13:44 +08:00
fn test_commut_dot_vec1() {
test_commut_dot_impl!(Vec1<f64>);
}
2013-05-19 01:04:03 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_commut_dot_vec2() {
test_commut_dot_impl!(Vec2<f64>);
}
2013-05-19 01:04:03 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_commut_dot_vec3() {
test_commut_dot_impl!(Vec3<f64>);
}
2013-07-20 23:02:54 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_commut_dot_vec4() {
test_commut_dot_impl!(Vec4<f64>);
}
2013-07-20 23:02:54 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_commut_dot_vec5() {
test_commut_dot_impl!(Vec5<f64>);
}
2013-07-20 23:02:54 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_commut_dot_vec6() {
test_commut_dot_impl!(Vec6<f64>);
}
2013-07-20 23:02:54 +08:00
2013-05-19 01:04:03 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_basis_vec1() {
test_basis_impl!(Vec1<f64>);
}
2013-05-19 01:04:03 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_basis_vec2() {
test_basis_impl!(Vec2<f64>);
}
2013-05-19 01:04:03 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_basis_vec3() {
test_basis_impl!(Vec3<f64>);
}
2013-05-19 01:04:03 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_basis_vec4() {
test_basis_impl!(Vec4<f64>);
}
2013-06-29 08:34:45 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_basis_vec5() {
test_basis_impl!(Vec5<f64>);
}
2013-06-29 08:34:45 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_basis_vec6() {
test_basis_impl!(Vec6<f64>);
}
2013-05-19 01:04:03 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_subspace_basis_vec1() {
test_subspace_basis_impl!(Vec1<f64>);
}
2013-05-19 01:04:03 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_subspace_basis_vec2() {
test_subspace_basis_impl!(Vec2<f64>);
}
2013-05-19 01:04:03 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_subspace_basis_vec3() {
test_subspace_basis_impl!(Vec3<f64>);
}
2013-05-19 01:04:03 +08:00
2013-05-22 07:15:03 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_subspace_basis_vec4() {
test_subspace_basis_impl!(Vec4<f64>);
}
2013-06-29 08:34:45 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_subspace_basis_vec5() {
test_subspace_basis_impl!(Vec5<f64>);
}
2013-06-29 08:34:45 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_subspace_basis_vec6() {
test_subspace_basis_impl!(Vec6<f64>);
}
2013-06-10 08:09:36 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_scalar_op_vec1() {
test_scalar_op_impl!(Vec1<f64>, f64);
}
#[test]
2013-08-05 16:13:44 +08:00
fn test_scalar_op_vec2() {
test_scalar_op_impl!(Vec2<f64>, f64);
}
2014-10-22 19:35:17 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_scalar_op_vec3() {
test_scalar_op_impl!(Vec3<f64>, f64);
}
2014-10-22 19:35:17 +08:00
2013-06-29 08:34:45 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_scalar_op_vec4() {
test_scalar_op_impl!(Vec4<f64>, f64);
}
2014-10-22 19:35:17 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_scalar_op_vec5() {
test_scalar_op_impl!(Vec5<f64>, f64);
}
2014-10-22 19:35:17 +08:00
2013-06-29 08:34:45 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_scalar_op_vec6() {
test_scalar_op_impl!(Vec6<f64>, f64);
}
#[test]
2013-08-05 16:13:44 +08:00
fn test_iterator_vec1() {
test_iterator_impl!(Vec1<f64>, f64);
}
#[test]
2013-08-05 16:13:44 +08:00
fn test_iterator_vec2() {
test_iterator_impl!(Vec2<f64>, f64);
}
2014-10-22 19:35:17 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_iterator_vec3() {
test_iterator_impl!(Vec3<f64>, f64);
}
2014-10-22 19:35:17 +08:00
2013-06-29 08:34:45 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_iterator_vec4() {
test_iterator_impl!(Vec4<f64>, f64);
}
2014-10-22 19:35:17 +08:00
2013-06-29 08:34:45 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_iterator_vec5() {
test_iterator_impl!(Vec5<f64>, f64);
}
2014-10-22 19:35:17 +08:00
#[test]
2013-08-05 16:13:44 +08:00
fn test_iterator_vec6() {
test_iterator_impl!(Vec6<f64>, f64);
}
#[test]
2013-08-05 16:13:44 +08:00
fn test_ord_vec3() {
// equality
assert!(Vec3::new(0.5f64, 0.5, 0.5) == Vec3::new(0.5, 0.5, 0.5));
assert!(!(Vec3::new(1.5f64, 0.5, 0.5) == Vec3::new(0.5, 0.5, 0.5)));
assert!(Vec3::new(1.5f64, 0.5, 0.5) != Vec3::new(0.5, 0.5, 0.5));
// comparable
assert!(na::partial_cmp(&Vec3::new(0.5f64, 0.3, 0.3), &Vec3::new(1.0, 2.0, 1.0)).is_le());
assert!(na::partial_cmp(&Vec3::new(0.5f64, 0.3, 0.3), &Vec3::new(1.0, 2.0, 1.0)).is_lt());
assert!(na::partial_cmp(&Vec3::new(2.0f64, 4.0, 2.0), &Vec3::new(1.0, 2.0, 1.0)).is_ge());
assert!(na::partial_cmp(&Vec3::new(2.0f64, 4.0, 2.0), &Vec3::new(1.0, 2.0, 1.0)).is_gt());
// not comparable
assert!(na::partial_cmp(&Vec3::new(0.0f64, 3.0, 0.0), &Vec3::new(1.0, 2.0, 1.0)).is_not_comparable());
}
#[test]
2013-08-05 16:13:44 +08:00
fn test_min_max_vec3() {
assert_eq!(na::sup(&Vec3::new(1.0f64, 2.0, 3.0), &Vec3::new(3.0, 2.0, 1.0)), Vec3::new(3.0, 2.0, 3.0));
assert_eq!(na::inf(&Vec3::new(1.0f64, 2.0, 3.0), &Vec3::new(3.0, 2.0, 1.0)), Vec3::new(1.0, 2.0, 1.0));
}
2013-08-12 22:45:31 +08:00
#[test]
fn test_outer_vec3() {
assert_eq!(
na::outer(&Vec3::new(1.0f64, 2.0, 3.0), &Vec3::new(4.0, 5.0, 6.0)),
Mat3::new(
4.0, 5.0, 6.0,
8.0, 10.0, 12.0,
12.0, 15.0, 18.0));
2013-08-12 22:45:31 +08:00
}
#[cfg(feature="generic_sizes")]
#[test]
fn test_vecn10_add_mul() {
for _ in 0usize .. 10000 {
let v1: VecN<f64, U10> = random();
assert!(na::approx_eq(&(v1 + v1), &(v1 * 2.0)))
}
}
#[test]
fn test_vec3_rotation_between() {
for _ in 0usize .. 10000 {
let v1: Vec3<f64> = random();
let mut v2: Vec3<f64> = random();
v2 = na::normalize(&v2) * na::norm(&v1);
let rot = na::rotation_between(&v1, &v2);
assert!(na::approx_eq(&(rot * v1), &v2))
}
}
#[test]
fn test_vec3_angle_between() {
for _ in 0usize .. 10000 {
let vec: Vec3<f64> = random();
let other: Vec3<f64> = random();
// Ensure the axis we are using is orthogonal to `vec`.
let axis_ang = na::cross(&vec, &other);
let ang = na::norm(&axis_ang);
let rot = Rot3::new(axis_ang);
let delta = na::angle_between(&vec, &(rot * vec));
assert!(na::approx_eq(&ang, &delta))
}
}
#[test]
fn test_vec2_rotation_between() {
for _ in 0usize .. 10000 {
let v1: Vec2<f64> = random();
let mut v2: Vec2<f64> = random();
v2 = na::normalize(&v2) * na::norm(&v1);
let rot = na::rotation_between(&v1, &v2);
assert!(na::approx_eq(&(rot * v1), &v2))
}
}
#[test]
fn test_vec2_angle_between() {
for _ in 0usize .. 10000 {
let axis_ang: Vec1<f64> = random();
let ang = na::norm(&axis_ang);
let rot: Rot2<f64> = Rot2::new(axis_ang);
let vec: Vec2<f64> = random();
let delta = na::angle_between(&vec, &(rot * vec));
assert!(na::approx_eq(&ang, &delta))
}
}