#ifndef PFOR_PFOR_INDEX_OPERATORS_H #define PFOR_PFOR_INDEX_OPERATORS_H #include "index.h" #include "op.h" #include "traits.h" #include "properties.h" namespace pfor { namespace index { /** * @brief operator+ */ template>* = nullptr> inline decltype(auto) operator+(Rhs&& rhs) { return std::forward(rhs); } /** * @brief operator- */ template and not isLinear>>* = nullptr> inline decltype(auto) operator-(Rhs&&) { using RhsT = std::decay_t; using RProp = typename RhsT::Properties; using Properties = ComputeProperties; return IndexImpl, Properties>{}; } template and isLinear>>* = nullptr> inline decltype(auto) operator-(Rhs&&) { using RhsT = std::decay_t; return LinearIndex<-linearSlope, -linearOffset>{}; } /** * @brief operator+ */ template< typename Lhs, typename Rhs, std::enable_if_t< allIndex and (not isLinear> or not isLinear>) >* = nullptr > inline decltype(auto) operator+(Lhs&&, Rhs&&) { using LhsT = std::decay_t; using RhsT = std::decay_t; using LProp = typename LhsT::Properties; using RProp = typename RhsT::Properties; using Properties = ComputeProperties; return IndexImpl, Properties>{}; } template< typename Lhs, typename Rhs, std::enable_if_t< allIndex and (isLinear> and isLinear>) >* = nullptr > inline decltype(auto) operator+(Lhs&&, Rhs&&) { using LhsT = std::decay_t; using RhsT = std::decay_t; return LinearIndex + linearSlope, linearOffset + linearOffset>{}; } /** * @brief operator- */ template< typename Lhs, typename Rhs, std::enable_if_t< allIndex and (not isLinear> or not isLinear>) >* = nullptr > inline decltype(auto) operator-(Lhs&&, Rhs&&) { using LhsT = std::decay_t; using RhsT = std::decay_t; using LProp = typename LhsT::Properties; using RProp = typename RhsT::Properties; using Properties = ComputeProperties; return IndexImpl, Properties>{}; } template< typename Lhs, typename Rhs, std::enable_if_t< allIndex and (isLinear> and isLinear>) >* = nullptr > inline decltype(auto) operator-(Lhs&&, Rhs&&) { using LhsT = std::decay_t; using RhsT = std::decay_t; return LinearIndex - linearSlope, linearOffset - linearOffset>{}; } /** * @brief operator* */ template< typename Lhs, typename Rhs, std::enable_if_t< allIndex and ( not isLinear> or not isLinear> or (not isConstant> and not isConstant>) ) >* = nullptr > inline decltype(auto) operator*(Lhs&&, Rhs&&) { using LhsT = std::decay_t; using RhsT = std::decay_t; using LProp = typename LhsT::Properties; using RProp = typename RhsT::Properties; using Properties = ComputeProperties; return IndexImpl, Properties>{}; } template< typename Lhs, typename Rhs, std::enable_if_t< allIndex and ( isLinear> and isLinear> and (isConstant> or isConstant>) ) >* = nullptr > inline decltype(auto) operator*(Lhs&&, Rhs&&) { using LhsT = std::decay_t; using RhsT = std::decay_t; constexpr auto slope = linearSlope + linearSlope; // because one is null constexpr auto scalar = linearSlope? linearOffset:linearOffset; constexpr auto offset = linearOffset * linearOffset; return LinearIndex{}; } } } #endif