164 lines
4.6 KiB
C++
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
|