File indexing completed on 2025-01-18 09:38:02
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_HANA_CYCLE_HPP
0011 #define BOOST_HANA_CYCLE_HPP
0012
0013 #include <boost/hana/fwd/cycle.hpp>
0014
0015 #include <boost/hana/at.hpp>
0016 #include <boost/hana/concat.hpp>
0017 #include <boost/hana/concept/integral_constant.hpp>
0018 #include <boost/hana/concept/monad_plus.hpp>
0019 #include <boost/hana/concept/sequence.hpp>
0020 #include <boost/hana/config.hpp>
0021 #include <boost/hana/core/dispatch.hpp>
0022 #include <boost/hana/core/make.hpp>
0023 #include <boost/hana/detail/array.hpp>
0024 #include <boost/hana/empty.hpp>
0025 #include <boost/hana/length.hpp>
0026
0027 #include <cstddef>
0028 #include <utility>
0029
0030
0031 namespace boost { namespace hana {
0032
0033 template <typename Xs, typename N>
0034 constexpr auto cycle_t::operator()(Xs&& xs, N const& n) const {
0035 using M = typename hana::tag_of<Xs>::type;
0036 using Cycle = BOOST_HANA_DISPATCH_IF(cycle_impl<M>,
0037 hana::MonadPlus<M>::value
0038 );
0039
0040 #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
0041 static_assert(hana::MonadPlus<M>::value,
0042 "hana::cycle(xs, n) requires 'xs' to be a MonadPlus");
0043
0044 static_assert(hana::IntegralConstant<N>::value,
0045 "hana::cycle(xs, n) requires 'n' to be an IntegralConstant");
0046 #endif
0047
0048 static_assert(N::value >= 0,
0049 "hana::cycle(xs, n) requires 'n' to be non-negative");
0050
0051 return Cycle::apply(static_cast<Xs&&>(xs), n);
0052 }
0053
0054
0055 namespace detail {
0056 template <typename M, std::size_t n, bool = n % 2 == 0>
0057 struct cycle_helper;
0058
0059 template <typename M>
0060 struct cycle_helper<M, 0, true> {
0061 template <typename Xs>
0062 static constexpr auto apply(Xs const&)
0063 { return hana::empty<M>(); }
0064 };
0065
0066 template <typename M, std::size_t n>
0067 struct cycle_helper<M, n, true> {
0068 template <typename Xs>
0069 static constexpr auto apply(Xs const& xs)
0070 { return cycle_helper<M, n/2>::apply(hana::concat(xs, xs)); }
0071 };
0072
0073 template <typename M, std::size_t n>
0074 struct cycle_helper<M, n, false> {
0075 template <typename Xs>
0076 static constexpr auto apply(Xs const& xs)
0077 { return hana::concat(xs, cycle_helper<M, n-1>::apply(xs)); }
0078 };
0079 }
0080
0081 template <typename M, bool condition>
0082 struct cycle_impl<M, when<condition>> : default_ {
0083 template <typename Xs, typename N>
0084 static constexpr auto apply(Xs const& xs, N const&) {
0085 constexpr std::size_t n = N::value;
0086 return detail::cycle_helper<M, n>::apply(xs);
0087 }
0088 };
0089
0090 namespace detail {
0091 template <std::size_t N, std::size_t Len>
0092 struct cycle_indices {
0093 static constexpr auto compute_value() {
0094 detail::array<std::size_t, N * Len> indices{};
0095
0096
0097 std::size_t len = Len;
0098 for (std::size_t i = 0; i < N * Len; ++i)
0099 indices[i] = i % len;
0100 return indices;
0101 }
0102
0103 static constexpr auto value = compute_value();
0104 };
0105 }
0106
0107 template <typename S>
0108 struct cycle_impl<S, when<Sequence<S>::value>> {
0109 template <typename Indices, typename Xs, std::size_t ...i>
0110 static constexpr auto cycle_helper(Xs&& xs, std::index_sequence<i...>) {
0111 constexpr auto indices = Indices::value;
0112 (void)indices;
0113 return hana::make<S>(hana::at_c<indices[i]>(xs)...);
0114 }
0115
0116 template <typename Xs, typename N>
0117 static constexpr auto apply(Xs&& xs, N const&) {
0118 constexpr std::size_t n = N::value;
0119 constexpr std::size_t len = decltype(hana::length(xs))::value;
0120 using Indices = detail::cycle_indices<n, len>;
0121 return cycle_helper<Indices>(static_cast<Xs&&>(xs),
0122 std::make_index_sequence<n * len>{});
0123 }
0124 };
0125 }}
0126
0127 #endif