forked from M-Labs/nalgebra
Add the types: DVec1, .., DVec6.
They are stack-allocated, dynamically sized vectors with a maximum size. This is useful for slicing small matrices, without allocation.
This commit is contained in:
parent
7d6884c3df
commit
40c9915870
@ -3,6 +3,6 @@ name = "nalgebra"
|
||||
version = "0.1.0"
|
||||
authors = [ "Sébastien Crozet <developer@crozet.re>" ] # FIXME: add the contributors.
|
||||
|
||||
[[lib]]
|
||||
[lib]
|
||||
name = "nalgebra"
|
||||
path = "src/lib.rs"
|
||||
|
@ -34,11 +34,12 @@ pub fn householder_matrix<N: Float,
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `m` - matrix to decompose
|
||||
pub fn decomp_qr<N: Float,
|
||||
pub fn qr<N: Float,
|
||||
V: Indexable<uint, N> + Norm<N>,
|
||||
M: Clone + Eye + ColSlice<V> + Transpose
|
||||
+ Indexable<(uint, uint), N> + Mul<M, M>>
|
||||
(m: &M) -> (M, M) {
|
||||
(m: &M)
|
||||
-> (M, M) {
|
||||
let (rows, cols) = m.shape();
|
||||
assert!(rows >= cols);
|
||||
let mut q : M = Eye::new_identity(rows);
|
||||
@ -67,4 +68,3 @@ pub fn decomp_qr<N: Float,
|
||||
|
||||
(q, r)
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
pub use self::decompositions::{decomp_qr, householder_matrix};
|
||||
pub use self::decompositions::{qr, eigen_qr, householder_matrix};
|
||||
|
||||
mod decompositions;
|
||||
|
@ -48,7 +48,8 @@ pub use traits::{
|
||||
|
||||
pub use structs::{
|
||||
Identity,
|
||||
DMat, DVec,
|
||||
DMat,
|
||||
DVec, DVec1, DVec2, DVec3, DVec4, DVec5, DVec6,
|
||||
Iso2, Iso3, Iso4,
|
||||
Mat1, Mat2, Mat3, Mat4,
|
||||
Mat5, Mat6,
|
||||
@ -57,7 +58,8 @@ pub use structs::{
|
||||
};
|
||||
|
||||
pub use linalg::{
|
||||
decomp_qr,
|
||||
qr,
|
||||
eigen_qr,
|
||||
householder_matrix
|
||||
};
|
||||
|
||||
|
@ -245,7 +245,7 @@ impl<N: Clone> Indexable<(uint, uint), N> for DMat<N> {
|
||||
#[inline]
|
||||
unsafe fn unsafe_at(&self, rowcol: (uint, uint)) -> N {
|
||||
let (row, col) = rowcol;
|
||||
(*self.mij.as_slice().unsafe_ref(self.offset(row, col))).clone()
|
||||
(*self.mij.as_slice().unsafe_get(self.offset(row, col))).clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -524,7 +524,7 @@ impl<N: Clone> ColSlice<DVec<N>> for DMat<N> {
|
||||
// we can init from slice thanks to the matrix being column major
|
||||
let start= self.offset(row_start, col_id);
|
||||
let stop = self.offset(row_end, col_id);
|
||||
let slice = DVec::from_vec(
|
||||
let slice = DVec::from_slice(
|
||||
row_end - row_start, self.mij.slice(start, stop));
|
||||
slice
|
||||
}
|
||||
|
@ -11,97 +11,13 @@ use std::iter::FromIterator;
|
||||
use traits::geometry::{Dot, Norm};
|
||||
use traits::structure::{Iterable, IterableMut, Indexable};
|
||||
|
||||
/// Vector with a dimension unknown at compile-time.
|
||||
/// Heap allocated, dynamically sized vector.
|
||||
#[deriving(Eq, PartialEq, Show, Clone)]
|
||||
pub struct DVec<N> {
|
||||
/// Components of the vector. Contains as much elements as the vector dimension.
|
||||
pub at: Vec<N>
|
||||
}
|
||||
|
||||
double_dispatch_binop_decl_trait!(DVec, DVecMulRhs)
|
||||
double_dispatch_binop_decl_trait!(DVec, DVecDivRhs)
|
||||
double_dispatch_binop_decl_trait!(DVec, DVecAddRhs)
|
||||
double_dispatch_binop_decl_trait!(DVec, DVecSubRhs)
|
||||
|
||||
mul_redispatch_impl!(DVec, DVecMulRhs)
|
||||
div_redispatch_impl!(DVec, DVecDivRhs)
|
||||
add_redispatch_impl!(DVec, DVecAddRhs)
|
||||
sub_redispatch_impl!(DVec, DVecSubRhs)
|
||||
|
||||
impl<N: Zero + Clone> DVec<N> {
|
||||
/// Builds a vector filled with zeros.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `dim` - The dimension of the vector.
|
||||
#[inline]
|
||||
pub fn new_zeros(dim: uint) -> DVec<N> {
|
||||
DVec::from_elem(dim, Zero::zero())
|
||||
}
|
||||
|
||||
/// Tests if all components of the vector are zeroes.
|
||||
#[inline]
|
||||
pub fn is_zero(&self) -> bool {
|
||||
self.at.iter().all(|e| e.is_zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone> Indexable<uint, N> for DVec<N> {
|
||||
|
||||
fn at(&self, i: uint) -> N {
|
||||
assert!(i < self.at.len());
|
||||
unsafe {
|
||||
self.unsafe_at(i)
|
||||
}
|
||||
}
|
||||
|
||||
fn set(&mut self, i: uint, val: N) {
|
||||
assert!(i < self.at.len());
|
||||
unsafe {
|
||||
self.unsafe_set(i, val);
|
||||
}
|
||||
}
|
||||
|
||||
fn swap(&mut self, i: uint, j: uint) {
|
||||
assert!(i < self.at.len());
|
||||
assert!(j < self.at.len());
|
||||
self.at.as_mut_slice().swap(i, j);
|
||||
}
|
||||
|
||||
fn shape(&self) -> uint {
|
||||
self.at.len()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unsafe_at(&self, i: uint) -> N {
|
||||
(*self.at.as_slice().unsafe_ref(i)).clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unsafe_set(&mut self, i: uint, val: N) {
|
||||
*self.at.as_mut_slice().unsafe_mut_ref(i) = val
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<N: One + Clone> DVec<N> {
|
||||
/// Builds a vector filled with ones.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `dim` - The dimension of the vector.
|
||||
#[inline]
|
||||
pub fn new_ones(dim: uint) -> DVec<N> {
|
||||
DVec::from_elem(dim, One::one())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Rand> DVec<N> {
|
||||
/// Builds a vector filled with random values.
|
||||
#[inline]
|
||||
pub fn new_random(dim: uint) -> DVec<N> {
|
||||
DVec::from_fn(dim, |_| rand::random())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> DVec<N> {
|
||||
/// Creates an uninitialized vec.
|
||||
#[inline]
|
||||
@ -113,24 +29,6 @@ impl<N> DVec<N> {
|
||||
at: vec
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a reference to of this vector data.
|
||||
#[inline]
|
||||
pub fn as_vec<'r>(&'r self) -> &'r [N] {
|
||||
self.at.as_slice()
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to of this vector data.
|
||||
#[inline]
|
||||
pub fn as_mut_vec<'r>(&'r mut self) -> &'r mut [N] {
|
||||
self.at.as_mut_slice()
|
||||
}
|
||||
|
||||
/// Extracts this vector data.
|
||||
#[inline]
|
||||
pub fn to_vec(self) -> Vec<N> {
|
||||
self.at
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone> DVec<N> {
|
||||
@ -144,7 +42,7 @@ impl<N: Clone> DVec<N> {
|
||||
///
|
||||
/// The vector must have at least `dim` elements.
|
||||
#[inline]
|
||||
pub fn from_vec(dim: uint, vec: &[N]) -> DVec<N> {
|
||||
pub fn from_slice(dim: uint, vec: &[N]) -> DVec<N> {
|
||||
assert!(dim <= vec.len());
|
||||
|
||||
DVec {
|
||||
@ -161,27 +59,6 @@ impl<N> DVec<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Collection for DVec<N> {
|
||||
#[inline]
|
||||
fn len(&self) -> uint {
|
||||
self.at.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Iterable<N> for DVec<N> {
|
||||
#[inline]
|
||||
fn iter<'l>(&'l self) -> Items<'l, N> {
|
||||
self.at.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> IterableMut<N> for DVec<N> {
|
||||
#[inline]
|
||||
fn mut_iter<'l>(&'l mut self) -> MutItems<'l, N> {
|
||||
self.at.mut_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> FromIterator<N> for DVec<N> {
|
||||
#[inline]
|
||||
fn from_iter<I: Iterator<N>>(mut param: I) -> DVec<N> {
|
||||
@ -195,258 +72,71 @@ impl<N> FromIterator<N> for DVec<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + 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.
|
||||
pub fn canonical_basis_with_dim(dim: uint) -> Vec<DVec<N>> {
|
||||
let mut res : Vec<DVec<N>> = Vec::new();
|
||||
|
||||
for i in range(0u, dim) {
|
||||
let mut basis_element : DVec<N> = DVec::new_zeros(dim);
|
||||
|
||||
*basis_element.at.get_mut(i) = One::one();
|
||||
|
||||
res.push(basis_element);
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
/// Computes a basis of the space orthogonal to the vector. If the input vector is of dimension
|
||||
/// `n`, this will return `n - 1` vectors.
|
||||
pub fn orthogonal_subspace_basis(&self) -> Vec<DVec<N>> {
|
||||
// compute the basis of the orthogonal subspace using Gram-Schmidt
|
||||
// orthogonalization algorithm
|
||||
let dim = self.at.len();
|
||||
let mut res : Vec<DVec<N>> = Vec::new();
|
||||
|
||||
for i in range(0u, dim) {
|
||||
let mut basis_element : DVec<N> = DVec::new_zeros(self.at.len());
|
||||
|
||||
*basis_element.at.get_mut(i) = One::one();
|
||||
|
||||
if res.len() == dim - 1 {
|
||||
break;
|
||||
}
|
||||
|
||||
let mut elt = basis_element.clone();
|
||||
|
||||
elt = elt - self * Dot::dot(&basis_element, self);
|
||||
|
||||
for v in res.iter() {
|
||||
elt = elt - v * Dot::dot(&elt, v)
|
||||
};
|
||||
|
||||
if !ApproxEq::approx_eq(&Norm::sqnorm(&elt), &Zero::zero()) {
|
||||
res.push(Norm::normalize_cpy(&elt));
|
||||
}
|
||||
}
|
||||
|
||||
assert!(res.len() == dim - 1);
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Add<N, N>> DVecAddRhs<N, DVec<N>> for DVec<N> {
|
||||
impl<N> Collection for DVec<N> {
|
||||
#[inline]
|
||||
fn binop(left: &DVec<N>, right: &DVec<N>) -> DVec<N> {
|
||||
assert!(left.at.len() == right.at.len());
|
||||
DVec {
|
||||
at: left.at.iter().zip(right.at.iter()).map(|(a, b)| *a + *b).collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Sub<N, N>> DVecSubRhs<N, DVec<N>> for DVec<N> {
|
||||
#[inline]
|
||||
fn binop(left: &DVec<N>, right: &DVec<N>) -> DVec<N> {
|
||||
assert!(left.at.len() == right.at.len());
|
||||
DVec {
|
||||
at: left.at.iter().zip(right.at.iter()).map(|(a, b)| *a - *b).collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Neg<N>> Neg<DVec<N>> for DVec<N> {
|
||||
#[inline]
|
||||
fn neg(&self) -> DVec<N> {
|
||||
DVec { at: self.at.iter().map(|a| -*a).collect() }
|
||||
fn len(&self) -> uint {
|
||||
self.at.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Num + Clone> Dot<N> for DVec<N> {
|
||||
#[inline]
|
||||
fn dot(a: &DVec<N>, b: &DVec<N>) -> N {
|
||||
assert!(a.at.len() == b.at.len());
|
||||
dvec_impl!(DVec, DVecMulRhs, DVecDivRhs, DVecAddRhs, DVecSubRhs)
|
||||
|
||||
let mut res: N = Zero::zero();
|
||||
|
||||
for i in range(0u, a.at.len()) {
|
||||
res = res + unsafe { a.unsafe_at(i) * b.unsafe_at(i) };
|
||||
/// Stack-allocated, dynamically sized vector with a maximum size of 1.
|
||||
pub struct DVec1<N> {
|
||||
at: [N, ..1],
|
||||
dim: uint
|
||||
}
|
||||
|
||||
res
|
||||
small_dvec_impl!(DVec1, 1, DVec1MulRhs, DVec1DivRhs, DVec1AddRhs, DVec1SubRhs, 0)
|
||||
small_dvec_from_impl!(DVec1, 1, Zero::zero())
|
||||
|
||||
|
||||
/// Stack-allocated, dynamically sized vector with a maximum size of 2.
|
||||
pub struct DVec2<N> {
|
||||
at: [N, ..2],
|
||||
dim: uint
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sub_dot(a: &DVec<N>, b: &DVec<N>, c: &DVec<N>) -> N {
|
||||
let mut res: N = Zero::zero();
|
||||
small_dvec_impl!(DVec2, 2, DVec2MulRhs, DVec2DivRhs, DVec2AddRhs, DVec2SubRhs, 0, 1)
|
||||
small_dvec_from_impl!(DVec2, 2, Zero::zero(), Zero::zero())
|
||||
|
||||
for i in range(0u, a.at.len()) {
|
||||
res = res + unsafe { (a.unsafe_at(i) - b.unsafe_at(i)) * c.unsafe_at(i) };
|
||||
|
||||
/// Stack-allocated, dynamically sized vector with a maximum size of 3.
|
||||
pub struct DVec3<N> {
|
||||
at: [N, ..3],
|
||||
dim: uint
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
small_dvec_impl!(DVec3, 3, DVec3MulRhs, DVec3DivRhs, DVec3AddRhs, DVec3SubRhs, 0, 1, 2)
|
||||
small_dvec_from_impl!(DVec3, 3, Zero::zero(), Zero::zero(), Zero::zero())
|
||||
|
||||
|
||||
/// Stack-allocated, dynamically sized vector with a maximum size of 4.
|
||||
pub struct DVec4<N> {
|
||||
at: [N, ..4],
|
||||
dim: uint
|
||||
}
|
||||
|
||||
impl<N: Float + Clone> Norm<N> for DVec<N> {
|
||||
#[inline]
|
||||
fn sqnorm(v: &DVec<N>) -> N {
|
||||
Dot::dot(v, v)
|
||||
small_dvec_impl!(DVec4, 4, DVec4MulRhs, DVec4DivRhs, DVec4AddRhs, DVec4SubRhs, 0, 1, 2, 3)
|
||||
small_dvec_from_impl!(DVec4, 4, Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero())
|
||||
|
||||
|
||||
/// Stack-allocated, dynamically sized vector with a maximum size of 5.
|
||||
pub struct DVec5<N> {
|
||||
at: [N, ..5],
|
||||
dim: uint
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn norm(v: &DVec<N>) -> N {
|
||||
Norm::sqnorm(v).sqrt()
|
||||
small_dvec_impl!(DVec5, 5, DVec5MulRhs, DVec5DivRhs, DVec5AddRhs, DVec5SubRhs, 0, 1, 2, 3, 4)
|
||||
small_dvec_from_impl!(DVec5, 5, Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero())
|
||||
|
||||
|
||||
/// Stack-allocated, dynamically sized vector with a maximum size of 6.
|
||||
pub struct DVec6<N> {
|
||||
at: [N, ..6],
|
||||
dim: uint
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn normalize_cpy(v: &DVec<N>) -> DVec<N> {
|
||||
let mut res : DVec<N> = v.clone();
|
||||
|
||||
let _ = res.normalize();
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn normalize(&mut self) -> N {
|
||||
let l = Norm::norm(self);
|
||||
|
||||
for i in range(0u, self.at.len()) {
|
||||
*self.at.get_mut(i) = self.at[i] / l;
|
||||
}
|
||||
|
||||
l
|
||||
}
|
||||
}
|
||||
|
||||
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_eq(a: &DVec<N>, b: &DVec<N>) -> bool {
|
||||
let mut zip = a.at.iter().zip(b.at.iter());
|
||||
|
||||
zip.all(|(a, b)| ApproxEq::approx_eq(a, b))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_eps(a: &DVec<N>, b: &DVec<N>, epsilon: &N) -> bool {
|
||||
let mut zip = a.at.iter().zip(b.at.iter());
|
||||
|
||||
zip.all(|(a, b)| ApproxEq::approx_eq_eps(a, b, epsilon))
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! scalar_mul_impl (
|
||||
($n: ident) => (
|
||||
impl DVecMulRhs<$n, DVec<$n>> for $n {
|
||||
#[inline]
|
||||
fn binop(left: &DVec<$n>, right: &$n) -> DVec<$n> {
|
||||
DVec { at: left.at.iter().map(|a| a * *right).collect() }
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! scalar_div_impl (
|
||||
($n: ident) => (
|
||||
impl DVecDivRhs<$n, DVec<$n>> for $n {
|
||||
#[inline]
|
||||
fn binop(left: &DVec<$n>, right: &$n) -> DVec<$n> {
|
||||
DVec { at: left.at.iter().map(|a| a / *right).collect() }
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! scalar_add_impl (
|
||||
($n: ident) => (
|
||||
impl DVecAddRhs<$n, DVec<$n>> for $n {
|
||||
#[inline]
|
||||
fn binop(left: &DVec<$n>, right: &$n) -> DVec<$n> {
|
||||
DVec { at: left.at.iter().map(|a| a + *right).collect() }
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! scalar_sub_impl (
|
||||
($n: ident) => (
|
||||
impl DVecSubRhs<$n, DVec<$n>> for $n {
|
||||
#[inline]
|
||||
fn binop(left: &DVec<$n>, right: &$n) -> DVec<$n> {
|
||||
DVec { at: left.at.iter().map(|a| a - *right).collect() }
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
scalar_mul_impl!(f64)
|
||||
scalar_mul_impl!(f32)
|
||||
scalar_mul_impl!(u64)
|
||||
scalar_mul_impl!(u32)
|
||||
scalar_mul_impl!(u16)
|
||||
scalar_mul_impl!(u8)
|
||||
scalar_mul_impl!(i64)
|
||||
scalar_mul_impl!(i32)
|
||||
scalar_mul_impl!(i16)
|
||||
scalar_mul_impl!(i8)
|
||||
scalar_mul_impl!(uint)
|
||||
scalar_mul_impl!(int)
|
||||
|
||||
scalar_div_impl!(f64)
|
||||
scalar_div_impl!(f32)
|
||||
scalar_div_impl!(u64)
|
||||
scalar_div_impl!(u32)
|
||||
scalar_div_impl!(u16)
|
||||
scalar_div_impl!(u8)
|
||||
scalar_div_impl!(i64)
|
||||
scalar_div_impl!(i32)
|
||||
scalar_div_impl!(i16)
|
||||
scalar_div_impl!(i8)
|
||||
scalar_div_impl!(uint)
|
||||
scalar_div_impl!(int)
|
||||
|
||||
scalar_add_impl!(f64)
|
||||
scalar_add_impl!(f32)
|
||||
scalar_add_impl!(u64)
|
||||
scalar_add_impl!(u32)
|
||||
scalar_add_impl!(u16)
|
||||
scalar_add_impl!(u8)
|
||||
scalar_add_impl!(i64)
|
||||
scalar_add_impl!(i32)
|
||||
scalar_add_impl!(i16)
|
||||
scalar_add_impl!(i8)
|
||||
scalar_add_impl!(uint)
|
||||
scalar_add_impl!(int)
|
||||
|
||||
scalar_sub_impl!(f64)
|
||||
scalar_sub_impl!(f32)
|
||||
scalar_sub_impl!(u64)
|
||||
scalar_sub_impl!(u32)
|
||||
scalar_sub_impl!(u16)
|
||||
scalar_sub_impl!(u8)
|
||||
scalar_sub_impl!(i64)
|
||||
scalar_sub_impl!(i32)
|
||||
scalar_sub_impl!(i16)
|
||||
scalar_sub_impl!(i8)
|
||||
scalar_sub_impl!(uint)
|
||||
scalar_sub_impl!(int)
|
||||
small_dvec_impl!(DVec6, 6, DVec6MulRhs, DVec6DivRhs, DVec6AddRhs, DVec6SubRhs, 0, 1, 2, 3, 4, 5)
|
||||
small_dvec_from_impl!(DVec6, 6, Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero())
|
||||
|
502
src/structs/dvec_macros.rs
Normal file
502
src/structs/dvec_macros.rs
Normal file
@ -0,0 +1,502 @@
|
||||
#![macro_escape]
|
||||
|
||||
macro_rules! dvec_impl(
|
||||
($dvec: ident, $mul: ident, $div: ident, $add: ident, $sub: ident) => (
|
||||
double_dispatch_binop_decl_trait!($dvec, $mul)
|
||||
double_dispatch_binop_decl_trait!($dvec, $div)
|
||||
double_dispatch_binop_decl_trait!($dvec, $add)
|
||||
double_dispatch_binop_decl_trait!($dvec, $sub)
|
||||
|
||||
mul_redispatch_impl!($dvec, $mul)
|
||||
div_redispatch_impl!($dvec, $div)
|
||||
add_redispatch_impl!($dvec, $add)
|
||||
sub_redispatch_impl!($dvec, $sub)
|
||||
|
||||
impl<N: Zero + Clone> $dvec<N> {
|
||||
/// Builds a vector filled with zeros.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `dim` - The dimension of the vector.
|
||||
#[inline]
|
||||
pub fn new_zeros(dim: uint) -> $dvec<N> {
|
||||
$dvec::from_elem(dim, Zero::zero())
|
||||
}
|
||||
|
||||
/// Tests if all components of the vector are zeroes.
|
||||
#[inline]
|
||||
pub fn is_zero(&self) -> bool {
|
||||
self.as_slice().iter().all(|e| e.is_zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> $dvec<N> {
|
||||
/// Slices this vector.
|
||||
#[inline]
|
||||
pub fn as_slice<'a>(&'a self) -> &'a [N] {
|
||||
self.at.slice_to(self.len())
|
||||
}
|
||||
|
||||
/// Mutably slices this vector.
|
||||
#[inline]
|
||||
pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [N] {
|
||||
let len = self.len();
|
||||
self.at.mut_slice_to(len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone> Indexable<uint, N> for $dvec<N> {
|
||||
#[inline]
|
||||
fn at(&self, i: uint) -> N {
|
||||
assert!(i < self.len());
|
||||
unsafe {
|
||||
self.unsafe_at(i)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set(&mut self, i: uint, val: N) {
|
||||
assert!(i < self.len());
|
||||
unsafe {
|
||||
self.unsafe_set(i, val);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn swap(&mut self, i: uint, j: uint) {
|
||||
assert!(i < self.len());
|
||||
assert!(j < self.len());
|
||||
self.as_mut_slice().swap(i, j);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn shape(&self) -> uint {
|
||||
self.len()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unsafe_at(&self, i: uint) -> N {
|
||||
(*self.at.as_slice().unsafe_get(i)).clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unsafe_set(&mut self, i: uint, val: N) {
|
||||
*self.at.as_mut_slice().unsafe_mut_ref(i) = val
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<N: One + Zero + Clone> $dvec<N> {
|
||||
/// Builds a vector filled with ones.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `dim` - The dimension of the vector.
|
||||
#[inline]
|
||||
pub fn new_ones(dim: uint) -> $dvec<N> {
|
||||
$dvec::from_elem(dim, One::one())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Rand + Zero> $dvec<N> {
|
||||
/// Builds a vector filled with random values.
|
||||
#[inline]
|
||||
pub fn new_random(dim: uint) -> $dvec<N> {
|
||||
$dvec::from_fn(dim, |_| rand::random())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Iterable<N> for $dvec<N> {
|
||||
#[inline]
|
||||
fn iter<'l>(&'l self) -> Items<'l, N> {
|
||||
self.as_slice().iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> IterableMut<N> for $dvec<N> {
|
||||
#[inline]
|
||||
fn mut_iter<'l>(&'l mut self) -> MutItems<'l, N> {
|
||||
self.as_mut_slice().mut_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Float + ApproxEq<N> + $mul<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.
|
||||
pub fn canonical_basis_with_dim(dim: uint) -> Vec<$dvec<N>> {
|
||||
let mut res : Vec<$dvec<N>> = Vec::new();
|
||||
|
||||
for i in range(0u, dim) {
|
||||
let mut basis_element : $dvec<N> = $dvec::new_zeros(dim);
|
||||
|
||||
basis_element.set(i, One::one());
|
||||
|
||||
res.push(basis_element);
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
/// Computes a basis of the space orthogonal to the vector. If the input vector is of dimension
|
||||
/// `n`, this will return `n - 1` vectors.
|
||||
pub fn orthogonal_subspace_basis(&self) -> Vec<$dvec<N>> {
|
||||
// compute the basis of the orthogonal subspace using Gram-Schmidt
|
||||
// orthogonalization algorithm
|
||||
let dim = self.len();
|
||||
let mut res : Vec<$dvec<N>> = Vec::new();
|
||||
|
||||
for i in range(0u, dim) {
|
||||
let mut basis_element : $dvec<N> = $dvec::new_zeros(self.len());
|
||||
|
||||
basis_element.set(i, One::one());
|
||||
|
||||
if res.len() == dim - 1 {
|
||||
break;
|
||||
}
|
||||
|
||||
let mut elt = basis_element.clone();
|
||||
|
||||
elt = elt - self * Dot::dot(&basis_element, self);
|
||||
|
||||
for v in res.iter() {
|
||||
elt = elt - v * Dot::dot(&elt, v)
|
||||
};
|
||||
|
||||
if !ApproxEq::approx_eq(&Norm::sqnorm(&elt), &Zero::zero()) {
|
||||
res.push(Norm::normalize_cpy(&elt));
|
||||
}
|
||||
}
|
||||
|
||||
assert!(res.len() == dim - 1);
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Add<N, N> + Zero> $add<N, $dvec<N>> for $dvec<N> {
|
||||
#[inline]
|
||||
fn binop(left: &$dvec<N>, right: &$dvec<N>) -> $dvec<N> {
|
||||
assert!(left.len() == right.len());
|
||||
FromIterator::from_iter(left.as_slice().iter().zip(right.as_slice().iter()).map(|(a, b)| *a + *b))
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Sub<N, N> + Zero> $sub<N, $dvec<N>> for $dvec<N> {
|
||||
#[inline]
|
||||
fn binop(left: &$dvec<N>, right: &$dvec<N>) -> $dvec<N> {
|
||||
assert!(left.len() == right.len());
|
||||
FromIterator::from_iter(left.as_slice().iter().zip(right.as_slice().iter()).map(|(a, b)| *a - *b))
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Neg<N> + Zero> Neg<$dvec<N>> for $dvec<N> {
|
||||
#[inline]
|
||||
fn neg(&self) -> $dvec<N> {
|
||||
FromIterator::from_iter(self.as_slice().iter().map(|a| -*a))
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Num + Clone> Dot<N> for $dvec<N> {
|
||||
#[inline]
|
||||
fn dot(a: &$dvec<N>, b: &$dvec<N>) -> N {
|
||||
assert!(a.len() == b.len());
|
||||
|
||||
let mut res: N = Zero::zero();
|
||||
|
||||
for i in range(0u, a.len()) {
|
||||
res = res + unsafe { a.unsafe_at(i) * b.unsafe_at(i) };
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sub_dot(a: &$dvec<N>, b: &$dvec<N>, c: &$dvec<N>) -> N {
|
||||
let mut res: N = Zero::zero();
|
||||
|
||||
for i in range(0u, a.len()) {
|
||||
res = res + unsafe { (a.unsafe_at(i) - b.unsafe_at(i)) * c.unsafe_at(i) };
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Float + Clone> Norm<N> for $dvec<N> {
|
||||
#[inline]
|
||||
fn sqnorm(v: &$dvec<N>) -> N {
|
||||
Dot::dot(v, v)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn norm(v: &$dvec<N>) -> N {
|
||||
Norm::sqnorm(v).sqrt()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn normalize_cpy(v: &$dvec<N>) -> $dvec<N> {
|
||||
let mut res : $dvec<N> = v.clone();
|
||||
|
||||
let _ = res.normalize();
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn normalize(&mut self) -> N {
|
||||
let l = Norm::norm(self);
|
||||
|
||||
for n in self.as_mut_slice().mut_iter() {
|
||||
*n = *n / l;
|
||||
}
|
||||
|
||||
l
|
||||
}
|
||||
}
|
||||
|
||||
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_eq(a: &$dvec<N>, b: &$dvec<N>) -> bool {
|
||||
let mut zip = a.as_slice().iter().zip(b.as_slice().iter());
|
||||
|
||||
zip.all(|(a, b)| ApproxEq::approx_eq(a, b))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_eps(a: &$dvec<N>, b: &$dvec<N>, epsilon: &N) -> bool {
|
||||
let mut zip = a.as_slice().iter().zip(b.as_slice().iter());
|
||||
|
||||
zip.all(|(a, b)| ApproxEq::approx_eq_eps(a, b, epsilon))
|
||||
}
|
||||
}
|
||||
|
||||
dvec_scalar_mul_impl!($dvec, f64, $mul)
|
||||
dvec_scalar_mul_impl!($dvec, f32, $mul)
|
||||
dvec_scalar_mul_impl!($dvec, u64, $mul)
|
||||
dvec_scalar_mul_impl!($dvec, u32, $mul)
|
||||
dvec_scalar_mul_impl!($dvec, u16, $mul)
|
||||
dvec_scalar_mul_impl!($dvec, u8, $mul)
|
||||
dvec_scalar_mul_impl!($dvec, i64, $mul)
|
||||
dvec_scalar_mul_impl!($dvec, i32, $mul)
|
||||
dvec_scalar_mul_impl!($dvec, i16, $mul)
|
||||
dvec_scalar_mul_impl!($dvec, i8, $mul)
|
||||
dvec_scalar_mul_impl!($dvec, uint, $mul)
|
||||
dvec_scalar_mul_impl!($dvec, int, $mul)
|
||||
|
||||
dvec_scalar_div_impl!($dvec, f64, $div)
|
||||
dvec_scalar_div_impl!($dvec, f32, $div)
|
||||
dvec_scalar_div_impl!($dvec, u64, $div)
|
||||
dvec_scalar_div_impl!($dvec, u32, $div)
|
||||
dvec_scalar_div_impl!($dvec, u16, $div)
|
||||
dvec_scalar_div_impl!($dvec, u8, $div)
|
||||
dvec_scalar_div_impl!($dvec, i64, $div)
|
||||
dvec_scalar_div_impl!($dvec, i32, $div)
|
||||
dvec_scalar_div_impl!($dvec, i16, $div)
|
||||
dvec_scalar_div_impl!($dvec, i8, $div)
|
||||
dvec_scalar_div_impl!($dvec, uint, $div)
|
||||
dvec_scalar_div_impl!($dvec, int, $div)
|
||||
|
||||
dvec_scalar_add_impl!($dvec, f64, $add)
|
||||
dvec_scalar_add_impl!($dvec, f32, $add)
|
||||
dvec_scalar_add_impl!($dvec, u64, $add)
|
||||
dvec_scalar_add_impl!($dvec, u32, $add)
|
||||
dvec_scalar_add_impl!($dvec, u16, $add)
|
||||
dvec_scalar_add_impl!($dvec, u8, $add)
|
||||
dvec_scalar_add_impl!($dvec, i64, $add)
|
||||
dvec_scalar_add_impl!($dvec, i32, $add)
|
||||
dvec_scalar_add_impl!($dvec, i16, $add)
|
||||
dvec_scalar_add_impl!($dvec, i8, $add)
|
||||
dvec_scalar_add_impl!($dvec, uint, $add)
|
||||
dvec_scalar_add_impl!($dvec, int, $add)
|
||||
|
||||
dvec_scalar_sub_impl!($dvec, f64, $sub)
|
||||
dvec_scalar_sub_impl!($dvec, f32, $sub)
|
||||
dvec_scalar_sub_impl!($dvec, u64, $sub)
|
||||
dvec_scalar_sub_impl!($dvec, u32, $sub)
|
||||
dvec_scalar_sub_impl!($dvec, u16, $sub)
|
||||
dvec_scalar_sub_impl!($dvec, u8, $sub)
|
||||
dvec_scalar_sub_impl!($dvec, i64, $sub)
|
||||
dvec_scalar_sub_impl!($dvec, i32, $sub)
|
||||
dvec_scalar_sub_impl!($dvec, i16, $sub)
|
||||
dvec_scalar_sub_impl!($dvec, i8, $sub)
|
||||
dvec_scalar_sub_impl!($dvec, uint, $sub)
|
||||
dvec_scalar_sub_impl!($dvec, int, $sub)
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! dvec_scalar_mul_impl (
|
||||
($dvec: ident, $n: ident, $mul: ident) => (
|
||||
impl $mul<$n, $dvec<$n>> for $n {
|
||||
#[inline]
|
||||
fn binop(left: &$dvec<$n>, right: &$n) -> $dvec<$n> {
|
||||
FromIterator::from_iter(left.as_slice().iter().map(|a| a * *right))
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! dvec_scalar_div_impl (
|
||||
($dvec: ident, $n: ident, $div: ident) => (
|
||||
impl $div<$n, $dvec<$n>> for $n {
|
||||
#[inline]
|
||||
fn binop(left: &$dvec<$n>, right: &$n) -> $dvec<$n> {
|
||||
FromIterator::from_iter(left.as_slice().iter().map(|a| a / *right))
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! dvec_scalar_add_impl (
|
||||
($dvec: ident, $n: ident, $add: ident) => (
|
||||
impl $add<$n, $dvec<$n>> for $n {
|
||||
#[inline]
|
||||
fn binop(left: &$dvec<$n>, right: &$n) -> $dvec<$n> {
|
||||
FromIterator::from_iter(left.as_slice().iter().map(|a| a + *right))
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! dvec_scalar_sub_impl (
|
||||
($dvec: ident, $n: ident, $sub: ident) => (
|
||||
impl $sub<$n, $dvec<$n>> for $n {
|
||||
#[inline]
|
||||
fn binop(left: &$dvec<$n>, right: &$n) -> $dvec<$n> {
|
||||
FromIterator::from_iter(left.as_slice().iter().map(|a| a - *right))
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! small_dvec_impl (
|
||||
($dvec: ident, $dim: expr, $mul: ident, $div: ident, $add: ident, $sub: ident $(,$idx: expr)*) => (
|
||||
impl<N> Collection for $dvec<N> {
|
||||
#[inline]
|
||||
fn len(&self) -> uint {
|
||||
self.dim
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: PartialEq> PartialEq for $dvec<N> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &$dvec<N>) -> bool {
|
||||
if self.len() != other.len() {
|
||||
return false; // FIXME: fail instead?
|
||||
}
|
||||
|
||||
for (a, b) in self.as_slice().iter().zip(other.as_slice().iter()) {
|
||||
if *a != *b {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone> Clone for $dvec<N> {
|
||||
fn clone(&self) -> $dvec<N> {
|
||||
let at: [N, ..$dim] = [ $( self.at[$idx].clone(), )* ];
|
||||
|
||||
$dvec {
|
||||
at: at,
|
||||
dim: self.dim
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dvec_impl!($dvec, $mul, $div, $add, $sub)
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! small_dvec_from_impl (
|
||||
($dvec: ident, $dim: expr $(,$zeros: expr)*) => (
|
||||
impl<N: Clone + Zero> $dvec<N> {
|
||||
/// Builds a vector filled with a constant.
|
||||
#[inline]
|
||||
pub fn from_elem(dim: uint, elem: N) -> $dvec<N> {
|
||||
assert!(dim <= $dim);
|
||||
|
||||
let mut at: [N, ..$dim] = [ $( $zeros, )* ];
|
||||
|
||||
for n in at.mut_slice_to(dim).mut_iter() {
|
||||
*n = elem.clone();
|
||||
}
|
||||
|
||||
$dvec {
|
||||
at: at,
|
||||
dim: dim
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Zero> $dvec<N> {
|
||||
/// Builds a vector filled with the components provided by a vector.
|
||||
///
|
||||
/// The vector must have at least `dim` elements.
|
||||
#[inline]
|
||||
pub fn from_slice(dim: uint, vec: &[N]) -> $dvec<N> {
|
||||
assert!(dim <= vec.len() && dim <= $dim);
|
||||
|
||||
// FIXME: not safe.
|
||||
let mut at: [N, ..$dim] = [ $( $zeros, )* ];
|
||||
|
||||
for (curr, other) in vec.iter().zip(at.mut_iter()) {
|
||||
*other = curr.clone();
|
||||
}
|
||||
|
||||
$dvec {
|
||||
at: at,
|
||||
dim: dim
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Zero> $dvec<N> {
|
||||
/// Builds a vector filled with the result of a function.
|
||||
#[inline(always)]
|
||||
pub fn from_fn(dim: uint, f: |uint| -> N) -> $dvec<N> {
|
||||
assert!(dim <= $dim);
|
||||
|
||||
let mut at: [N, ..$dim] = [ $( $zeros, )* ];
|
||||
|
||||
for i in range(0, dim) {
|
||||
at[i] = f(i);
|
||||
}
|
||||
|
||||
$dvec {
|
||||
at: at,
|
||||
dim: dim
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Zero> FromIterator<N> for $dvec<N> {
|
||||
#[inline]
|
||||
fn from_iter<I: Iterator<N>>(mut param: I) -> $dvec<N> {
|
||||
let mut at: [N, ..$dim] = [ $( $zeros, )* ];
|
||||
|
||||
let mut dim = 0;
|
||||
|
||||
for n in param {
|
||||
if dim == $dim {
|
||||
break;
|
||||
}
|
||||
|
||||
at[dim] = n;
|
||||
|
||||
dim = dim + 1;
|
||||
}
|
||||
|
||||
$dvec {
|
||||
at: at,
|
||||
dim: dim
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
@ -6,9 +6,9 @@ use std::mem;
|
||||
use std::num::{One, Zero};
|
||||
use traits::operations::ApproxEq;
|
||||
use std::slice::{Items, MutItems};
|
||||
use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6, Vec1MulRhs, Vec4MulRhs,
|
||||
Vec5MulRhs, Vec6MulRhs};
|
||||
use structs::dvec::DVec;
|
||||
use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6,
|
||||
Vec1MulRhs, Vec4MulRhs, Vec5MulRhs, Vec6MulRhs};
|
||||
use structs::dvec::{DVec1, DVec2, DVec3, DVec4, DVec5, DVec6};
|
||||
|
||||
use traits::structure::{Cast, Row, Col, Iterable, IterableMut, Dim, Indexable,
|
||||
Eye, ColSlice, RowSlice};
|
||||
@ -118,8 +118,8 @@ transpose_impl!(Mat1, 1)
|
||||
approx_eq_impl!(Mat1)
|
||||
row_impl!(Mat1, Vec1, 1)
|
||||
col_impl!(Mat1, Vec1, 1)
|
||||
col_slice_impl!(Mat1, Vec1, 1)
|
||||
row_slice_impl!(Mat1, Vec1, 1)
|
||||
col_slice_impl!(Mat1, Vec1, DVec1, 1)
|
||||
row_slice_impl!(Mat1, Vec1, DVec1, 1)
|
||||
to_homogeneous_impl!(Mat1, Mat2, 1, 2)
|
||||
from_homogeneous_impl!(Mat1, Mat2, 1, 2)
|
||||
outer_impl!(Vec1, Mat1)
|
||||
@ -219,8 +219,8 @@ transpose_impl!(Mat2, 2)
|
||||
approx_eq_impl!(Mat2)
|
||||
row_impl!(Mat2, Vec2, 2)
|
||||
col_impl!(Mat2, Vec2, 2)
|
||||
col_slice_impl!(Mat2, Vec2, 2)
|
||||
row_slice_impl!(Mat2, Vec2, 2)
|
||||
col_slice_impl!(Mat2, Vec2, DVec2, 2)
|
||||
row_slice_impl!(Mat2, Vec2, DVec2, 2)
|
||||
to_homogeneous_impl!(Mat2, Mat3, 2, 3)
|
||||
from_homogeneous_impl!(Mat2, Mat3, 2, 3)
|
||||
outer_impl!(Vec2, Mat2)
|
||||
@ -334,8 +334,8 @@ transpose_impl!(Mat3, 3)
|
||||
approx_eq_impl!(Mat3)
|
||||
// (specialized) row_impl!(Mat3, Vec3, 3)
|
||||
// (specialized) col_impl!(Mat3, Vec3, 3)
|
||||
col_slice_impl!(Mat3, Vec3, 3)
|
||||
row_slice_impl!(Mat3, Vec3, 3)
|
||||
col_slice_impl!(Mat3, Vec3, DVec3, 3)
|
||||
row_slice_impl!(Mat3, Vec3, DVec3, 3)
|
||||
to_homogeneous_impl!(Mat3, Mat4, 3, 4)
|
||||
from_homogeneous_impl!(Mat3, Mat4, 3, 4)
|
||||
outer_impl!(Vec3, Mat3)
|
||||
@ -501,8 +501,8 @@ transpose_impl!(Mat4, 4)
|
||||
approx_eq_impl!(Mat4)
|
||||
row_impl!(Mat4, Vec4, 4)
|
||||
col_impl!(Mat4, Vec4, 4)
|
||||
col_slice_impl!(Mat4, Vec4, 4)
|
||||
row_slice_impl!(Mat4, Vec4, 4)
|
||||
col_slice_impl!(Mat4, Vec4, DVec4, 4)
|
||||
row_slice_impl!(Mat4, Vec4, DVec4, 4)
|
||||
to_homogeneous_impl!(Mat4, Mat5, 4, 5)
|
||||
from_homogeneous_impl!(Mat4, Mat5, 4, 5)
|
||||
outer_impl!(Vec4, Mat4)
|
||||
@ -684,8 +684,8 @@ transpose_impl!(Mat5, 5)
|
||||
approx_eq_impl!(Mat5)
|
||||
row_impl!(Mat5, Vec5, 5)
|
||||
col_impl!(Mat5, Vec5, 5)
|
||||
col_slice_impl!(Mat5, Vec5, 5)
|
||||
row_slice_impl!(Mat5, Vec5, 5)
|
||||
col_slice_impl!(Mat5, Vec5, DVec5, 5)
|
||||
row_slice_impl!(Mat5, Vec5, DVec5, 5)
|
||||
to_homogeneous_impl!(Mat5, Mat6, 5, 6)
|
||||
from_homogeneous_impl!(Mat5, Mat6, 5, 6)
|
||||
outer_impl!(Vec5, Mat5)
|
||||
@ -919,6 +919,6 @@ transpose_impl!(Mat6, 6)
|
||||
approx_eq_impl!(Mat6)
|
||||
row_impl!(Mat6, Vec6, 6)
|
||||
col_impl!(Mat6, Vec6, 6)
|
||||
col_slice_impl!(Mat6, Vec6, 6)
|
||||
row_slice_impl!(Mat6, Vec6, 6)
|
||||
col_slice_impl!(Mat6, Vec6, DVec6, 6)
|
||||
row_slice_impl!(Mat6, Vec6, DVec6, 6)
|
||||
outer_impl!(Vec6, Mat6)
|
||||
|
@ -226,20 +226,12 @@ macro_rules! indexable_impl(
|
||||
)
|
||||
|
||||
macro_rules! col_slice_impl(
|
||||
($t: ident, $tv: ident, $dim: expr) => (
|
||||
impl<N: Clone + Zero> ColSlice<DVec<N>> for $t<N> {
|
||||
fn col_slice(& self, cid: uint, rstart: uint, rend: uint) -> DVec<N> {
|
||||
assert!(cid < $dim);
|
||||
assert!(rstart < rend);
|
||||
assert!(rend <= $dim);
|
||||
($t: ident, $tv: ident, $slice: ident, $dim: expr) => (
|
||||
impl<N: Clone + Zero> ColSlice<$slice<N>> for $t<N> {
|
||||
fn col_slice(&self, cid: uint, rstart: uint, rend: uint) -> $slice<N> {
|
||||
let col = self.col(cid);
|
||||
let res = DVec::from_vec(
|
||||
rend - rstart,
|
||||
unsafe {
|
||||
mem::transmute::<&$tv<N>, & [N, ..$dim]>
|
||||
(&col).slice(rstart, rend)
|
||||
});
|
||||
res
|
||||
|
||||
$slice::from_slice(rend - rstart, col.as_slice().slice(rstart, rend))
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -275,20 +267,12 @@ macro_rules! row_impl(
|
||||
)
|
||||
|
||||
macro_rules! row_slice_impl(
|
||||
($t: ident, $tv: ident, $dim: expr) => (
|
||||
impl<N: Clone + Zero> RowSlice<DVec<N>> for $t<N> {
|
||||
fn row_slice(& self, rid: uint, cstart: uint, cend: uint) -> DVec<N> {
|
||||
assert!(rid < $dim);
|
||||
assert!(cstart < cend);
|
||||
assert!(cend <= $dim);
|
||||
($t: ident, $tv: ident, $slice: ident, $dim: expr) => (
|
||||
impl<N: Clone + Zero> RowSlice<$slice<N>> for $t<N> {
|
||||
fn row_slice(&self, rid: uint, cstart: uint, cend: uint) -> $slice<N> {
|
||||
let row = self.row(rid);
|
||||
let res = DVec::from_vec(
|
||||
cend - cstart,
|
||||
unsafe {
|
||||
mem::transmute::<&$tv<N>, & [N, ..$dim]>
|
||||
(&row).slice(cstart, cend)
|
||||
});
|
||||
res
|
||||
|
||||
$slice::from_slice(cend - cstart, row.as_slice().slice(cstart, cend))
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Data structures and implementations.
|
||||
|
||||
pub use self::dmat::DMat;
|
||||
pub use self::dvec::DVec;
|
||||
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::mat::{Identity, Mat1, Mat2, Mat3, Mat4, Mat5, Mat6};
|
||||
pub use self::rot::{Rot2, Rot3, Rot4};
|
||||
@ -18,6 +18,7 @@ pub use self::mat::{Mat1MulRhs, Mat2MulRhs, Mat3MulRhs, Mat4MulRhs, Mat5MulRhs,
|
||||
|
||||
mod metal;
|
||||
mod dmat;
|
||||
mod dvec_macros;
|
||||
mod dvec;
|
||||
mod vec_macros;
|
||||
mod vec;
|
||||
|
@ -38,6 +38,7 @@ new_impl!(Vec1, x)
|
||||
ord_impl!(Vec1, x)
|
||||
vec_axis_impl!(Vec1, x)
|
||||
vec_cast_impl!(Vec1, Vec1Cast, x)
|
||||
as_slice_impl!(Vec1, 1)
|
||||
indexable_impl!(Vec1, 1)
|
||||
at_fast_impl!(Vec1, 1)
|
||||
new_repeat_impl!(Vec1, val, x)
|
||||
@ -135,6 +136,7 @@ new_impl!(Vec2, x, y)
|
||||
ord_impl!(Vec2, x, y)
|
||||
vec_axis_impl!(Vec2, x, y)
|
||||
vec_cast_impl!(Vec2, Vec2Cast, x, y)
|
||||
as_slice_impl!(Vec2, 2)
|
||||
indexable_impl!(Vec2, 2)
|
||||
at_fast_impl!(Vec2, 2)
|
||||
new_repeat_impl!(Vec2, val, x, y)
|
||||
@ -234,6 +236,7 @@ new_impl!(Vec3, x, y, z)
|
||||
ord_impl!(Vec3, x, y, z)
|
||||
vec_axis_impl!(Vec3, x, y, z)
|
||||
vec_cast_impl!(Vec3, Vec3Cast, x, y, z)
|
||||
as_slice_impl!(Vec3, 3)
|
||||
indexable_impl!(Vec3, 3)
|
||||
at_fast_impl!(Vec3, 3)
|
||||
new_repeat_impl!(Vec3, val, x, y, z)
|
||||
@ -339,6 +342,7 @@ new_impl!(Vec4, x, y, z, w)
|
||||
ord_impl!(Vec4, x, y, z, w)
|
||||
vec_axis_impl!(Vec4, x, y, z, w)
|
||||
vec_cast_impl!(Vec4, Vec4Cast, x, y, z, w)
|
||||
as_slice_impl!(Vec4, 4)
|
||||
indexable_impl!(Vec4, 4)
|
||||
at_fast_impl!(Vec4, 4)
|
||||
new_repeat_impl!(Vec4, val, x, y, z, w)
|
||||
@ -442,6 +446,7 @@ new_impl!(Vec5, x, y, z, w, a)
|
||||
ord_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)
|
||||
as_slice_impl!(Vec5, 5)
|
||||
indexable_impl!(Vec5, 5)
|
||||
at_fast_impl!(Vec5, 5)
|
||||
new_repeat_impl!(Vec5, val, x, y, z, w, a)
|
||||
@ -547,6 +552,7 @@ new_impl!(Vec6, x, y, z, w, a, b)
|
||||
ord_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)
|
||||
as_slice_impl!(Vec6, 6)
|
||||
indexable_impl!(Vec6, 6)
|
||||
at_fast_impl!(Vec6, 6)
|
||||
new_repeat_impl!(Vec6, val, x, y, z, w, a, b)
|
||||
|
@ -15,6 +15,26 @@ macro_rules! new_impl(
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! as_slice_impl(
|
||||
($t: ident, $dim: expr) => (
|
||||
impl<N> $t<N> {
|
||||
/// Slices this vector.
|
||||
pub fn as_slice<'a>(&'a self) -> &'a [N] {
|
||||
unsafe {
|
||||
mem::transmute::<&$t<N>, &[N, ..$dim]>(self).as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
/// Mutably slices this vector.
|
||||
pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [N] {
|
||||
unsafe {
|
||||
mem::transmute::<&mut $t<N>, &mut [N, ..$dim]>(self).as_mut_slice()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! at_fast_impl(
|
||||
($t: ident, $dim: expr) => (
|
||||
impl<N: Clone> $t<N> {
|
||||
|
@ -2,7 +2,6 @@ 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;
|
||||
use na::decomp_qr;
|
||||
use std::cmp::{min, max};
|
||||
|
||||
macro_rules! test_inv_mat_impl(
|
||||
@ -25,12 +24,12 @@ macro_rules! test_transpose_mat_impl(
|
||||
);
|
||||
)
|
||||
|
||||
macro_rules! test_decomp_qr_impl(
|
||||
macro_rules! test_qr_impl(
|
||||
($t: ty) => (
|
||||
for _ in range(0u, 10000) {
|
||||
let randmat : $t = random();
|
||||
|
||||
let (q, r) = decomp_qr(&randmat);
|
||||
let (q, r) = na::qr(&randmat);
|
||||
let recomp = q * r;
|
||||
|
||||
assert!(na::approx_eq(&randmat, &recomp));
|
||||
@ -38,6 +37,35 @@ macro_rules! test_decomp_qr_impl(
|
||||
);
|
||||
)
|
||||
|
||||
macro_rules! test_eigen_qr_impl(
|
||||
($t: ty) => {
|
||||
for _ in range(0u, 10000) {
|
||||
let randmat : $t = random();
|
||||
|
||||
let (eigenvalues, eigenvectors) = na::eigen_qr(&randmat, &Float::epsilon(), 1000);
|
||||
|
||||
// FIXME: provide a method to initialize a matrix from its diagonal!
|
||||
let diag: $t = na::zero();
|
||||
|
||||
for i in range(0, na::dim::<$t>()) {
|
||||
diag.set((i, i), eigenvalues.at(i));
|
||||
}
|
||||
|
||||
let recomp = na::transpose(&eigenvectors) * diag * eigenvectors;
|
||||
|
||||
println!("mat: {}", randmat);
|
||||
println!("eigenvectors: {}", eigenvectors);
|
||||
println!("eigenvalues: {}", eigenvalues);
|
||||
println!("recomp: {}", recomp);
|
||||
|
||||
assert!(false);
|
||||
fail!("what!");
|
||||
|
||||
assert!(na::approx_eq(&randmat, &recomp));
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
#[test]
|
||||
fn test_transpose_mat1() {
|
||||
test_transpose_mat_impl!(Mat1<f64>);
|
||||
@ -139,7 +167,7 @@ fn test_mean_dmat() {
|
||||
]
|
||||
);
|
||||
|
||||
assert!(na::approx_eq(&na::mean(&mat), &DVec::from_vec(3, [4.0f64, 5.0, 6.0])));
|
||||
assert!(na::approx_eq(&na::mean(&mat), &DVec::from_slice(3, [4.0f64, 5.0, 6.0])));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -223,14 +251,14 @@ fn test_dmat_from_vec() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decomp_qr() {
|
||||
fn test_qr() {
|
||||
for _ in range(0u, 10) {
|
||||
let dim1: uint = random();
|
||||
let dim2: uint = random();
|
||||
let rows = min(40, max(dim1, dim2));
|
||||
let cols = min(40, min(dim1, dim2));
|
||||
let randmat: DMat<f64> = DMat::new_random(rows, cols);
|
||||
let (q, r) = decomp_qr(&randmat);
|
||||
let (q, r) = na::qr(&randmat);
|
||||
let recomp = q * r;
|
||||
|
||||
assert!(na::approx_eq(&randmat, &recomp));
|
||||
@ -238,40 +266,68 @@ fn test_decomp_qr() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decomp_qr_mat1() {
|
||||
test_decomp_qr_impl!(Mat1<f64>);
|
||||
fn test_qr_mat1() {
|
||||
test_qr_impl!(Mat1<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decomp_qr_mat2() {
|
||||
test_decomp_qr_impl!(Mat2<f64>);
|
||||
fn test_qr_mat2() {
|
||||
test_qr_impl!(Mat2<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decomp_qr_mat3() {
|
||||
test_decomp_qr_impl!(Mat3<f64>);
|
||||
fn test_qr_mat3() {
|
||||
test_qr_impl!(Mat3<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decomp_qr_mat4() {
|
||||
test_decomp_qr_impl!(Mat4<f64>);
|
||||
fn test_qr_mat4() {
|
||||
test_qr_impl!(Mat4<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decomp_qr_mat5() {
|
||||
test_decomp_qr_impl!(Mat5<f64>);
|
||||
fn test_qr_mat5() {
|
||||
test_qr_impl!(Mat5<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decomp_qr_mat6() {
|
||||
test_decomp_qr_impl!(Mat6<f64>);
|
||||
fn test_qr_mat6() {
|
||||
test_qr_impl!(Mat6<f64>);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn test_eigen_qr_mat1() {
|
||||
// test_eigen_qr_impl!(Mat1<f64>);
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn test_eigen_qr_mat2() {
|
||||
// test_eigen_qr_impl!(Mat2<f64>);
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn test_eigen_qr_mat3() {
|
||||
// test_eigen_qr_impl!(Mat3<f64>);
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn test_eigen_qr_mat4() {
|
||||
// test_eigen_qr_impl!(Mat4<f64>);
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn test_eigen_qr_mat5() {
|
||||
// test_eigen_qr_impl!(Mat5<f64>);
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn test_eigen_qr_mat6() {
|
||||
// test_eigen_qr_impl!(Mat6<f64>);
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_from_fn() {
|
||||
let actual: DMat<uint> = DMat::from_fn( 3, 4,
|
||||
|i,j| 10*i + j);
|
||||
let actual: DMat<uint> = DMat::from_fn(3, 4, |i, j| 10 * i + j);
|
||||
let expected: DMat<uint> = DMat::from_row_vec(3, 4,
|
||||
[0_0, 0_1, 0_2, 0_3,
|
||||
1_0, 1_1, 1_2, 1_3,
|
||||
|
Loading…
Reference in New Issue
Block a user