

#ifndef __eigen_openma_Functors_h
#define __eigen_openma_Functors_h

#define OPENMA_EIGEN_VECTOROP_MEMBER_FUNCTOR(MEMBER,COST)                  \
  template <typename ResultType>                                        \
  struct openma_eigen_vectorop_member_##MEMBER {                           \
    EIGEN_EMPTY_STRUCT_CTOR(openma_eigen_vectorop_member_##MEMBER)         \
    typedef ResultType result_type;                                     \
    template<typename Scalar, int Size> struct Cost                     \
    { enum { value = COST }; };                                         \
    template<typename XprType>                                          \
    EIGEN_STRONG_INLINE ResultType operator()(const XprType& mat) const \
    { return mat.MEMBER(); } \
  };
  
// NOTE: The given cost is the upper bound: O(n*n) + addition + multiplication
OPENMA_EIGEN_VECTOROP_MEMBER_FUNCTOR(median, (Size*Size)*Eigen::NumTraits<Scalar>::ReadCost + Eigen::NumTraits<Scalar>::AddCost + Eigen::NumTraits<Scalar>::MulCost);

// NOTE: The detailed cost is the following:
// -  Computation of the mean: Size * AddCost + 1 * MulCost
//  - Difference of each element with the mean: Size * AddCost
//  - Computation of the squared sum: Size * AddCost + Size * MulCost
//  - Average: 1 * AddCost + 1 * MulCost
//  The total is then: (3 * Size + 1) * AddCost + (Size + 2) * MulCost
OPENMA_EIGEN_VECTOROP_MEMBER_FUNCTOR(std, (3*Size+1)*Eigen::NumTraits<Scalar>::MulCost + (Size+2)*Eigen::NumTraits<Scalar>::AddCost);

#endif // __eigen_openma_Functors_h