pfor/src/pfor/index/operators.h

135 lines
4.1 KiB
C++

#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<typename Rhs, std::enable_if_t<isIndex<Rhs>>* = nullptr>
inline decltype(auto) operator+(Rhs&& rhs) {
return std::forward<Rhs>(rhs);
}
/**
* @brief operator-
*/
template<typename Rhs, std::enable_if_t<isIndex<Rhs> and not isLinear<std::decay_t<Rhs>>>* = nullptr>
inline decltype(auto) operator-(Rhs&&) {
using RhsT = std::decay_t<Rhs>;
using RProp = typename RhsT::Properties;
using Properties = ComputeProperties<op::Minus, RProp, RProp>;
return IndexImpl<Pack<op::Minus, RhsT>, Properties>{};
}
template<typename Rhs, std::enable_if_t<isIndex<Rhs> and isLinear<std::decay_t<Rhs>>>* = nullptr>
inline decltype(auto) operator-(Rhs&&) {
using RhsT = std::decay_t<Rhs>;
return LinearIndex<-linearSlope<RhsT>, -linearOffset<RhsT>>{};
}
/**
* @brief operator+
*/
template<
typename Lhs, typename Rhs, std::enable_if_t<
allIndex<Lhs, Rhs> and (not isLinear<std::decay_t<Lhs>> or not isLinear<std::decay_t<Rhs>>)
>* = nullptr
>
inline decltype(auto) operator+(Lhs&&, Rhs&&) {
using LhsT = std::decay_t<Lhs>;
using RhsT = std::decay_t<Rhs>;
using LProp = typename LhsT::Properties;
using RProp = typename RhsT::Properties;
using Properties = ComputeProperties<op::Addition, LProp, RProp>;
return IndexImpl<Pack<op::Addition, LhsT, RhsT>, Properties>{};
}
template<
typename Lhs, typename Rhs, std::enable_if_t<
allIndex<Lhs, Rhs> and (isLinear<std::decay_t<Lhs>> and isLinear<std::decay_t<Rhs>>)
>* = nullptr
>
inline decltype(auto) operator+(Lhs&&, Rhs&&) {
using LhsT = std::decay_t<Lhs>;
using RhsT = std::decay_t<Rhs>;
return LinearIndex<linearSlope<LhsT> + linearSlope<RhsT>, linearOffset<LhsT> + linearOffset<RhsT>>{};
}
/**
* @brief operator-
*/
template<
typename Lhs, typename Rhs, std::enable_if_t<
allIndex<Lhs, Rhs> and (not isLinear<std::decay_t<Lhs>> or not isLinear<std::decay_t<Rhs>>)
>* = nullptr
>
inline decltype(auto) operator-(Lhs&&, Rhs&&) {
using LhsT = std::decay_t<Lhs>;
using RhsT = std::decay_t<Rhs>;
using LProp = typename LhsT::Properties;
using RProp = typename RhsT::Properties;
using Properties = ComputeProperties<op::Subtraction, LProp, RProp>;
return IndexImpl<Pack<op::Subtraction, LhsT, RhsT>, Properties>{};
}
template<
typename Lhs, typename Rhs, std::enable_if_t<
allIndex<Lhs, Rhs> and (isLinear<std::decay_t<Lhs>> and isLinear<std::decay_t<Rhs>>)
>* = nullptr
>
inline decltype(auto) operator-(Lhs&&, Rhs&&) {
using LhsT = std::decay_t<Lhs>;
using RhsT = std::decay_t<Rhs>;
return LinearIndex<linearSlope<LhsT> - linearSlope<RhsT>, linearOffset<LhsT> - linearOffset<RhsT>>{};
}
/**
* @brief operator*
*/
template<
typename Lhs, typename Rhs, std::enable_if_t<
allIndex<Lhs, Rhs> and (
not isLinear<std::decay_t<Lhs>> or not isLinear<std::decay_t<Rhs>> or
(not isConstant<std::decay_t<Lhs>> and not isConstant<std::decay_t<Rhs>>)
)
>* = nullptr
>
inline decltype(auto) operator*(Lhs&&, Rhs&&) {
using LhsT = std::decay_t<Lhs>;
using RhsT = std::decay_t<Rhs>;
using LProp = typename LhsT::Properties;
using RProp = typename RhsT::Properties;
using Properties = ComputeProperties<op::Multiplication, LProp, RProp>;
return IndexImpl<Pack<op::Multiplication, LhsT, RhsT>, Properties>{};
}
template<
typename Lhs, typename Rhs, std::enable_if_t<
allIndex<Lhs, Rhs> and (
isLinear<std::decay_t<Lhs>> and isLinear<std::decay_t<Rhs>> and
(isConstant<std::decay_t<Lhs>> or isConstant<std::decay_t<Rhs>>)
)
>* = nullptr
>
inline decltype(auto) operator*(Lhs&&, Rhs&&) {
using LhsT = std::decay_t<Lhs>;
using RhsT = std::decay_t<Rhs>;
constexpr auto slope = linearSlope<LhsT> + linearSlope<RhsT>; // because one is null
constexpr auto scalar = linearSlope<LhsT>? linearOffset<RhsT>:linearOffset<LhsT>;
constexpr auto offset = linearOffset<LhsT> * linearOffset<RhsT>;
return LinearIndex<scalar * slope, offset>{};
}
}
}
#endif