Browse Source

perf: upgrade group interfaces

legacy
Dnomd343 2 months ago
parent
commit
e42b54c9bf
  1. 82
      src/core/group/group.h
  2. 8
      src/core/group/internal/group_cases_pro.cc
  3. 8
      src/core/group/internal/group_pro.cc
  4. 127
      src/core/group/internal/group_pro.inl
  5. 22
      src/core/group/internal/group_union.inl
  6. 2
      src/core/main.cc
  7. 20
      src/core_test/cases/group_pro.cc
  8. 2
      src/core_test/cases/group_union.cc

82
src/core/group/group.h

@ -115,6 +115,8 @@ public:
[[nodiscard]] std::vector<GroupPro> 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<GroupPro> 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;
};

8
src/core/group/internal/group_cases_pro.cc

@ -45,7 +45,7 @@ std::vector<std::vector<RangesUnion>> build_ranges_unions() {
std::vector<RangesUnion> 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<case_info_t> 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,
};
}

8
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<uint64_t, GroupPro> 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;

127
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> 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);
}
}

22
src/core/group/internal/group_union.inl

@ -64,22 +64,22 @@ inline std::vector<GroupPro> GroupUnion::groups_pro() const {
std::vector<GroupPro> 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;
}
}

2
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;

20
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<uint64_t> 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<uint64_t> cases;

2
src/core_test/cases/group_union.cc

@ -112,7 +112,7 @@ TEST(GroupUnion, values_pro) {
std::vector<uint32_t> 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);

Loading…
Cancel
Save