diff --git a/sprout/index_tuple.hpp b/sprout/index_tuple.hpp index ca0a1142..aacc7053 100644 --- a/sprout/index_tuple.hpp +++ b/sprout/index_tuple.hpp @@ -2,6 +2,7 @@ #define SPROUT_INDEX_TUPLE_HPP #include +#include #include namespace sprout { @@ -19,45 +20,110 @@ namespace sprout { // // index_range // - template< - sprout::index_t First, - sprout::index_t Last, - sprout::index_t Step = 1, - typename Acc = sprout::index_tuple<>, - bool Break = (First >= Last) - > - struct index_range { - typedef Acc type; - }; - template< - sprout::index_t First, - sprout::index_t Last, - sprout::index_t Step, - sprout::index_t... Indexes - > - struct index_range, false> - : public sprout::index_range > + namespace detail { + template + struct index_range_next; + template + struct index_range_next, Next> { + public: + typedef sprout::index_tuple type; + }; + + template + struct index_range_next2; + template + struct index_range_next2, Next, Tail> { + public: + typedef sprout::index_tuple type; + }; + + template + struct index_range_impl; + template + struct index_range_impl< + First, + Step, + N, + typename std::enable_if<(N == 0)>::type + > { + public: + typedef sprout::index_tuple<> type; + }; + template + struct index_range_impl< + First, + Step, + N, + typename std::enable_if<(N == 1)>::type + > { + public: + typedef sprout::index_tuple type; + }; + template + struct index_range_impl< + First, + Step, + N, + typename std::enable_if<(N > 1 && N % 2 == 0)>::type + > + : public sprout::detail::index_range_next< + typename sprout::detail::index_range_impl::type, + First + N / 2 * Step + > + {}; + template + struct index_range_impl< + First, + Step, + N, + typename std::enable_if<(N > 1 && N % 2 == 1)>::type + > + : public sprout::detail::index_range_next2< + typename sprout::detail::index_range_impl::type, + First + N / 2 * Step, + First + (N - 1) * Step + > + {}; + } // namespace detail + template + struct index_range + : public sprout::detail::index_range_impl< + First, + Step, + ((Last - First) + (Step - 1)) / Step + > {}; // // index_n // + namespace detail { + template< + sprout::index_t I, + std::size_t N, + typename Acc, + bool Break = (N == 0) + > + struct index_n_impl { + public: + typedef Acc type; + }; + template< + sprout::index_t I, + std::size_t N, + sprout::index_t... Indexes + > + struct index_n_impl, false> + : public sprout::detail::index_n_impl > + {}; + } // namespace detail template< sprout::index_t I, - sprout::index_t N, - typename Acc = sprout::index_tuple<>, - bool Break = (N == 0) + std::size_t N, + typename Acc = sprout::index_tuple<> > - struct index_n { - typedef Acc type; - }; - template< - sprout::index_t I, - sprout::index_t N, - sprout::index_t... Indexes - > - struct index_n, false> - : public sprout::index_n > + struct index_n + : public sprout::detail::index_n_impl {}; } // namespace sprout