#include "core/core.h" #include "group/group.h" #include "constant/group_union.h" using klotski::codec::RawCode; using klotski::codec::CommonCode; using klotski::cases::GroupUnion; #define RANGE_DERIVE(HEAD) ranges.derive(HEAD, cases[HEAD]) static KLSK_INLINE uint32_t to_type_id(const int n, const int n_2x1, const int n_1x1) { constexpr int offset[8] = {0, 15, 41, 74, 110, 145, 175, 196}; return offset[n] + (15 - n * 2) * n_2x1 + n_1x1; } uint32_t GroupUnion::type_id(const CommonCode common_code) { const auto range = static_cast(common_code.unwrap()); const auto n_1x1 = std::popcount((range >> 1) & range & 0x55555555); const auto n_2x1 = std::popcount((range >> 1) & ~range & 0x55555555); return to_type_id(std::popcount(range) - n_1x1 * 2, n_2x1, n_1x1); } uint32_t GroupUnion::type_id(const RawCode raw_code) { const auto code = raw_code.unwrap(); const auto n = std::popcount(((code >> 1) ^ code) & 0x0249249249249249); const auto n_2x1 = std::popcount((code >> 1) & ~code & 0x0249249249249249); const auto n_1x1 = std::popcount((code >> 1) & code & 0x0249249249249249) - n - 3; return to_type_id(n, n_2x1, n_1x1); } klotski::cases::RangesUnion GroupUnion::cases() const { auto [n, n_2x1, n_1x1] = BLOCK_NUM[type_id_]; auto [s_a, s_b, s_c, s_d] = GROUP_UNION_CASES_NUM[type_id_]; Ranges ranges {}; ranges.reserve(BASIC_RANGES_NUM[type_id_]); ranges.spawn(n, n_2x1, n_1x1); ranges.reverse(); RangesUnion cases; cases[0x0].reserve(s_a); cases[0x1].reserve(s_b); cases[0x2].reserve(s_a); cases[0x4].reserve(s_c); cases[0x5].reserve(s_d); cases[0x6].reserve(s_c); cases[0x8].reserve(s_c); cases[0x9].reserve(s_d); cases[0xA].reserve(s_c); cases[0xC].reserve(s_a); cases[0xD].reserve(s_b); cases[0xE].reserve(s_a); RANGE_DERIVE(0x0); RANGE_DERIVE(0x1); RANGE_DERIVE(0x2); RANGE_DERIVE(0x4); RANGE_DERIVE(0x5); RANGE_DERIVE(0x6); RANGE_DERIVE(0x8); RANGE_DERIVE(0x9); RANGE_DERIVE(0xA); RANGE_DERIVE(0xC); RANGE_DERIVE(0xD); RANGE_DERIVE(0xE); return cases; }