Commit 25ff5a6b authored by Jakub Klinkovský's avatar Jakub Klinkovský
Browse files

Simplified implementation of staticFor and unrolledFor

parent addfae54
Loading
Loading
Loading
Loading
+30 −29
Original line number Diff line number Diff line
@@ -17,6 +17,13 @@ namespace TNL {
namespace Algorithms {

namespace detail {

// special dispatch for `begin >= end` (i.e. empty loop)
template< typename Index, Index begin, Index end,  typename Func >
constexpr std::enable_if_t< (begin >= end) >
static_for_dispatch( Func &&f )
{}

#if __cplusplus >= 201703L

// C++17 version using fold expression
@@ -26,49 +33,43 @@ constexpr void static_for_impl( Func &&f, std::integer_sequence< Index, idx... >
   ( f( std::integral_constant<Index, begin + idx>{} ), ... );
}

#else

// C++14 version using recursion and variadic pack
template< typename Index, Index begin,  typename Func, Index idx >
constexpr void static_for_impl( Func &&f, std::integer_sequence< Index, idx > )
{
   f( std::integral_constant<Index, begin + idx>{} );
}

template< typename Index, Index begin,  typename Func, Index idx, Index... indices >
// WTF why, clang, why...
//constexpr void
constexpr std::enable_if_t< sizeof...(indices) >= 1 >
static_for_impl( Func &&f, std::integer_sequence< Index, idx, indices... > )
// general dispatch for `begin < end`
template< typename Index, Index begin, Index end,  typename Func >
constexpr std::enable_if_t< (begin < end) >
static_for_dispatch( Func &&f )
{
   static_for_impl< Index, begin >(
         std::forward< Func >( f ),
         std::integer_sequence< Index, idx >{}
   );
   static_for_impl< Index, begin >(
         std::forward< Func >( f ),
         std::integer_sequence< Index, indices... >{}
         std::make_integer_sequence< Index, end - begin >{}
   );
}

#endif
#else

// general specialization for `begin < end`
// C++14 version using recursive folding
// (We avoid manual folding with std::integer_sequence, because it cannot be
// empty, so it would be rather weird. Folding is done by bisection to limit
// the recursion depth.)

// special dispatch for 1 iteration
template< typename Index, Index begin, Index end,  typename Func >
constexpr std::enable_if_t< (begin < end) >
constexpr std::enable_if_t< (begin < end && end - begin == 1) >
static_for_dispatch( Func &&f )
{
   static_for_impl< Index, begin >(
         std::forward< Func >( f ),
         std::make_integer_sequence< Index, end - begin >{}
   );
   f( std::integral_constant< Index, begin >{} );
}

// specialization for `begin >= end` (i.e. empty loop)
// general dispatch for at least 2 iterations
template< typename Index, Index begin, Index end,  typename Func >
constexpr std::enable_if_t< (begin >= end) >
constexpr std::enable_if_t< (begin < end && end - begin >= 2) >
static_for_dispatch( Func &&f )
{}
{
   constexpr Index mid = begin + (end - begin) / 2;
   static_for_dispatch< Index, begin, mid >( std::forward< Func >( f ) );
   static_for_dispatch< Index, mid, end >( std::forward< Func >( f ) );
}

#endif

} // namespace detail

+17 −27
Original line number Diff line number Diff line
@@ -17,49 +17,39 @@ namespace Algorithms {

namespace detail {

template< typename Index, Index begin, Index end >
struct UnrolledFor
{
   static_assert( begin < end, "internal error - wrong iteration index for UnrolledFor" );
// special dispatch for empty loop
template< typename Index, Index begin, Index end, Index unrollFactor,  typename Func >
constexpr std::enable_if_t< (begin >= end) >
unrolled_for_dispatch( Func&& f )
{}

   template< typename Func >
   static constexpr void exec( Func&& f )
// special dispatch for 1 iteration
template< typename Index, Index begin, Index end, Index unrollFactor,  typename Func >
constexpr std::enable_if_t< (begin < end && end - begin == 1) >
unrolled_for_dispatch( Func&& f )
{
   f( begin );
      UnrolledFor< Index, begin + 1, end >::exec( std::forward< Func >( f ) );
}
};

template< typename Index, Index end >
struct UnrolledFor< Index, end, end >
{
   template< typename Func >
   static constexpr void exec( Func&& f ) {}
};

// specialization for short loops - unrolling
// specialization for unrolling short loops (at least 2, but at most unrollFactor iterations)
template< typename Index, Index begin, Index end, Index unrollFactor,  typename Func >
constexpr std::enable_if_t< (begin < end && end - begin <= unrollFactor) >
constexpr std::enable_if_t< (begin < end && end - begin >= 2 && end - begin <= unrollFactor) >
unrolled_for_dispatch( Func&& f )
{
   UnrolledFor< Index, begin, end >::exec( std::forward< Func >( f ) );
   constexpr Index mid = begin + (end - begin) / 2;
   unrolled_for_dispatch< Index, begin, mid, unrollFactor >( std::forward< Func >( f ) );
   unrolled_for_dispatch< Index, mid, end, unrollFactor >( std::forward< Func >( f ) );
}

// specialization for long loops - normal for-loop
template< typename Index, Index begin, Index end, Index unrollFactor,  typename Func >
constexpr std::enable_if_t< (begin < end && end - begin > unrollFactor) >
constexpr std::enable_if_t< (begin < end && end - begin > 1 && end - begin > unrollFactor) >
unrolled_for_dispatch( Func&& f )
{
   for( Index i = begin; i < end; i++ )
      f( i );
}

// specialization for empty loop
template< typename Index, Index begin, Index end, Index unrollFactor,  typename Func >
constexpr std::enable_if_t< (begin >= end) >
unrolled_for_dispatch( Func&& f )
{}

} // namespace detail

/**