1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#![doc="Functions for vectors

For many operations below, 
it doesn't matter whether the vector is a column vector
or a row vector. The stride is always one in both cases.
"]


// std imports

// external imports
use num::traits::{One, Zero};


// local imports
use algebra::structure::{MagmaBase, CommutativeMonoidAddPartial, CommutativeRingPartial};
use matrix::matrix::Matrix;
use matrix::traits::{Shape, MatrixBuffer};

pub struct VecIterator<T:MagmaBase> {
    ptr : *const T,
    pos : usize,
    len : usize
}

impl <T:MagmaBase> VecIterator<T> {
    pub fn new (ptr: *const T, len : usize)->VecIterator<T>{
        VecIterator{ptr: ptr, pos : 0, len : len}
    } 
}

/// Implementation of iterator trait
impl<T:MagmaBase> Iterator for VecIterator<T>{
    type Item = T;
    /// Next element in the vector
    fn next(&mut self)->Option<T> {
        if self.pos == self.len {
            return None;
        }
        let offset = self.pos;
        self.pos += 1;
        Some(unsafe{*self.ptr.offset(offset as isize)})
    }

    /// Returns the upper and lower bound on the remaining length
    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) { 
        let n = self.len  - self.pos;
        (n, Some(n)) 
    }    
} 

/// Constructs a vector iterator for a matrix with the
/// assumption that the matrix is indeed a vector
pub fn vec_iter<T:MagmaBase>(m : &Matrix<T>) -> VecIterator<T> {
    assert!(m.is_vector());
    VecIterator::new(m.as_ptr(), m.num_cells())
}

/// Computes the sum of entries in vector v
pub fn vec_reduce_sum<T:CommutativeMonoidAddPartial>(v : &Matrix<T>) -> T{
    let mut result : T = Zero::zero();
    for entry in vec_iter(v){
        result = result + entry;
    }
    result
}


/// Computes the product of entries in vector v
pub fn vec_reduce_product<T:CommutativeRingPartial>(v : &Matrix<T>) -> T{
    let mut result : T = One::one();
    for entry in vec_iter(v){
        result = result * entry;
    }
    result
}


/******************************************************
 *
 *   Unit tests follow.
 *
 *******************************************************/
#[cfg(test)]
mod test{

    use super::*;
    use matrix::traits::*;
    use matrix::constructors::*;

    #[test]
    fn test_vec_iter(){
        // A column vector
        let v = vector_i64(&[1, 2, 3, 4]);
        assert!(v.is_col());
        let mut i = vec_iter(&v);
        assert_eq!(i.next(), Some(1));
        assert_eq!(i.next(), Some(2));
        assert_eq!(i.next(), Some(3));
        assert_eq!(i.next(), Some(4));
        assert_eq!(i.next(), None);
        // A row vector
        let v = v.transpose();
        assert!(v.is_row());
        let mut i = vec_iter(&v);
        assert_eq!(i.next(), Some(1));
        assert_eq!(i.next(), Some(2));
        assert_eq!(i.next(), Some(3));
        assert_eq!(i.next(), Some(4));
        assert_eq!(i.next(), None);
    }

    #[test]
    fn test_vec_reduce_sum(){
        // A column vector
        let v = vector_i64(&[1, 2, 3, 4]);
        assert_eq!(vec_reduce_sum(&v), 10);
        // A row vector
        let v = v.transpose();
        assert_eq!(vec_reduce_sum(&v), 10);
    }

    #[test]
    fn test_vec_reduce_prod(){
        // A column vector
        let v = vector_i64(&[1, 2, 3, 4]);
        assert_eq!(vec_reduce_product(&v), 24);
        // A row vector
        let v = v.transpose();
        assert_eq!(vec_reduce_product(&v), 24);
    }

}