extern crate num;
use matrix::Matrix;
use ops_inplace::VectorVectorOpsInPlace;
use math::Dimension;
use math::SumVec;
pub trait MeanVec<T> {
fn mean(&self) -> T;
}
macro_rules! mean_vec_impl {
($($t:ty)*) => ($(
impl MeanVec<$t> for Vec<$t> {
fn mean(&self) -> $t {
(&self[..]).mean()
}
}
impl MeanVec<$t> for [$t] {
fn mean(&self) -> $t {
let n = if self.len() == 0 { 1 as $t } else { self.len() as $t };
self.sum() / n
}
}
)*)
}
mean_vec_impl!{ usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
pub trait Mean<T> {
fn mean(&self, dim: Dimension) -> T;
}
macro_rules! mean_impl {
($($t:ty)*) => ($(
impl Mean<Vec<$t>> for Matrix<$t> {
fn mean(&self, dim: Dimension) -> Vec<$t> {
if self.rows() == 0 || self.cols() == 0 {
return vec![];
}
match dim {
Dimension::Column => {
let mut r: Vec<$t> = self.iter().take(self.cols()).cloned().collect();
for row in self.row_iter_at(1) {
r.iadd(row);
}
let n = self.rows() as $t;
for i in r.iter_mut() {
*i = *i / n;
}
r
}
Dimension::Row => {
let n = self.cols() as $t;
self.row_iter().map(|row| row.sum() / n).collect()
}
}
}
}
)*)
}
mean_impl!{ f32 f64 }
#[cfg(test)]
mod tests {
use super::*;
use matrix::*;
use math::Dimension;
#[test]
fn test_mean_vec_f32() {
let x: Vec<f32> = vec![1.0, 2.0, 3.0, 4.0];
assert_eq!(x.mean(), 2.5);
let a: Vec<f32> = Vec::new();
assert_eq!(a.mean(), 0.0);
let b = [1.0f32, 2.0, 3.0, 4.0];
assert_eq!(b.mean(), 2.5);
}
#[test]
fn test_mean_mat_f32() {
let a = Matrix::<f32>::new();
assert_eq!(a.mean(Dimension::Column), vec![]);
assert_eq!(a.mean(Dimension::Row), vec![]);
let b = mat![5.0, 6.0];
assert_eq!(b.mean(Dimension::Column), vec![5.0, 6.0]);
assert_eq!(b.mean(Dimension::Row), vec![5.5]);
let x = mat![
1.0, 2.0;
3.0, 4.0
];
assert_eq!(x.mean(Dimension::Column), vec![2.0, 3.0]);
assert_eq!(x.mean(Dimension::Row), vec![1.5, 3.5]);
}
}