From e42b54c9bf0616997b8a00515a64cb4025efc801 Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Sat, 19 Oct 2024 12:30:28 +0800 Subject: [PATCH] perf: upgrade group interfaces --- src/core/group/group.h | 82 +++++++++---- src/core/group/internal/group_cases_pro.cc | 8 +- src/core/group/internal/group_pro.cc | 8 +- src/core/group/internal/group_pro.inl | 127 +++++++++++++-------- src/core/group/internal/group_union.inl | 22 ++-- src/core/main.cc | 2 +- src/core_test/cases/group_pro.cc | 20 ++-- src/core_test/cases/group_union.cc | 2 +- 8 files changed, 167 insertions(+), 104 deletions(-) diff --git a/src/core/group/group.h b/src/core/group/group.h index 8369e77..a3ba5e2 100644 --- a/src/core/group/group.h +++ b/src/core/group/group.h @@ -115,6 +115,8 @@ public: [[nodiscard]] std::vector groups_pro() const; + // TODO: get target pattern_id + // ------------------------------------------------------------------------------------- // /// Get all cases under the current type id. @@ -161,33 +163,65 @@ class GroupPro { public: GroupPro() = delete; + // ------------------------------------------------------------------------------------- // + + enum class Toward { + A = 0, // baseline + B = 1, // horizontal mirror + C = 2, // vertical mirror + D = 3, // diagonal mirror + }; + enum class MirrorType { - FullMirror = 0, - HorizontalMirror = 1, - CentroMirror = 2, - VerticalMirror = 3, - NonMirror = 4, + Full = 0, // fully self-symmetry + Horizontal = 1, // horizontal self-symmetry + Centro = 2, // centrosymmetric + Vertical = 3, // vertical self-symmetry + Ordinary = 4, // non self-symmetric }; - // NOTE: using enum `MirrorTowards` - static GroupPro unsafe_create(uint32_t type_id, uint32_t pattern_id, uint32_t mirror_toward) { - return {type_id, pattern_id, mirror_toward}; - } + // ------------------------------------------------------------------------------------- // - [[nodiscard]] constexpr uint32_t type_id() const { - return type_id_; - } + /// Get the mirror toward. + [[nodiscard]] constexpr Toward toward() const; - [[nodiscard]] constexpr uint32_t pattern_id() const { - return pattern_id_; - } + /// Get the original type id. + [[nodiscard]] constexpr uint32_t type_id() const; - [[nodiscard]] constexpr uint32_t mirror_toward() const { - return mirror_toward_; - } + /// Get the original pattern id. + [[nodiscard]] constexpr uint32_t pattern_id() const; + + // ------------------------------------------------------------------------------------- // + + /// Create Group without any check. + static constexpr GroupPro unsafe_create(uint32_t type_id, + uint32_t pattern_id, Toward toward); + /// Create Group with validity check. + static constexpr std::optional create(uint32_t type_id, + uint32_t pattern_id, Toward toward); + + // ------------------------------------------------------------------------------------- // + + /// Get all cases under current group. + [[nodiscard]] RangesUnion cases() const; + + /// Get the number of klotski cases contained. [[nodiscard]] constexpr uint32_t size() const; + // ------------------------------------------------------------------------------------- // + + /// Create Group from RawCode. + static GroupPro from_raw_code(codec::RawCode raw_code); + + /// Create Group from ShortCode. + static GroupPro from_short_code(codec::ShortCode short_code); + + /// Create Group from CommonCode. + static GroupPro from_common_code(codec::CommonCode common_code); + + // ------------------------------------------------------------------------------------- // + [[nodiscard]] constexpr MirrorType mirror_type() const; [[nodiscard]] constexpr bool is_vertical_mirror() const; @@ -196,22 +230,20 @@ public: [[nodiscard]] constexpr GroupPro to_vertical_mirror() const; [[nodiscard]] constexpr GroupPro to_horizontal_mirror() const; - [[nodiscard]] RangesUnion cases() const; - - static GroupPro from_raw_code(codec::RawCode raw_code); - static GroupPro from_common_code(codec::CommonCode common_code); + // ------------------------------------------------------------------------------------- // private: uint32_t type_id_; + Toward toward_; uint32_t pattern_id_; - uint32_t mirror_toward_; - GroupPro(uint32_t type_id, uint32_t pattern_id, uint32_t mirror_toward) { + GroupPro(uint32_t type_id, uint32_t pattern_id, Toward toward) { type_id_ = type_id; pattern_id_ = pattern_id; - mirror_toward_ = mirror_toward; + toward_ = toward; } + /// Tiled merge of type_id and pattern_id. [[nodiscard]] constexpr uint32_t flat_id() const; }; diff --git a/src/core/group/internal/group_cases_pro.cc b/src/core/group/internal/group_cases_pro.cc index 2d7bd61..c9762e6 100644 --- a/src/core/group/internal/group_cases_pro.cc +++ b/src/core/group/internal/group_cases_pro.cc @@ -45,7 +45,7 @@ std::vector> build_ranges_unions() { std::vector tmp {4}; for (auto group : groups) { - tmp[group.mirror_toward()] = group.cases(); + tmp[(int)group.toward()] = group.cases(); } unions.emplace_back(tmp); } @@ -62,7 +62,7 @@ static std::vector build_tmp_data() { auto group_union = GroupUnion::unsafe_create(type_id); for (auto group : group_union.groups_pro()) { uint32_t pattern_id = group.pattern_id(); - uint32_t toward_id = group.mirror_toward(); + auto toward_id = (uint32_t)group.toward(); // TODO: batch mirror base on pattern auto codes = group.cases().codes(); @@ -90,7 +90,7 @@ CommonCode GroupCasesPro::fast_parse(CaseInfo info) { auto flat_id = PATTERN_OFFSET[info.group.type_id()] + info.group.pattern_id(); - auto &cases = (*ru_data)[flat_id][info.group.mirror_toward()]; + auto &cases = (*ru_data)[flat_id][(int)info.group.toward()]; // TODO: make offset table for perf uint64_t head = 0; @@ -115,7 +115,7 @@ GroupCasesPro::CaseInfo GroupCasesPro::fast_obtain(codec::ShortCode short_code) auto case_id = (*rev_data)[short_code.unwrap()].case_id; return CaseInfo { - .group = GroupPro::unsafe_create(type_id, pattern_id, toward_id), + .group = GroupPro::unsafe_create(type_id, pattern_id, (GroupPro::Toward)toward_id), .case_id = case_id, }; } diff --git a/src/core/group/internal/group_pro.cc b/src/core/group/internal/group_pro.cc index 581dc0a..4c9161a 100644 --- a/src/core/group/internal/group_pro.cc +++ b/src/core/group/internal/group_pro.cc @@ -15,11 +15,11 @@ RangesUnion GroupPro::cases() const { auto seed = CommonCode::unsafe_create(GROUP_PRO_SEED[flat_id()]); // NOTE: convert as RawCode directly - if (mirror_toward_ == 1) { + if (toward_ == Toward::B) { seed = seed.to_horizontal_mirror(); - } else if (mirror_toward_ == 2) { + } else if (toward_ == Toward::C) { seed = seed.to_vertical_mirror(); - } else if (mirror_toward_ == 3) { + } else if (toward_ == Toward::D) { // NOTE: avoid multi convert seed = seed.to_vertical_mirror().to_horizontal_mirror(); } @@ -47,7 +47,7 @@ static std::unordered_map build_map_data() { uint32_t pattern_id = (raw >> 38) & 0b1111111111; uint32_t toward = (raw >> 36) & 0b11; auto seed = CommonCode::unsafe_create(raw & (uint64_t)0xFFFFFFFFF).unwrap(); - auto group = GroupPro::unsafe_create(type_id, pattern_id, toward); + auto group = GroupPro::unsafe_create(type_id, pattern_id, (GroupPro::Toward)toward); data.emplace(seed, group); } return data; diff --git a/src/core/group/internal/group_pro.inl b/src/core/group/internal/group_pro.inl index 3a07ad1..984aae5 100644 --- a/src/core/group/internal/group_pro.inl +++ b/src/core/group/internal/group_pro.inl @@ -4,6 +4,33 @@ namespace klotski::cases { +[[nodiscard]] constexpr uint32_t GroupPro::type_id() const { + return type_id_; +} + +[[nodiscard]] constexpr uint32_t GroupPro::pattern_id() const { + return pattern_id_; +} + +[[nodiscard]] constexpr GroupPro::Toward GroupPro::toward() const { + return toward_; +} + +constexpr GroupPro GroupPro::unsafe_create(uint32_t type_id, uint32_t pattern_id, Toward toward) { + return {type_id, pattern_id, toward}; +} + +constexpr std::optional GroupPro::create(uint32_t type_id, uint32_t pattern_id, Toward toward) { + if (type_id >= TYPE_ID_LIMIT) { + return std::nullopt; + } + if (pattern_id >= GroupUnion::unsafe_create(type_id).pattern_num()) { + return std::nullopt; + } + // TODO: toward check + return unsafe_create(type_id, pattern_id, toward); +} + constexpr uint32_t GroupPro::flat_id() const { return PATTERN_OFFSET[type_id_] + pattern_id_; } @@ -12,6 +39,10 @@ constexpr uint32_t GroupPro::size() const { return GROUP_PRO_SIZE[flat_id()]; } +inline GroupPro GroupPro::from_short_code(codec::ShortCode short_code) { + return from_common_code(short_code.to_common_code()); +} + inline GroupPro GroupPro::from_common_code(codec::CommonCode common_code) { return from_raw_code(common_code.to_raw_code()); } @@ -19,96 +50,96 @@ inline GroupPro GroupPro::from_common_code(codec::CommonCode common_code) { constexpr GroupPro::MirrorType GroupPro::mirror_type() const { switch (GROUP_PRO_TYPE[flat_id()]) { case 0: - return MirrorType::FullMirror; + return MirrorType::Full; case 1: - return MirrorType::HorizontalMirror; + return MirrorType::Horizontal; case 2: - return MirrorType::CentroMirror; + return MirrorType::Centro; case 3: - return MirrorType::VerticalMirror; + return MirrorType::Vertical; case 4: - return MirrorType::NonMirror; + return MirrorType::Ordinary; } } constexpr bool GroupPro::is_vertical_mirror() const { switch (mirror_type()) { - case MirrorType::FullMirror: + case MirrorType::Full: return true; - case MirrorType::HorizontalMirror: + case MirrorType::Horizontal: return false; - case MirrorType::CentroMirror: + case MirrorType::Centro: return false; - case MirrorType::VerticalMirror: + case MirrorType::Vertical: return true; - case MirrorType::NonMirror: + case MirrorType::Ordinary: return false; } } constexpr bool GroupPro::is_horizontal_mirror() const { switch (mirror_type()) { - case MirrorType::FullMirror: + case MirrorType::Full: return true; - case MirrorType::HorizontalMirror: + case MirrorType::Horizontal: return true; - case MirrorType::CentroMirror: + case MirrorType::Centro: return false; - case MirrorType::VerticalMirror: + case MirrorType::Vertical: return false; - case MirrorType::NonMirror: + case MirrorType::Ordinary: return false; } } constexpr GroupPro GroupPro::to_vertical_mirror() const { switch (mirror_type()) { - case MirrorType::FullMirror: + case MirrorType::Full: return *this; - case MirrorType::HorizontalMirror: - if (mirror_toward_ == 0) { - return GroupPro::unsafe_create(type_id_, pattern_id_, 2); + case MirrorType::Horizontal: + if (toward_ == Toward::A) { + return GroupPro::unsafe_create(type_id_, pattern_id_, Toward::C); } - return GroupPro::unsafe_create(type_id_, pattern_id_, 0); - case MirrorType::CentroMirror: - if (mirror_toward_ == 0) { - return GroupPro::unsafe_create(type_id_, pattern_id_, 1); + return GroupPro::unsafe_create(type_id_, pattern_id_, Toward::A); + case MirrorType::Centro: + if (toward_ == Toward::A) { + return GroupPro::unsafe_create(type_id_, pattern_id_, Toward::B); } - return GroupPro::unsafe_create(type_id_, pattern_id_, 0); - case MirrorType::VerticalMirror: + return GroupPro::unsafe_create(type_id_, pattern_id_, Toward::A); + case MirrorType::Vertical: return *this; - case MirrorType::NonMirror: - if (mirror_toward_ == 0) { - return GroupPro::unsafe_create(type_id_, pattern_id_, 2); - } else if (mirror_toward_ == 1) { - return GroupPro::unsafe_create(type_id_, pattern_id_, 3); - } else if (mirror_toward_ == 2) { - return GroupPro::unsafe_create(type_id_, pattern_id_, 0); + case MirrorType::Ordinary: + if (toward_ == Toward::A) { + return GroupPro::unsafe_create(type_id_, pattern_id_, Toward::C); + } else if (toward_ == Toward::B) { + return GroupPro::unsafe_create(type_id_, pattern_id_, Toward::D); + } else if (toward_ == Toward::C) { + return GroupPro::unsafe_create(type_id_, pattern_id_, Toward::A); } - return GroupPro::unsafe_create(type_id_, pattern_id_, 1); + return GroupPro::unsafe_create(type_id_, pattern_id_, Toward::B); } } constexpr GroupPro GroupPro::to_horizontal_mirror() const { switch (mirror_type()) { - case MirrorType::FullMirror: - case MirrorType::HorizontalMirror: + case MirrorType::Full: + case MirrorType::Horizontal: return *this; - case MirrorType::CentroMirror: - case MirrorType::VerticalMirror: - if (mirror_toward_ == 0) { - return GroupPro::unsafe_create(type_id_, pattern_id_, 1); + case MirrorType::Centro: + case MirrorType::Vertical: + if (toward_ == Toward::A) { + return GroupPro::unsafe_create(type_id_, pattern_id_, Toward::B); } - return GroupPro::unsafe_create(type_id_, pattern_id_, 0); - case MirrorType::NonMirror: - if (mirror_toward_ == 0) { - return GroupPro::unsafe_create(type_id_, pattern_id_, 1); - } else if (mirror_toward_ == 1) { - return GroupPro::unsafe_create(type_id_, pattern_id_, 0); - } else if (mirror_toward_ == 2) { - return GroupPro::unsafe_create(type_id_, pattern_id_, 3); + return GroupPro::unsafe_create(type_id_, pattern_id_, Toward::A); + case MirrorType::Ordinary: + if (toward_ == Toward::A) { + return GroupPro::unsafe_create(type_id_, pattern_id_, Toward::B); + } else if (toward_ == Toward::B) { + return GroupPro::unsafe_create(type_id_, pattern_id_, Toward::A); + } else if (toward_ == Toward::C) { + return GroupPro::unsafe_create(type_id_, pattern_id_, Toward::D); } - return GroupPro::unsafe_create(type_id_, pattern_id_, 2); + return GroupPro::unsafe_create(type_id_, pattern_id_, Toward::C); } } diff --git a/src/core/group/internal/group_union.inl b/src/core/group/internal/group_union.inl index fb813be..91d4101 100644 --- a/src/core/group/internal/group_union.inl +++ b/src/core/group/internal/group_union.inl @@ -64,22 +64,22 @@ inline std::vector GroupUnion::groups_pro() const { std::vector groups; groups.reserve(group_num()); for (uint32_t pattern_id = 0; pattern_id < pattern_num(); ++pattern_id) { - auto group = GroupPro::unsafe_create(type_id_, pattern_id, 0); + auto group = GroupPro::unsafe_create(type_id_, pattern_id, GroupPro::Toward::A); groups.emplace_back(group); switch (group.mirror_type()) { - case GroupPro::MirrorType::FullMirror: + case GroupPro::MirrorType::Full: continue; - case GroupPro::MirrorType::HorizontalMirror: - groups.emplace_back(GroupPro::unsafe_create(type_id_, pattern_id, 2)); + case GroupPro::MirrorType::Horizontal: + groups.emplace_back(GroupPro::unsafe_create(type_id_, pattern_id, GroupPro::Toward::C)); break; - case GroupPro::MirrorType::CentroMirror: - case GroupPro::MirrorType::VerticalMirror: - groups.emplace_back(GroupPro::unsafe_create(type_id_, pattern_id, 1)); + case GroupPro::MirrorType::Centro: + case GroupPro::MirrorType::Vertical: + groups.emplace_back(GroupPro::unsafe_create(type_id_, pattern_id, GroupPro::Toward::B)); break; - case GroupPro::MirrorType::NonMirror: - groups.emplace_back(GroupPro::unsafe_create(type_id_, pattern_id, 1)); - groups.emplace_back(GroupPro::unsafe_create(type_id_, pattern_id, 2)); - groups.emplace_back(GroupPro::unsafe_create(type_id_, pattern_id, 3)); + case GroupPro::MirrorType::Ordinary: + groups.emplace_back(GroupPro::unsafe_create(type_id_, pattern_id, GroupPro::Toward::B)); + groups.emplace_back(GroupPro::unsafe_create(type_id_, pattern_id, GroupPro::Toward::C)); + groups.emplace_back(GroupPro::unsafe_create(type_id_, pattern_id, GroupPro::Toward::D)); break; } } diff --git a/src/core/main.cc b/src/core/main.cc index 4ab1b40..c4f3761 100644 --- a/src/core/main.cc +++ b/src/core/main.cc @@ -64,7 +64,7 @@ int main() { GroupCasesPro::build(); auto kk = GroupCasesPro::fast_obtain(CommonCode::unsafe_create(0x1A9BF0C00).to_short_code()); - std::cout << std::format("{}-{}-{}-{}", kk.group.type_id(), kk.group.pattern_id(), kk.group.mirror_toward(), kk.case_id) << std::endl; + std::cout << std::format("{}-{}-{}-{}", kk.group.type_id(), kk.group.pattern_id(), (int)kk.group.toward(), kk.case_id) << std::endl; auto code = GroupCasesPro::fast_parse(kk); std::cout << code << std::endl; diff --git a/src/core_test/cases/group_pro.cc b/src/core_test/cases/group_pro.cc index 22ea40b..7f60872 100644 --- a/src/core_test/cases/group_pro.cc +++ b/src/core_test/cases/group_pro.cc @@ -21,23 +21,23 @@ TEST(GroupPro, demo) { std::cout << GroupUnion::unsafe_create(169).group_num() << std::endl; std::cout << (int)helper::pattern_mirror_type(169, 0) << std::endl; - std::cout << (int)GroupPro::unsafe_create(169, 0, 0).mirror_type() << std::endl; + std::cout << (int)GroupPro::unsafe_create(169, 0, GroupPro::Toward::A).mirror_type() << std::endl; std::cout << std::format("{}", helper::pattern_toward_list(169, 0)) << std::endl; - std::cout << (int)GroupUnion::unsafe_create(169).groups_pro()[0].mirror_toward() << std::endl; - std::cout << (int)GroupUnion::unsafe_create(169).groups_pro()[1].mirror_toward() << std::endl; + std::cout << (int)GroupUnion::unsafe_create(169).groups_pro()[0].toward() << std::endl; + std::cout << (int)GroupUnion::unsafe_create(169).groups_pro()[1].toward() << std::endl; auto group_1 = GroupUnion::unsafe_create(169).groups_pro()[0]; - EXPECT_EQ(group_1.cases().codes(), helper::group_cases(169, 0, group_1.mirror_toward())); + EXPECT_EQ(group_1.cases().codes(), helper::group_cases(169, 0, (uint32_t)group_1.toward())); auto group_2 = GroupUnion::unsafe_create(169).groups_pro()[1]; - EXPECT_EQ(group_2.cases().codes(), helper::group_cases(169, 0, group_2.mirror_toward())); + EXPECT_EQ(group_2.cases().codes(), helper::group_cases(169, 0, (uint32_t)group_2.toward())); } TEST(GroupPro, cases) { GROUP_UNION_PARALLEL({ for (auto group : group_union.groups_pro()) { - const auto &cases = helper::group_cases(group.type_id(), group.pattern_id(), group.mirror_toward()); + const auto &cases = helper::group_cases(group.type_id(), group.pattern_id(), (uint32_t)group.toward()); EXPECT_EQ(group.size(), cases.size()); EXPECT_EQ(group.cases().codes(), cases); @@ -46,12 +46,12 @@ TEST(GroupPro, cases) { auto g1 = GroupPro::from_common_code(cases.front()); EXPECT_EQ(g1.type_id(), group.type_id()); EXPECT_EQ(g1.pattern_id(), group.pattern_id()); - EXPECT_EQ(g1.mirror_toward(), group.mirror_toward()); + EXPECT_EQ(g1.toward(), group.toward()); auto g2 = GroupPro::from_common_code(cases.back()); EXPECT_EQ(g2.type_id(), group.type_id()); EXPECT_EQ(g2.pattern_id(), group.pattern_id()); - EXPECT_EQ(g2.mirror_toward(), group.mirror_toward()); + EXPECT_EQ(g2.toward(), group.toward()); } }); } @@ -62,7 +62,7 @@ TEST(GroupPro, v_mirror) { auto g = group.to_vertical_mirror(); EXPECT_EQ(group.type_id(), g.type_id()); EXPECT_EQ(group.pattern_id(), g.pattern_id()); - if (group.mirror_toward() == g.mirror_toward()) { + if (group.toward() == g.toward()) { EXPECT_TRUE(group.is_vertical_mirror()); std::unordered_set cases; @@ -102,7 +102,7 @@ TEST(GroupPro, h_mirror) { auto g = group.to_horizontal_mirror(); EXPECT_EQ(group.type_id(), g.type_id()); EXPECT_EQ(group.pattern_id(), g.pattern_id()); - if (group.mirror_toward() == g.mirror_toward()) { + if (group.toward() == g.toward()) { EXPECT_TRUE(group.is_horizontal_mirror()); std::unordered_set cases; diff --git a/src/core_test/cases/group_union.cc b/src/core_test/cases/group_union.cc index 785d0b7..03b464a 100644 --- a/src/core_test/cases/group_union.cc +++ b/src/core_test/cases/group_union.cc @@ -112,7 +112,7 @@ TEST(GroupUnion, values_pro) { std::vector towards; for (auto group : groups) { if (group.pattern_id() == pattern_id) { - towards.emplace_back(group.mirror_toward()); + towards.emplace_back((uint32_t)group.toward()); } } auto exp_towards = helper::pattern_toward_list(type_id, pattern_id);