diff --git a/src/structs/dvec.rs b/src/structs/dvec.rs index 4f31a273..ba8b27ec 100644 --- a/src/structs/dvec.rs +++ b/src/structs/dvec.rs @@ -7,7 +7,8 @@ use std::ops::{Add, Sub, Mul, Div, Neg, AddAssign, SubAssign, MulAssign, DivAssi use std::mem; use rand::{self, Rand}; use num::{Zero, One}; -use traits::operations::{ApproxEq, Axpy, Mean}; +use structs::DMat; +use traits::operations::{ApproxEq, Axpy, Mean, Outer}; use traits::geometry::{Dot, Norm}; use traits::structure::{Iterable, IterableMut, Indexable, Shape, BaseFloat, BaseNum, Cast}; #[cfg(feature="arbitrary")] @@ -57,7 +58,7 @@ impl DVec { /// Builds a vector filled with the results of a function applied to each of its component coordinates. #[inline(always)] pub fn from_fn N>(dim: usize, mut f: F) -> DVec { - DVec { at: (0..dim).map(|i| f(i)).collect() } + DVec { at: (0 .. dim).map(|i| f(i)).collect() } } /// The vector length. @@ -74,6 +75,25 @@ impl FromIterator for DVec { } } +impl Outer for DVec { + type OuterProductType = DMat; + + #[inline] + fn outer(&self, other: &DVec) -> DMat { + let mut res = unsafe { DMat::new_uninitialized(self.at.len(), other.at.len()) }; + + for i in 0 .. self.at.len() { + for j in 0 .. other.at.len() { + unsafe { + res.unsafe_set((i, j), self.unsafe_at(i) * other.unsafe_at(j)); + } + } + } + + res + } +} + #[cfg(feature="arbitrary")] impl Arbitrary for DVec { fn arbitrary(g: &mut G) -> DVec { diff --git a/tests/mat.rs b/tests/mat.rs index 1eeefd9d..fce64edc 100644 --- a/tests/mat.rs +++ b/tests/mat.rs @@ -835,3 +835,11 @@ fn test_transpose_square_mat() { assert_eq!(&[0, 1, 2, 3], &mat.row_slice(i, 0, num_cols)[..]); } } + +#[test] +fn test_outer_dvec() { + let vec = DVec::from_slice(5, &[ 1.0, 2.0, 3.0, 4.0, 5.0 ]); + let row = DMat::from_row_vec(1, 5, &vec[..]); + + assert_eq!(row.transpose() * row, na::outer(&vec, &vec)) +}