From cb37a775dea395a5bcf97ef3fa2e4e2d76bd9a7e Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Sun, 2 Mar 2025 17:17:20 +0800 Subject: [PATCH] update: using macros to simplify cases mirror --- src/core/group/internal/group_cases.cc | 284 ++++++++++++------------- 1 file changed, 140 insertions(+), 144 deletions(-) diff --git a/src/core/group/internal/group_cases.cc b/src/core/group/internal/group_cases.cc index 786b248..cc66817 100644 --- a/src/core/group/internal/group_cases.cc +++ b/src/core/group/internal/group_cases.cc @@ -1,3 +1,4 @@ +#include #include #include @@ -14,6 +15,8 @@ using klotski::codec::CommonCode; using klotski::group::Group; using klotski::group::GroupCases; using klotski::group::GroupUnion; + +using klotski::cases::Ranges; using klotski::cases::RangesUnion; using klotski::group::CaseInfo; @@ -30,6 +33,16 @@ using klotski::group::PATTERN_DATA; using klotski::group::PATTERN_OFFSET; using klotski::group::ALL_PATTERN_NUM; +using klotski::group::BLOCK_NUM; +using klotski::cases::BASIC_RANGES_NUM; +using klotski::group::GROUP_UNION_CASES_NUM; + +#define RANGE_RESERVE(HEAD, SIZE) cases.ranges(HEAD).reserve(SIZE) + +#define RANGE_DERIVE_WITHOUT(HEAD) ranges.derive_without(HEAD, cases.ranges(HEAD), data.ranges(HEAD)) + +using MirrorType = Group::MirrorType; + struct case_info_t { uint32_t pattern_id : 10; uint32_t toward_id : 2; @@ -42,12 +55,6 @@ static std::array *ru_data_array = nullptr; static std::vector *rev_data = nullptr; -// #define RELEASE_INTO(RU) \ -// [&RU](const RawCode raw_code) { \ -// const auto code = raw_code.to_common_code().unwrap(); \ -// RU.ranges(code >> 32).emplace_back(static_cast(code)); \ -// } - #define EMPLACE_INTO_IMPL(RU, VAR, EXPR) \ const auto VAR = (EXPR).to_common_code().unwrap(); \ RU.ranges(VAR >> 32).emplace_back(static_cast(VAR)); @@ -55,8 +62,32 @@ static std::vector *rev_data = nullptr; #define EMPLACE_INTO(RU, EXPR) \ EMPLACE_INTO_IMPL(RU, KLSK_UNIQUE(tmp), EXPR) -#define NO_MIRROR \ - [](RawCode, auto) {} +#define NO_MIRROR [](RawCode, auto) {} + +#define CTR_MIRROR \ + [](const RawCode code, auto spawn) { \ + spawn(code.to_diagonal_mirror()); \ + } + +#define HOR_MIRROR \ + [](const RawCode code, auto spawn) { \ + if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) { \ + spawn(m_hor); \ + } \ + } + +#define VRT_MIRROR \ + [](const RawCode code, auto spawn) { \ + spawn(code.to_vertical_mirror()); \ + } + +#define FULL_MIRROR \ + [](const RawCode code, auto spawn) { \ + const auto m_vrt = code.to_vertical_mirror(); spawn(m_vrt); \ + if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) { \ + spawn(m_hor); spawn(m_vrt.to_horizontal_mirror()); \ + } \ + } template KLSK_NOINLINE static void extend(const RawCode seed, const size_t reserve, MF add_mirror, RF release) { @@ -94,197 +125,162 @@ KLSK_NOINLINE static void extend(const RawCode seed, const size_t reserve, MF ad for (const auto code : mirrors) { release(code); } } -template -static void extend_pattern(RawCode seed, size_t size, RangesUnion *kk) { - using MirrorType = Group::MirrorType; +// #define RELEASE_TO(A, B, C, D) \ +// [&data_a, &data_b, &data_c, &data_d](const RawCode code) { \ +// if constexpr(A == 'A') { EMPLACE_INTO(data_a, code); } \ +// if constexpr(B == 'B') { EMPLACE_INTO(data_b, code.to_horizontal_mirror()); } \ +// if constexpr(C == 'C') { EMPLACE_INTO(data_c, code.to_vertical_mirror()); } \ +// if constexpr(D == 'D') { EMPLACE_INTO(data_d, code.to_diagonal_mirror()); } \ +// } - RangesUnion &a = kk[0]; - RangesUnion &b = kk[1]; - RangesUnion &c = kk[2]; - RangesUnion &d = kk[3]; +template +static void spawn_pattern(RawCode seed, size_t size, RangesUnion *data) { + RangesUnion &ga = data[0]; + RangesUnion &gb = data[1]; + RangesUnion &gc = data[2]; + RangesUnion &gd = data[3]; if constexpr(TYPE == MirrorType::Full) { - const auto mirror_func = [](const RawCode code, auto spawn) { - const auto m_vrt = code.to_vertical_mirror(); - spawn(m_vrt); - if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) { - spawn(m_hor); - spawn(m_vrt.to_horizontal_mirror()); - } - }; - extend(seed, size, mirror_func, [&a](const RawCode raw_code) { - // const auto code = raw_code.to_common_code().unwrap(); - // a.ranges(code >> 32).emplace_back(static_cast(code)); - EMPLACE_INTO(a, raw_code); + extend(seed, size, FULL_MIRROR, [&ga](const RawCode code) { + EMPLACE_INTO(ga, code); }); + // extend(seed, size, HOR_MIRROR, RELEASE_TO('A', 0, 0, 0)); } if constexpr(TYPE == MirrorType::Horizontal) { - const auto mirror_func = [](const RawCode code, auto spawn) { - if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) { - spawn(m_hor); - } - }; - extend(seed, size, mirror_func, [&a, &c](const RawCode raw_code) { - // const auto code = raw_code.to_common_code().unwrap(); - // a.ranges(code >> 32).emplace_back(static_cast(code)); - EMPLACE_INTO(a, raw_code); - - // const auto code_ = raw_code.to_vertical_mirror().to_common_code().unwrap(); - // c.ranges(code_ >> 32).emplace_back(static_cast(code_)); - EMPLACE_INTO(c, raw_code.to_vertical_mirror()); + extend(seed, size, HOR_MIRROR, [&ga, &gc](const RawCode code) { + EMPLACE_INTO(ga, code); + EMPLACE_INTO(gc, code.to_vertical_mirror()); }); + // extend(seed, size, HOR_MIRROR, RELEASE_TO('A', 0, 'C', 0)); } if constexpr(TYPE == MirrorType::Centro) { - const auto mirror_func = [](const RawCode code, auto spawn) { - spawn(code.to_diagonal_mirror()); - }; - extend(seed, size, mirror_func, [&a, &b](const RawCode raw_code) { - // const auto code = raw_code.to_common_code().unwrap(); - // a.ranges(code >> 32).emplace_back(static_cast(code)); - EMPLACE_INTO(a, raw_code); - - // const auto code_ = raw_code.to_horizontal_mirror().to_common_code().unwrap(); - // b.ranges(code_ >> 32).emplace_back(static_cast(code_)); - EMPLACE_INTO(b, raw_code.to_horizontal_mirror()); + extend(seed, size, CTR_MIRROR, [&ga, &gb](const RawCode code) { + EMPLACE_INTO(ga, code); + EMPLACE_INTO(gb, code.to_horizontal_mirror()); }); + // extend(seed, size, CTR_MIRROR, RELEASE_TO('A', 'B', 0, 0)); } if constexpr(TYPE == MirrorType::Vertical) { - const auto mirror_func = [](const RawCode code, auto spawn) { - spawn(code.to_vertical_mirror()); - }; - extend(seed, size, mirror_func, [&a, &b](const RawCode raw_code) { - // const auto code = raw_code.to_common_code().unwrap(); - // a.ranges(code >> 32).emplace_back(static_cast(code)); - EMPLACE_INTO(a, raw_code); - - // const auto code_ = raw_code.to_horizontal_mirror().to_common_code().unwrap(); - // b.ranges(code_ >> 32).emplace_back(static_cast(code_)); - EMPLACE_INTO(b, raw_code.to_horizontal_mirror()); + extend(seed, size, VRT_MIRROR, [&ga, &gb](const RawCode code) { + EMPLACE_INTO(ga, code); + EMPLACE_INTO(gb, code.to_horizontal_mirror()); }); + // extend(seed, size, VRT_MIRROR, RELEASE_TO('A', 'B', 0, 0)); } if constexpr(TYPE == MirrorType::Ordinary) { - extend(seed, size, NO_MIRROR, [&a, &b, &c, &d](const RawCode raw_code) { - // const auto code = raw_code.to_common_code().unwrap(); - // a.ranges(code >> 32).emplace_back(static_cast(code)); - EMPLACE_INTO(a, raw_code); - - // const auto code_1 = raw_code.to_horizontal_mirror().to_common_code().unwrap(); - // b.ranges(code_1 >> 32).emplace_back(static_cast(code_1)); - EMPLACE_INTO(b, raw_code.to_horizontal_mirror()); - - // const auto code_2 = raw_code.to_vertical_mirror().to_common_code().unwrap(); - // c.ranges(code_2 >> 32).emplace_back(static_cast(code_2)); - EMPLACE_INTO(c, raw_code.to_vertical_mirror()); - - // const auto code_3 = raw_code.to_diagonal_mirror().to_common_code().unwrap(); - // d.ranges(code_3 >> 32).emplace_back(static_cast(code_3)); - EMPLACE_INTO(d, raw_code.to_diagonal_mirror()); + extend(seed, size, NO_MIRROR, [&ga, &gb, &gc, &gd](const RawCode code) { + EMPLACE_INTO(ga, code); + EMPLACE_INTO(gb, code.to_horizontal_mirror()); + EMPLACE_INTO(gc, code.to_vertical_mirror()); + EMPLACE_INTO(gd, code.to_diagonal_mirror()); }); + // extend(seed, size, NO_MIRROR, RELEASE_TO('A', 'B', 'C', 'D')); } - for (auto head : RangesUnion::Heads) { - std::stable_sort(a.ranges(head).begin(), a.ranges(head).end()); - + for (const auto head : RangesUnion::Heads) { + std::stable_sort(ga.ranges(head).begin(), ga.ranges(head).end()); if constexpr(TYPE == MirrorType::Centro || TYPE == MirrorType::Vertical || TYPE == MirrorType::Ordinary) { - std::stable_sort(b.ranges(head).begin(), b.ranges(head).end()); + std::stable_sort(gb.ranges(head).begin(), gb.ranges(head).end()); } - if constexpr(TYPE == MirrorType::Horizontal || TYPE == MirrorType::Ordinary) { - std::stable_sort(c.ranges(head).begin(), c.ranges(head).end()); + std::stable_sort(gc.ranges(head).begin(), gc.ranges(head).end()); } - if constexpr(TYPE == MirrorType::Ordinary) { - std::stable_sort(d.ranges(head).begin(), d.ranges(head).end()); + std::stable_sort(gd.ranges(head).begin(), gd.ranges(head).end()); } } } -// static void build_ru_arr(uint8_t type_id, std::array &data) { -static void build_ru_arr(uint8_t type_id, RangesUnion *offset) { - auto group_union = GroupUnion::unsafe_create(type_id); - - // auto offset = &data[PATTERN_OFFSET[type_id] * 4]; +// KLSK_INLINE static std::tuple get_info(uint8_t type_id, uint16_t pattern_id) { +// const auto flat_id = PATTERN_OFFSET[type_id] + pattern_id; + +// const auto mirror_type = static_cast(PATTERN_DATA[flat_id] & 0b111); + +// const auto seed_val = PATTERN_DATA[flat_id] >> 23; +// auto seed = CommonCode::unsafe_create(seed_val).to_raw_code(); +// const auto size = (PATTERN_DATA[flat_id] >> 3) & 0xFFFFF; + +// return {mirror_type, seed, size}; +// } + +static RangesUnion cases_without(uint8_t type_id, const RangesUnion &data) { + Ranges ranges {}; + ranges.reserve(BASIC_RANGES_NUM[type_id]); + const auto [n, n_2x1, n_1x1] = BLOCK_NUM[type_id]; + ranges.spawn(n, n_2x1, n_1x1); + ranges.reverse(); + + RangesUnion cases; + const auto [na, nb, nc, nd] = GROUP_UNION_CASES_NUM[type_id]; + RANGE_RESERVE(0x0, na); RANGE_RESERVE(0x1, nb); RANGE_RESERVE(0x2, na); + RANGE_RESERVE(0x4, nc); RANGE_RESERVE(0x5, nd); RANGE_RESERVE(0x6, nc); + RANGE_RESERVE(0x8, nc); RANGE_RESERVE(0x9, nd); RANGE_RESERVE(0xA, nc); + RANGE_RESERVE(0xC, na); RANGE_RESERVE(0xD, nb); RANGE_RESERVE(0xE, na); + + RANGE_DERIVE_WITHOUT(0x0); RANGE_DERIVE_WITHOUT(0x1); RANGE_DERIVE_WITHOUT(0x2); + RANGE_DERIVE_WITHOUT(0x4); RANGE_DERIVE_WITHOUT(0x5); RANGE_DERIVE_WITHOUT(0x6); + RANGE_DERIVE_WITHOUT(0x8); RANGE_DERIVE_WITHOUT(0x9); RANGE_DERIVE_WITHOUT(0xA); + RANGE_DERIVE_WITHOUT(0xC); RANGE_DERIVE_WITHOUT(0xD); RANGE_DERIVE_WITHOUT(0xE); + return cases; +} - if (group_union.group_num() == 1) { // only single group - // data[PATTERN_OFFSET[type_id] * 4] = group_union.cases(); - *offset = group_union.cases(); +static void build_ru_arr(uint8_t type_id, RangesUnion *output) { + const auto gu = GroupUnion::unsafe_create(type_id); + if (gu.group_num() == 1) { // with single group + *output = gu.cases(); return; } - uint32_t pattern_id_begin = 0; - if ((PATTERN_DATA[PATTERN_OFFSET[type_id]] & 0b111) == 0) { // first pattern is `x` - pattern_id_begin = 1; - } + const bool ff_mode = (PATTERN_DATA[PATTERN_OFFSET[type_id]] & 0b111) == 0; - for (uint32_t pattern_id = pattern_id_begin; pattern_id < group_union.pattern_num(); ++pattern_id) { + // uint32_t pattern_id_begin = 0; + // if ((PATTERN_DATA[PATTERN_OFFSET[type_id]] & 0b111) == 0) { // first pattern type `Full` + // pattern_id_begin = 1; + // } + + for (uint16_t pattern_id = ff_mode ? 1 : 0; pattern_id < gu.pattern_num(); ++pattern_id) { const auto flat_id = PATTERN_OFFSET[type_id] + pattern_id; - const auto mirror_type = static_cast(PATTERN_DATA[flat_id] & 0b111); + const auto mirror_type = static_cast(PATTERN_DATA[flat_id] & 0b111); const auto seed_val = PATTERN_DATA[flat_id] >> 23; auto seed = CommonCode::unsafe_create(seed_val).to_raw_code(); const auto size = (PATTERN_DATA[flat_id] >> 3) & 0xFFFFF; - // auto kk = &data[flat_id * 4]; - const auto kk = offset + pattern_id * 4; - - if (mirror_type == Group::MirrorType::Full) { - extend_pattern(seed, size, kk); - } else if (mirror_type == Group::MirrorType::Horizontal) { - extend_pattern(seed, size, kk); - } else if (mirror_type == Group::MirrorType::Centro) { - extend_pattern(seed, size, kk); - } else if (mirror_type == Group::MirrorType::Vertical) { - extend_pattern(seed, size, kk); - } else if (mirror_type == Group::MirrorType::Ordinary) { - extend_pattern(seed, size, kk); - } + // const auto [mirror_type, seed, size] = get_info(type_id, pattern_id); - // RangesUnion &a = kk[0]; - // RangesUnion &b = kk[1]; - // RangesUnion &c = kk[2]; - // RangesUnion &d = kk[3]; - // - // for (auto head : RangesUnion::Heads) { - // std::stable_sort(a.ranges(head).begin(), a.ranges(head).end()); - // std::stable_sort(b.ranges(head).begin(), b.ranges(head).end()); - // std::stable_sort(c.ranges(head).begin(), c.ranges(head).end()); - // std::stable_sort(d.ranges(head).begin(), d.ranges(head).end()); - // } + const auto kk = output + pattern_id * 4; + if (mirror_type == MirrorType::Full) { + spawn_pattern(seed, size, kk); + } else if (mirror_type == MirrorType::Horizontal) { + spawn_pattern(seed, size, kk); + } else if (mirror_type == MirrorType::Centro) { + spawn_pattern(seed, size, kk); + } else if (mirror_type == MirrorType::Vertical) { + spawn_pattern(seed, size, kk); + } else if (mirror_type == MirrorType::Ordinary) { + spawn_pattern(seed, size, kk); + } } - if (pattern_id_begin == 1) { // first pattern is `x` + if (ff_mode) { RangesUnion others; - // size_t index_begin = (PATTERN_OFFSET[type_id] + 1) * 4; - // size_t index_end = (PATTERN_OFFSET[type_id] + group_union.pattern_num()) * 4; - // - // for (size_t index = index_begin; index < index_end; ++index) { - // others += data[index]; - // } - // TODO: try to reserve - for (auto *ptr = offset + 4; ptr < offset + group_union.pattern_num() * 4; ++ptr) { + for (auto *ptr = output + 4; ptr < output + gu.pattern_num() * 4; ++ptr) { others += *ptr; } - // for (size_t index = 4; index < group_union.pattern_num() * 4; ++index) { - // others += *(offset + index); - // } - - // RangesUnion init; - // auto others = std::accumulate(offset + 4, offset + group_union.pattern_num() * 4, init, [](RangesUnion a, RangesUnion b) { return a += b; }); - for (auto head : RangesUnion::Heads) { + for (const auto head : RangesUnion::Heads) { std::stable_sort(others.ranges(head).begin(), others.ranges(head).end()); } - - // data[PATTERN_OFFSET[type_id] * 4] = group_union.cases_without(others); - *offset = group_union.cases_without(others); + // *output = gu.cases_without(others); + *output = cases_without(type_id, others); } }