#ifndef _NTPM_AI_BINARYOP_H
#define _NTPM_AI_BINARYOP_H

#include <arithmetic_iterators/arithmetic_iterator.h>

namespace NTPMai {


template <class T_V1_IT, class T_V2_IT, class BINOP>
class binary_op_iterator : public arithmetic_iterator
{
public:
    typedef binary_op_iterator<T_V1_IT,T_V2_IT,BINOP> Self;
    typedef typename BINOP::result_type value_type;
    typedef typename iterator_traits<T_V1_IT>::difference_type difference_type;
    typedef value_type *pointer;
    typedef value_type &reference;
    typedef forward_iterator_tag iterator_category;

    binary_op_iterator() {}
    binary_op_iterator(T_V1_IT _it1, T_V2_IT _it2) : it1(_it1), it2(_it2) {}
    value_type operator*() {
	BINOP op;
	return op(typename BINOP::first_argument_type(*it1),
		  typename BINOP::second_argument_type(*it2));
    }
    Self &operator++() { ++it1; ++it2; return *this; }
    bool operator==(const Self &i) const {
	return (it1==i.it1) && (it2==i.it2);
    }

    T_V1_IT it1;
    T_V2_IT it2;
};

template <class T_P1, class T_P2, class BINOP>
struct BINOP_Deffer{
    typedef Promise<binary_op_iterator<typename T_P1::const_iterator,
				       typename T_P2::const_iterator,
				       BINOP> > V;
};


// handles binary operations on all promises. returns a generic promise.
template <class T_PROMISE1, class T_PROMISE2, class BINOP>
typename BINOP_Deffer<T_PROMISE1,T_PROMISE2,BINOP>::V
make_binary_op_promise(T_PROMISE1 p1, T_PROMISE2 p2, const BINOP &)
{
    typedef binary_op_iterator<typename T_PROMISE1::const_iterator,
 	                       typename T_PROMISE2::const_iterator,
	                       BINOP> BINOPIT;
    BINOPIT begin(p1.begin(), p2.begin());
    BINOPIT end(p1.end(), p2.end());
    return Promise<BINOPIT>(begin,end);
}


}

#endif // _NTPM_AI_BINARYOP_H
