54 lines
1.5 KiB
C++
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
|