nalgebra/src/structs/dvec.rs

435 lines
10 KiB
Rust
Raw Normal View History

//! Vector with dimensions unknown at compile-time.
#[allow(missing_doc)]; // we hide doc to not have to document the $trhs double dispatch trait.
use std::num::{Zero, One, Real};
use std::rand::Rand;
use std::rand;
use std::vec;
use std::vec::{Items, MutItems};
use traits::operations::ApproxEq;
2013-09-09 17:19:54 +08:00
use std::iter::FromIterator;
Api change: deal with inplace/out of place methods. Before, it was too easy to use an out of place method instead of the inplace one since they name were pretty mutch the same. This kind of confusion may lead to silly bugs very hard to understand. Thus the following changes have been made when a method is available both inplace and out-of-place: * inplace version keep a short name. * out-of-place version are suffixed by `_cpy` (meaning `copy`), and are static methods. Methods applying transformations (rotation, translation or general transform) are now prefixed by `append`, and a `prepend` version is available too. Also, free functions doing in-place modifications dont really make sense. They have been removed. Here are the naming changes: * `invert` -> `inv` * `inverted` -> `Inv::inv_cpy` * `transpose` -> `transpose` * `transposed` -> `Transpose::transpose_cpy` * `transform_by` -> `append_transformation` * `transformed` -> `Transform::append_transformation_cpy` * `rotate_by` -> `apppend_rotation` * `rotated` -> `Rotation::append_rotation_cpy` * `translate_by` -> `apppend_translation` * `translate` -> `Translation::append_translation_cpy` * `normalized` -> `Norm::normalize_cpy` * `rotated_wrt_point` -> `RotationWithTranslation::append_rotation_wrt_point_cpy` * `rotated_wrt_center` -> `RotationWithTranslation::append_rotation_wrt_center_cpy` Note that using those static methods is very verbose, and using in-place methods require an explicit import of the related trait. This is a way to convince the user to use free functions most of the time.
2013-10-14 16:22:32 +08:00
use traits::geometry::{Dot, Norm};
use traits::structure::{Iterable, IterableMut};
2013-05-31 17:01:07 +08:00
#[doc(hidden)]
mod metal;
2013-07-24 22:50:40 +08:00
/// Vector with a dimension unknown at compile-time.
#[deriving(Eq, ToStr, Clone)]
2013-08-05 16:13:44 +08:00
pub struct DVec<N> {
2013-08-05 15:44:56 +08:00
/// Components of the vector. Contains as much elements as the vector dimension.
at: ~[N]
2013-05-31 17:01:07 +08:00
}
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
2014-01-19 22:48:07 +08:00
/// * `dim` - The dimension of the vector.
#[inline]
pub fn new_zeros(dim: uint) -> DVec<N> {
DVec::from_elem(dim, Zero::zero())
}
2013-05-31 17:01:07 +08:00
/// Tests if all components of the vector are zeroes.
#[inline]
pub fn is_zero(&self) -> bool {
self.at.iter().all(|e| e.is_zero())
}
2013-08-05 16:13:44 +08:00
}
2013-05-31 17:01:07 +08:00
impl<N: Clone> DVec<N> {
/// Indexing without bounds checking.
pub unsafe fn at_fast(&self, i: uint) -> N {
2013-12-16 19:04:02 +08:00
(*self.at.unsafe_ref(i)).clone()
}
}
impl<N: One + Clone> DVec<N> {
/// Builds a vector filled with ones.
///
/// # Arguments
2014-01-19 22:48:07 +08:00
/// * `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]
pub unsafe fn new_uninitialized(dim: uint) -> DVec<N> {
let mut vec = vec::with_capacity(dim);
2013-12-16 19:04:02 +08:00
vec.set_len(dim);
DVec {
at: vec
}
}
#[inline]
pub unsafe fn set_fast(&mut self, i: uint, val: N) {
*self.at.unsafe_mut_ref(i) = val
}
2014-01-19 22:48:07 +08:00
/// Gets a reference to of this vector data.
#[inline]
pub fn as_vec<'r>(&'r self) -> &'r [N] {
let data: &'r [N] = self.at;
data
}
2014-01-19 22:48:07 +08:00
/// Gets a mutable reference to of this vector data.
#[inline]
pub fn as_mut_vec<'r>(&'r mut self) -> &'r mut [N] {
let data: &'r mut [N] = self.at;
data
}
2014-01-19 22:48:07 +08:00
/// Extracts this vector data.
#[inline]
pub fn to_vec(self) -> ~[N] {
self.at
}
}
impl<N: Clone> DVec<N> {
/// Builds a vector filled with a constant.
#[inline]
pub fn from_elem(dim: uint, elem: N) -> DVec<N> {
DVec { at: vec::from_elem(dim, elem) }
}
/// Builds a vector filled with the components provided by a vector.
///
/// The vector must have at least `dim` elements.
#[inline]
pub fn from_vec(dim: uint, vec: &[N]) -> DVec<N> {
assert!(dim <= vec.len());
DVec {
at: vec.slice_to(dim).to_owned()
}
}
}
impl<N> DVec<N> {
/// Builds a vector filled with the result of a function.
#[inline(always)]
2013-11-27 18:16:16 +08:00
pub fn from_fn(dim: uint, f: |uint| -> N) -> DVec<N> {
DVec { at: vec::from_fn(dim, |i| f(i)) }
}
}
impl<N> Container for DVec<N> {
#[inline]
fn len(&self) -> uint {
self.at.len()
}
}
2013-08-05 16:13:44 +08:00
impl<N> Iterable<N> for DVec<N> {
#[inline]
fn iter<'l>(&'l self) -> Items<'l, N> {
2013-08-05 16:13:44 +08:00
self.at.iter()
}
}
2013-08-05 16:13:44 +08:00
impl<N> IterableMut<N> for DVec<N> {
#[inline]
fn mut_iter<'l>(&'l mut self) -> MutItems<'l, N> {
2013-08-05 16:13:44 +08:00
self.at.mut_iter()
}
}
2013-08-16 16:14:01 +08:00
impl<N> FromIterator<N> for DVec<N> {
#[inline]
2013-08-16 16:14:01 +08:00
fn from_iterator<I: Iterator<N>>(mut param: &mut I) -> DVec<N> {
2013-08-05 15:44:56 +08:00
let mut res = DVec { at: ~[] };
2013-08-05 16:13:44 +08:00
for e in param {
res.at.push(e)
}
2013-08-05 15:44:56 +08:00
res
}
}
impl<N: Clone + Num + Real + ApproxEq<N> + DVecMulRhs<N, DVec<N>>> DVec<N> {
2013-08-05 15:44:56 +08:00
/// Computes the canonical basis for the given dimension. A canonical basis is a set of
2014-01-19 22:48:07 +08:00
/// vectors, mutually orthogonal, with all its component equal to 0.0 except one which is equal
2013-08-05 15:44:56 +08:00
/// to 1.0.
2013-08-05 16:13:44 +08:00
pub fn canonical_basis_with_dim(dim: uint) -> ~[DVec<N>] {
2013-08-05 15:44:56 +08:00
let mut res : ~[DVec<N>] = ~[];
2013-05-31 17:01:07 +08:00
2013-08-05 16:13:44 +08:00
for i in range(0u, dim) {
let mut basis_element : DVec<N> = DVec::new_zeros(dim);
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
basis_element.at[i] = One::one();
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
res.push(basis_element);
}
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
res
}
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
/// Computes a basis of the space orthogonal to the vector. If the input vector is of dimension
/// `n`, this will return `n - 1` vectors.
2013-08-05 16:13:44 +08:00
pub fn orthogonal_subspace_basis(&self) -> ~[DVec<N>] {
2013-08-05 15:44:56 +08:00
// compute the basis of the orthogonal subspace using Gram-Schmidt
// orthogonalization algorithm
let dim = self.at.len();
let mut res : ~[DVec<N>] = ~[];
2013-05-31 17:01:07 +08:00
2013-08-05 16:13:44 +08:00
for i in range(0u, dim) {
let mut basis_element : DVec<N> = DVec::new_zeros(self.at.len());
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
basis_element.at[i] = One::one();
2013-05-31 17:01:07 +08:00
2013-08-05 16:13:44 +08:00
if res.len() == dim - 1 {
break;
}
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
let mut elt = basis_element.clone();
2013-05-31 17:01:07 +08:00
elt = elt - self * Dot::dot(&basis_element, self);
2013-05-31 17:01:07 +08:00
2013-08-05 16:13:44 +08:00
for v in res.iter() {
elt = elt - v * Dot::dot(&elt, v)
2013-08-05 16:13:44 +08:00
};
2013-08-05 15:44:56 +08:00
if !ApproxEq::approx_eq(&Norm::sqnorm(&elt), &Zero::zero()) {
Api change: deal with inplace/out of place methods. Before, it was too easy to use an out of place method instead of the inplace one since they name were pretty mutch the same. This kind of confusion may lead to silly bugs very hard to understand. Thus the following changes have been made when a method is available both inplace and out-of-place: * inplace version keep a short name. * out-of-place version are suffixed by `_cpy` (meaning `copy`), and are static methods. Methods applying transformations (rotation, translation or general transform) are now prefixed by `append`, and a `prepend` version is available too. Also, free functions doing in-place modifications dont really make sense. They have been removed. Here are the naming changes: * `invert` -> `inv` * `inverted` -> `Inv::inv_cpy` * `transpose` -> `transpose` * `transposed` -> `Transpose::transpose_cpy` * `transform_by` -> `append_transformation` * `transformed` -> `Transform::append_transformation_cpy` * `rotate_by` -> `apppend_rotation` * `rotated` -> `Rotation::append_rotation_cpy` * `translate_by` -> `apppend_translation` * `translate` -> `Translation::append_translation_cpy` * `normalized` -> `Norm::normalize_cpy` * `rotated_wrt_point` -> `RotationWithTranslation::append_rotation_wrt_point_cpy` * `rotated_wrt_center` -> `RotationWithTranslation::append_rotation_wrt_center_cpy` Note that using those static methods is very verbose, and using in-place methods require an explicit import of the related trait. This is a way to convince the user to use free functions most of the time.
2013-10-14 16:22:32 +08:00
res.push(Norm::normalize_cpy(&elt));
2013-08-05 16:13:44 +08:00
}
2013-08-05 15:44:56 +08:00
}
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
assert!(res.len() == dim - 1);
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
res
}
2013-05-31 17:01:07 +08:00
}
impl<N: Add<N, N>> DVecAddRhs<N, DVec<N>> for DVec<N> {
2013-08-05 15:44:56 +08:00
#[inline]
fn binop(left: &DVec<N>, right: &DVec<N>) -> DVec<N> {
assert!(left.at.len() == right.at.len());
2013-08-05 15:44:56 +08:00
DVec {
at: left.at.iter().zip(right.at.iter()).map(|(a, b)| *a + *b).collect()
2013-08-05 15:44:56 +08:00
}
2013-07-02 18:00:55 +08:00
}
2013-05-31 17:01:07 +08:00
}
impl<N: Sub<N, N>> DVecSubRhs<N, DVec<N>> for DVec<N> {
2013-08-05 15:44:56 +08:00
#[inline]
fn binop(left: &DVec<N>, right: &DVec<N>) -> DVec<N> {
assert!(left.at.len() == right.at.len());
2013-08-05 15:44:56 +08:00
DVec {
at: left.at.iter().zip(right.at.iter()).map(|(a, b)| *a - *b).collect()
2013-08-05 15:44:56 +08:00
}
2013-07-02 18:00:55 +08:00
}
2013-05-31 17:01:07 +08:00
}
2013-08-05 16:13:44 +08:00
impl<N: Neg<N>> Neg<DVec<N>> for DVec<N> {
2013-08-05 15:44:56 +08:00
#[inline]
2013-08-05 16:13:44 +08:00
fn neg(&self) -> DVec<N> {
2013-08-11 22:07:34 +08:00
DVec { at: self.at.iter().map(|a| -a).collect() }
2013-08-05 16:13:44 +08:00
}
2013-05-31 17:01:07 +08:00
}
2013-09-26 23:05:11 +08:00
impl<N: Num + Clone> Dot<N> for DVec<N> {
2013-08-05 15:44:56 +08:00
#[inline]
fn dot(a: &DVec<N>, b: &DVec<N>) -> N {
assert!(a.at.len() == b.at.len());
2013-05-31 17:01:07 +08:00
let mut res: N = Zero::zero();
2013-05-31 17:01:07 +08:00
for i in range(0u, a.at.len()) {
res = res + unsafe { a.at_fast(i) * b.at_fast(i) };
2013-08-05 16:13:44 +08:00
}
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
res
}
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
#[inline]
fn sub_dot(a: &DVec<N>, b: &DVec<N>, c: &DVec<N>) -> N {
let mut res: N = Zero::zero();
2013-05-31 17:01:07 +08:00
for i in range(0u, a.at.len()) {
res = res + unsafe { (a.at_fast(i) - b.at_fast(i)) * c.at_fast(i) };
2013-08-05 16:13:44 +08:00
}
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
res
}
2013-05-31 17:01:07 +08:00
}
impl<N: Num + Real + Clone> Norm<N> for DVec<N> {
2013-08-05 15:44:56 +08:00
#[inline]
fn sqnorm(v: &DVec<N>) -> N {
Dot::dot(v, v)
2013-08-05 16:13:44 +08:00
}
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
#[inline]
fn norm(v: &DVec<N>) -> N {
Norm::sqnorm(v).sqrt()
2013-08-05 16:13:44 +08:00
}
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
#[inline]
Api change: deal with inplace/out of place methods. Before, it was too easy to use an out of place method instead of the inplace one since they name were pretty mutch the same. This kind of confusion may lead to silly bugs very hard to understand. Thus the following changes have been made when a method is available both inplace and out-of-place: * inplace version keep a short name. * out-of-place version are suffixed by `_cpy` (meaning `copy`), and are static methods. Methods applying transformations (rotation, translation or general transform) are now prefixed by `append`, and a `prepend` version is available too. Also, free functions doing in-place modifications dont really make sense. They have been removed. Here are the naming changes: * `invert` -> `inv` * `inverted` -> `Inv::inv_cpy` * `transpose` -> `transpose` * `transposed` -> `Transpose::transpose_cpy` * `transform_by` -> `append_transformation` * `transformed` -> `Transform::append_transformation_cpy` * `rotate_by` -> `apppend_rotation` * `rotated` -> `Rotation::append_rotation_cpy` * `translate_by` -> `apppend_translation` * `translate` -> `Translation::append_translation_cpy` * `normalized` -> `Norm::normalize_cpy` * `rotated_wrt_point` -> `RotationWithTranslation::append_rotation_wrt_point_cpy` * `rotated_wrt_center` -> `RotationWithTranslation::append_rotation_wrt_center_cpy` Note that using those static methods is very verbose, and using in-place methods require an explicit import of the related trait. This is a way to convince the user to use free functions most of the time.
2013-10-14 16:22:32 +08:00
fn normalize_cpy(v: &DVec<N>) -> DVec<N> {
let mut res : DVec<N> = v.clone();
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
res.normalize();
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
res
}
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
#[inline]
2013-09-09 00:29:51 +08:00
fn normalize(&mut self) -> N {
let l = Norm::norm(self);
2013-05-31 17:01:07 +08:00
2013-08-05 16:13:44 +08:00
for i in range(0u, self.at.len()) {
self.at[i] = self.at[i] / l;
}
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
l
}
2013-05-31 17:01:07 +08:00
}
2013-08-05 16:13:44 +08:00
impl<N: ApproxEq<N>> ApproxEq<N> for DVec<N> {
2013-08-05 15:44:56 +08:00
#[inline]
fn approx_epsilon(_: Option<DVec<N>>) -> N {
ApproxEq::approx_epsilon(None::<N>)
2013-08-05 16:13:44 +08:00
}
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
#[inline]
fn approx_eq(a: &DVec<N>, b: &DVec<N>) -> bool {
let mut zip = a.at.iter().zip(b.at.iter());
2013-06-09 20:09:22 +08:00
zip.all(|(a, b)| ApproxEq::approx_eq(a, b))
2013-08-05 15:44:56 +08:00
}
2013-05-31 17:01:07 +08:00
2013-08-05 15:44:56 +08:00
#[inline]
fn approx_eq_eps(a: &DVec<N>, b: &DVec<N>, epsilon: &N) -> bool {
let mut zip = a.at.iter().zip(b.at.iter());
2013-06-09 20:09:22 +08:00
zip.all(|(a, b)| ApproxEq::approx_eq_eps(a, b, epsilon))
2013-08-05 15:44:56 +08:00
}
2013-05-31 17:01:07 +08:00
}
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)