Update to the last Rust.

Version of rustc: 0.10-pre (b0ce960 2014-02-17 22:16:51 -0800)
This replaces uses of the `Orderable` trait by a `PartialOrd` trait: the `min` and `max` methods
are replaced by `inf` and `sup` methods.
Vectors do not implement the `Ord` trait any more.

Fix #4
This commit is contained in:
Sébastien Crozet 2014-02-18 12:13:40 +01:00
parent d9ace45141
commit becb77843e
18 changed files with 317 additions and 125 deletions

View File

@ -4,13 +4,13 @@ nalgebra_doc_path=doc
all:
mkdir -p $(nalgebra_lib_path)
rustc src/lib.rs --out-dir $(nalgebra_lib_path) --opt-level 3
rustc src/lib.rs --out-dir $(nalgebra_lib_path) --crate-type dylib --opt-level 3
test:
mkdir -p $(nalgebra_lib_path)
rustc --test src/lib.rs --opt-level 3 -o test~ && ./test~
rm test~
# FIXME:
# rustdoc --test -L lib src/lib.rs
rustdoc --test -L lib src/lib.rs
bench:
rustc --test src/lib.rs --opt-level 3 -o bench~ && ./bench~ --bench

View File

@ -18,7 +18,7 @@ out-of-place modifications.
* You can import the whole prelude using:
```
```.ignore
use nalgebra::na::*;
```
@ -26,7 +26,7 @@ The preferred way to use **nalgebra** is to import types and traits explicitly,
free-functions using the `na::` prefix:
```.rust
extern mod nalgebra;
extern crate nalgebra;
use nalgebra::na::{Vec3, Rot3, Rotation};
use nalgebra::na;
@ -57,7 +57,7 @@ and keeps an optimized set of tools for computational graphics and physics. Thos
For example, the following works:
```rust
extern mod nalgebra;
extern crate nalgebra;
use nalgebra::na::{Vec3, Mat3};
use nalgebra::na;
@ -76,13 +76,15 @@ fn main() {
You will need the last rust compiler from the master branch.
If you encounter problems, make sure you have the last version before creating an issue.
git clone git://github.com/sebcrozet/nalgebra.git
cd nalgebra
make
```.ignore
git clone git://github.com/sebcrozet/nalgebra.git
cd nalgebra
make
```
You can build the documentation on the `doc` folder using:
```
```.ignore
make doc
```
@ -107,9 +109,9 @@ Feel free to add your project to this list if you happen to use **nalgebra**!
#[feature(macro_rules)];
#[doc(html_root_url = "http://www.rust-ci.org/sebcrozet/nalgebra/doc")];
extern mod std;
extern mod extra;
extern mod serialize;
extern crate std;
extern crate extra;
extern crate serialize;
pub mod na;
mod structs;

109
src/na.rs
View File

@ -1,12 +1,14 @@
//! **nalgebra** prelude.
use std::num::{Zero, One};
use std::cmp;
pub use traits::{Less, Equal, Greater, NotComparable};
pub use traits::{
Absolute,
AbsoluteRotate,
ApproxEq,
RealVec,
RealVecExt,
FloatVec,
FloatVecExt,
Basis,
Cast,
Col,
@ -25,6 +27,8 @@ pub use traits::{
Mean,
Norm,
Outer,
PartialOrd,
PartialOrdering,
RMul,
Rotate, Rotation, RotationMatrix, RotationWithTranslation,
Row,
@ -48,6 +52,71 @@ pub use structs::{
Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6
};
/// Change the input value to ensure it is on the range `[min, max]`.
#[inline(always)]
pub fn clamp<T: Ord>(val: T, min: T, max: T) -> T {
if val > min {
if val < max {
val
}
else {
max
}
}
else {
min
}
}
/// Same as `cmp::max`.
#[inline(always)]
pub fn max<T: Ord>(a: T, b: T) -> T {
cmp::max(a, b)
}
/// Same as `cmp::min`.
#[inline(always)]
pub fn min<T: Ord>(a: T, b: T) -> T {
cmp::min(a, b)
}
/// Returns the infimum of `a` and `b`.
#[inline(always)]
pub fn inf<T: PartialOrd>(a: &T, b: &T) -> T {
PartialOrd::inf(a, b)
}
/// Returns the supremum of `a` and `b`.
#[inline(always)]
pub fn sup<T: PartialOrd>(a: &T, b: &T) -> T {
PartialOrd::sup(a, b)
}
/// Compare `a` and `b` using a partial ordering relation.
#[inline(always)]
pub fn partial_cmp<T: PartialOrd>(a: &T, b: &T) -> PartialOrdering {
PartialOrd::partial_cmp(a, b)
}
/// Return the minimum of `a` and `b` if they are comparable.
#[inline(always)]
pub fn partial_min<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> Option<&'a T> {
PartialOrd::partial_min(a, b)
}
/// Return the maximum of `a` and `b` if they are comparable.
#[inline(always)]
pub fn partial_max<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> Option<&'a T> {
PartialOrd::partial_max(a, b)
}
/// Clamp `value` between `min` and `max`. Returns `None` if `value` is not comparable to
/// `min` or `max`.
#[inline(always)]
pub fn partial_clamp<'a, T: PartialOrd>(value: &'a T, min: &'a T, max: &'a T) -> Option<&'a T> {
PartialOrd::partial_clamp(value, min, max)
}
//
//
// Constructors
@ -89,7 +158,7 @@ pub fn one<T: One>() -> T {
*/
/// 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 perspective3d<N: Real + Cast<f32> + Zero + One>(width: N, height: N, fov: N, znear: N, zfar: N) -> Mat4<N> {
pub fn perspective3d<N: Float + Cast<f32> + Zero + One>(width: N, height: N, fov: N, znear: N, zfar: N) -> Mat4<N> {
let aspect = width / height;
let _1: N = one();
@ -112,7 +181,7 @@ pub fn perspective3d<N: Real + Cast<f32> + Zero + One>(width: N, height: N, fov:
/// Gets the translation applicable by `m`.
///
/// ```rust
/// extern mod nalgebra;
/// extern crate nalgebra;
/// use nalgebra::na::{Vec3, Iso3};
/// use nalgebra::na;
///
@ -131,7 +200,7 @@ pub fn translation<V, M: Translation<V>>(m: &M) -> V {
/// Gets the inverse translation applicable by `m`.
///
/// ```rust
/// extern mod nalgebra;
/// extern crate nalgebra;
/// use nalgebra::na::{Vec3, Iso3};
/// use nalgebra::na;
///
@ -160,7 +229,7 @@ pub fn append_translation<V, M: Translation<V>>(m: &M, v: &V) -> M {
/// Applies a translation to a vector.
///
/// ```rust
/// extern mod nalgebra;
/// extern crate nalgebra;
/// use nalgebra::na::{Vec3, Iso3};
/// use nalgebra::na;
///
@ -181,7 +250,7 @@ pub fn translate<V, M: Translate<V>>(m: &M, v: &V) -> V {
/// Applies an inverse translation to a vector.
///
/// ```rust
/// extern mod nalgebra;
/// extern crate nalgebra;
/// use nalgebra::na::{Vec3, Iso3};
/// use nalgebra::na;
///
@ -205,7 +274,7 @@ pub fn inv_translate<V, M: Translate<V>>(m: &M, v: &V) -> V {
/// Gets the rotation applicable by `m`.
///
/// ```rust
/// extern mod nalgebra;
/// extern crate nalgebra;
/// use nalgebra::na::{Vec3, Rot3};
/// use nalgebra::na;
///
@ -224,7 +293,7 @@ pub fn rotation<V, M: Rotation<V>>(m: &M) -> V {
/// Gets the inverse rotation applicable by `m`.
///
/// ```rust
/// extern mod nalgebra;
/// extern crate nalgebra;
/// use nalgebra::na::{Vec3, Rot3};
/// use nalgebra::na;
///
@ -243,7 +312,7 @@ pub fn inv_rotation<V, M: Rotation<V>>(m: &M) -> V {
/// Applies the rotation `v` to a copy of `m`.
///
/// ```rust
/// extern mod nalgebra;
/// extern crate nalgebra;
/// use nalgebra::na::{Vec3, Rot3};
/// use nalgebra::na;
///
@ -264,7 +333,7 @@ pub fn append_rotation<V, M: Rotation<V>>(m: &M, v: &V) -> M {
/// Pre-applies the rotation `v` to a copy of `m`.
///
/// ```rust
/// extern mod nalgebra;
/// extern crate nalgebra;
/// use nalgebra::na::{Vec3, Rot3};
/// use nalgebra::na;
///
@ -288,13 +357,13 @@ pub fn prepend_rotation<V, M: Rotation<V>>(m: &M, v: &V) -> M {
/// Applies a rotation to a vector.
///
/// ```rust
/// extern mod nalgebra;
/// use std::num::Real;
/// extern crate nalgebra;
/// use std::num::Float;
/// use nalgebra::na::{Rot3, Vec3};
/// use nalgebra::na;
///
/// fn main() {
/// let t = Rot3::new(Vec3::new(0.0, 0.0, 0.5 * Real::pi()));
/// let t = Rot3::new(Vec3::new(0.0, 0.0, 0.5 * Float::pi()));
/// let v = Vec3::new(1.0, 0.0, 0.0);
///
/// let tv = na::rotate(&t, &v);
@ -311,13 +380,13 @@ pub fn rotate<V, M: Rotate<V>>(m: &M, v: &V) -> V {
/// Applies an inverse rotation to a vector.
///
/// ```rust
/// extern mod nalgebra;
/// use std::num::Real;
/// extern crate nalgebra;
/// use std::num::Float;
/// use nalgebra::na::{Rot3, Vec3};
/// use nalgebra::na;
///
/// fn main() {
/// let t = Rot3::new(Vec3::new(0.0, 0.0, 0.5 * Real::pi()));
/// let t = Rot3::new(Vec3::new(0.0, 0.0, 0.5 * Float::pi()));
/// let v = Vec3::new(1.0, 0.0, 0.0);
///
/// let tv = na::inv_rotate(&t, &v);
@ -435,19 +504,19 @@ pub fn sub_dot<V: Dot<N>, N>(a: &V, b: &V, c: &V) -> N {
/// Computes the L2 norm of a vector.
#[inline(always)]
pub fn norm<V: Norm<N>, N: Real>(v: &V) -> N {
pub fn norm<V: Norm<N>, N: Float>(v: &V) -> N {
Norm::norm(v)
}
/// Computes the squared L2 norm of a vector.
#[inline(always)]
pub fn sqnorm<V: Norm<N>, N: Real>(v: &V) -> N {
pub fn sqnorm<V: Norm<N>, N: Float>(v: &V) -> N {
Norm::sqnorm(v)
}
/// Gets the normalized version of a vector.
#[inline(always)]
pub fn normalize<V: Norm<N>, N: Real>(v: &V) -> V {
pub fn normalize<V: Norm<N>, N: Float>(v: &V) -> V {
Norm::normalize_cpy(v)
}

View File

@ -2,7 +2,7 @@
#[allow(missing_doc)]; // we hide doc to not have to document the $trhs double dispatch trait.
use std::num::{Zero, One, Real};
use std::num::{Zero, One, Float};
use std::rand::Rand;
use std::rand;
use std::vec;
@ -177,7 +177,7 @@ impl<N> FromIterator<N> for DVec<N> {
}
}
impl<N: Clone + Num + Real + ApproxEq<N> + DVecMulRhs<N, DVec<N>>> DVec<N> {
impl<N: Clone + Num + Float + ApproxEq<N> + DVecMulRhs<N, DVec<N>>> DVec<N> {
/// Computes the canonical basis for the given dimension. A canonical basis is a set of
/// vectors, mutually orthogonal, with all its component equal to 0.0 except one which is equal
/// to 1.0.
@ -284,7 +284,7 @@ impl<N: Num + Clone> Dot<N> for DVec<N> {
}
}
impl<N: Num + Real + Clone> Norm<N> for DVec<N> {
impl<N: Num + Float + Clone> Norm<N> for DVec<N> {
#[inline]
fn sqnorm(v: &DVec<N>) -> N {
Dot::dot(v, v)

View File

@ -51,7 +51,7 @@ pub struct Iso4<N> {
translation: Vec4<N>
}
impl<N: Clone + Num + Real> Iso3<N> {
impl<N: Clone + Num + Float> Iso3<N> {
/// Reorient and translate this transformation such that its local `x` axis points to a given
/// direction. Note that the usually known `look_at` function does the same thing but with the
/// `z` axis. See `look_at_z` for that.

View File

@ -2,7 +2,7 @@
macro_rules! iso_impl(
($t: ident, $submat: ident, $subvec: ident, $subrotvec: ident) => (
impl<N: Clone + Real + Real + Num> $t<N> {
impl<N: Clone + Float + Float + Num> $t<N> {
/// Creates a new isometry from a rotation matrix and a vector.
#[inline]
pub fn new(translation: $subvec<N>, rotation: $subrotvec<N>) -> $t<N> {
@ -26,7 +26,7 @@ macro_rules! iso_impl(
macro_rules! rotation_matrix_impl(
($t: ident, $trot: ident, $tlv: ident, $tav: ident) => (
impl<N: Cast<f32> + Real + Real + Num + Clone>
impl<N: Cast<f32> + Float + Float + Num + Clone>
RotationMatrix<$tlv<N>, $tav<N>, $trot<N>> for $t<N> {
#[inline]
fn to_rot_mat(&self) -> $trot<N> {
@ -50,7 +50,7 @@ macro_rules! dim_impl(
macro_rules! one_impl(
($t: ident) => (
impl<N: Real + Real + Num + Clone> One for $t<N> {
impl<N: Float + Float + Num + Clone> One for $t<N> {
#[inline]
fn one() -> $t<N> {
$t::new_with_rotmat(Zero::zero(), One::one())
@ -61,7 +61,7 @@ macro_rules! one_impl(
macro_rules! iso_mul_iso_impl(
($t: ident, $tmul: ident) => (
impl<N: Num + Real + Real + Clone> $tmul<N, $t<N>> for $t<N> {
impl<N: Num + Float + Float + Clone> $tmul<N, $t<N>> for $t<N> {
#[inline]
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
$t::new_with_rotmat(
@ -96,7 +96,7 @@ macro_rules! vec_mul_iso_impl(
macro_rules! translation_impl(
($t: ident, $tv: ident) => (
impl<N: Real + Num + Real + Clone> Translation<$tv<N>> for $t<N> {
impl<N: Float + Num + Float + Clone> Translation<$tv<N>> for $t<N> {
#[inline]
fn translation(&self) -> $tv<N> {
self.translation.clone()
@ -153,7 +153,7 @@ macro_rules! translate_impl(
macro_rules! rotation_impl(
($t: ident, $trot: ident, $tav: ident) => (
impl<N: Cast<f32> + Num + Real + Real + Clone> Rotation<$tav<N>> for $t<N> {
impl<N: Cast<f32> + Num + Float + Float + Clone> Rotation<$tav<N>> for $t<N> {
#[inline]
fn rotation(&self) -> $tav<N> {
self.rotation.rotation()
@ -220,7 +220,7 @@ macro_rules! rotate_impl(
macro_rules! transformation_impl(
($t: ident) => (
impl<N: Num + Real + Real + Clone> Transformation<$t<N>> for $t<N> {
impl<N: Num + Float + Float + Clone> Transformation<$t<N>> for $t<N> {
fn transformation(&self) -> $t<N> {
self.clone()
}
@ -336,7 +336,7 @@ macro_rules! approx_eq_impl(
macro_rules! rand_impl(
($t: ident) => (
impl<N: Rand + Clone + Real + Real + Num> Rand for $t<N> {
impl<N: Rand + Clone + Float + Float + Num> Rand for $t<N> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> $t<N> {
$t::new(rng.gen(), rng.gen())

View File

@ -20,7 +20,7 @@ pub struct Rot2<N> {
priv submat: Mat2<N>
}
impl<N: Clone + Real + Neg<N>> Rot2<N> {
impl<N: Clone + Float + Neg<N>> Rot2<N> {
/// Builds a 2 dimensional rotation matrix from an angle in radian.
pub fn new(angle: Vec1<N>) -> Rot2<N> {
let (sia, coa) = angle.x.sin_cos();
@ -31,7 +31,7 @@ impl<N: Clone + Real + Neg<N>> Rot2<N> {
}
}
impl<N: Real + Num + Clone>
impl<N: Float + Num + Clone>
Rotation<Vec1<N>> for Rot2<N> {
#[inline]
fn rotation(&self) -> Vec1<N> {
@ -69,7 +69,7 @@ Rotation<Vec1<N>> for Rot2<N> {
}
}
impl<N: Clone + Rand + Real + Neg<N>> Rand for Rot2<N> {
impl<N: Clone + Rand + Float + Neg<N>> Rand for Rot2<N> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Rot2<N> {
Rot2::new(rng.gen())
@ -99,7 +99,7 @@ pub struct Rot3<N> {
}
impl<N: Clone + Real + Num + Real> Rot3<N> {
impl<N: Clone + Float + Num + Float> Rot3<N> {
/// Builds a 3 dimensional rotation matrix from an axis and an angle.
///
/// # Arguments
@ -140,7 +140,7 @@ impl<N: Clone + Real + Num + Real> Rot3<N> {
}
}
impl<N: Clone + Num + Real> Rot3<N> {
impl<N: Clone + Num + Float> Rot3<N> {
/// Reorient this matrix such that its local `x` axis points to a given point. Note that the
/// usually known `look_at` function does the same thing but with the `z` axis. See `look_at_z`
/// for that.
@ -180,7 +180,7 @@ impl<N: Clone + Num + Real> Rot3<N> {
}
}
impl<N: Clone + Real + Num + Real + Cast<f32>>
impl<N: Clone + Float + Num + Float + Cast<f32>>
Rotation<Vec3<N>> for Rot3<N> {
#[inline]
fn rotation(&self) -> Vec3<N> {
@ -245,7 +245,7 @@ Rotation<Vec3<N>> for Rot3<N> {
}
}
impl<N: Clone + Rand + Real + Num + Real>
impl<N: Clone + Rand + Float + Num + Float>
Rand for Rot3<N> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Rot3<N> {
@ -309,7 +309,7 @@ impl<N: Signed> AbsoluteRotate<Vec4<N>> for Rot4<N> {
}
}
impl<N: Real + Num + Clone>
impl<N: Float + Num + Clone>
Rotation<Vec4<N>> for Rot4<N> {
#[inline]
fn rotation(&self) -> Vec4<N> {

View File

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

View File

@ -91,7 +91,7 @@ impl<N: Clone + One + Zero + Neg<N>> Basis for Vec2<N> {
}
}
impl<N: Clone + Ord + Real + Signed> Basis for Vec3<N> {
impl<N: Clone + Ord + Float + Signed> Basis for Vec3<N> {
#[inline(always)]
fn canonical_basis(f: |Vec3<N>| -> bool) {
if !f(Vec3::new(One::one(), Zero::zero(), Zero::zero())) { return };

View File

@ -1,5 +1,5 @@
use std::cast;
use std::num::{Zero, One, Real, Bounded};
use std::num::{Zero, One, Float, Bounded};
use std::vec::{Items, MutItems};
use std::iter::{Iterator, FromIterator};
use traits::operations::ApproxEq;
@ -159,7 +159,7 @@ impl<N: Clone + Add<N, N> + Neg<N>> Translation<vec::Vec0<N>> for vec::Vec0<N> {
}
}
impl<N: Num + Real> Norm<N> for vec::Vec0<N> {
impl<N: Num + Float> Norm<N> for vec::Vec0<N> {
#[inline]
fn sqnorm(_: &vec::Vec0<N>) -> N {
Zero::zero()

View File

@ -3,10 +3,11 @@
#[allow(missing_doc)]; // we allow missing to avoid having to document the vector components.
use std::cast;
use std::num::{Zero, One, Real, Bounded};
use std::cmp;
use std::num::{Zero, One, Float, Bounded};
use std::vec::{Items, MutItems};
use std::iter::{Iterator, FromIterator};
use traits::operations::ApproxEq;
use traits::operations::{ApproxEq, PartialOrd, PartialOrdering, Less, Equal, Greater, NotComparable};
use traits::geometry::{Transform, Rotate, FromHomogeneous, ToHomogeneous, Dot, Norm,
Translation, Translate};
@ -38,7 +39,6 @@ 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, Vec1Cast, x)
indexable_impl!(Vec1, 1)
@ -137,7 +137,6 @@ 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, Vec2Cast, x, y)
indexable_impl!(Vec2, 2)
@ -238,7 +237,6 @@ 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, Vec3Cast, x, y, z)
indexable_impl!(Vec3, 3)
@ -345,7 +343,6 @@ 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, Vec4Cast, x, y, z, w)
indexable_impl!(Vec4, 4)
@ -450,7 +447,6 @@ 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, Vec5Cast, x, y, z, w, a)
indexable_impl!(Vec5, 5)
@ -557,7 +553,6 @@ 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, Vec6Cast, x, y, z, w, a, b)
indexable_impl!(Vec6, 6)

View File

@ -36,47 +36,52 @@ macro_rules! at_fast_impl(
macro_rules! ord_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Ord> Ord for $t<N> {
impl<N: Ord + Eq + Clone> PartialOrd for $t<N> {
#[inline]
fn lt(&self, other: &$t<N>) -> bool {
self.$comp0 < other.$comp0 $(&& self.$compN < other.$compN)*
fn inf(a: &$t<N>, b: &$t<N>) -> $t<N> {
$t::new(cmp::min(a.$comp0.clone(), b.$comp0.clone())
$(, cmp::min(a.$compN.clone(), b.$compN.clone()))*)
}
#[inline]
fn le(&self, other: &$t<N>) -> bool {
self.$comp0 <= other.$comp0 $(&& self.$compN <= other.$compN)*
fn sup(a: &$t<N>, b: &$t<N>) -> $t<N> {
$t::new(cmp::max(a.$comp0.clone(), b.$comp0.clone())
$(, cmp::max(a.$compN.clone(), b.$compN.clone()))*)
}
#[inline]
fn gt(&self, other: &$t<N>) -> bool {
self.$comp0 > other.$comp0 $(&& self.$compN > other.$compN)*
}
#[allow(unused_mut)] // otherwise there will be a warning for is_eq or Vec1.
fn partial_cmp(a: &$t<N>, b: &$t<N>) -> PartialOrdering {
let is_lt = a.$comp0 < b.$comp0;
let mut is_eq = a.$comp0 == b.$comp0;
#[inline]
fn ge(&self, other: &$t<N>) -> bool {
self.$comp0 >= other.$comp0 $(&& self.$compN >= other.$compN)*
}
}
)
)
if is_lt { // <
$(
if a.$compN > b.$compN {
return NotComparable
}
)*
macro_rules! orderable_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + Orderable> Orderable for $t<N> {
#[inline]
fn max(&self, other: &$t<N>) -> $t<N> {
$t::new(self.$comp0.max(&other.$comp0) $(, self.$compN.max(&other.$compN))*)
}
Less
}
else { // >=
$(
if a.$compN < b.$compN {
return NotComparable
}
else if a.$compN > b.$compN {
is_eq = false;
}
#[inline]
fn min(&self, other: &$t<N>) -> $t<N> {
$t::new(self.$comp0.min(&other.$comp0) $(, self.$compN.min(&other.$compN))*)
}
)*
#[inline]
fn clamp(&self, min: &$t<N>, max: &$t<N>) -> $t<N> {
$t::new(self.$comp0.clamp(&min.$comp0, &max.$comp0)
$(, self.$compN.clamp(&min.$comp0, &max.$comp0))*)
if is_eq {
Equal
}
else {
Greater
}
}
}
}
)
@ -223,7 +228,7 @@ macro_rules! container_impl(
macro_rules! basis_impl(
($t: ident, $trhs: ident, $dim: expr) => (
impl<N: Clone + Num + Real + ApproxEq<N> + $trhs<N, $t<N>>> Basis for $t<N> {
impl<N: Clone + Num + Float + ApproxEq<N> + $trhs<N, $t<N>>> Basis for $t<N> {
#[inline]
fn canonical_basis(f: |$t<N>| -> bool) {
for i in range(0u, $dim) {
@ -433,7 +438,7 @@ macro_rules! translation_impl(
macro_rules! norm_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + Num + Real> Norm<N> for $t<N> {
impl<N: Clone + Num + Float> Norm<N> for $t<N> {
#[inline]
fn sqnorm(v: &$t<N>) -> N {
Dot::dot(v, v)

View File

@ -1,4 +1,4 @@
use std::num::{Real, abs};
use std::num::{Float, abs};
use std::rand::random;
use na::{Vec1, Vec3, Mat1, Mat2, Mat3, Mat4, Mat5, Mat6, Rot3, DMat, DVec, Indexable};
use na;
@ -87,7 +87,7 @@ fn test_inv_mat6() {
fn test_rotation2() {
for _ in range(0, 10000) {
let randmat: na::Rot2<f64> = na::one();
let ang = Vec1::new(abs::<f64>(random()) % Real::pi());
let ang = Vec1::new(abs::<f64>(random()) % Float::pi());
assert!(na::approx_eq(&na::rotation(&na::append_rotation(&randmat, &ang)), &ang));
}
@ -105,7 +105,7 @@ fn test_inv_rotation3() {
for _ in range(0, 10000) {
let randmat: Rot3<f64> = na::one();
let dir: Vec3<f64> = random();
let ang = na::normalize(&dir) * (abs::<f64>(random()) % Real::pi());
let ang = na::normalize(&dir) * (abs::<f64>(random()) % Float::pi());
let rot = na::append_rotation(&randmat, &ang);
assert!(na::approx_eq(&(na::transpose(&rot) * rot), &na::one()));

View File

@ -292,23 +292,19 @@ fn test_ord_vec3() {
assert!(Vec3::new(1.5, 0.5, 0.5) != Vec3::new(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::partial_cmp(&Vec3::new(0.5, 0.3, 0.3), &Vec3::new(1.0, 2.0, 1.0)).is_le());
assert!(na::partial_cmp(&Vec3::new(0.5, 0.3, 0.3), &Vec3::new(1.0, 2.0, 1.0)).is_lt());
assert!(na::partial_cmp(&Vec3::new(2.0, 4.0, 2.0), &Vec3::new(1.0, 2.0, 1.0)).is_ge());
assert!(na::partial_cmp(&Vec3::new(2.0, 4.0, 2.0), &Vec3::new(1.0, 2.0, 1.0)).is_gt());
// 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::partial_cmp(&Vec3::new(0.0, 3.0, 0.0), &Vec3::new(1.0, 2.0, 1.0)).is_not_comparable());
}
#[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::sup(&Vec3::new(1, 2, 3), &Vec3::new(3, 2, 1)), Vec3::new(3, 2, 3));
assert_eq!(na::inf(&Vec3::new(1, 2, 3), &Vec3::new(3, 2, 1)), Vec3::new(1, 2, 1));
}
#[test]

View File

@ -153,9 +153,9 @@ pub trait RotationMatrix<LV, AV, M: Mat<LV, LV> + Rotation<AV>> : Rotation<AV> {
pub trait AbsoluteRotate<V> {
/// This is the same as:
///
/// ~~~
/// ```.ignore
/// self.rotation_matrix().absolute().rmul(v)
/// ~~~
/// ```
fn absolute_rotate(&self, v: &V) -> V;
}
@ -208,9 +208,9 @@ pub trait Dot<N> {
* computing intermediate vectors.
* The following equation must be verified:
*
* ~~~
* ```.ignore
* a.sub_dot(b, c) == (a - b).dot(c)
* ~~~
* ```
*
*/
#[inline]
@ -218,7 +218,7 @@ pub trait Dot<N> {
}
/// Traits of objects having an euclidian norm.
pub trait Norm<N: Real> {
pub trait Norm<N: Float> {
/// Computes the norm of `self`.
#[inline]
fn norm(v: &Self) -> N {

View File

@ -4,11 +4,12 @@ pub use self::geometry::{AbsoluteRotate, Cross, CrossMatrix, Dot, FromHomogeneou
Rotation, RotationMatrix, RotationWithTranslation, ToHomogeneous,
Transform, Transformation, Translate, Translation, UniformSphereSample};
pub use self::structure::{RealVec, RealVecExt, Basis, Cast, Col, Dim, Indexable,
pub use self::structure::{FloatVec, FloatVecExt, Basis, Cast, Col, Dim, Indexable,
Iterable, IterableMut, Mat, Row, Vec, VecExt};
pub use self::operations::{Absolute, ApproxEq, Cov, Inv, LMul, Mean, Outer, RMul, ScalarAdd,
ScalarSub, Transpose};
pub use self::operations::{Absolute, ApproxEq, Cov, Inv, LMul, Mean, Outer, PartialOrd, RMul,
ScalarAdd, ScalarSub, Transpose};
pub use self::operations::{PartialOrdering, Less, Equal, Greater, NotComparable};
pub mod geometry;
pub mod structure;

View File

@ -1,5 +1,129 @@
//! Low level operations on vectors and matrices.
use std::cmp;
/// Result of a partial ordering.
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr, Show)]
pub enum PartialOrdering {
/// Result of a strict comparison.
Less,
/// Equality relationship.
Equal,
/// Result of a strict comparison.
Greater,
/// Result of a comparison between two objects that are not comparable.
NotComparable
}
impl PartialOrdering {
/// Returns `true` if `self` is equal to `Equal`.
pub fn is_eq(&self) -> bool {
*self == Equal
}
/// Returns `true` if `self` is equal to `Less`.
pub fn is_lt(&self) -> bool {
*self == Less
}
/// Returns `true` if `self` is equal to `Less` or `Equal`.
pub fn is_le(&self) -> bool {
*self == Less || *self == Equal
}
/// Returns `true` if `self` is equal to `Greater`.
pub fn is_gt(&self) -> bool {
*self == Greater
}
/// Returns `true` if `self` is equal to `Greater` or `Equal`.
pub fn is_ge(&self) -> bool {
*self == Greater || *self == Equal
}
/// Returns `true` if `self` is equal to `NotComparable`.
pub fn is_not_comparable(&self) -> bool {
*self == NotComparable
}
/// Creates a `PartialOrdering` from an `Ordering`.
pub fn from_ordering(ord: Ordering) -> PartialOrdering {
match ord {
cmp::Less => Less,
cmp::Equal => Equal,
cmp::Greater => Greater
}
}
/// Converts this `PartialOrdering` to an `Ordering`.
///
/// Returns `None` if `self` is `NotComparable`.
pub fn to_ordering(self) -> Option<Ordering> {
match self {
Less => Some(cmp::Less),
Equal => Some(cmp::Equal),
Greater => Some(cmp::Greater),
NotComparable => None
}
}
}
/// Pointwise ordering operations.
pub trait PartialOrd {
/// Returns the infimum of `a` and `b`.
fn inf(a: &Self, b: &Self) -> Self;
/// Returns the supremum of `a` and `b`.
fn sup(a: &Self, b: &Self) -> Self;
/// Compare `a` and `b` using a partial ordering relation.
fn partial_cmp(a: &Self, b: &Self) -> PartialOrdering;
/// Return the minimum of `a` and `b` if they are comparable.
#[inline]
fn partial_min<'a>(a: &'a Self, b: &'a Self) -> Option<&'a Self> {
match PartialOrd::partial_cmp(a, b) {
Less | Equal => Some(a),
Greater => Some(b),
NotComparable => None
}
}
/// Return the maximum of `a` and `b` if they are comparable.
#[inline]
fn partial_max<'a>(a: &'a Self, b: &'a Self) -> Option<&'a Self> {
match PartialOrd::partial_cmp(a, b) {
Greater | Equal => Some(a),
Less => Some(b),
NotComparable => None
}
}
/// Clamp `value` between `min` and `max`. Returns `None` if `value` is not comparable to
/// `min` or `max`.
#[inline]
fn partial_clamp<'a>(value: &'a Self, min: &'a Self, max: &'a Self) -> Option<&'a Self> {
let v_min = PartialOrd::partial_cmp(value, min);
let v_max = PartialOrd::partial_cmp(value, max);
if v_min.is_not_comparable() || v_max.is_not_comparable() {
None
}
else {
if v_min.is_lt() {
Some(min)
}
else if v_max.is_gt() {
Some(max)
}
else {
Some(value)
}
}
}
}
/// Trait for testing approximate equality
pub trait ApproxEq<Eps> {
/// Default epsilon for approximation.

View File

@ -27,31 +27,31 @@ pub trait Vec<N>: Dim + Sub<Self, Self> + Add<Self, Self> + Neg<Self> + Zero + E
+ Div<N, Self> + Dot<N> {
}
/// Trait of vector with components implementing the `Real` trait.
pub trait RealVec<N: Real>: Vec<N> + Norm<N> {
/// Trait of vector with components implementing the `Float` trait.
pub trait FloatVec<N: Float>: Vec<N> + Norm<N> {
}
/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
/// operations on vectors.
pub trait VecExt<N>: Vec<N> + Indexable<uint, N> + Iterable<N> +
UniformSphereSample + ScalarAdd<N> + ScalarSub<N> + Bounded + Orderable
UniformSphereSample + ScalarAdd<N> + ScalarSub<N> + Bounded
{ }
/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
/// operations on vectors.
pub trait RealVecExt<N: Real>: RealVec<N> + VecExt<N> + Basis + Round { }
pub trait FloatVecExt<N: Float>: FloatVec<N> + VecExt<N> + Basis + Round { }
impl<N, V: Dim + Sub<V, V> + Add<V, V> + Neg<V> + Zero + Eq + Mul<N, V> + Div<N, V> + Dot<N>>
Vec<N> for V { }
impl<N: Real, V: Vec<N> + Norm<N>> RealVec<N> for V { }
impl<N: Float, V: Vec<N> + Norm<N>> FloatVec<N> for V { }
impl<N,
V: Vec<N> + Indexable<uint, N> + Iterable<N> +
UniformSphereSample + ScalarAdd<N> + ScalarSub<N> + Bounded + Orderable>
UniformSphereSample + ScalarAdd<N> + ScalarSub<N> + Bounded>
VecExt<N> for V { }
impl<N: Real, V: RealVec<N> + VecExt<N> + Basis + Round> RealVecExt<N> for V { }
impl<N: Float, V: FloatVec<N> + VecExt<N> + Basis + Round> FloatVecExt<N> for V { }
// FIXME: return an iterator instead
/// Traits of objects which can form a basis (typically vectors).