// BITSET2 // // Copyright Claas Bontus // // Use, modification and distribution is subject to the // Boost Software License, Version 1.0. (See accompanying // file LICENSE.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Project home: https://github.com/ClaasBontus/bitset2 // #pragma once #include "h_types.hpp" namespace detail { /// \brief Convert std::array to std::array template struct array2array { using h_t_trgt = h_types; using h_t_src = h_types; using trgt_array_t = typename h_t_trgt::template array_t; using src_array_t = typename h_t_src::template array_t; enum : size_t { trgt_base_n_bits = h_t_trgt::base_t_n_bits, src_base_n_bits = h_t_src::base_t_n_bits }; enum : bool { small_to_large = (src_base_n_bits < trgt_base_n_bits) }; enum : size_t { ts_div = small_to_large ? trgt_base_n_bits / src_base_n_bits : src_base_n_bits / trgt_base_n_bits }; enum : Tsrc { h_all_set = Tsrc(Ttrgt(~Ttrgt(0))) }; /// Applies pttrn to most significant entry in result constexpr trgt_array_t operator()(Ttrgt pttrn, src_array_t const &src) const noexcept { static_assert((small_to_large && trgt_base_n_bits % src_base_n_bits == 0) || (!small_to_large && src_base_n_bits % trgt_base_n_bits == 0), "Conversion between arrays of these types not supported"); return small_to_large ? conv_small_to_large(pttrn, src, std::make_index_sequence()) : conv_large_to_small(pttrn, src, std::make_index_sequence()); } template constexpr trgt_array_t conv_small_to_large(Ttrgt pttrn, src_array_t const &src, std::index_sequence) const noexcept { return { {get_from_smaller(S1, src, S1 * ts_div)..., Ttrgt(get_from_smaller(trgt_n - 1, src, (trgt_n - 1) * ts_div) & pttrn)} }; } template constexpr trgt_array_t conv_large_to_small(Ttrgt pttrn, src_array_t const &src, std::index_sequence) const noexcept { return { {get_from_larger(S1 / ts_div, S1 % ts_div, src)..., Ttrgt(get_from_larger((trgt_n - 1) / ts_div, (trgt_n - 1) % ts_div, src) & pttrn)} }; } constexpr Ttrgt get_from_smaller(size_t trgt_idx, src_array_t const &src, size_t src_idx, size_t src_ct = 0, Ttrgt so_far = Ttrgt(0)) const noexcept { return (src_ct >= ts_div || src_idx >= src_n) ? so_far : get_from_smaller(trgt_idx, src, src_idx + 1, src_ct + 1, so_far | Ttrgt(Ttrgt(src[src_idx]) << (src_base_n_bits * src_ct))); } constexpr Ttrgt get_from_larger(size_t div_val, size_t mod_val, src_array_t const &src) const noexcept { return (div_val >= src_n) ? Ttrgt(0) : Ttrgt(Tsrc(src[div_val] >> (mod_val * trgt_base_n_bits)) & h_all_set); } }; // struct array2array } // namespace detail