From 78c108ab1ab6f2e962022dba235d610ef4aceb50 Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Sat, 22 Feb 2025 18:16:27 +0800 Subject: [PATCH] update: try to optimize code structure --- src/core/group/internal/group.cc | 347 ++++++++++++++++++++----------- 1 file changed, 227 insertions(+), 120 deletions(-) diff --git a/src/core/group/internal/group.cc b/src/core/group/internal/group.cc index b91d26f..ebd1bd5 100644 --- a/src/core/group/internal/group.cc +++ b/src/core/group/internal/group.cc @@ -18,12 +18,12 @@ using klotski::group::GROUP_DATA; using klotski::group::PATTERN_DATA; template -KLSK_NOINLINE static void extend(RawCode seed, const size_t size, MF add_mirror, RF release) { +KLSK_NOINLINE static void extend(const RawCode seed, const size_t reserve, MF add_mirror, RF release) { std::vector queue, mirrors; phmap::flat_hash_map cases; - queue.reserve(size); mirrors.reserve(size); - cases.reserve(static_cast(static_cast(size) * 1.56)); // reduce load factor + 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) { @@ -53,174 +53,204 @@ KLSK_NOINLINE static void extend(RawCode seed, const size_t size, MF add_mirror, for (const auto code : mirrors) { release(code); } } -static RangesUnion extend_type_common(RawCode seed, size_t reserve) { +#define RELEASE_TO(RU) \ + [&data](const RawCode raw_code) { \ + const auto code = raw_code.to_common_code().unwrap(); \ + data.ranges(code >> 32).emplace_back(static_cast(code)); \ + } + +template +static RangesUnion extend_type_xxx(const RawCode seed, const size_t reserve) { RangesUnion data {}; - extend(seed, reserve, [](RawCode, auto) {}, [&data](const RawCode raw_code) { - const auto code = raw_code.to_common_code().unwrap(); - data.ranges(code >> 32).emplace_back(static_cast(code)); - }); - return data; -} -static RangesUnion extend_type_hor(RawCode seed, size_t reserve) { + if constexpr(TYPE == Group::MirrorType::Ordinary) { - // size_t size_a = static_cast(static_cast(size) * 0.500892) + 11; - // size_t size_b = static_cast(static_cast(size) * 0.499108) + 10; + extend(seed, reserve, [](RawCode, auto) {}, RELEASE_TO(data)); - RangesUnion data {}; + } else if constexpr(TYPE == Group::MirrorType::Horizontal) { - // TODO: how to reserve - // size_t 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); + 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)); - extend(seed, reserve, [](const RawCode code, auto callback) { - if (const auto mirror = code.to_horizontal_mirror(); mirror != code) { - callback(mirror); - } - }, [&data](const RawCode raw_code) { - const auto code = raw_code.to_common_code().unwrap(); - data.ranges(code >> 32).emplace_back(static_cast(code)); - }); + } else if constexpr(TYPE == Group::MirrorType::Vertical) { - return data; -} + extend(seed, reserve, [](const RawCode code, auto callback) { + callback(code.to_vertical_mirror()); + }, RELEASE_TO(data)); -static RangesUnion extend_type_ver(RawCode seed, size_t reserve) { - RangesUnion data {}; - extend(seed, reserve, [](const RawCode code, auto callback) { - callback(code.to_vertical_mirror()); - }, [&data](const RawCode raw_code) { - const auto code = raw_code.to_common_code().unwrap(); - data.ranges(code >> 32).emplace_back(static_cast(code)); - }); - return data; -} + } else if constexpr(TYPE == Group::MirrorType::Centro) { -static RangesUnion extend_type_diag(RawCode seed, size_t reserve) { - RangesUnion data {}; - extend(seed, reserve, [](const RawCode code, auto callback) { - callback(code.to_diagonal_mirror()); - }, [&data](const RawCode raw_code) { - const auto code = raw_code.to_common_code().unwrap(); - data.ranges(code >> 32).emplace_back(static_cast(code)); - }); - return data; -} + extend(seed, reserve, [](const RawCode code, auto callback) { + callback(code.to_diagonal_mirror()); + }, RELEASE_TO(data)); + + } else if constexpr(TYPE == Group::MirrorType::Full) { + + 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)); + + } -static RangesUnion extend_type_x(RawCode seed, size_t reserve) { - RangesUnion data {}; - extend(seed, reserve, [](const RawCode code, auto callback) { - const auto mirror_1 = code.to_vertical_mirror(); - callback(mirror_1); - if (const auto mirror_2 = code.to_horizontal_mirror(); mirror_2 != code) { - callback(mirror_2); - callback(mirror_1.to_horizontal_mirror()); - } - }, [&data](const RawCode raw_code) { - const auto code = raw_code.to_common_code().unwrap(); - data.ranges(code >> 32).emplace_back(static_cast(code)); - }); 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 spawn_pattern(RawCode seed, const size_t reserve, MFunc add_mirror, RFunc release) { - - std::vector codes; + std::vector queue; std::vector mirrors; - phmap::flat_hash_map cases; // + phmap::flat_hash_map cases; - codes.reserve(reserve); - mirrors.reserve(reserve); // TODO: cal max size-coff + queue.reserve(reserve); + mirrors.reserve(reserve); cases.reserve(static_cast(reserve * 1.56)); - auto core = MaskMover([&codes, &cases, &mirrors, add_mirror](RawCode code, uint64_t hint) { + 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; } - codes.emplace_back(code); + queue.emplace_back(code); add_mirror(code, [&cases, &mirrors](RawCode mirror) { - cases.emplace(mirror, 0); + cases.emplace(mirror, 0); // without hint mirrors.emplace_back(mirror); }); }); uint64_t offset = 0; - codes.emplace_back(seed); - cases.emplace(seed, 0); // without hint + queue.emplace_back(seed); + cases.emplace(seed, 0); add_mirror(seed, [&mirrors, &cases](RawCode mirror) { - cases.emplace(mirror, 0); + cases.emplace(mirror, 0); // without hint mirrors.emplace_back(mirror); }); - while (offset != codes.size()) { - const auto curr = codes[offset++]; - core.next_cases(curr, cases.find(curr)->second); + while (offset != queue.size()) { + const auto curr = queue[offset++]; + mover.next_cases(curr, cases.find(curr)->second); } - for (const auto code : codes) { - release(code); - } - for (const auto code : mirrors) { - release(code); - } + for (const auto code : queue) { release(code); } + for (const auto code : mirrors) { release(code); } } +#define OUTPUT(VAR, EXPL, OUT) \ + const auto VAR = (EXPL).to_common_code().unwrap(); \ + OUT.ranges(VAR >> 32).emplace_back(static_cast(VAR)) + +#define KLSK_CONCAT_IMPL(X, Y) X##Y + +#define KLSK_CONCAT(X, Y) KLSK_CONCAT_IMPL(X, Y) + +#define OUTPUT_IMPL(VAR, EXPL, OUT) \ + const auto VAR = (EXPL).to_common_code().unwrap(); \ + OUT.ranges(VAR >> 32).emplace_back(static_cast(VAR)) + +#define OUTPUT(EXPL, OUT) \ + OUTPUT_IMPL(KLSK_CONCAT(c_, __COUNTER__), EXPL, OUT) + KLSK_NOINLINE static void spawn_full_pattern(RawCode seed, const size_t reserve, RangesUnion &output) { spawn_pattern(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) { - const auto code = raw_code.to_common_code().unwrap(); - output.ranges(code >> 32).emplace_back(static_cast(code)); + // const auto code = raw_code.to_common_code().unwrap(); + // output.ranges(code >> 32).emplace_back(static_cast(code)); + // OUTPUT(code, raw_code, output); + OUTPUT(raw_code, output); }); } KLSK_NOINLINE static void spawn_hor_pattern(RawCode seed, const size_t reserve, RangesUnion &output) { spawn_pattern(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) { - const auto code = raw_code.to_common_code().unwrap(); - output.ranges(code >> 32).emplace_back(static_cast(code)); + // const auto code = raw_code.to_common_code().unwrap(); + // output.ranges(code >> 32).emplace_back(static_cast(code)); + OUTPUT(raw_code, output); - const auto code_ = raw_code.to_vertical_mirror().to_common_code().unwrap(); - output.ranges(code_ >> 32).emplace_back(static_cast(code_)); + // const auto code_ = raw_code.to_vertical_mirror().to_common_code().unwrap(); + // output.ranges(code_ >> 32).emplace_back(static_cast(code_)); + OUTPUT(raw_code.to_vertical_mirror(), output); }); } KLSK_NOINLINE static void spawn_ver_pattern(RawCode seed, const size_t reserve, RangesUnion &output) { spawn_pattern(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) { - const auto code = raw_code.to_common_code().unwrap(); - output.ranges(code >> 32).emplace_back(static_cast(code)); + // const auto code = raw_code.to_common_code().unwrap(); + // output.ranges(code >> 32).emplace_back(static_cast(code)); + OUTPUT(raw_code, output); - const auto code_ = raw_code.to_horizontal_mirror().to_common_code().unwrap(); - output.ranges(code_ >> 32).emplace_back(static_cast(code_)); + // const auto code_ = raw_code.to_horizontal_mirror().to_common_code().unwrap(); + // output.ranges(code_ >> 32).emplace_back(static_cast(code_)); + OUTPUT(raw_code.to_horizontal_mirror(), output); }); } KLSK_NOINLINE static void spawn_ord_pattern(RawCode seed, const size_t reserve, RangesUnion &output) { spawn_pattern(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) { - const auto code = raw_code.to_common_code().unwrap(); - output.ranges(code >> 32).emplace_back(static_cast(code)); + // const auto code = raw_code.to_common_code().unwrap(); + // output.ranges(code >> 32).emplace_back(static_cast(code)); + OUTPUT(raw_code, output); - const auto code_1 = raw_code.to_vertical_mirror().to_common_code().unwrap(); - output.ranges(code_1 >> 32).emplace_back(static_cast(code_1)); + // const auto code_1 = raw_code.to_vertical_mirror().to_common_code().unwrap(); + // output.ranges(code_1 >> 32).emplace_back(static_cast(code_1)); + OUTPUT(raw_code.to_vertical_mirror(), output); - const auto code_2 = raw_code.to_horizontal_mirror().to_common_code().unwrap(); - output.ranges(code_2 >> 32).emplace_back(static_cast(code_2)); + // const auto code_2 = raw_code.to_horizontal_mirror().to_common_code().unwrap(); + // output.ranges(code_2 >> 32).emplace_back(static_cast(code_2)); + OUTPUT(raw_code.to_horizontal_mirror(), output); - const auto code_3 = raw_code.to_diagonal_mirror().to_common_code().unwrap(); - output.ranges(code_3 >> 32).emplace_back(static_cast(code_3)); + // const auto code_3 = raw_code.to_diagonal_mirror().to_common_code().unwrap(); + // output.ranges(code_3 >> 32).emplace_back(static_cast(code_3)); + OUTPUT(raw_code.to_diagonal_mirror(), output); // TODO: perf it }); } @@ -263,7 +293,8 @@ RangesUnion Group::cases() const { // return GroupUnion::unsafe_create(type_id_).cases(); } - auto seed = CommonCode::unsafe_create(PATTERN_DATA[flat_id()] >> 23).to_raw_code(); + const auto seed_val = PATTERN_DATA[flat_id()] >> 23; + auto seed = CommonCode::unsafe_create(seed_val).to_raw_code(); if (toward_ == Toward::B) { seed = seed.to_horizontal_mirror(); } else if (toward_ == Toward::C) { @@ -272,20 +303,96 @@ RangesUnion Group::cases() const { seed = seed.to_diagonal_mirror(); } + // const auto centro_mirror = [](const RawCode code, auto callback) { + // callback(code.to_diagonal_mirror()); + // }; + // const auto vertical_mirror = [](const RawCode code, auto callback) { + // callback(code.to_vertical_mirror()); + // }; + // const auto horizontal_mirror = [](const RawCode code, auto callback) { + // if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) { + // callback(m_hor); + // } + // }; + // const auto full_mirror = [](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()); + // } + // }; + + // TODO: how to reserve `data` RangesUnion data; + + // if (mirror_type() == MirrorType::Ordinary) { + // // std::println("Ordinary"); // 24892 + // // extend(seed, size(), [](RawCode, auto) {}, RELEASE_TO(data)); + // + // data = extend_ord(seed, size()); + // + // } else if (mirror_type() == MirrorType::Horizontal) { + // // std::println("Horizontal"); // 294 + // // extend(seed, size(), [](const RawCode code, auto callback) { + // // if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) { + // // callback(m_hor); + // // } + // // }, RELEASE_TO(data)); + // // return extend_hor(seed, size()); + // + // data = extend_hor(seed, size()); + // + // } else if (mirror_type() == MirrorType::Vertical) { + // // std::println("Vertical"); // 54 + // // extend(seed, size(), vertical_mirror, RELEASE_TO(data)); + // + // data = extend_ver(seed, size()); + // + // } else if (mirror_type() == MirrorType::Full) { + // // std::println("Full"); // 3 + // // extend(seed, size(), full_mirror, RELEASE_TO(data)); + // + // data = extend_type_x(seed, size()); + // + // } else { + // // std::println("Centro"); // 4 + // // extend(seed, size(), centro_mirror, RELEASE_TO(data)); + // + // data = extend_diag(seed, size()); + // + // } + if (mirror_type() == MirrorType::Full) { - data = extend_type_x(seed, size()); + // data = extend_type_full(seed, size()); + data = extend_type_xxx(seed, size()); } else if (mirror_type() == MirrorType::Horizontal) { - data = extend_type_hor(seed, size()); + // data = extend_type_hor(seed, size()); + data = extend_type_xxx(seed, size()); } else if (mirror_type() == MirrorType::Vertical) { - data = extend_type_ver(seed, size()); + // data = extend_type_vrt(seed, size()); + data = extend_type_xxx(seed, size()); } else if (mirror_type() == MirrorType::Centro) { - data = extend_type_diag(seed, size()); + // data = extend_type_diag(seed, size()); + data = extend_type_xxx(seed, size()); } else { - data = extend_type_common(seed, size()); + // data = extend_type_ord(seed, size()); + data = extend_type_xxx(seed, size()); } - for (int head = 0; head < 16; ++head) { + // if (mirror_type() == MirrorType::Ordinary) { + // data = extend_type_ord(seed, size()); + // } else if (mirror_type() == MirrorType::Horizontal) { + // data = extend_type_hor(seed, size()); + // } else if (mirror_type() == MirrorType::Vertical) { + // data = extend_type_vrt(seed, size()); + // } else if (mirror_type() == MirrorType::Full) { + // data = extend_type_full(seed, size()); + // } else { + // data = extend_type_diag(seed, size()); + // } + + for (const auto head : RangesUnion::Heads) { std::stable_sort(data.ranges(head).begin(), data.ranges(head).end()); } return data;