// -------------------------------- // See LICENCE file at project root // File : meta/utils.hpp // -------------------------------- #ifndef SCALFMM_META_UTILS_HPP #define SCALFMM_META_UTILS_HPP #include #include #include #include #include #include #include #include #include #include #include #include "scalfmm/meta/traits.hpp" #include "scalfmm/meta/forward.hpp" namespace scalfmm::meta { struct noop_t { template noop_t(const Types&... ts) { } }; struct noop_f { template noop_f(F... fs) { } }; template struct cat; template struct cat, std::tuple> { using type = std::tuple; }; // standart traits and forward declaration template struct tuple_size : std::tuple_size { }; template static constexpr std::size_t tuple_size_v = meta::tuple_size::value; template struct tuple_size> : tuple_size::base_type> { }; template class Container, typename... Types> struct tuple_size> : tuple_size::base_type> { }; template struct tuple_size> : tuple_size::base_type> { }; template struct tuple_size> : tuple_size::base_type> { }; template struct tuple_size> : tuple_size::base_type> { }; template struct tuple_size> : tuple_size::base_type> { }; template struct tuple_size> : tuple_size::base_type> { }; template struct tuple_size> : std::integral_constant { }; template inline constexpr auto get(T&& t) noexcept -> auto&& { return std::get(std::forward(t)); } template inline constexpr auto get(container::point const& p) noexcept -> ValueType const& { return p.at(I); } template inline constexpr auto get(container::point& p) noexcept -> ValueType& { return p.at(I); } ////////////////////////////////////////////// template inline constexpr auto add_to_sequence(std::index_sequence seq) { return std::index_sequence<(Added + Is)...>{}; } template inline constexpr auto reverse_impl(T&& t, std::index_sequence /*unused*/) -> std::tuple::type...> { return std::make_tuple(meta::get(std::forward(t))...); } template inline constexpr auto reverse(T&& t) -> decltype(reverse_impl(std::forward(t), std::make_index_sequence>::value>())) { return reverse_impl(std::forward(t), std::make_index_sequence>::value>()); } // Genrate a tuple of Ts template using type_id = T; template inline constexpr auto generate_tuple(std::index_sequence s) { return std::tuple...>{}; } template inline constexpr auto generate_tuple() { return generate_tuple(std::make_index_sequence{}); } template using generate_tuple_t = decltype(generate_tuple()); template class New, typename Tuple, std::size_t... Is> inline constexpr auto replace_inner_tuple_type(std::index_sequence s) { return std::tuple::type>>...>{}; } template class New, typename Tuple> inline constexpr auto replace_inner_tuple_type() { return replace_inner_tuple_type(std::make_index_sequence>{}); } template class New, typename Tuple> using replace_inner_tuple_type_t = decltype(replace_inner_tuple_type()); template>>> constexpr inline auto to_array(Tuple t) { return std::apply([](auto... elems) { return std::array{elems...}; }, t); } template constexpr inline auto to_tuple(std::array a) { return std::apply([](auto... elems) { return std::make_tuple(elems...); }, a); } template struct offset_sequence; template struct offset_sequence> { using type = std::index_sequence; }; template using offset_sequence_t = typename offset_sequence::type; template struct make_range_sequence : public offset_sequence_t> { }; template constexpr inline auto sub_tuple(T&& t, std::index_sequence s) { return std::forward_as_tuple(meta::get(std::forward(t))...); } template inline auto print(std::ostream& out, Args&&... args) { ((out << ' ' << std::forward(args)), ...); } template inline constexpr auto multiply(Args&... args) { return (args * ...); } template inline constexpr auto all(Args... args) -> bool { return (... && args); } namespace details { template inline constexpr auto tuple_sum_update(T&& lhs, U&& rhs, std::index_sequence s) -> void { noop_t{((meta::get(std::forward(lhs)) += meta::get(std::forward(rhs))), 0)...}; } template inline constexpr auto tuple_min_update(T&& lhs, U&& rhs, std::index_sequence s) -> void { noop_t{((meta::get(std::forward(lhs)) -= meta::get(std::forward(rhs))), 0)...}; } template inline constexpr auto for_each(std::index_sequence s, F&& f, LHS&& lhs, RHS1&& rhs1, RHS2&& rhs2) -> void { noop_t{(((meta::get(std::forward(lhs)) = std::invoke(std::forward(f), meta::get(std::forward(rhs1)), meta::get(std::forward(rhs2))))), 0)...}; } template inline constexpr auto for_each(T&& lhs, U&& rhs, F&& f, std::index_sequence s) -> void { noop_t{((meta::get(std::forward(lhs)) = std::invoke(std::forward(f), meta::get(std::forward(rhs)))), 0)...}; } template inline constexpr auto for_each(T&& t, F&& f, std::index_sequence s) -> void { noop_t{(std::invoke(std::forward(f), meta::get(std::forward(t))), 0)...}; } template inline constexpr auto repeat(F&& f, T0&& t0, T1&& t1, T2&& t2, T3&& t3, std::index_sequence s) -> void { noop_t{( (std::invoke(std::forward(f), meta::get(std::forward(t0)), meta::get(std::forward(t1)), meta::get(std::forward(t2)), meta::get(std::forward(t3)))), 0)...}; } template inline constexpr auto repeat(F&& f, T0&& t0, T1&& t1, T2&& t2, std::index_sequence s) -> void { noop_t{((std::invoke(std::forward(f), meta::get(std::forward(t0)), meta::get(std::forward(t1)), meta::get(std::forward(t2)))), 0)...}; } template inline constexpr auto repeat(F&& f, T0&& t0, T1&& t1, std::index_sequence s) -> void { noop_t{((std::invoke(std::forward(f), meta::get(std::forward(t0)), meta::get(std::forward(t1)))), 0)...}; } template inline constexpr auto repeat(F&& f, T0&& t0, std::index_sequence s) -> void { noop_t{((std::invoke(std::forward(f), meta::get(std::forward(t0)))), 0)...}; } template inline constexpr auto repeat_indexed(F&& f, T0&& t0, T1&& t1, T2&& t2, T3&& t3, std::index_sequence s) -> void { noop_t{((std::invoke(std::forward(f), Is, meta::get(std::forward(t0)), meta::get(std::forward(t1)), meta::get(std::forward(t2)), meta::get(std::forward(t3)))), 0)...}; } template inline constexpr auto repeat_indexed(F&& f, T0&& t0, T1&& t1, T2&& t2, std::index_sequence s) -> void { noop_t{((std::invoke(std::forward(f), Is, meta::get(std::forward(t0)), meta::get(std::forward(t1)), meta::get(std::forward(t2)))), 0)...}; } template inline constexpr auto repeat_indexed(F&& f, T0&& t0, T1&& t1, std::index_sequence s) -> void { noop_t{((std::invoke(std::forward(f), Is, meta::get(std::forward(t0)), meta::get(std::forward(t1)))), 0)...}; } template inline constexpr auto repeat_indexed(F&& f, T0&& t0, std::index_sequence s) -> void { noop_t{((std::invoke(std::forward(f), Is, meta::get(std::forward(t0)))), 0)...}; } template inline constexpr auto apply(T&& t, F&& f, std::index_sequence s) { return std::make_tuple(std::invoke(std::forward(f), meta::get(std::forward(t)))...); } } // namespace details template inline constexpr auto tuple_sum_update(T&& lhs, U&& rhs) -> void { return details::tuple_sum_update(std::forward(lhs), std::forward(rhs), std::make_index_sequence>::value>{}); } template inline constexpr auto tuple_min_update(T&& lhs, U&& rhs) -> void { return details::tuple_min_update(std::forward(lhs), std::forward(rhs), std::make_index_sequence>::value>{}); } template inline constexpr auto for_each(LHS&& lhs, RHS1&& rhs1, RHS2&& rhs2, F&& f) -> void { return details::for_each(std::make_index_sequence>::value>{}, std::forward(f), std::forward(lhs), std::forward(rhs1), std::forward(rhs2)); } template inline constexpr auto for_each(T&& lhs, U&& rhs, F&& f) -> void { return details::for_each(std::forward(lhs), std::forward(rhs), std::forward(f), std::make_index_sequence>::value>{}); } template inline constexpr auto for_each(T&& tuple, F&& f) -> void { return details::for_each(std::forward(tuple), std::forward(f), std::make_index_sequence>::value>{}); } template inline constexpr auto repeat(F&& f, T0&& t0, T1&& t1, T2&& t2, T3&& t3) -> void { details::repeat(std::forward(f), std::forward(t0), std::forward(t1), std::forward(t2), std::forward(t3), std::make_index_sequence>::value>{}); } template inline constexpr auto repeat(F&& f, T0&& t0, T1&& t1, T2&& t2) -> void { details::repeat(std::forward(f), std::forward(t0), std::forward(t1), std::forward(t2), std::make_index_sequence>::value>{}); } template inline constexpr auto repeat(F&& f, T0&& t0, T1&& t1) -> void { details::repeat(std::forward(f), std::forward(t0), std::forward(t1), std::make_index_sequence>::value>{}); } template inline constexpr auto repeat(F&& f, T0&& t0) -> void { details::repeat(std::forward(f), std::forward(t0), std::make_index_sequence>::value>{}); } template inline constexpr auto repeat_indexed(F&& f, T0&& t0, T1&& t1, T2&& t2, T3&& t3) -> void { details::repeat_indexed(std::forward(f), std::forward(t0), std::forward(t1), std::forward(t2), std::forward(t3), std::make_index_sequence>::value>{}); } template inline constexpr auto repeat_indexed(F&& f, T0&& t0, T1&& t1, T2&& t2) -> void { details::repeat_indexed(std::forward(f), std::forward(t0), std::forward(t1), std::forward(t2), std::make_index_sequence>::value>{}); } template inline constexpr auto repeat_indexed(F&& f, T0&& t0, T1&& t1) -> void { details::repeat_indexed(std::forward(f), std::forward(t0), std::forward(t1), std::make_index_sequence>::value>{}); } template inline constexpr auto repeat_indexed(F&& f, T0&& t0) -> void { details::repeat_indexed(std::forward(f), std::forward(t0), std::make_index_sequence>::value>{}); } template inline constexpr auto apply(T&& t, F&& f) { return details::apply(std::forward(t), std::forward(f), std::make_index_sequence>::value>{}); } template struct looper { template constexpr inline auto operator()(F&& f, std::array const& stops, Is&... is) { for(std::size_t i = 0; i < meta::get(stops); ++i) { looper()(std::forward(f), stops, is..., i); } } }; template<> struct looper<1> { template constexpr inline auto operator()(F&& f, std::array const& stops, Is&... is) { for(std::size_t i = 0; i < meta::get<0>(stops); ++i) { f(is..., i); } } }; template struct looper_range { template constexpr inline auto operator()(F&& f, std::array const& starts, std::array const& stops, Is&... is) { for(int i = meta::get(starts); i < meta::get(stops); ++i) { looper_range()(std::forward(f), starts, stops, is..., i); } } }; template<> struct looper_range<1> { template constexpr inline auto operator()(F&& f, std::array const& starts, std::array const& stops, Is&... is) { for(int i = meta::get<0>(starts); i < meta::get<0>(stops); ++i) { std::invoke(std::forward(f), is..., i); } } }; template auto inline as_tuple(ParticleOrTuple&& p) { if constexpr(is_particle_v>) { return std::forward(p).as_tuple(); } else if constexpr(is_tuple_v>) { return std::forward(p); } } } // namespace scalfmm::meta #endif // SCALFMM_META_UTILS_HPP