#ifndef NFL_PERMUT_HPP #define NFL_PERMUT_HPP #define PERMUT_LIMIT_UNROLL 1024 #include namespace nfl { namespace details { // meta-compilation of the bit-reversing permutation template struct r_loop { static constexpr size_t value = r_loop<(H << 1), degree, (R << 1) | (I & 1), (I >> 1)>::value; }; template struct r_loop { static constexpr size_t value = R; }; template struct r_set { template void operator()(value_type *y, value_type const *x) { r_set<2*I,2*J, degree>{}(y, x); r_set<2*I + 1,2*J, degree>{}(y, x); } }; template struct r_set { template void operator()(value_type *y, value_type const *x) { constexpr size_t r = r_loop<1, degree, 0u, I>::value; y[r] = x[I]; } }; template struct uint_value_t { using type = typename std::conditional< N <= std::numeric_limits::max(), uint8_t, typename std::conditional< N <= std::numeric_limits::max(), uint16_t, typename std::conditional< N <= std::numeric_limits::max(), uint32_t, uint64_t>::type >::type >::type; }; template struct permut_compute { using idx_type = typename uint_value_t::type; idx_type data_[degree]; permut_compute() { for (idx_type i = 0; i < degree; ++i) { idx_type ii = i; idx_type r = 0; for (idx_type h = 1; h < degree; h=h<<1) { r = (r << 1) | (ii & 1); ii >>= 1; } data_[i] = r; } } inline idx_type operator()(size_t i) const { assert(i < degree); return data_[i]; } }; template struct permut; template struct permut { template static inline void compute(V* y, V const* x) { r_set<0, 1, degree>{}(y, x); } }; template struct permut { static permut_compute P; template static inline void compute(V* y, V const* x) { for (size_t i = 0; i < degree; ++i) { y[i] = x[P(i)]; } } }; template permut_compute permut::P; } // details template struct permut: public details::permut { }; } // nfl #endif