Add vector perametrizable by their sizes.

This commit is contained in:
Sébastien Crozet 2016-03-24 19:03:29 +01:00
parent 20070e9677
commit f8f4924e47
14 changed files with 505 additions and 321 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "nalgebra"
version = "0.5.1"
version = "0.6.0"
authors = [ "Sébastien Crozet <developer@crozet.re>" ] # FIXME: add the contributors.
description = "Linear algebra library for computer physics, computer graphics and general low-dimensional linear algebra for Rust."
@ -17,12 +17,14 @@ path = "src/lib.rs"
[features]
# Generate arbitrary instances of nalgebra types for testing with quickcheck
arbitrary = ["quickcheck"]
arbitrary = [ "quickcheck" ]
[dependencies]
rustc-serialize = "0.3.*"
rand = "0.3.*"
num = "0.1.*"
generic-array = "0.2.*"
typenum = "1.3.*"
[dependencies.quickcheck]
optional = true

View File

@ -2,11 +2,13 @@
extern crate test;
extern crate rand;
extern crate typenum;
extern crate nalgebra as na;
use rand::{IsaacRng, Rng};
use test::Bencher;
use na::{Vec2, Vec3, Vec4};
use typenum::{U2, U3, U4};
use na::{Vec2, Vec3, Vec4, VecN};
use std::ops::{Add, Sub, Mul, Div};
#[path="common/macros.rs"]
@ -15,45 +17,78 @@ mod macros;
bench_binop!(_bench_vec2_add_v, Vec2<f32>, Vec2<f32>, add);
bench_binop!(_bench_vec3_add_v, Vec3<f32>, Vec3<f32>, add);
bench_binop!(_bench_vec4_add_v, Vec4<f32>, Vec4<f32>, add);
bench_binop!(_bench_vecn2_add_v, VecN<f32, U2>, VecN<f32, U2>, add);
bench_binop!(_bench_vecn3_add_v, VecN<f32, U3>, VecN<f32, U3>, add);
bench_binop!(_bench_vecn4_add_v, VecN<f32, U4>, VecN<f32, U4>, add);
bench_binop!(_bench_vec2_sub_v, Vec2<f32>, Vec2<f32>, sub);
bench_binop!(_bench_vec3_sub_v, Vec3<f32>, Vec3<f32>, sub);
bench_binop!(_bench_vec4_sub_v, Vec4<f32>, Vec4<f32>, sub);
bench_binop!(_bench_vecn2_sub_v, VecN<f32, U2>, VecN<f32, U2>, sub);
bench_binop!(_bench_vecn3_sub_v, VecN<f32, U3>, VecN<f32, U3>, sub);
bench_binop!(_bench_vecn4_sub_v, VecN<f32, U4>, VecN<f32, U4>, sub);
bench_binop!(_bench_vec2_mul_v, Vec2<f32>, Vec2<f32>, mul);
bench_binop!(_bench_vec3_mul_v, Vec3<f32>, Vec3<f32>, mul);
bench_binop!(_bench_vec4_mul_v, Vec4<f32>, Vec4<f32>, mul);
bench_binop!(_bench_vecn2_mul_v, VecN<f32, U2>, VecN<f32, U2>, mul);
bench_binop!(_bench_vecn3_mul_v, VecN<f32, U3>, VecN<f32, U3>, mul);
bench_binop!(_bench_vecn4_mul_v, VecN<f32, U4>, VecN<f32, U4>, mul);
bench_binop!(_bench_vec2_div_v, Vec2<f32>, Vec2<f32>, div);
bench_binop!(_bench_vec3_div_v, Vec3<f32>, Vec3<f32>, div);
bench_binop!(_bench_vec4_div_v, Vec4<f32>, Vec4<f32>, div);
bench_binop!(_bench_vecn2_div_v, VecN<f32, U2>, VecN<f32, U2>, div);
bench_binop!(_bench_vecn3_div_v, VecN<f32, U3>, VecN<f32, U3>, div);
bench_binop!(_bench_vecn4_div_v, VecN<f32, U4>, VecN<f32, U4>, div);
bench_binop!(_bench_vec2_add_s, Vec2<f32>, f32, add);
bench_binop!(_bench_vec3_add_s, Vec3<f32>, f32, add);
bench_binop!(_bench_vec4_add_s, Vec4<f32>, f32, add);
bench_binop!(_bench_vecn2_add_s, VecN<f32, U2>, f32, add);
bench_binop!(_bench_vecn3_add_s, VecN<f32, U3>, f32, add);
bench_binop!(_bench_vecn4_add_s, VecN<f32, U4>, f32, add);
bench_binop!(_bench_vec2_sub_s, Vec2<f32>, f32, sub);
bench_binop!(_bench_vec3_sub_s, Vec3<f32>, f32, sub);
bench_binop!(_bench_vec4_sub_s, Vec4<f32>, f32, sub);
bench_binop!(_bench_vecn2_sub_s, VecN<f32, U2>, f32, sub);
bench_binop!(_bench_vecn3_sub_s, VecN<f32, U3>, f32, sub);
bench_binop!(_bench_vecn4_sub_s, VecN<f32, U4>, f32, sub);
bench_binop!(_bench_vec2_mul_s, Vec2<f32>, f32, mul);
bench_binop!(_bench_vec3_mul_s, Vec3<f32>, f32, mul);
bench_binop!(_bench_vec4_mul_s, Vec4<f32>, f32, mul);
bench_binop!(_bench_vecn2_mul_s, VecN<f32, U2>, f32, mul);
bench_binop!(_bench_vecn3_mul_s, VecN<f32, U3>, f32, mul);
bench_binop!(_bench_vecn4_mul_s, VecN<f32, U4>, f32, mul);
bench_binop!(_bench_vec2_div_s, Vec2<f32>, f32, div);
bench_binop!(_bench_vec3_div_s, Vec3<f32>, f32, div);
bench_binop!(_bench_vec4_div_s, Vec4<f32>, f32, div);
bench_binop!(_bench_vecn2_div_s, VecN<f32, U2>, f32, div);
bench_binop!(_bench_vecn3_div_s, VecN<f32, U3>, f32, div);
bench_binop!(_bench_vecn4_div_s, VecN<f32, U4>, f32, div);
bench_binop_na!(_bench_vec2_dot, Vec2<f32>, Vec2<f32>, dot);
bench_binop_na!(_bench_vec3_dot, Vec3<f32>, Vec3<f32>, dot);
bench_binop_na!(_bench_vec4_dot, Vec4<f32>, Vec4<f32>, dot);
bench_binop_na!(_bench_vecn2_dot, VecN<f32, U2>, VecN<f32, U2>, dot);
bench_binop_na!(_bench_vecn3_dot, VecN<f32, U3>, VecN<f32, U3>, dot);
bench_binop_na!(_bench_vecn4_dot, VecN<f32, U4>, VecN<f32, U4>, dot);
bench_binop_na!(_bench_vec3_cross, Vec3<f32>, Vec3<f32>, cross);
bench_unop!(_bench_vec2_norm, Vec2<f32>, norm);
bench_unop!(_bench_vec3_norm, Vec3<f32>, norm);
bench_unop!(_bench_vec4_norm, Vec4<f32>, norm);
bench_unop!(_bench_vecn2_norm, VecN<f32, U2>, norm);
bench_unop!(_bench_vecn3_norm, VecN<f32, U3>, norm);
bench_unop!(_bench_vecn4_norm, VecN<f32, U4>, norm);
bench_unop!(_bench_vec2_normalize, Vec2<f32>, normalize);
bench_unop!(_bench_vec3_normalize, Vec3<f32>, normalize);
bench_unop!(_bench_vec4_normalize, Vec4<f32>, normalize);
bench_unop!(_bench_vecn2_normalize, VecN<f32, U2>, normalize);
bench_unop!(_bench_vecn3_normalize, VecN<f32, U3>, normalize);
bench_unop!(_bench_vecn4_normalize, VecN<f32, U4>, normalize);

View File

@ -76,6 +76,7 @@ Feel free to add your project to this list if you happen to use **nalgebra**!
extern crate rustc_serialize;
extern crate rand;
extern crate num;
extern crate generic_array;
#[cfg(feature="arbitrary")]
extern crate quickcheck;
@ -141,7 +142,7 @@ pub use structs::{
Mat1, Mat2, Mat3, Mat4,
Mat5, Mat6,
Rot2, Rot3, Rot4,
Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6,
VecN, Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6,
Pnt0, Pnt1, Pnt2, Pnt3, Pnt4, Pnt5, Pnt6,
Persp3, PerspMat3,
Ortho3, OrthoMat3,

View File

@ -62,6 +62,7 @@ impl<N> DVec<N> {
DVec { at: (0..dim).map(|i| f(i)).collect() }
}
/// The vector length.
#[inline]
pub fn len(&self) -> usize {
self.at.len()

View File

@ -2,6 +2,8 @@
macro_rules! dvec_impl(
($dvec: ident) => (
vecn_dvec_common_impl!($dvec);
impl<N: Zero + Copy + Clone> $dvec<N> {
/// Builds a vector filled with zeros.
///
@ -11,68 +13,6 @@ macro_rules! dvec_impl(
pub fn new_zeros(dim: usize) -> $dvec<N> {
$dvec::from_elem(dim, ::zero())
}
/// Tests if all components of the vector are zeroes.
#[inline]
pub fn is_zero(&self) -> bool {
self.as_ref().iter().all(|e| e.is_zero())
}
}
impl<N> $dvec<N> {
/// Slices this vector.
#[inline]
pub fn as_ref<'a>(&'a self) -> &'a [N] {
&self.at[.. self.len()]
}
/// Mutably slices this vector.
#[inline]
pub fn as_mut<'a>(&'a mut self) -> &'a mut [N] {
let len = self.len();
&mut self.at[.. len]
}
}
impl<N> Shape<usize> for $dvec<N> {
#[inline]
fn shape(&self) -> usize {
self.len()
}
}
impl<N: Copy> Indexable<usize, N> for $dvec<N> {
#[inline]
fn swap(&mut self, i: usize, j: usize) {
assert!(i < self.len());
assert!(j < self.len());
self.as_mut().swap(i, j);
}
#[inline]
unsafe fn unsafe_at(&self, i: usize) -> N {
*self.at[..].get_unchecked(i)
}
#[inline]
unsafe fn unsafe_set(&mut self, i: usize, val: N) {
*self.at[..].get_unchecked_mut(i) = val
}
}
impl<N, T> Index<T> for $dvec<N> where [N]: Index<T> {
type Output = <[N] as Index<T>>::Output;
fn index(&self, i: T) -> &<[N] as Index<T>>::Output {
&self.as_ref()[i]
}
}
impl<N, T> IndexMut<T> for $dvec<N> where [N]: IndexMut<T> {
fn index_mut(&mut self, i: T) -> &mut <[N] as Index<T>>::Output {
&mut self.as_mut()[i]
}
}
impl<N: One + Zero + Copy + Clone> $dvec<N> {
@ -94,33 +34,6 @@ macro_rules! dvec_impl(
}
}
impl<N> Iterable<N> for $dvec<N> {
#[inline]
fn iter<'l>(&'l self) -> Iter<'l, N> {
self.as_ref().iter()
}
}
impl<N> IterableMut<N> for $dvec<N> {
#[inline]
fn iter_mut<'l>(&'l mut self) -> IterMut<'l, N> {
self.as_mut().iter_mut()
}
}
impl<N: Copy + Add<N, Output = N> + Mul<N, Output = N>> Axpy<N> for $dvec<N> {
fn axpy(&mut self, a: &N, x: &$dvec<N>) {
assert!(self.len() == x.len());
for i in 0..x.len() {
unsafe {
let self_i = self.unsafe_at(i);
self.unsafe_set(i, self_i + *a * x.unsafe_at(i))
}
}
}
}
impl<N: BaseFloat + ApproxEq<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
@ -128,7 +41,7 @@ macro_rules! dvec_impl(
pub fn canonical_basis_with_dim(dim: usize) -> Vec<$dvec<N>> {
let mut res : Vec<$dvec<N>> = Vec::new();
for i in 0..dim {
for i in 0 .. dim {
let mut basis_element : $dvec<N> = $dvec::new_zeros(dim);
basis_element[i] = ::one();
@ -147,7 +60,7 @@ macro_rules! dvec_impl(
let dim = self.len();
let mut res : Vec<$dvec<N>> = Vec::new();
for i in 0..dim {
for i in 0 .. dim {
let mut basis_element : $dvec<N> = $dvec::new_zeros(self.len());
basis_element[i] = ::one();
@ -175,217 +88,13 @@ macro_rules! dvec_impl(
res
}
}
impl<N: Copy + Mul<N, Output = N> + Zero> Mul<$dvec<N>> for $dvec<N> {
type Output = $dvec<N>;
#[inline]
fn mul(self, right: $dvec<N>) -> $dvec<N> {
assert!(self.len() == right.len());
let mut res = self;
for (left, right) in res.as_mut().iter_mut().zip(right.as_ref().iter()) {
*left = *left * *right
}
res
}
}
impl<N: Copy + Div<N, Output = N> + Zero> Div<$dvec<N>> for $dvec<N> {
type Output = $dvec<N>;
#[inline]
fn div(self, right: $dvec<N>) -> $dvec<N> {
assert!(self.len() == right.len());
let mut res = self;
for (left, right) in res.as_mut().iter_mut().zip(right.as_ref().iter()) {
*left = *left / *right
}
res
}
}
impl<N: Copy + Add<N, Output = N> + Zero> Add<$dvec<N>> for $dvec<N> {
type Output = $dvec<N>;
#[inline]
fn add(self, right: $dvec<N>) -> $dvec<N> {
assert!(self.len() == right.len());
let mut res = self;
for (left, right) in res.as_mut().iter_mut().zip(right.as_ref().iter()) {
*left = *left + *right
}
res
}
}
impl<N: Copy + Sub<N, Output = N> + Zero> Sub<$dvec<N>> for $dvec<N> {
type Output = $dvec<N>;
#[inline]
fn sub(self, right: $dvec<N>) -> $dvec<N> {
assert!(self.len() == right.len());
let mut res = self;
for (left, right) in res.as_mut().iter_mut().zip(right.as_ref().iter()) {
*left = *left - *right
}
res
}
}
impl<N: Neg<Output = N> + Zero + Copy> Neg for $dvec<N> {
type Output = $dvec<N>;
#[inline]
fn neg(self) -> $dvec<N> {
FromIterator::from_iter(self.as_ref().iter().map(|a| -*a))
}
}
impl<N: BaseNum> Dot<N> for $dvec<N> {
#[inline]
fn dot(&self, other: &$dvec<N>) -> N {
assert!(self.len() == other.len());
let mut res: N = ::zero();
for i in 0..self.len() {
res = res + unsafe { self.unsafe_at(i) * other.unsafe_at(i) };
}
res
}
}
impl<N: BaseFloat> Norm<N> for $dvec<N> {
#[inline]
fn sqnorm(&self) -> N {
Dot::dot(self, self)
}
#[inline]
fn normalize(&self) -> $dvec<N> {
let mut res : $dvec<N> = self.clone();
let _ = res.normalize_mut();
res
}
#[inline]
fn normalize_mut(&mut self) -> N {
let l = Norm::norm(self);
for n in self.as_mut().iter_mut() {
*n = *n / l;
}
l
}
}
impl<N: BaseFloat + Cast<f64>> Mean<N> for $dvec<N> {
#[inline]
fn mean(&self) -> N {
let normalizer = ::cast(1.0f64 / self.len() as f64);
self.iter().fold(::zero(), |acc, x| acc + *x * normalizer)
}
}
impl<N: ApproxEq<N>> ApproxEq<N> for $dvec<N> {
#[inline]
fn approx_epsilon(_: Option<$dvec<N>>) -> N {
ApproxEq::approx_epsilon(None::<N>)
}
#[inline]
fn approx_ulps(_: Option<$dvec<N>>) -> u32 {
ApproxEq::approx_ulps(None::<N>)
}
#[inline]
fn approx_eq_eps(&self, other: &$dvec<N>, epsilon: &N) -> bool {
let mut zip = self.as_ref().iter().zip(other.as_ref().iter());
zip.all(|(a, b)| ApproxEq::approx_eq_eps(a, b, epsilon))
}
#[inline]
fn approx_eq_ulps(&self, other: &$dvec<N>, ulps: u32) -> bool {
let mut zip = self.as_ref().iter().zip(other.as_ref().iter());
zip.all(|(a, b)| ApproxEq::approx_eq_ulps(a, b, ulps))
}
}
impl<N: Copy + Mul<N, Output = N> + Zero> Mul<N> for $dvec<N> {
type Output = $dvec<N>;
#[inline]
fn mul(self, right: N) -> $dvec<N> {
let mut res = self;
for e in res.as_mut().iter_mut() {
*e = *e * right
}
res
}
}
impl<N: Copy + Div<N, Output = N> + Zero> Div<N> for $dvec<N> {
type Output = $dvec<N>;
#[inline]
fn div(self, right: N) -> $dvec<N> {
let mut res = self;
for e in res.as_mut().iter_mut() {
*e = *e / right
}
res
}
}
impl<N: Copy + Add<N, Output = N> + Zero> Add<N> for $dvec<N> {
type Output = $dvec<N>;
#[inline]
fn add(self, right: N) -> $dvec<N> {
let mut res = self;
for e in res.as_mut().iter_mut() {
*e = *e + right
}
res
}
}
impl<N: Copy + Sub<N, Output = N> + Zero> Sub<N> for $dvec<N> {
type Output = $dvec<N>;
#[inline]
fn sub(self, right: N) -> $dvec<N> {
let mut res = self;
for e in res.as_mut().iter_mut() {
*e = *e - right
}
res
}
}
)
);
macro_rules! small_dvec_impl (
($dvec: ident, $dim: expr, $($idx: expr),*) => (
dvec_impl!($dvec);
impl<N> $dvec<N> {
/// The number of elements of this vector.
#[inline]
@ -434,8 +143,6 @@ macro_rules! small_dvec_impl (
}
}
}
dvec_impl!($dvec);
)
);
@ -490,7 +197,7 @@ macro_rules! small_dvec_from_impl (
let mut at: [N; $dim] = [ $( $zeros, )* ];
for i in 0..dim {
for i in 0 .. dim {
at[i] = f(i);
}

View File

@ -3,6 +3,7 @@
pub use self::dmat::{DMat, DMat1, DMat2, DMat3, DMat4, DMat5, DMat6};
pub use self::dvec::{DVec, DVec1, DVec2, DVec3, DVec4, DVec5, DVec6};
pub use self::vec::{Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6};
pub use self::vecn::VecN;
pub use self::pnt::{Pnt0, Pnt1, Pnt2, Pnt3, Pnt4, Pnt5, Pnt6};
pub use self::mat::{Identity, Mat1, Mat2, Mat3, Mat4, Mat5, Mat6};
pub use self::rot::{Rot2, Rot3, Rot4};
@ -13,6 +14,8 @@ pub use self::quat::{Quat, UnitQuat};
mod dmat_macros;
mod dmat;
mod vecn_macros;
mod vecn;
mod dvec_macros;
mod dvec;
mod vec_macros;

View File

@ -48,7 +48,7 @@ pub struct Pnt1<N> {
new_impl!(Pnt1, x);
orig_impl!(Pnt1, x);
ord_impl!(Pnt1, x,);
pord_impl!(Pnt1, x,);
scalar_mul_impl!(Pnt1, x);
scalar_div_impl!(Pnt1, x);
scalar_add_impl!(Pnt1, x);
@ -90,7 +90,7 @@ pub struct Pnt2<N> {
new_impl!(Pnt2, x, y);
orig_impl!(Pnt2, x, y);
ord_impl!(Pnt2, x, y);
pord_impl!(Pnt2, x, y);
scalar_mul_impl!(Pnt2, x, y);
scalar_div_impl!(Pnt2, x, y);
scalar_add_impl!(Pnt2, x, y);
@ -134,7 +134,7 @@ pub struct Pnt3<N> {
new_impl!(Pnt3, x, y, z);
orig_impl!(Pnt3, x, y, z);
ord_impl!(Pnt3, x, y, z);
pord_impl!(Pnt3, x, y, z);
scalar_mul_impl!(Pnt3, x, y, z);
scalar_div_impl!(Pnt3, x, y, z);
scalar_add_impl!(Pnt3, x, y, z);
@ -180,7 +180,7 @@ pub struct Pnt4<N> {
new_impl!(Pnt4, x, y, z, w);
orig_impl!(Pnt4, x, y, z, w);
ord_impl!(Pnt4, x, y, z, w);
pord_impl!(Pnt4, x, y, z, w);
scalar_mul_impl!(Pnt4, x, y, z, w);
scalar_div_impl!(Pnt4, x, y, z, w);
scalar_add_impl!(Pnt4, x, y, z, w);
@ -228,7 +228,7 @@ pub struct Pnt5<N> {
new_impl!(Pnt5, x, y, z, w, a);
orig_impl!(Pnt5, x, y, z, w, a);
ord_impl!(Pnt5, x, y, z, w, a);
pord_impl!(Pnt5, x, y, z, w, a);
scalar_mul_impl!(Pnt5, x, y, z, w, a);
scalar_div_impl!(Pnt5, x, y, z, w, a);
scalar_add_impl!(Pnt5, x, y, z, w, a);
@ -278,7 +278,7 @@ pub struct Pnt6<N> {
new_impl!(Pnt6, x, y, z, w, a, b);
orig_impl!(Pnt6, x, y, z, w, a, b);
ord_impl!(Pnt6, x, y, z, w, a, b);
pord_impl!(Pnt6, x, y, z, w, a, b);
scalar_mul_impl!(Pnt6, x, y, z, w, a, b);
scalar_div_impl!(Pnt6, x, y, z, w, a, b);
scalar_add_impl!(Pnt6, x, y, z, w, a, b);

View File

@ -515,7 +515,7 @@ impl<N: Arbitrary + BaseFloat> Arbitrary for UnitQuat<N> {
}
ord_impl!(Quat, w, i, j, k);
pord_impl!(Quat, w, i, j, k);
vec_axis_impl!(Quat, w, i, j, k);
vec_cast_impl!(Quat, w, i, j, k);
conversion_impl!(Quat, 4);

View File

@ -49,7 +49,7 @@ pub struct Vec1<N> {
}
new_impl!(Vec1, x);
ord_impl!(Vec1, x,);
pord_impl!(Vec1, x,);
vec_axis_impl!(Vec1, x);
vec_cast_impl!(Vec1, x);
conversion_impl!(Vec1, 1);
@ -103,7 +103,7 @@ pub struct Vec2<N> {
}
new_impl!(Vec2, x, y);
ord_impl!(Vec2, x, y);
pord_impl!(Vec2, x, y);
vec_axis_impl!(Vec2, x, y);
vec_cast_impl!(Vec2, x, y);
conversion_impl!(Vec2, 2);
@ -159,7 +159,7 @@ pub struct Vec3<N> {
}
new_impl!(Vec3, x, y, z);
ord_impl!(Vec3, x, y, z);
pord_impl!(Vec3, x, y, z);
vec_axis_impl!(Vec3, x, y, z);
vec_cast_impl!(Vec3, x, y, z);
conversion_impl!(Vec3, 3);
@ -218,7 +218,7 @@ pub struct Vec4<N> {
}
new_impl!(Vec4, x, y, z, w);
ord_impl!(Vec4, x, y, z, w);
pord_impl!(Vec4, x, y, z, w);
vec_axis_impl!(Vec4, x, y, z, w);
vec_cast_impl!(Vec4, x, y, z, w);
conversion_impl!(Vec4, 4);
@ -278,7 +278,7 @@ pub struct Vec5<N> {
}
new_impl!(Vec5, x, y, z, w, a);
ord_impl!(Vec5, x, y, z, w, a);
pord_impl!(Vec5, x, y, z, w, a);
vec_axis_impl!(Vec5, x, y, z, w, a);
vec_cast_impl!(Vec5, x, y, z, w, a);
conversion_impl!(Vec5, 5);
@ -340,7 +340,7 @@ pub struct Vec6<N> {
}
new_impl!(Vec6, x, y, z, w, a, b);
ord_impl!(Vec6, x, y, z, w, a, b);
pord_impl!(Vec6, x, y, z, w, a, b);
vec_axis_impl!(Vec6, x, y, z, w, a, b);
vec_cast_impl!(Vec6, x, y, z, w, a, b);
conversion_impl!(Vec6, 6);

View File

@ -74,7 +74,7 @@ macro_rules! at_fast_impl(
// FIXME: N should be bounded by Ord instead of BaseFloat…
// However, f32/f64 does not implement Ord…
macro_rules! ord_impl(
macro_rules! pord_impl(
($t: ident, $comp0: ident, $($compN: ident),*) => (
impl<N: BaseFloat> POrd for $t<N> {
#[inline]

112
src/structs/vecn.rs Normal file
View File

@ -0,0 +1,112 @@
use std::slice::{Iter, IterMut};
use std::iter::{FromIterator, IntoIterator};
use std::ops::{Add, Sub, Mul, Div, Neg, Index, IndexMut};
use std::mem;
use rand::{Rand, Rng};
use num::{Zero, One};
use generic_array::{GenericArray, ArrayLength};
use traits::operations::{ApproxEq, Axpy, Mean};
use traits::geometry::{Dot, Norm};
use traits::structure::{Iterable, IterableMut, Indexable, Shape, BaseFloat, BaseNum, Cast, Dim};
#[cfg(feature="arbitrary")]
use quickcheck::{Arbitrary, Gen};
/// A static array of arbitrary dimension.
#[repr(C)]
#[derive(Eq, PartialEq, Debug)] // FIXME: Hash, RustcEncodable, RustcDecodable
pub struct VecN<N, D: ArrayLength<N>> {
/// The underlying data of the vector.
pub at: GenericArray<N, D>
}
impl<N: Clone, D: ArrayLength<N>> Clone for VecN<N, D> {
fn clone(&self) -> VecN<N, D> {
VecN::new(self.at.clone())
}
}
impl<N: Copy, D: ArrayLength<N>> Copy for VecN<N, D>
where D::ArrayType: Copy { }
impl<N, D: ArrayLength<N>> VecN<N, D> {
/// Creates a new vector from a given arbirtarily-sized array.
#[inline]
pub fn new(components: GenericArray<N, D>) -> VecN<N, D> {
VecN {
at: components
}
}
/// The vector length.
#[inline]
pub fn len(&self) -> usize {
self.at.len()
}
}
impl<N, D: ArrayLength<N>> Dim for VecN<N, D> {
fn dim(_unused: Option<Self>) -> usize {
D::to_usize()
}
}
impl<N: Copy, D: ArrayLength<N>> FromIterator<N> for VecN<N, D> {
#[inline]
fn from_iter<I: IntoIterator<Item = N>>(param: I) -> VecN<N, D> {
let mut res: VecN<N, D> = unsafe { mem::uninitialized() };
let mut it = param.into_iter();
for e in res.iter_mut() {
*e = it.next().expect("Not enough data into the provided iterator to initialize this `VecN`.");
}
res
}
}
impl<N: Rand + Zero, D: ArrayLength<N>> Rand for VecN<N, D> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> VecN<N, D> {
let mut res: VecN<N, D> = unsafe { mem::uninitialized() };
for e in res.iter_mut() {
*e = Rand::rand(rng)
}
res
}
}
impl<N: Copy + One + Zero, D: ArrayLength<N>> One for VecN<N, D> {
#[inline]
fn one() -> VecN<N, D> {
let mut res: VecN<N, D> = unsafe { mem::uninitialized() };
for e in res.iter_mut() {
*e = ::one()
}
res
}
}
impl<N: Copy + Zero, D: ArrayLength<N>> Zero for VecN<N, D> {
#[inline]
fn zero() -> VecN<N, D> {
let mut res: VecN<N, D> = unsafe { mem::uninitialized() };
for e in res.iter_mut() {
*e = ::zero()
}
res
}
#[inline]
fn is_zero(&self) -> bool {
self.iter().all(|e| e.is_zero())
}
}
vecn_dvec_common_impl!(VecN, D);

312
src/structs/vecn_macros.rs Normal file
View File

@ -0,0 +1,312 @@
#![macro_use]
macro_rules! vecn_dvec_common_impl(
($vecn: ident $(, $param: ident)*) => (
impl<N: Zero + Copy + Clone $(, $param: ArrayLength<N>)*> $vecn<N $(, $param)*> {
/// Tests if all components of the vector are zeroes.
#[inline]
pub fn is_zero(&self) -> bool {
self.as_ref().iter().all(|e| e.is_zero())
}
}
impl<N $(, $param: ArrayLength<N>)*> AsRef<[N]> for $vecn<N $(, $param)*> {
#[inline]
fn as_ref(&self) -> &[N] {
&self[.. self.len()]
}
}
impl<N $(, $param: ArrayLength<N>)*> AsMut<[N]> for $vecn<N $(, $param)*> {
#[inline]
fn as_mut(&mut self) -> &mut [N] {
let len = self.len();
&mut self[.. len]
}
}
impl<N $(, $param: ArrayLength<N>)*> Shape<usize> for $vecn<N $(, $param)*> {
#[inline]
fn shape(&self) -> usize {
self.len()
}
}
impl<N: Copy $(, $param : ArrayLength<N>)*> Indexable<usize, N> for $vecn<N $(, $param)*> {
#[inline]
fn swap(&mut self, i: usize, j: usize) {
assert!(i < self.len());
assert!(j < self.len());
self.as_mut().swap(i, j);
}
#[inline]
unsafe fn unsafe_at(&self, i: usize) -> N {
*self[..].get_unchecked(i)
}
#[inline]
unsafe fn unsafe_set(&mut self, i: usize, val: N) {
*self[..].get_unchecked_mut(i) = val
}
}
impl<N, T $(, $param: ArrayLength<N>)*> Index<T> for $vecn<N $(, $param)*> where [N]: Index<T> {
type Output = <[N] as Index<T>>::Output;
fn index(&self, i: T) -> &<[N] as Index<T>>::Output {
&self.as_ref()[i]
}
}
impl<N, T $(, $param: ArrayLength<N>)*> IndexMut<T> for $vecn<N $(, $param)*> where [N]: IndexMut<T> {
fn index_mut(&mut self, i: T) -> &mut <[N] as Index<T>>::Output {
&mut self.as_mut()[i]
}
}
impl<N $(, $param : ArrayLength<N>)*> Iterable<N> for $vecn<N $(, $param)*> {
#[inline]
fn iter<'l>(&'l self) -> Iter<'l, N> {
self.as_ref().iter()
}
}
impl<N $(, $param : ArrayLength<N>)*> IterableMut<N> for $vecn<N $(, $param)*> {
#[inline]
fn iter_mut<'l>(&'l mut self) -> IterMut<'l, N> {
self.as_mut().iter_mut()
}
}
impl<N: Copy + Add<N, Output = N> + Mul<N, Output = N> $(, $param : ArrayLength<N>)*>
Axpy<N> for $vecn<N $(, $param)*> {
fn axpy(&mut self, a: &N, x: &$vecn<N $(, $param)*>) {
assert!(self.len() == x.len());
for i in 0 .. x.len() {
unsafe {
let self_i = self.unsafe_at(i);
self.unsafe_set(i, self_i + *a * x.unsafe_at(i))
}
}
}
}
impl<N: Copy + Mul<N, Output = N> + Zero $(, $param : ArrayLength<N>)*>
Mul<$vecn<N $(, $param)*>> for $vecn<N $(, $param)*> {
type Output = $vecn<N $(, $param)*>;
#[inline]
fn mul(self, right: $vecn<N $(, $param)*>) -> $vecn<N $(, $param)*> {
assert!(self.len() == right.len());
let mut res = self;
for (left, right) in res.as_mut().iter_mut().zip(right.as_ref().iter()) {
*left = *left * *right
}
res
}
}
impl<N: Copy + Div<N, Output = N> + Zero $(, $param : ArrayLength<N>)*>
Div<$vecn<N $(, $param)*>> for $vecn<N $(, $param)*> {
type Output = $vecn<N $(, $param)*>;
#[inline]
fn div(self, right: $vecn<N $(, $param)*>) -> $vecn<N $(, $param)*> {
assert!(self.len() == right.len());
let mut res = self;
for (left, right) in res.as_mut().iter_mut().zip(right.as_ref().iter()) {
*left = *left / *right
}
res
}
}
impl<N: Copy + Add<N, Output = N> + Zero $(, $param : ArrayLength<N>)*>
Add<$vecn<N $(, $param)*>> for $vecn<N $(, $param)*> {
type Output = $vecn<N $(, $param)*>;
#[inline]
fn add(self, right: $vecn<N $(, $param)*>) -> $vecn<N $(, $param)*> {
assert!(self.len() == right.len());
let mut res = self;
for (left, right) in res.as_mut().iter_mut().zip(right.as_ref().iter()) {
*left = *left + *right
}
res
}
}
impl<N: Copy + Sub<N, Output = N> + Zero $(, $param : ArrayLength<N>)*>
Sub<$vecn<N $(, $param)*>> for $vecn<N $(, $param)*> {
type Output = $vecn<N $(, $param)*>;
#[inline]
fn sub(self, right: $vecn<N $(, $param)*>) -> $vecn<N $(, $param)*> {
assert!(self.len() == right.len());
let mut res = self;
for (left, right) in res.as_mut().iter_mut().zip(right.as_ref().iter()) {
*left = *left - *right
}
res
}
}
impl<N: Neg<Output = N> + Zero + Copy $(, $param : ArrayLength<N>)*> Neg for $vecn<N $(, $param)*> {
type Output = $vecn<N $(, $param)*>;
#[inline]
fn neg(mut self) -> $vecn<N $(, $param)*> {
for e in self.as_mut().iter_mut() {
*e = -*e;
}
self
}
}
impl<N: BaseNum $(, $param : ArrayLength<N>)*> Dot<N> for $vecn<N $(, $param)*> {
#[inline]
fn dot(&self, other: &$vecn<N $(, $param)*>) -> N {
assert!(self.len() == other.len());
let mut res: N = ::zero();
for i in 0 .. self.len() {
res = res + unsafe { self.unsafe_at(i) * other.unsafe_at(i) };
}
res
}
}
impl<N: BaseFloat $(, $param : ArrayLength<N>)*> Norm<N> for $vecn<N $(, $param)*> {
#[inline]
fn sqnorm(&self) -> N {
Dot::dot(self, self)
}
#[inline]
fn normalize(&self) -> $vecn<N $(, $param)*> {
let mut res : $vecn<N $(, $param)*> = self.clone();
let _ = res.normalize_mut();
res
}
#[inline]
fn normalize_mut(&mut self) -> N {
let l = Norm::norm(self);
for n in self.as_mut().iter_mut() {
*n = *n / l;
}
l
}
}
impl<N: BaseFloat + Cast<f64> $(, $param : ArrayLength<N>)*> Mean<N> for $vecn<N $(, $param)*> {
#[inline]
fn mean(&self) -> N {
let normalizer = ::cast(1.0f64 / self.len() as f64);
self.iter().fold(::zero(), |acc, x| acc + *x * normalizer)
}
}
impl<N: ApproxEq<N> $(, $param : ArrayLength<N>)*> ApproxEq<N> for $vecn<N $(, $param)*> {
#[inline]
fn approx_epsilon(_: Option<$vecn<N $(, $param)*>>) -> N {
ApproxEq::approx_epsilon(None::<N>)
}
#[inline]
fn approx_ulps(_: Option<$vecn<N $(, $param)*>>) -> u32 {
ApproxEq::approx_ulps(None::<N>)
}
#[inline]
fn approx_eq_eps(&self, other: &$vecn<N $(, $param)*>, epsilon: &N) -> bool {
let mut zip = self.as_ref().iter().zip(other.as_ref().iter());
zip.all(|(a, b)| ApproxEq::approx_eq_eps(a, b, epsilon))
}
#[inline]
fn approx_eq_ulps(&self, other: &$vecn<N $(, $param)*>, ulps: u32) -> bool {
let mut zip = self.as_ref().iter().zip(other.as_ref().iter());
zip.all(|(a, b)| ApproxEq::approx_eq_ulps(a, b, ulps))
}
}
impl<N: Copy + Mul<N, Output = N> + Zero $(, $param : ArrayLength<N>)*>
Mul<N> for $vecn<N $(, $param)*> {
type Output = $vecn<N $(, $param)*>;
#[inline]
fn mul(self, right: N) -> $vecn<N $(, $param)*> {
let mut res = self;
for e in res.as_mut().iter_mut() {
*e = *e * right
}
res
}
}
impl<N: Copy + Div<N, Output = N> + Zero $(, $param : ArrayLength<N>)*> Div<N> for $vecn<N $(, $param)*> {
type Output = $vecn<N $(, $param)*>;
#[inline]
fn div(self, right: N) -> $vecn<N $(, $param)*> {
let mut res = self;
for e in res.as_mut().iter_mut() {
*e = *e / right
}
res
}
}
impl<N: Copy + Add<N, Output = N> + Zero $(, $param : ArrayLength<N>)*> Add<N> for $vecn<N $(, $param)*> {
type Output = $vecn<N $(, $param)*>;
#[inline]
fn add(self, right: N) -> $vecn<N $(, $param)*> {
let mut res = self;
for e in res.as_mut().iter_mut() {
*e = *e + right
}
res
}
}
impl<N: Copy + Sub<N, Output = N> + Zero $(, $param : ArrayLength<N>)*> Sub<N> for $vecn<N $(, $param)*> {
type Output = $vecn<N $(, $param)*>;
#[inline]
fn sub(self, right: N) -> $vecn<N $(, $param)*> {
let mut res = self;
for e in res.as_mut().iter_mut() {
*e = *e - right
}
res
}
}
)
);

View File

@ -158,7 +158,7 @@ pub trait RowSlice<R> {
/// Trait of objects having a spacial dimension known at compile time.
pub trait Dim: Sized {
/// The dimension of the object.
fn dim(unused_mut: Option<Self>) -> usize;
fn dim(_unused: Option<Self>) -> usize;
}
/// Trait to get the diagonal of square matrices.

View File

@ -1,8 +1,10 @@
extern crate nalgebra as na;
extern crate rand;
extern crate typenum;
extern crate nalgebra as na;
use rand::random;
use na::{Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6, Mat3, Rot2, Rot3, Iterable, IterableMut};
use typenum::U10;
use na::{VecN, Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6, Mat3, Rot2, Rot3, Iterable, IterableMut};
macro_rules! test_iterator_impl(
($t: ty, $n: ty) => (
@ -318,6 +320,15 @@ fn test_outer_vec3() {
12.0, 15.0, 18.0));
}
#[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() {