use core::num::{Zero, One, Algebraic}; use core::vec::{map_zip, map, all2, len, from_elem, all}; use core::cmp::ApproxEq; use traits::ring::Ring; use traits::division_ring::DivisionRing; use traits::dot::Dot; use traits::sub_dot::SubDot; use traits::norm::Norm; use traits::translation::Translation; use traits::workarounds::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub}; #[deriving(Eq, ToStr, Clone)] pub struct DVec { at: ~[T] } pub fn zero_vec_with_dim(dim: uint) -> DVec { DVec { at: from_elem(dim, Zero::zero::()) } } pub fn is_zero_vec(vec: &DVec) -> bool { all(vec.at, |e| e.is_zero()) } // FIXME: is Clone needed? impl> DVec { pub fn canonical_basis_with_dim(dim: uint) -> ~[DVec] { let mut res : ~[DVec] = ~[]; for uint::range(0u, dim) |i| { let mut basis_element : DVec = zero_vec_with_dim(dim); basis_element.at[i] = One::one(); res.push(basis_element); } res } pub fn orthogonal_subspace_basis(&self) -> ~[DVec] { // compute the basis of the orthogonal subspace using Gram-Schmidt // orthogonalization algorithm let dim = len(self.at); let mut res : ~[DVec] = ~[]; for uint::range(0u, dim) |i| { let mut basis_element : DVec = zero_vec_with_dim(len(self.at)); basis_element.at[i] = One::one(); if (res.len() == dim - 1) { break; } let mut elt = basis_element.clone(); elt -= self.scalar_mul(&basis_element.dot(self)); for res.each |v| { elt -= v.scalar_mul(&elt.dot(v)) }; if (!elt.sqnorm().approx_eq(&Zero::zero())) { res.push(elt.normalized()); } } assert!(res.len() == dim - 1); res } } impl> Add, DVec> for DVec { fn add(&self, other: &DVec) -> DVec { assert!(len(self.at) == len(other.at)); DVec { at: map_zip(self.at, other.at, | a, b | { *a + *b }) } } } impl> Sub, DVec> for DVec { fn sub(&self, other: &DVec) -> DVec { assert!(len(self.at) == len(other.at)); DVec { at: map_zip(self.at, other.at, | a, b | *a - *b) } } } impl> Neg> for DVec { fn neg(&self) -> DVec { DVec { at: map(self.at, |a| -a) } } } impl Dot for DVec { fn dot(&self, other: &DVec) -> T { assert!(len(self.at) == len(other.at)); let mut res = Zero::zero::(); for uint::range(0u, len(self.at)) |i| { res += self.at[i] * other.at[i]; } res } } impl SubDot for DVec { fn sub_dot(&self, a: &DVec, b: &DVec) -> T { let mut res = Zero::zero::(); for uint::range(0u, len(self.at)) |i| { res += (self.at[i] - a.at[i]) * b.at[i]; } res } } impl> ScalarMul for DVec { fn scalar_mul(&self, s: &T) -> DVec { DVec { at: map(self.at, |a| a * *s) } } fn scalar_mul_inplace(&mut self, s: &T) { for uint::range(0u, len(self.at)) |i| { self.at[i] *= *s; } } } impl> ScalarDiv for DVec { fn scalar_div(&self, s: &T) -> DVec { DVec { at: map(self.at, |a| a / *s) } } fn scalar_div_inplace(&mut self, s: &T) { for uint::range(0u, len(self.at)) |i| { self.at[i] /= *s; } } } impl> ScalarAdd for DVec { fn scalar_add(&self, s: &T) -> DVec { DVec { at: map(self.at, |a| a + *s) } } fn scalar_add_inplace(&mut self, s: &T) { for uint::range(0u, len(self.at)) |i| { self.at[i] += *s; } } } impl> ScalarSub for DVec { fn scalar_sub(&self, s: &T) -> DVec { DVec { at: map(self.at, |a| a - *s) } } fn scalar_sub_inplace(&mut self, s: &T) { for uint::range(0u, len(self.at)) |i| { self.at[i] -= *s; } } } impl> Translation> for DVec { fn translation(&self) -> DVec { self.clone() } fn translated(&self, t: &DVec) -> DVec { self + *t } fn translate(&mut self, t: &DVec) { *self = *self + *t; } } impl Norm for DVec { fn sqnorm(&self) -> T { self.dot(self) } fn norm(&self) -> T { self.sqnorm().sqrt() } fn normalized(&self) -> DVec { let mut res : DVec = self.clone(); res.normalize(); res } fn normalize(&mut self) -> T { let l = self.norm(); for uint::range(0u, len(self.at)) |i| { self.at[i] /= l; } l } } impl> ApproxEq for DVec { fn approx_epsilon() -> T { ApproxEq::approx_epsilon::() } fn approx_eq(&self, other: &DVec) -> bool { all2(self.at, other.at, |a, b| a.approx_eq(b)) } fn approx_eq_eps(&self, other: &DVec, epsilon: &T) -> bool { all2(self.at, other.at, |a, b| a.approx_eq_eps(b, epsilon)) } }