#ifndef _NTPM_AI_MULT_H
#define _NTPM_AI_MULT_H

#include <arithmetic_iterators/arithmetic_iterator.h>

namespace NTPMai {

template <class T_M_IT, class T_V_IT>
class multiply_matrix_vector_iterator : public arithmetic_iterator
{
public:
    typedef multiply_matrix_vector_iterator<T_M_IT,T_V_IT> Self;
    typedef typename iterator_traits<T_M_IT>::value_type value_type;
    typedef typename iterator_traits<T_M_IT>::difference_type difference_type;
    typedef typename iterator_traits<T_M_IT>::pointer pointer;
    typedef typename iterator_traits<T_M_IT>::reference reference;
    typedef input_iterator_tag iterator_category;


    multiply_matrix_vector_iterator(T_M_IT _mit, T_V_IT _vit, int _ncols) :
	mit(_mit), mnext(mit), vit(_vit), ncols(_ncols) {}

    value_type operator *() {
	value_type acc = 0;
	T_V_IT vv = vit;
	mnext = mit;
	for(int i=0; i<ncols; ++i, ++vv, ++mnext)
	    acc += (*mnext) * (*vv);
	return acc;
    }

    Self &operator++() {
	if(mnext == mit)
	    advance(mnext, ncols);
	mit = mnext;
	return *this;
    }

    bool operator==(const multiply_matrix_vector_iterator &i) const {
	return mit==i.mit;
    }

private:
    T_M_IT mit, mnext;
    T_V_IT vit;
    int ncols;
};



// multiplies a matrix promise by a simple promise, returning a simple
// promise.
template <class T_MIT, class T_VIT>
Promise<multiply_matrix_vector_iterator<MatrixPromise<T_MIT>::const_iterator,
					Promise<T_VIT>::const_iterator> >
multiply_matrix_vector(MatrixPromise<T_MIT> mpromise, Promise<T_VIT> vpromise)
{
    typedef multiply_matrix_vector_iterator<MatrixPromise<T_MIT>::const_iterator,
	                                     Promise<T_VIT>::const_iterator>
	                                   MVIT;
    MVIT begin(mpromise.begin(),vpromise.begin(),mpromise.ncols());
    MVIT end(mpromise.end(),vpromise.end(),mpromise.ncols());
    return Promise<MVIT>(begin, end);
}



}

#endif // _NTPM_AI_MULT_H
