Update to the last Rust.

Also use free-functions on tests.
This commit is contained in:
Sébastien Crozet 2013-10-08 01:22:56 +02:00
parent 3f99bd62c6
commit edf17b5667
14 changed files with 196 additions and 94 deletions

View File

@ -29,15 +29,15 @@ use nalgebra::traits::*;
```.rust
use nalgebra::structs::*;
```
Of course, you can still import `nalgebra::na` alone, and get anything you want using the `na`
prefix.
Of course, you can still import `nalgebra::na` alone, and get anything you want using the prefix
`na`.
## Features
**nalgebra** is meant to be a general-purpose linear algebra library (but is very far from that…),
and keeps an optimized set of tools for computational graphics and physics. Those features include:
* Vectors with static sizes: `Vec0`, `Vec1`, `Vec2`, ..., `Vec6`.
* Square matrices with static sizes: `Mat1`, `Mat2`, ..., `Mat6 `.
* Vectors with static sizes: `Vec0`, `Vec1`, `Vec2`, `Vec3`, `Vec4`, `Vec5`, `Vec6`.
* Square matrices with static sizes: `Mat1`, `Mat2`, `Mat3`, `Mat4`, `Mat5`, `Mat6 `.
* Rotation matrices: `Rot2`, `Rot3`, `Rot4`.
* Isometries: `Iso2`, `Iso3`, `Iso4`.
* Dynamically sized vector: `DVec`.
@ -46,7 +46,7 @@ and keeps an optimized set of tools for computational graphics and physics. Thos
* Almost one trait per functionality: useful for generic programming.
* Operator overloading using the double trait dispatch
[trick](http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/).
For example, the following work:
For example, the following works:
```rust
extern mod nalgebra;

View File

@ -1,6 +1,6 @@
use std::rand::random;
use extra::test::BenchHarness;
use na::*;
use na::{Vec2, Vec3, Vec4, Vec5, Vec6, DVec, Mat2, Mat3, Mat4, Mat5, Mat6, DMat};
macro_rules! bench_mul_mat(
($bh: expr, $t: ty) => {

View File

@ -1,6 +1,7 @@
use std::rand::random;
use extra::test::BenchHarness;
use na::*;
use na::{Vec2, Vec3, Vec4, Vec5, Vec6};
use na;
macro_rules! bench_dot_vec(
($bh: expr, $t: ty) => {
@ -11,7 +12,7 @@ macro_rules! bench_dot_vec(
do $bh.iter {
do 1000.times {
d = d + a.dot(&b);
d = d + na::dot(&a, &b);
}
}
}

View File

@ -30,15 +30,15 @@ use nalgebra::traits::*;
```.rust
use nalgebra::structs::*;
```
Of course, you can still import `nalgebra::na` alone, and get anything you want using the `na`
prefix.
Of course, you can still import `nalgebra::na` alone, and get anything you want using the prefix
`na`.
## Features
**nalgebra** is meant to be a general-purpose linear algebra library (but is very far from that),
and keeps an optimized set of tools for computational graphics and physics. Those features include:
* Vectors with static sizes: `Vec0`, `Vec1`, `Vec2`, ..., `Vec6`.
* Square matrices with static sizes: `Mat1`, `Mat2`, ..., `Mat6 `.
* Vectors with static sizes: `Vec0`, `Vec1`, `Vec2`, `Vec3`, `Vec4`, `Vec5`, `Vec6`.
* Square matrices with static sizes: `Mat1`, `Mat2`, `Mat3`, `Mat4`, `Mat5`, `Mat6 `.
* Rotation matrices: `Rot2`, `Rot3`, `Rot4`.
* Isometries: `Iso2`, `Iso3`, `Iso4`.
* Dynamically sized vector: `DVec`.
@ -47,7 +47,7 @@ and keeps an optimized set of tools for computational graphics and physics. Thos
* Almost one trait per functionality: useful for generic programming.
* Operator overloading using the double trait dispatch
[trick](http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/).
For example, the following work:
For example, the following works:
```rust
extern mod nalgebra;
@ -98,6 +98,7 @@ Feel free to add your project to this list if you happen to use **nalgebra**!
#[deny(non_uppercase_statics)];
#[deny(unnecessary_qualification)];
#[deny(missing_doc)];
#[feature(macro_rules)];
extern mod std;
extern mod extra;

101
src/na.rs
View File

@ -1,5 +1,6 @@
//! **nalgebra** prelude.
pub use std::num::{Zero, One};
pub use traits::{
Absolute,
AbsoluteRotate,
@ -46,6 +47,106 @@ pub use structs::{
Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6
};
//
//
// Constructors
//
//
/// Create a zero-valued value.
///
/// This is the same as `std::num::Zero::zero()`.
#[inline(always)]
pub fn zero<T: Zero>() -> T {
Zero::zero()
}
/// Create a one-valued value.
///
/// This is the same as `std::num::One::one()`.
#[inline(always)]
pub fn one<T: One>() -> T {
One::one()
}
/// Creates a new 1d vector.
///
/// This is the same as `Vec1::new(x)`.
#[inline(always)]
pub fn vec1<N>(x: N) -> Vec1<N> {
Vec1::new(x)
}
/// Creates a new 2d vector.
///
/// This is the same as `Vec2::new(x, y)`.
#[inline(always)]
pub fn vec2<N>(x: N, y: N) -> Vec2<N> {
Vec2::new(x, y)
}
/// Creates a new 3d vector.
///
/// This is the same as `Vec3::new(x, y, z)`.
#[inline(always)]
pub fn vec3<N>(x: N, y: N, z: N) -> Vec3<N> {
Vec3::new(x, y, z)
}
/// Creates a new 4d vector.
///
/// This is the same as `Vec4::new(x, y, z, w)`.
#[inline(always)]
pub fn vec4<N>(x: N, y: N, z: N, w: N) -> Vec4<N> {
Vec4::new(x, y, z, w)
}
/// Creates a new 1d matrix.
///
/// This is the same as `Mat1::new(...)`.
#[inline(always)]
pub fn mat1<N>(m11: N) -> Mat1<N> {
Mat1::new(m11)
}
/// Creates a new 2d matrix.
///
/// This is the same as `Mat2::new(...)`.
#[inline(always)]
pub fn mat2<N>(m11: N, m12: N,
m21: N, m22: N) -> Mat2<N> {
Mat2::new(
m11, m12,
m21, m22)
}
/// Creates a new 3d matrix.
///
/// This is the same as `Mat3::new(...)`.
#[inline(always)]
pub fn mat3<N>(m11: N, m12: N, m13: N,
m21: N, m22: N, m23: N,
m31: N, m32: N, m33: N) -> Mat3<N> {
Mat3::new(
m11, m12, m13,
m21, m22, m23,
m31, m32, m33)
}
/// Creates a new 4d matrix.
///
/// This is the same as `Mat4::new(...)`.
#[inline(always)]
pub fn mat4<N>(m11: N, m12: N, m13: N, m14: N,
m21: N, m22: N, m23: N, m24: N,
m31: N, m32: N, m33: N, m34: N,
m41: N, m42: N, m43: N, m44: N) -> Mat4<N> {
Mat4::new(
m11, m12, m13, m14,
m21, m22, m23, m24,
m31, m32, m33, m34,
m41, m42, m43, m44)
}
//
//
// Geometry

View File

@ -4,7 +4,7 @@
use std::rand::Rand;
use std::rand;
use std::num::{One, Zero};
use std::num::{One, Zero, from_f32, from_uint};
use std::vec;
use std::cmp::ApproxEq;
use std::util;
@ -409,10 +409,10 @@ impl<N: Clone> Transpose for DMat<N> {
}
}
impl<N: Num + NumCast + Clone> Mean<DVec<N>> for DMat<N> {
impl<N: Num + FromPrimitive + 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 = NumCast::from(1.0f64 / NumCast::from(self.nrows));
let normalizer: N = from_f32(1.0f32 / from_uint(self.nrows).unwrap()).unwrap();
for i in range(0u, self.nrows) {
for j in range(0u, self.ncols) {
@ -427,7 +427,7 @@ impl<N: Num + NumCast + Clone> Mean<DVec<N>> for DMat<N> {
}
}
impl<N: Clone + Num + NumCast + DMatDivRhs<N, DMat<N>> + ToStr > Cov<DMat<N>> for DMat<N> {
impl<N: Clone + Num + FromPrimitive + 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 +445,7 @@ impl<N: Clone + Num + NumCast + DMatDivRhs<N, DMat<N>> + ToStr > Cov<DMat<N>> fo
}
// FIXME: return a triangular matrix?
let normalizer: N = NumCast::from(self.nrows() - 1);
let normalizer: N = from_uint(self.nrows() - 1).unwrap();
// FIXME: this will do 2 allocations for temporaries!
(centered.transposed() * centered) / normalizer
}

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: NumCast + Algebraic + Trigonometric + Num + Clone>
impl<N: FromPrimitive + 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 + NumCast + Clone> Rotation<$tav<N>> for $t<N> {
impl<N: Num + Trigonometric + Algebraic + FromPrimitive + Clone> Rotation<$tav<N>> for $t<N> {
#[inline]
fn rotation(&self) -> $tav<N> {
self.rotation.rotation()

View File

@ -37,7 +37,7 @@ macro_rules! mat_cast_impl(
impl<Nin: NumCast + Clone, Nout: NumCast> MatCast<$t<Nout>> for $t<Nin> {
#[inline]
fn from(m: $t<Nin>) -> $t<Nout> {
$t::new(NumCast::from(m.$comp0.clone()) $(, NumCast::from(m.$compN.clone()) )*)
$t::new(NumCast::from(m.$comp0.clone()).unwrap() $(, NumCast::from(m.$compN.clone()).unwrap() )*)
}
}
)

View File

@ -2,7 +2,7 @@
#[allow(missing_doc)];
use std::num::{Zero, One};
use std::num::{Zero, One, from_f32};
use std::rand::{Rand, Rng};
use traits::geometry::{Rotate, Rotation, AbsoluteRotate, RotationMatrix, Transform, ToHomogeneous,
Norm, Cross};
@ -168,11 +168,11 @@ impl<N: Clone + Num + Algebraic> Rot3<N> {
}
}
impl<N: Clone + Trigonometric + Num + Algebraic + NumCast>
impl<N: Clone + Trigonometric + Num + Algebraic + FromPrimitive>
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()) / NumCast::from(2.0)).acos();
let angle = ((self.submat.m11 + self.submat.m22 + self.submat.m33 - One::one()) / from_f32(2.0).unwrap()).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: NumCast + Algebraic + Trigonometric + Num + Clone>
impl<N: FromPrimitive + 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,4 +1,4 @@
use std::num::{Zero, One};
use std::num::{Zero, One, from_f32};
use structs::vec::{Vec2, Vec3, Vec2MulRhs, Vec3MulRhs};
use structs::mat::{Mat1, Mat2, Mat3, Mat3MulRhs, Mat2MulRhs};
use structs::mat;
@ -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 + NumCast + Zero + One> mat::Mat4<N> {
impl<N: Real + FromPrimitive + 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 * NumCast::from(0.5)).tan();
let sy = _1 / (fov * from_f32(0.5).unwrap()).tan();
let sx = -sy / aspect;
let sz = -(zfar + znear) / (znear - zfar);
let tz = zfar * znear * NumCast::from(2.0) / (znear - zfar);
let tz = zfar * znear * from_f32(2.0).unwrap() / (znear - zfar);
mat::Mat4::new(
sx, Zero::zero(), Zero::zero(), Zero::zero(),

View File

@ -115,7 +115,7 @@ macro_rules! vec_cast_impl(
impl<Nin: NumCast + Clone, Nout: Clone + NumCast> VecCast<$t<Nout>> for $t<Nin> {
#[inline]
fn from(v: $t<Nin>) -> $t<Nout> {
$t::new(NumCast::from(v.$comp0.clone()) $(, NumCast::from(v.$compN.clone()))*)
$t::new(NumCast::from(v.$comp0.clone()).unwrap() $(, NumCast::from(v.$compN.clone()).unwrap())*)
}
}
)

View File

@ -1,14 +1,16 @@
use std::num::{Real, One, abs};
use std::num::{Real, abs};
use std::rand::random;
use std::cmp::ApproxEq;
use na::*;
use na::{DMat, DVec};
use na::Indexable; // FIXME: get rid of that
use na;
macro_rules! test_inv_mat_impl(
($t: ty) => (
do 10000.times {
let randmat : $t = random();
assert!((randmat.inverted().unwrap() * randmat).approx_eq(&One::one()));
assert!((na::inverted(&randmat).unwrap() * randmat).approx_eq(&na::one()));
}
);
)
@ -18,97 +20,97 @@ macro_rules! test_transpose_mat_impl(
do 10000.times {
let randmat : $t = random();
assert!(randmat.transposed().transposed().eq(&randmat));
assert!(na::transposed(&na::transposed(&randmat)) == randmat);
}
);
)
#[test]
fn test_transpose_mat1() {
test_transpose_mat_impl!(Mat1<f64>);
test_transpose_mat_impl!(na::Mat1<f64>);
}
#[test]
fn test_transpose_mat2() {
test_transpose_mat_impl!(Mat2<f64>);
test_transpose_mat_impl!(na::Mat2<f64>);
}
#[test]
fn test_transpose_mat3() {
test_transpose_mat_impl!(Mat3<f64>);
test_transpose_mat_impl!(na::Mat3<f64>);
}
#[test]
fn test_transpose_mat4() {
test_transpose_mat_impl!(Mat4<f64>);
test_transpose_mat_impl!(na::Mat4<f64>);
}
#[test]
fn test_transpose_mat5() {
test_transpose_mat_impl!(Mat5<f64>);
test_transpose_mat_impl!(na::Mat5<f64>);
}
#[test]
fn test_transpose_mat6() {
test_transpose_mat_impl!(Mat6<f64>);
test_transpose_mat_impl!(na::Mat6<f64>);
}
#[test]
fn test_inv_mat1() {
test_inv_mat_impl!(Mat1<f64>);
test_inv_mat_impl!(na::Mat1<f64>);
}
#[test]
fn test_inv_mat2() {
test_inv_mat_impl!(Mat2<f64>);
test_inv_mat_impl!(na::Mat2<f64>);
}
#[test]
fn test_inv_mat3() {
test_inv_mat_impl!(Mat3<f64>);
test_inv_mat_impl!(na::Mat3<f64>);
}
#[test]
fn test_inv_mat4() {
test_inv_mat_impl!(Mat4<f64>);
test_inv_mat_impl!(na::Mat4<f64>);
}
#[test]
fn test_inv_mat5() {
test_inv_mat_impl!(Mat5<f64>);
test_inv_mat_impl!(na::Mat5<f64>);
}
#[test]
fn test_inv_mat6() {
test_inv_mat_impl!(Mat6<f64>);
test_inv_mat_impl!(na::Mat6<f64>);
}
#[test]
fn test_rotation2() {
do 10000.times {
let randmat: Rot2<f64> = One::one();
let ang = &Vec1::new(abs::<f64>(random()) % Real::pi());
let randmat: na::Rot2<f64> = na::one();
let ang = na::vec1(abs::<f64>(random()) % Real::pi());
assert!(randmat.rotated(ang).rotation().approx_eq(ang));
assert!(na::rotation(&na::rotated(&randmat, &ang)).approx_eq(&ang));
}
}
#[test]
fn test_index_mat2() {
let mat: Mat2<f64> = random();
let mat: na::Mat2<f64> = random();
assert!(mat.at((0, 1)) == mat.transposed().at((1, 0)));
assert!(mat.at((0, 1)) == na::transposed(&mat).at((1, 0)));
}
#[test]
fn test_inv_rotation3() {
do 10000.times {
let randmat: Rot3<f64> = One::one();
let dir: Vec3<f64> = random();
let ang = &(dir.normalized() * (abs::<f64>(random()) % Real::pi()));
let rot = randmat.rotated(ang);
let randmat: na::Rot3<f64> = na::one();
let dir: na::Vec3<f64> = random();
let ang = na::normalized(&dir) * (abs::<f64>(random()) % Real::pi());
let rot = na::rotated(&randmat, &ang);
assert!((rot.transposed() * rot).approx_eq(&One::one()));
assert!((na::transposed(&rot) * rot).approx_eq(&na::one()));
}
}
@ -124,7 +126,7 @@ fn test_mean_dmat() {
]
);
assert!(mat.mean().approx_eq(&DVec::from_vec(3, [4.0f64, 5.0, 6.0])));
assert!(na::mean(&mat).approx_eq(&DVec::from_vec(3, [4.0f64, 5.0, 6.0])));
}
#[test]
@ -151,5 +153,5 @@ fn test_cov_dmat() {
]
);
assert!(mat.cov().approx_eq(&expected));
assert!(na::cov(&mat).approx_eq(&expected));
}

View File

@ -1,7 +1,8 @@
use std::num::{Zero, One};
use std::rand::{random};
use std::cmp::ApproxEq;
use na::*;
use na::{Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6};
use na::{Iterable, IterableMut}; // FIXME: get rid of that
use na;
macro_rules! test_iterator_impl(
($t: ty, $n: ty) => (
@ -27,7 +28,7 @@ macro_rules! test_commut_dot_impl(
let v1 : $t = random();
let v2 : $t = random();
assert!(v1.dot(&v2).approx_eq(&v2.dot(&v1)));
assert!(na::dot(&v1, &v2).approx_eq(&na::dot(&v2, &v1)));
}
);
)
@ -58,14 +59,14 @@ macro_rules! test_scalar_op_impl(
macro_rules! test_basis_impl(
($t: ty) => (
do 10000.times {
do Basis::canonical_basis |e1: $t| {
do Basis::canonical_basis |e2: $t| {
assert!(e1 == e2 || e1.dot(&e2).approx_eq(&Zero::zero()));
do na::canonical_basis |e1: $t| {
do na::canonical_basis |e2: $t| {
assert!(e1 == e2 || na::dot(&e1, &e2).approx_eq(&na::zero()));
true
}
assert!(e1.norm().approx_eq(&One::one()));
assert!(na::norm(&e1).approx_eq(&na::one()));
true
}
@ -77,16 +78,16 @@ macro_rules! test_subspace_basis_impl(
($t: ty) => (
do 10000.times {
let v : $t = random();
let v1 = v.normalized();
let v1 = na::normalized(&v);
do v1.orthonormal_subspace_basis() |e1| {
do na::orthonormal_subspace_basis(&v1) |e1| {
// check vectors are orthogonal to v1
assert!(v1.dot(&e1).approx_eq(&Zero::zero()));
assert!(na::dot(&v1, &e1).approx_eq(&na::zero()));
// check vectors form an orthonormal basis
assert!(e1.norm().approx_eq(&One::one()));
assert!(na::norm(&e1).approx_eq(&na::one()));
// check vectors form an ortogonal basis
do v1.orthonormal_subspace_basis() |e2| {
assert!(e1 == e2 || e1.dot(&e2).approx_eq(&Zero::zero()));
do na::orthonormal_subspace_basis(&v1) |e2| {
assert!(e1 == e2 || na::dot(&e1, &e2).approx_eq(&na::zero()));
true
}
@ -102,10 +103,10 @@ fn test_cross_vec3() {
do 10000.times {
let v1 : Vec3<f64> = random();
let v2 : Vec3<f64> = random();
let v3 : Vec3<f64> = v1.cross(&v2);
let v3 : Vec3<f64> = na::cross(&v1, &v2);
assert!(v3.dot(&v2).approx_eq(&Zero::zero()));
assert!(v3.dot(&v1).approx_eq(&Zero::zero()));
assert!(na::dot(&v3, &v2).approx_eq(&na::zero()));
assert!(na::dot(&v3, &v1).approx_eq(&na::zero()));
}
}
@ -287,39 +288,35 @@ fn test_iterator_vec6() {
#[test]
fn test_ord_vec3() {
// equality
assert!(Vec3::new(0.5, 0.5, 0.5) == Vec3::new(0.5, 0.5, 0.5));
assert!(!(Vec3::new(1.5, 0.5, 0.5) == Vec3::new(0.5, 0.5, 0.5)));
assert!(Vec3::new(1.5, 0.5, 0.5) != Vec3::new(0.5, 0.5, 0.5));
assert!(na::vec3(0.5, 0.5, 0.5) == na::vec3(0.5, 0.5, 0.5));
assert!(!(na::vec3(1.5, 0.5, 0.5) == na::vec3(0.5, 0.5, 0.5)));
assert!(na::vec3(1.5, 0.5, 0.5) != na::vec3(0.5, 0.5, 0.5));
// comparable
assert!(Vec3::new(0.5, 0.3, 0.3) < Vec3::new(1.0, 2.0, 1.0));
assert!(Vec3::new(0.5, 0.3, 0.3) <= Vec3::new(1.0, 2.0, 1.0));
assert!(Vec3::new(2.0, 4.0, 2.0) > Vec3::new(1.0, 2.0, 1.0));
assert!(Vec3::new(2.0, 4.0, 2.0) >= Vec3::new(1.0, 2.0, 1.0));
assert!(na::vec3(0.5, 0.3, 0.3) < na::vec3(1.0, 2.0, 1.0));
assert!(na::vec3(0.5, 0.3, 0.3) <= na::vec3(1.0, 2.0, 1.0));
assert!(na::vec3(2.0, 4.0, 2.0) > na::vec3(1.0, 2.0, 1.0));
assert!(na::vec3(2.0, 4.0, 2.0) >= na::vec3(1.0, 2.0, 1.0));
// not comparable
assert!(!(Vec3::new(0.0, 3.0, 0.0) < Vec3::new(1.0, 2.0, 1.0)));
assert!(!(Vec3::new(0.0, 3.0, 0.0) > Vec3::new(1.0, 2.0, 1.0)));
assert!(!(Vec3::new(0.0, 3.0, 0.0) <= Vec3::new(1.0, 2.0, 1.0)));
assert!(!(Vec3::new(0.0, 3.0, 0.0) >= Vec3::new(1.0, 2.0, 1.0)));
assert!(!(na::vec3(0.0, 3.0, 0.0) < na::vec3(1.0, 2.0, 1.0)));
assert!(!(na::vec3(0.0, 3.0, 0.0) > na::vec3(1.0, 2.0, 1.0)));
assert!(!(na::vec3(0.0, 3.0, 0.0) <= na::vec3(1.0, 2.0, 1.0)));
assert!(!(na::vec3(0.0, 3.0, 0.0) >= na::vec3(1.0, 2.0, 1.0)));
}
#[test]
fn test_min_max_vec3() {
assert_eq!(Vec3::new(1, 2, 3).max(&Vec3::new(3, 2, 1)), Vec3::new(3, 2, 3));
assert_eq!(Vec3::new(1, 2, 3).min(&Vec3::new(3, 2, 1)), Vec3::new(1, 2, 1));
assert_eq!(
Vec3::new(0, 2, 4).clamp(
&Vec3::new(1, 1, 1), &Vec3::new(3, 3, 3)
), Vec3::new(1, 2, 3)
);
assert_eq!(na::vec3(1, 2, 3).max(&na::vec3(3, 2, 1)), na::vec3(3, 2, 3));
assert_eq!(na::vec3(1, 2, 3).min(&na::vec3(3, 2, 1)), na::vec3(1, 2, 1));
assert_eq!(na::vec3(0, 2, 4).clamp(&na::vec3(1, 1, 1), &na::vec3(3, 3, 3)), na::vec3(1, 2, 3));
}
#[test]
fn test_outer_vec3() {
assert_eq!(
Vec3::new(1, 2, 3).outer(&Vec3::new(4, 5, 6)),
Mat3::new(
na::outer(&na::vec3(1, 2, 3), &na::vec3(4, 5, 6)),
na::mat3(
4, 5, 6,
8, 10, 12,
12, 15, 18));