use std::ops::Mul; use std::fmt::Debug; use num::Zero; use na::{Outer, Inverse}; use na; use math::{Point, Vector}; // FIXME: move this to nalgebra? /// Computes the convariance matrix of a set of points. pub fn cov

(pts: &[P]) -> ::OuterProductType where P: Point, P::Vector: Outer, ::OuterProductType: Zero { cov_and_center(pts).0 } /// Computes the covariance matrix and center of a set of points. pub fn cov_and_center

(pts: &[P]) -> (::OuterProductType, P) where P: Point, P::Vector: Outer, ::OuterProductType: Zero { let center = ::center(pts); let mut cov: ::OuterProductType = na::zero(); let normalizer: P::Real = na::convert(1.0 / (pts.len() as f64)); for p in pts.iter() { let cp = *p - center; cov = cov + na::outer(&cp, &(cp * normalizer)); } (cov, center) } /// Centers and reduces a set of data. /// /// Returns the covariance matrix, the center of the data, and a boolean that is `true` if the /// operation succeeded (otherwise, the returned value as valid, by the input points are left /// unchanged). pub fn center_reduce

(pts: &mut [P]) -> (::OuterProductType, P, bool) where P: Point, P::Vector: Vector + Outer, ::OuterProductType: Zero + Mul + Inverse + Copy + Debug { let (cov, center) = cov_and_center(pts); match na::inverse(&cov) { None => (cov, center, false), Some(icov) => { for pt in pts.iter_mut() { // FIXME: the `+ (-` is ugly but required until the trait reform is implemented in // rustc! *pt = icov * (*pt + (-*center.as_vector())); } (cov, center, true) } } }