From 7b6a428b94c4fd180c3df64f29e164f71226f9d3 Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Sun, 23 Feb 2025 16:12:05 +0800 Subject: [PATCH] update: cleanup the impl code --- src/core/group/internal/group.cc | 299 +++++++++---------------------- 1 file changed, 89 insertions(+), 210 deletions(-) diff --git a/src/core/group/internal/group.cc b/src/core/group/internal/group.cc index 1d0a90b..03d700b 100644 --- a/src/core/group/internal/group.cc +++ b/src/core/group/internal/group.cc @@ -16,13 +16,17 @@ using klotski::mover::MaskMover; using klotski::group::GROUP_DATA; using klotski::group::PATTERN_DATA; +using klotski::group::PATTERN_OFFSET; -#define RELEASE_TO(RU) \ +#define RELEASE_INTO(RU) \ [&data](const RawCode raw_code) { \ const auto code = raw_code.to_common_code().unwrap(); \ data.ranges(code >> 32).emplace_back(static_cast(code)); \ } +#define NO_MIRROR \ + [](RawCode, auto) {} + template KLSK_NOINLINE static void extend(const RawCode seed, const size_t reserve, MF add_mirror, RF release) { std::vector queue, mirrors; @@ -60,248 +64,124 @@ KLSK_NOINLINE static void extend(const RawCode seed, const size_t reserve, MF ad } template -static RangesUnion spawn_group(const RawCode seed, const size_t reserve) { - const auto ctr_mirror = [](const RawCode code, auto spawn) { - spawn(code.to_diagonal_mirror()); - }; - - const auto vrt_mirror = [](const RawCode code, auto spawn) { - spawn(code.to_vertical_mirror()); - }; - - const auto hor_mirror = [](const RawCode code, auto spawn) { - if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) { - spawn(m_hor); - } - }; - - const auto 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()); - } - }; +static RangesUnion build_group(const RawCode seed, const size_t reserve) { + RangesUnion data {}; + if constexpr(TYPE == Group::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, reserve, mirror_func, RELEASE_INTO(data)); + } - RangesUnion data {}; // TODO: how to reserve `data` + if constexpr(TYPE == Group::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, reserve, mirror_func, RELEASE_INTO(data)); + } - // TODO: it seems that reserve will actually lose speed, why??? - // auto val = reserve / 8; - // data.ranges(0).reserve(val); data.ranges(1).reserve(val); data.ranges(2).reserve(val); - // data.ranges(4).reserve(val); data.ranges(5).reserve(val); data.ranges(6).reserve(val); - // data.ranges(8).reserve(val); data.ranges(9).reserve(val); data.ranges(10).reserve(val); - // data.ranges(12).reserve(val); data.ranges(13).reserve(val); data.ranges(14).reserve(val); + if constexpr(TYPE == Group::MirrorType::Centro) { + const auto mirror_func = [](const RawCode code, auto spawn) { + spawn(code.to_diagonal_mirror()); + }; + extend(seed, reserve, mirror_func, RELEASE_INTO(data)); + } - // TODO: maybe we don't need `else` - if constexpr(TYPE == Group::MirrorType::Full) { - extend(seed, reserve, full_mirror, RELEASE_TO(data)); - } else if constexpr(TYPE == Group::MirrorType::Horizontal) { - extend(seed, reserve, hor_mirror, RELEASE_TO(data)); - } else if constexpr(TYPE == Group::MirrorType::Centro) { - extend(seed, reserve, ctr_mirror, RELEASE_TO(data)); - } else if constexpr(TYPE == Group::MirrorType::Vertical) { - extend(seed, reserve, vrt_mirror, RELEASE_TO(data)); - } else if constexpr(TYPE == Group::MirrorType::Ordinary) { - extend(seed, reserve, [](RawCode, auto) {}, RELEASE_TO(data)); + if constexpr(TYPE == Group::MirrorType::Vertical) { + const auto mirror_func = [](const RawCode code, auto spawn) { + spawn(code.to_vertical_mirror()); + }; + extend(seed, reserve, mirror_func, RELEASE_INTO(data)); + } + + if constexpr(TYPE == Group::MirrorType::Ordinary) { + extend(seed, reserve, NO_MIRROR, RELEASE_INTO(data)); } return data; } -// static RangesUnion extend_type_ord(const RawCode seed, const size_t reserve) { -// RangesUnion data {}; -// extend(seed, reserve, [](RawCode, auto) {}, RELEASE_TO(data)); -// return data; -// } -// -// static RangesUnion extend_type_hor(const RawCode seed, const size_t reserve) { -// RangesUnion data {}; -// extend(seed, reserve, [](const RawCode code, auto callback) { -// if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) { -// callback(m_hor); -// } -// }, RELEASE_TO(data)); -// return data; -// } -// -// static RangesUnion extend_type_vrt(const RawCode seed, const size_t reserve) { -// RangesUnion data {}; -// extend(seed, reserve, [](const RawCode code, auto callback) { -// callback(code.to_vertical_mirror()); -// }, RELEASE_TO(data)); -// return data; -// } -// -// static RangesUnion extend_type_diag(const RawCode seed, const size_t reserve) { -// RangesUnion data {}; -// extend(seed, reserve, [](const RawCode code, auto callback) { -// callback(code.to_diagonal_mirror()); -// }, RELEASE_TO(data)); -// return data; -// } -// -// static RangesUnion extend_type_full(const RawCode seed, const size_t reserve) { -// RangesUnion data {}; -// extend(seed, reserve, [](const RawCode code, auto callback) { -// const auto m_vrt = code.to_vertical_mirror(); -// callback(m_vrt); -// if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) { -// callback(m_hor); -// callback(m_vrt.to_horizontal_mirror()); -// } -// }, RELEASE_TO(data)); -// return data; -// } - -// template -// KLSK_NOINLINE static void extend_2(const RawCode seed, const size_t reserve, MF add_mirror, RF release) { -// std::vector queue, mirrors; -// phmap::flat_hash_map cases; -// -// queue.reserve(reserve); mirrors.reserve(reserve); -// cases.reserve(static_cast(static_cast(reserve) * 1.56)); // reduce load factor -// -// auto mover = MaskMover([&queue, &cases, &mirrors, add_mirror](RawCode code, uint64_t hint) { -// if (const auto [iter, ret] = cases.try_emplace(code, hint); !ret) { -// iter->second |= hint; // update hint -// return; -// } -// queue.emplace_back(code); -// add_mirror(code, [&cases, &mirrors](RawCode mirror) { -// cases.emplace(mirror, 0); // without hint -// mirrors.emplace_back(mirror); -// }); -// }); -// -// queue.emplace_back(seed); -// cases.emplace(seed, 0); -// add_mirror(seed, [&mirrors, &cases](RawCode mirror) { -// cases.emplace(mirror, 0); // without hint -// mirrors.emplace_back(mirror); -// }); -// -// uint64_t offset = 0; -// while (offset != queue.size()) { -// const auto curr = queue[offset++]; -// mover.next_cases(curr, cases.find(curr)->second); -// } -// -// for (const auto code : queue) { release(code); } -// for (const auto code : mirrors) { release(code); } -// } - -#define OUTPUT_IMPL(VAR, EXPL, OUT) \ - const auto VAR = (EXPL).to_common_code().unwrap(); \ +#define EMPLACE_INTO_IMPL(VAR, EXPR, OUT) \ + const auto VAR = (EXPR).to_common_code().unwrap(); \ OUT.ranges(VAR >> 32).emplace_back(static_cast(VAR)) -#define OUTPUT(EXPL, OUT) \ - OUTPUT_IMPL(KLSK_UNIQUE(tmp), EXPL, OUT) +#define EMPLACE_INTO(RU, EXPR) \ + EMPLACE_INTO_IMPL(KLSK_UNIQUE(tmp), EXPR, RU) template -KLSK_NOINLINE static void spawn_xxx_pattern(RawCode seed, const size_t reserve, RangesUnion &output) { - +KLSK_NOINLINE static void spawn_pattern(RawCode seed, const size_t reserve, RangesUnion &data) { if constexpr(TYPE == Group::MirrorType::Full) { - extend(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) { - OUTPUT(raw_code, output); + extend(seed, reserve, NO_MIRROR, [&data](const RawCode code) { + EMPLACE_INTO(data, code); }); } if constexpr(TYPE == Group::MirrorType::Horizontal) { - extend(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) { - OUTPUT(raw_code, output); - OUTPUT(raw_code.to_vertical_mirror(), output); + extend(seed, reserve, NO_MIRROR, [&data](const RawCode code) { + EMPLACE_INTO(data, code); + EMPLACE_INTO(data, code.to_vertical_mirror()); }); } if constexpr(TYPE == Group::MirrorType::Vertical) { - extend(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) { - OUTPUT(raw_code, output); - OUTPUT(raw_code.to_horizontal_mirror(), output); + extend(seed, reserve, NO_MIRROR, [&data](const RawCode code) { + EMPLACE_INTO(data, code); + EMPLACE_INTO(data, code.to_horizontal_mirror()); }); } if constexpr(TYPE == Group::MirrorType::Ordinary) { - extend(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) { - OUTPUT(raw_code, output); - OUTPUT(raw_code.to_vertical_mirror(), output); - OUTPUT(raw_code.to_horizontal_mirror(), output); - OUTPUT(raw_code.to_diagonal_mirror(), output); // TODO: perf it + extend(seed, reserve, NO_MIRROR, [&data](const RawCode code) { + // const auto m_vrt = code.to_vertical_mirror(); + // EMPLACE_INTO(data, code); + // EMPLACE_INTO(data, m_vrt); + // EMPLACE_INTO(data, code.to_horizontal_mirror()); + // EMPLACE_INTO(data, m_vrt.to_horizontal_mirror()); + EMPLACE_INTO(data, code); + EMPLACE_INTO(data, code.to_vertical_mirror()); + EMPLACE_INTO(data, code.to_horizontal_mirror()); + EMPLACE_INTO(data, code.to_diagonal_mirror()); }); } } -// KLSK_NOINLINE static void spawn_full_pattern(RawCode seed, const size_t reserve, RangesUnion &output) { -// extend(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) { -// OUTPUT(raw_code, output); -// }); -// } -// -// KLSK_NOINLINE static void spawn_hor_pattern(RawCode seed, const size_t reserve, RangesUnion &output) { -// extend(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) { -// OUTPUT(raw_code, output); -// OUTPUT(raw_code.to_vertical_mirror(), output); -// }); -// } -// -// KLSK_NOINLINE static void spawn_ver_pattern(RawCode seed, const size_t reserve, RangesUnion &output) { -// extend(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) { -// OUTPUT(raw_code, output); -// OUTPUT(raw_code.to_horizontal_mirror(), output); -// }); -// } -// -// KLSK_NOINLINE static void spawn_ord_pattern(RawCode seed, const size_t reserve, RangesUnion &output) { -// extend(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) { -// OUTPUT(raw_code, output); -// OUTPUT(raw_code.to_vertical_mirror(), output); -// OUTPUT(raw_code.to_horizontal_mirror(), output); -// OUTPUT(raw_code.to_diagonal_mirror(), output); // TODO: perf it -// }); -// } - -KLSK_NOINLINE static RangesUnion extend_pro(uint8_t type_id) { +KLSK_NOINLINE static RangesUnion first_x_group(const uint8_t type_id) { RangesUnion others {}; - auto gu = GroupUnion::unsafe_create(type_id); - for (int pattern_id = 1; pattern_id < gu.pattern_num(); ++pattern_id) { - - auto flat_id = klotski::group::PATTERN_OFFSET[type_id] + pattern_id; - auto mirror_type = static_cast(PATTERN_DATA[flat_id] & 0b111); - auto seed = CommonCode::unsafe_create(PATTERN_DATA[flat_id] >> 23).to_raw_code(); - auto size = (PATTERN_DATA[flat_id] >> 3) & 0xFFFFF; - - if (mirror_type == Group::MirrorType::Full) { - spawn_xxx_pattern(seed, size, others); - // spawn_full_pattern(seed, size, others); - } else if (mirror_type == Group::MirrorType::Horizontal) { - // spawn_hor_pattern(seed, size, others); - spawn_xxx_pattern(seed, size, others); - } else if (mirror_type == Group::MirrorType::Vertical) { - // spawn_ver_pattern(seed, size, others); - spawn_xxx_pattern(seed, size, others); - } else if (mirror_type == Group::MirrorType::Ordinary) { - // spawn_ord_pattern(seed, size, others); - spawn_xxx_pattern(seed, size, others); + const auto gu = GroupUnion::unsafe_create(type_id); + for (uint32_t pattern_id = 1; pattern_id < gu.pattern_num(); ++pattern_id) { + const auto flat_id = PATTERN_OFFSET[type_id] + pattern_id; + const auto type = static_cast(PATTERN_DATA[flat_id] & 0b111); + const auto seed = CommonCode::unsafe_create(PATTERN_DATA[flat_id] >> 23).to_raw_code(); + const auto size = (PATTERN_DATA[flat_id] >> 3) & 0xFFFFF; + + if (type == Group::MirrorType::Full) { + spawn_pattern(seed, size, others); + } else if (type == Group::MirrorType::Horizontal) { + spawn_pattern(seed, size, others); + } else if (type == Group::MirrorType::Vertical) { + spawn_pattern(seed, size, others); + } else if (type == Group::MirrorType::Ordinary) { + spawn_pattern(seed, size, others); } } - - for (auto head : RangesUnion::Heads) { + for (const auto head : RangesUnion::Heads) { std::stable_sort(others.ranges(head).begin(), others.ranges(head).end()); } - // return others; - return GroupUnion::unsafe_create(type_id).cases_without(others); } RangesUnion Group::cases() const { - if (const auto gu = GroupUnion::unsafe_create(type_id_); gu.group_num() == 1) { - // std::println("type_a: {}", size()); - return gu.cases(); + if (GroupUnion::unsafe_create(type_id_).group_num() == 1) { + return GroupUnion::unsafe_create(type_id_).cases(); } - if (pattern_id_ == 0 && mirror_type() == MirrorType::Full) { // TODO: black-list filter - // std::println("type_b: {}", size()); - return extend_pro(type_id_); - // return GroupUnion::unsafe_create(type_id_).cases(); + return first_x_group(type_id_); } const auto seed_val = PATTERN_DATA[flat_id()] >> 23; @@ -316,20 +196,19 @@ RangesUnion Group::cases() const { RangesUnion data; if (mirror_type() == MirrorType::Full) { - data = spawn_group(seed, size()); + data = build_group(seed, size()); } else if (mirror_type() == MirrorType::Horizontal) { - data = spawn_group(seed, size()); + data = build_group(seed, size()); } else if (mirror_type() == MirrorType::Vertical) { - data = spawn_group(seed, size()); + data = build_group(seed, size()); } else if (mirror_type() == MirrorType::Centro) { - data = spawn_group(seed, size()); + data = build_group(seed, size()); } else { - data = spawn_group(seed, size()); + data = build_group(seed, size()); } for (const auto head : RangesUnion::Heads) { std::stable_sort(data.ranges(head).begin(), data.ranges(head).end()); } - // std::println("type_c: {}", size()); return data; }