rust-numpy 0.1.0

A row version of a convinient rust-numpy library which target is to dublicate functionality of well known python library 'numpy'.
Documentation
use crate::{Dot};
use crate::Init;
use crate::matrix::Matrix;

use impl_ops::*;
use std::ops;


pub struct Vector {
    array : Vec<f64>,
}


impl Vector {

    #[inline]
    pub fn from(array: Vec<f64>) -> Vector {
        Vector { array }
    }

    #[inline]
    pub fn empty() -> Vector {
        Vector { array : Vec::new() }
    }

    #[inline]
    pub fn iter(&self) -> std::slice::Iter<'_, f64> {
        self.array.iter()
    }
    
    #[inline]
    pub fn iter_mut(&mut self) -> std::slice::IterMut<'_,f64> {
        self.array.iter_mut()
    }

    #[inline]
    pub fn len(&self) -> usize {
        self.array.len()
    }

    pub fn into_vec(&self) -> Vec<f64> {
        self.array.clone()
    }

    pub fn to_vec(&self) -> &Vec<f64> {
        &self.array
    }
}



impl Init for Vector {
    type Output = Vector;
    type Size = usize;

    fn init(value: f64, size: Self::Size) -> Self::Output {
        Vector { array : vec![value; size] }
    }

    fn init_func<F>(func: F, size: Self::Size) -> Self::Output
        where F: Fn(Self::Size) -> f64 {
        Vector {
            array : (0..size).map(func).collect(),
        }
    }
}


impl std::clone::Clone for Vector {

    fn clone(&self) -> Self {
        Vector { array : self.array.clone() }
    }
}


impl Dot<Vector> for Vector {
    type Output = f64;

    fn dot(&self, rhs: &Vector) -> Self::Output {
        assert_eq!(self.len(), rhs.len());

        self.array.iter()
            .zip(rhs.array.iter())
            .map(|(x,y)| x*y)
            .sum()
    }
}


impl Dot<Matrix> for Vector {
    type Output = Vector;

    fn dot(&self, rhs: &Matrix) -> Self::Output {
        // xA = (A^T x^T)^T && x^T = x
        rhs.transpose().dot(self)
    }
}


impl std::ops::Index<usize> for Vector {
    type Output = f64;

    #[inline]
    fn index(&self, index: usize) -> &Self::Output {
        &self.array[index]
    }
}


impl std::ops::IndexMut<usize> for Vector {
    #[inline]
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        &mut self.array[index]
    }
}


impl std::ops::Neg for Vector {
    type Output = Vector;

    // moves self !!!
    fn neg(self) -> Self::Output {
        Vector::from(self.iter().map(|x| -x).collect())
    }
}

impl std::ops::Neg for &Vector {
    type Output = Vector;
    fn neg(self) -> Self::Output {
        Vector::from(self.iter().map(|x| -x).collect())
    }
}


macro_rules! impl_operator {
    ( $($op:tt),* ) => {
        $(
        impl_op_ex!($op |a: &Vector, b: &Vector| -> Vector {
            Vector::from(a.iter()
                .zip(b.iter())
                .map(|(x,y)| x $op y)
                .collect()
            )
        });

        impl_op_ex!($op |a: &Vector, k: &f64| -> Vector {
            Vector::from(a.iter()
                .map(|x| x $op k)
                .collect()
            )
        });
        )*
    }
}


macro_rules! impl_operator_assign {
    ( $($op:tt),* ) => {
        $(
        impl_op_ex!($op |a: &mut Vector, b: &Vector| {
            a.iter_mut().zip(b.iter())
                .for_each(|(x,y)| *x $op y);
        });

        impl_op_ex!($op |a: &mut Vector, k: &f64| {
            a.iter_mut().for_each(|x| *x $op k);
        });
        )*
    }
}

impl_operator![+, -, *, /];
impl_operator_assign![+=, -=, *=, /=];