diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 217af06..dd29134 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -27,6 +27,7 @@ set(KLOTSKI_CORE_SRC group/internal/group.cc group/internal/group_pro.cc group/internal/group_cases.cc + group/internal/group_cases_pro.cc ranges/internal/spawn.cc ranges/internal/ranges.cc diff --git a/src/core/group/group.h b/src/core/group/group.h index 93360d8..8369e77 100644 --- a/src/core/group/group.h +++ b/src/core/group/group.h @@ -272,6 +272,23 @@ public: static std::vector extend(codec::RawCode raw_code, uint32_t reserve = 0); }; +class GroupCasesPro { +public: + struct CaseInfo { + GroupPro group; + uint32_t case_id; + }; + + // TODO: allow cal Group directly + + static void build(); + + static codec::CommonCode fast_parse(CaseInfo info); + + static CaseInfo fast_obtain(codec::ShortCode short_code); + +}; + class GroupCases { public: // TODO: rename as Info and changed as class diff --git a/src/core/group/internal/group_cases_pro.cc b/src/core/group/internal/group_cases_pro.cc new file mode 100644 index 0000000..2d7bd61 --- /dev/null +++ b/src/core/group/internal/group_cases_pro.cc @@ -0,0 +1,121 @@ +#include + +#include "group/group.h" + +using klotski::codec::ShortCode; +using klotski::codec::CommonCode; + +using klotski::cases::GroupPro; +using klotski::cases::GroupUnion; +using klotski::cases::RangesUnion; +using klotski::cases::GroupCasesPro; + +using klotski::cases::ALL_GROUP_NUM; +using klotski::cases::TYPE_ID_LIMIT; +using klotski::cases::ALL_CASES_NUM_; + +struct case_info_t { + uint32_t pattern_id : 10; + uint32_t toward_id : 2; + uint32_t case_id : 20; +}; + +static_assert(sizeof(case_info_t) == 4); + +// TODO: we need multi-thread support (Executor) + +static std::vector> *ru_data = nullptr; +static std::vector *rev_data = nullptr; + +std::vector> build_ranges_unions() { + std::vector> unions; + unions.reserve(ALL_GROUP_NUM); + + // TODO: add white list for single-group unions + + for (uint32_t type_id = 0; type_id < TYPE_ID_LIMIT; ++type_id) { + auto group_union = GroupUnion::unsafe_create(type_id); + for (uint32_t pattern_id = 0; pattern_id < group_union.pattern_num(); ++pattern_id) { + std::vector groups; + for (auto group : group_union.groups_pro()) { + if (group.pattern_id() == pattern_id) { + groups.emplace_back(group); + } + } + + std::vector tmp {4}; + for (auto group : groups) { + tmp[group.mirror_toward()] = group.cases(); + } + unions.emplace_back(tmp); + } + } + return unions; +} + +static std::vector build_tmp_data() { + std::vector data; + data.resize(ALL_CASES_NUM_); + ShortCode::speed_up(true); + + for (uint32_t type_id = 0; type_id < TYPE_ID_LIMIT; ++type_id) { + 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(); + + // TODO: batch mirror base on pattern + auto codes = group.cases().codes(); + for (uint32_t case_id = 0; case_id < codes.size(); ++case_id) { + auto short_code = codes[case_id].to_short_code(); + data[short_code.unwrap()] = case_info_t { + .pattern_id = pattern_id, + .toward_id = toward_id, + .case_id = case_id, + }; + } + } + } + return data; +} + +void GroupCasesPro::build() { + static auto data_1 = build_ranges_unions(); + static auto data_2 = build_tmp_data(); + ru_data = &data_1; + rev_data = &data_2; +} + +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()]; + // TODO: make offset table for perf + + uint64_t head = 0; + + for (;;) { + if (info.case_id >= cases[head].size()) { + info.case_id -= cases[head].size(); + ++head; + } else { + break; + } + } + + auto range = cases[head][info.case_id]; + return CommonCode::unsafe_create(head << 32 | range); +} + +GroupCasesPro::CaseInfo GroupCasesPro::fast_obtain(codec::ShortCode short_code) { + uint16_t type_id = GroupUnion::from_short_code(short_code).unwrap(); // NOTE: need to convert as CommonCode + uint16_t pattern_id = (*rev_data)[short_code.unwrap()].pattern_id; + uint16_t toward_id = (*rev_data)[short_code.unwrap()].toward_id; + auto case_id = (*rev_data)[short_code.unwrap()].case_id; + + return CaseInfo { + .group = GroupPro::unsafe_create(type_id, pattern_id, toward_id), + .case_id = case_id, + }; +} diff --git a/src/core/main.cc b/src/core/main.cc index fbf5365..5b9137e 100644 --- a/src/core/main.cc +++ b/src/core/main.cc @@ -30,6 +30,7 @@ using klotski::cases::Group; using klotski::cases::GroupPro; using klotski::cases::GroupCases; using klotski::cases::GroupUnion; +using klotski::cases::GroupCasesPro; using klotski::cases::TYPE_ID_LIMIT; using klotski::cases::ALL_CASES_NUM_; @@ -43,22 +44,30 @@ int main() { const auto start = std::chrono::system_clock::now(); - ShortCode::speed_up(true); - - std::unordered_set data_r; - std::unordered_set data_s; - std::unordered_set data_c; - data_r.reserve(ALL_CASES_NUM_); - data_s.reserve(ALL_CASES_NUM_); - data_c.reserve(ALL_CASES_NUM_); - for (auto code : AllCases::instance().fetch().codes()) { - data_c.emplace(code); - data_r.emplace(code.to_raw_code()); - data_s.emplace(code.to_short_code()); - } - std::cout << data_r.size() << std::endl; - std::cout << data_s.size() << std::endl; - std::cout << data_c.size() << std::endl; +// ShortCode::speed_up(true); +// +// std::unordered_set data_r; +// std::unordered_set data_s; +// std::unordered_set data_c; +// data_r.reserve(ALL_CASES_NUM_); +// data_s.reserve(ALL_CASES_NUM_); +// data_c.reserve(ALL_CASES_NUM_); +// for (auto code : AllCases::instance().fetch().codes()) { +// data_c.emplace(code); +// data_r.emplace(code.to_raw_code()); +// data_s.emplace(code.to_short_code()); +// } +// std::cout << data_r.size() << std::endl; +// std::cout << data_s.size() << std::endl; +// std::cout << data_c.size() << std::endl; + + 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; + + auto code = GroupCasesPro::fast_parse(kk); + std::cout << code << std::endl; // const auto common_code = CommonCode::unsafe_create(0x1A9BF0C00); // const auto group = Group::from_common_code(common_code);