pfor/src/pfor/strategies/loopunrolling.h

54 lines
1.5 KiB
C++

#ifndef PFOR_PFOR_STRATEGIES_LOOPUNROLLING_H
#define PFOR_PFOR_STRATEGIES_LOOPUNROLLING_H
#include <array>
#include <cstdint>
#include <utility>
namespace pfor {
template<std::size_t n>
struct ForLoopUnrolling {
template<bool par, typename E, typename Range>
struct Template {
using Index = typename Range::ValueType;
using Indices = std::array<Index, n>;
static void eval(Range const& range, E e) {
constexpr auto indexSeq = std::make_index_sequence<n>();
Index const count = (range.end() - range.begin() + (range.step()-(range.step() > 0? +1 : -1)))/range.step();
Index const lEnd = count/n;
for(Index it{}; it != lEnd; ++it)
evalUnroll(e, indexSeq, makeIndices(indexSeq, it));
evalUnrollRemainder(e, indexSeq, makeIndices(indexSeq, lEnd), range.end());
}
private:
template<std::size_t... indices>
static void evalUnroll(E& e, std::index_sequence<indices...>, Indices const& i) {
using Expander = int[];
static_cast<void>(Expander{(e[i[indices]], 0)...});
}
template<std::size_t index, std::size_t... indices>
static void evalUnrollRemainder(E& e, std::index_sequence<index, indices...>, Indices const& i, Index const& end) {
if(i[index] == end) return;
e[i[index]];
evalUnrollRemainder(e, std::index_sequence<indices...>{}, i, end);
}
static void evalUnrollRemainder(E&, std::index_sequence<>, Indices const&, Index const&) {}
template<std::size_t... indices>
static Indices makeIndices(std::index_sequence<indices...>, Index i) {
return {(Index{n}*i+Index{indices})...};
}
};
};
}
#endif