pfor/src/pfor/expression/algorithm.h

164 lines
4.6 KiB
C++

#ifndef PFOR_PFOR_EXPRESSION_ALGORITHM_H
#define PFOR_PFOR_EXPRESSION_ALGORITHM_H
#include "access.h"
#include "expression.h"
#include "operandtag.h"
#include "../mp/pack.h"
#include "../mp/meta.h"
namespace pfor {
namespace expr {
/**
* @brief returns a pack of sub expressions
*/
template<typename> struct SplitCommaImpl;
template<typename... Ts>
struct SplitCommaImpl<Expression<op::Comma, Ts...>> {
using type = Pack<Ts...>;
};
template<typename Op, typename... Ts>
struct SplitCommaImpl<Expression<Op, Ts...>> {
using type = Pack<Expression<Op, Ts...>>;
};
template<typename E>
using SplitComma = typename SplitCommaImpl<E>::type;
/**
* @brief returns a comma separated expression from pack
*/
template<typename> struct MergeCommaImpl;
template<typename... Ts>
struct MergeCommaImpl<Pack<Ts...>> {
using type = Expression<op::Comma, Ts...>;
};
template<typename T>
struct MergeCommaImpl<Pack<T>> {
using type = T;
};
template<typename P>
using MergeComma = typename MergeCommaImpl<P>::type;
/**
* @brief returns the worst access (write being worse than read)
*/
template<Access...> struct WorstAccess;
template<Access access, Access... accesses>
struct WorstAccess<access, accesses...> {
static constexpr Access value = (access == Access::write? Access::write:WorstAccess<accesses...>::value);
};
template<Access access>
struct WorstAccess<access> {
static constexpr Access value = access;
};
/**
*/
template<typename, typename> struct IncludeTagsImpl;
template<typename IncludeId, typename Id, Access access, typename Index, typename... Ts>
struct IncludeTagsImpl<IncludeId, Pack<OperandTag<Id, access, Index>, Ts...>> {
using trail = typename IncludeTagsImpl<IncludeId, Pack<Ts...>>::type;
using trailit = typename IncludeTagsImpl<IncludeId, Pack<Ts...>>::indices;
using type = pfor::If<std::is_same<IncludeId, Id>{}, PackPrepend<trail, OperandTag<Id, access, Index>>, trail>;
using indices = pfor::If<std::is_same<IncludeId, Id>{}, PackPrepend<trailit, Index>, trailit>;
};
template<typename IncludeId>
struct IncludeTagsImpl<IncludeId, Pack<>> {
using type = Pack<>;
using indices = Pack<>;
};
template<typename IncludeId, typename Tags>
using IncludeTags = typename IncludeTagsImpl<IncludeId, Tags>::type;
/**
*/
template<typename, typename> struct ExcludeTagsImpl;
template<typename ExcludeId, typename Id, Access access, typename Index, typename... Ts>
struct ExcludeTagsImpl<ExcludeId, Pack<OperandTag<Id, access, Index>, Ts...>> {
using trail = typename ExcludeTagsImpl<ExcludeId, Pack<Ts...>>::type;
using type = pfor::If<not std::is_same<ExcludeId, Id>{}, PackPrepend<trail, OperandTag<Id, access, Index>>, trail>;
};
template<typename ExcludeId>
struct ExcludeTagsImpl<ExcludeId, Pack<>> {
using type = Pack<>;
};
template<typename ExcludeId, typename Tags>
using ExcludeTags = typename ExcludeTagsImpl<ExcludeId, Tags>::type;
/**
*/
template<typename> struct CountWrite;
template<typename Id, Access access, typename Index, typename... Ts>
struct CountWrite<Pack<OperandTag<Id, access, Index>, Ts...>> {
static constexpr std::size_t value = (access == Access::write? 1:0) + CountWrite<Pack<Ts...>>::value;
};
template<>
struct CountWrite<Pack<>> {
static constexpr std::size_t value = 0;
};
template<typename P>
constexpr std::size_t countWrite = CountWrite<P>::value;
/**
*/
template<typename, Access> struct FilterOperandTagsImpl;
template<typename Id, Access access, typename Index, typename... Ts, Access accessReq>
struct FilterOperandTagsImpl<Pack<OperandTag<Id, access, Index>, Ts...>, accessReq> {
using trail = typename FilterOperandTagsImpl<Pack<Ts...>, accessReq>::type;
using type = pfor::If<access == accessReq, PackPrepend<trail, OperandTag<Id, access, Index>>, trail>;
};
template<Access access, typename Index, typename... Ts, Access accessReq>
struct FilterOperandTagsImpl<Pack<OperandTag<IgnoredId, access, Index>, Ts...>, accessReq> {
using type = typename FilterOperandTagsImpl<Pack<Ts...>, accessReq>::type;
};
template<Access access>
struct FilterOperandTagsImpl<Pack<>, access> {
using type = Pack<>;
};
template<typename E, Access access>
using FilterOperandTags = typename FilterOperandTagsImpl<E, access>::type;
/**
*/
template<typename> struct IndicesFromOperandTagsImpl;
template<typename Id, Access access, typename Index, typename... Ts>
struct IndicesFromOperandTagsImpl<Pack<OperandTag<Id, access, Index>, Ts...>> {
using type = PackPrepend<typename IndicesFromOperandTagsImpl<Pack<Ts...>>::type, Index>;
};
template<>
struct IndicesFromOperandTagsImpl<Pack<>> {
using type = Pack<>;
};
template<typename P>
using IndicesFromOperandTags = typename IndicesFromOperandTagsImpl<P>::type;
}
}
#endif