From 0750c50b6067b2fef88deab00f0b907c831a83b5 Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Wed, 4 Oct 2023 13:27:06 +0800 Subject: [PATCH] update: using inline impl --- src/core/common_code/common_code.h | 48 +---------- src/core/common_code/inline_impl.h | 56 +++++++++++++ src/core/main.cc | 48 +++++------ src/core/raw_code/inline_impl.h | 70 ++++++++++++++++ src/core/raw_code/mirror.cc | 42 +++------- src/core/raw_code/raw_code.h | 54 +++---------- src/core/short_code/convert.cc | 81 +++++-------------- src/core/short_code/inline_impl.h | 56 +++++++++++++ src/core/short_code/offset/all_cases_offset.h | 18 ----- .../offset/{basic_ranges_offset.h => basic.h} | 25 +++++- .../{range_prefix_offset.h => range_prefix.h} | 13 ++- src/core/short_code/serialize.cc | 8 -- src/core/short_code/serialize_chars.h | 28 +++---- src/core/short_code/short_code.cc | 22 ++--- src/core/short_code/short_code.h | 48 +---------- src/core/short_code/sundry.cc | 66 +++++++++++++-- 16 files changed, 359 insertions(+), 324 deletions(-) create mode 100644 src/core/common_code/inline_impl.h create mode 100644 src/core/raw_code/inline_impl.h create mode 100644 src/core/short_code/inline_impl.h delete mode 100644 src/core/short_code/offset/all_cases_offset.h rename src/core/short_code/offset/{basic_ranges_offset.h => basic.h} (98%) rename src/core/short_code/offset/{range_prefix_offset.h => range_prefix.h} (73%) diff --git a/src/core/common_code/common_code.h b/src/core/common_code/common_code.h index 6522ac0..fd2f67c 100644 --- a/src/core/common_code/common_code.h +++ b/src/core/common_code/common_code.h @@ -101,51 +101,7 @@ private: static std::optional string_decode(const std::string &common_code) noexcept; }; -/// CommonCode compare implements. -inline bool operator==(uint64_t c1, CommonCode c2) noexcept { - return c1 == c2.unwrap(); -} - -inline bool operator==(CommonCode c1, CommonCode c2) noexcept { - return c1.unwrap() == c2.unwrap(); -} - -inline bool operator<(CommonCode c1, CommonCode c2) noexcept { - return c1.unwrap() < c2.unwrap(); -} - -inline bool operator>(CommonCode c1, CommonCode c2) noexcept { - return c1.unwrap() > c2.unwrap(); -} - -/// Get the original 64-bit code. -inline uint64_t CommonCode::unwrap() const noexcept { - return code_; -} - -/// Implicit conversion to 64-bit code. -inline CommonCode::operator uint64_t() const noexcept { - return code_; -} - -/// CommonCode create without any check. -inline CommonCode CommonCode::unsafe_create(uint64_t common_code) noexcept { - return *reinterpret_cast(&common_code); // init directly -} - -/// CommonCode create with valid check. -inline std::optional CommonCode::create(uint64_t common_code) noexcept { - if (!CommonCode::check(common_code)) { - return std::nullopt; - } - return CommonCode::unsafe_create(common_code); -} - -/// Output string encoding of CommonCode. -inline std::ostream& operator<<(std::ostream &out, CommonCode self) { - out << CommonCode::string_encode(self.code_); - return out; -} - } // namespace codec } // namespace klotski + +#include "inline_impl.h" diff --git a/src/core/common_code/inline_impl.h b/src/core/common_code/inline_impl.h new file mode 100644 index 0000000..6cfe1a3 --- /dev/null +++ b/src/core/common_code/inline_impl.h @@ -0,0 +1,56 @@ +#pragma once + +namespace klotski { +namespace codec { + +/// Get the original 64-bit code. +inline uint64_t CommonCode::unwrap() const noexcept { + return code_; +} + +/// Implicit conversion to 64-bit code. +inline CommonCode::operator uint64_t() const noexcept { + return code_; +} + +/// Equality comparison between CommonCode and numbers. +inline bool operator==(CommonCode c1, uint64_t c2) noexcept { + return c1.unwrap() == c2; +} + +/// CommonCode equal comparison implement. +inline bool operator==(CommonCode c1, CommonCode c2) noexcept { + return c1.unwrap() == c2.unwrap(); +} + +/// CommonCode less than comparison implement. +inline bool operator<(CommonCode c1, CommonCode c2) noexcept { + return c1.unwrap() < c2.unwrap(); +} + +/// CommonCode greater than comparison implement. +inline bool operator>(CommonCode c1, CommonCode c2) noexcept { + return c1.unwrap() > c2.unwrap(); +} + +/// CommonCode create without any check. +inline CommonCode CommonCode::unsafe_create(uint64_t common_code) noexcept { + return *reinterpret_cast(&common_code); // init directly +} + +/// CommonCode create with valid check. +inline std::optional CommonCode::create(uint64_t common_code) noexcept { + if (!CommonCode::check(common_code)) { + return std::nullopt; // invalid common code + } + return CommonCode::unsafe_create(common_code); +} + +/// Output string encoding of CommonCode. +inline std::ostream& operator<<(std::ostream &out, CommonCode self) { + out << CommonCode::string_encode(self.code_); + return out; +} + +} // namespace codec +} // namespace klotski diff --git a/src/core/main.cc b/src/core/main.cc index 72f8dae..4c59625 100644 --- a/src/core/main.cc +++ b/src/core/main.cc @@ -1,34 +1,29 @@ #include +#include "raw_code.h" +#include "all_cases.h" +#include "short_code.h" #include "common_code.h" -#include "all_cases/all_cases.h" using klotski::cases::AllCases; using klotski::cases::BasicRanges; +using klotski::codec::RawCode; +using klotski::codec::ShortCode; using klotski::codec::CommonCode; int main() { -// std::cout << (int)'0' << std::endl; -// std::cout << (int)'A' << std::endl; -// std::cout << CommonCode::string_encode(0x1A9BF0C00, false) << std::endl; -// std::cout << CommonCode::string_encode(0x0'10'00'00'00, false) << std::endl; -// return 0; +// AllCases::instance().build(); + BasicRanges::instance().build(); -// printf("%09llX\n", CommonCode::string_decode("1A9BF0C").value()); -// return 0; +// std::vector common_codes; +// common_codes.reserve(klotski::cases::ALL_CASES_NUM_); -// BasicRanges::Instance().Build(); - AllCases::Instance().Build(); - - std::vector common_codes; - common_codes.reserve(klotski::cases::ALL_CASES_NUM_); - - for (uint64_t head = 0; head < 15; ++head) { - for (auto range : AllCases::Instance().Fetch()[head]) { - common_codes.emplace_back(head << 32 | range); - } - } +// for (uint64_t head = 0; head < 15; ++head) { +// for (auto range : AllCases::instance().fetch()[head]) { +// common_codes.emplace_back(head << 32 | range); +// } +// } // std::vector common_codes_str; // common_codes_str.reserve(klotski::cases::ALL_CASES_NUM_); @@ -50,19 +45,12 @@ int main() { // CommonCode::string_decode(common_code_str); // } -// BasicRanges::Instance().Build(); - -// AllCases::Instance().Build(); -// AllCases::Instance().BuildParallel([](auto f) {f();}); -// AllCases::Instance().BuildParallelAsync([](auto f) {f();}, []() {}); +// BasicRanges::instance().build(); +// AllCases::instance().build(); +// AllCases::instance().build_parallel([](auto f) {f();}); +// AllCases::instance().build_parallel_async([](auto f) {f();}, []() {}); std::cerr << ((clock() - start) * 1000 / CLOCKS_PER_SEC) << "ms" << std::endl; -// for (uint64_t head = 0; head < 15; ++head) { -// for (auto range : AllCases::Instance().Fetch()[head]) { -// printf("%09llX\n", head << 32 | range); -// } -// } - return 0; } diff --git a/src/core/raw_code/inline_impl.h b/src/core/raw_code/inline_impl.h new file mode 100644 index 0000000..ca6d9a6 --- /dev/null +++ b/src/core/raw_code/inline_impl.h @@ -0,0 +1,70 @@ +#pragma once + +namespace klotski { +namespace codec { + +/// Get the original 64-bit code. +inline uint64_t RawCode::unwrap() const noexcept { + return code_; +} + +/// Implicit conversion to 64-bit code. +inline RawCode::operator uint64_t() const noexcept { + return code_; +} + +/// Equality comparison between RawCode and numbers. +inline bool operator==(RawCode r1, uint64_t r2) noexcept { + return r1.unwrap() == r2; +} + +/// RawCode equal comparison implement. +inline bool operator==(RawCode r1, RawCode r2) noexcept { + return r1.unwrap() == r2.unwrap(); +} + +/// RawCode create without any check. +inline RawCode RawCode::unsafe_create(uint64_t raw_code) noexcept { + return *reinterpret_cast(&raw_code); // init directly +} + +/// RawCode create with valid check. +inline std::optional RawCode::create(uint64_t raw_code) noexcept { + if (!RawCode::check(raw_code)) { + return std::nullopt; // invalid raw code + } + return RawCode::unsafe_create(raw_code); +} + +/// Calculate vertically symmetrical case. +inline RawCode RawCode::to_vertical_mirror() const noexcept { + return RawCode::unsafe_create(get_vertical_mirror(code_)); +} + +/// Calculate horizontally symmetrical case. +inline RawCode RawCode::to_horizontal_mirror() const noexcept { + return RawCode::unsafe_create(get_horizontal_mirror(code_)); +} + +/// Determine whether the case is vertically symmetrical. +inline bool RawCode::is_vertical_mirror() const noexcept { + return check_vertical_mirror(code_); +} + +/// Determine whether the case is horizontally symmetrical. +inline bool RawCode::is_horizontal_mirror() const noexcept { + return check_horizontal_mirror(code_); +} + +/// Determine whether two cases are vertically symmetrical to each other. +inline bool RawCode::is_vertical_mirror(RawCode raw_code) const noexcept { + return raw_code.code_ == get_vertical_mirror(code_); +} + +/// Determine whether two cases are horizontally symmetrical to each other. +inline bool RawCode::is_horizontal_mirror(RawCode raw_code) const noexcept { + return raw_code.code_ == get_horizontal_mirror(code_); +} + +} // namespace codec +} // namespace klotski diff --git a/src/core/raw_code/mirror.cc b/src/core/raw_code/mirror.cc index 59c1867..aecd7c5 100644 --- a/src/core/raw_code/mirror.cc +++ b/src/core/raw_code/mirror.cc @@ -4,35 +4,7 @@ namespace klotski { namespace codec { -/// ----------------------------- Mirror Convert ------------------------------ - -RawCode RawCode::to_vertical_mirror() const noexcept { - return RawCode::unsafe_create(get_vertical_mirror(code_)); -} - -RawCode RawCode::to_horizontal_mirror() const noexcept { - return RawCode::unsafe_create(get_horizontal_mirror(code_)); -} - -/// ------------------------------ Mirror Check ------------------------------- - -bool RawCode::is_vertical_mirror() const noexcept { - return check_vertical_mirror(code_); -} - -bool RawCode::is_horizontal_mirror() const noexcept { - return check_horizontal_mirror(code_); -} - -bool RawCode::is_vertical_mirror(RawCode raw_code) const noexcept { - return raw_code.unwrap() == get_vertical_mirror(code_); -} - -bool RawCode::is_horizontal_mirror(RawCode raw_code) const noexcept { - return raw_code.unwrap() == get_horizontal_mirror(code_); -} - -/// ----------------------------- Basic Functions ----------------------------- +// ----------------------------------------------------------------------------------------- // /// MASK_MIRROR_H1 | MASK_MIRROR_H2 /// 111 000 000 000 | 000 111 000 000 @@ -55,7 +27,9 @@ constexpr uint64_t MASK_MIRROR_V1 = 0x0'000'000'000'000'FFF; constexpr uint64_t MASK_MIRROR_V2 = 0x0'000'000'000'FFF'000; constexpr uint64_t MASK_MIRROR_V3 = 0x0'000'000'FFF'000'000; -inline void vertical_fill(uint64_t &raw_code) { +// ----------------------------------------------------------------------------------------- // + +inline static void vertical_fill(uint64_t &raw_code) { uint64_t mask = 0; for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bit switch ((raw_code >> addr) & 0b111) { @@ -76,7 +50,7 @@ inline void vertical_fill(uint64_t &raw_code) { } } -inline void horizontal_fill(uint64_t &raw_code) { +inline static void horizontal_fill(uint64_t &raw_code) { for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bit switch ((raw_code >> addr) & 0b111) { case BLOCK_1x2: @@ -91,7 +65,7 @@ inline void horizontal_fill(uint64_t &raw_code) { } } -inline void vertical_clear(uint64_t &raw_code) { +inline static void vertical_clear(uint64_t &raw_code) { for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bit switch ((raw_code >> addr) & 0b111) { case BLOCK_2x1: @@ -101,7 +75,7 @@ inline void vertical_clear(uint64_t &raw_code) { } } -inline void horizontal_clear(uint64_t &raw_code) { +inline static void horizontal_clear(uint64_t &raw_code) { for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bit switch ((raw_code >> addr) & 0b111) { case BLOCK_1x2: @@ -111,6 +85,8 @@ inline void horizontal_clear(uint64_t &raw_code) { } } +// ----------------------------------------------------------------------------------------- // + uint64_t RawCode::get_vertical_mirror(uint64_t raw_code) noexcept { vertical_fill(raw_code); raw_code = (raw_code & MASK_MIRROR_V3) diff --git a/src/core/raw_code/raw_code.h b/src/core/raw_code/raw_code.h index bd23e7a..71f87b9 100644 --- a/src/core/raw_code/raw_code.h +++ b/src/core/raw_code/raw_code.h @@ -95,53 +95,23 @@ private: static uint64_t extract(uint64_t common_code) noexcept; public: - RawCode to_vertical_mirror() const noexcept; - RawCode to_horizontal_mirror() const noexcept; + [[nodiscard]] RawCode to_vertical_mirror() const noexcept; + [[nodiscard]] RawCode to_horizontal_mirror() const noexcept; - bool is_vertical_mirror() const noexcept; - bool is_horizontal_mirror() const noexcept; - bool is_vertical_mirror(RawCode raw_code) const noexcept; - bool is_horizontal_mirror(RawCode raw_code) const noexcept; + [[nodiscard]] bool is_vertical_mirror() const noexcept; + [[nodiscard]] bool is_horizontal_mirror() const noexcept; + [[nodiscard]] bool is_vertical_mirror(RawCode raw_code) const noexcept; + [[nodiscard]] bool is_horizontal_mirror(RawCode raw_code) const noexcept; private: - static inline bool check_vertical_mirror(uint64_t raw_code) noexcept; - static inline bool check_horizontal_mirror(uint64_t raw_code) noexcept; + static bool check_vertical_mirror(uint64_t raw_code) noexcept; + static bool check_horizontal_mirror(uint64_t raw_code) noexcept; - static inline uint64_t get_vertical_mirror(uint64_t raw_code) noexcept; - static inline uint64_t get_horizontal_mirror(uint64_t raw_code) noexcept; + static uint64_t get_vertical_mirror(uint64_t raw_code) noexcept; + static uint64_t get_horizontal_mirror(uint64_t raw_code) noexcept; }; -/// RawCode compare implements. -inline bool operator==(uint64_t r1, RawCode r2) noexcept { - return r1 == r2.unwrap(); -} - -inline bool operator==(RawCode r1, RawCode r2) noexcept { - return r1.unwrap() == r2.unwrap(); -} - -/// Get the original 64-bit code. -inline uint64_t RawCode::unwrap() const noexcept { - return code_; -} - -/// Implicit conversion to 64-bit code. -inline RawCode::operator uint64_t() const noexcept { - return code_; -} - -/// RawCode create without any check. -inline RawCode RawCode::unsafe_create(uint64_t raw_code) noexcept { - return *reinterpret_cast(&raw_code); // init directly -} - -/// RawCode create with valid check. -inline std::optional RawCode::create(uint64_t raw_code) noexcept { - if (!RawCode::check(raw_code)) { - return std::nullopt; - } - return RawCode::unsafe_create(raw_code); -} - } // namespace codec } // namespace klotski + +#include "inline_impl.h" diff --git a/src/core/short_code/convert.cc b/src/core/short_code/convert.cc index 8937018..aee2eaa 100644 --- a/src/core/short_code/convert.cc +++ b/src/core/short_code/convert.cc @@ -1,76 +1,31 @@ #include -#include "common.h" #include "short_code.h" -#include "common_code.h" -#include "all_cases.h" -#include "offset/all_cases_offset.h" -#include "offset/basic_ranges_offset.h" -#include "offset/range_prefix_offset.h" - -namespace klotski { -namespace codec { +#include "offset/basic.h" +#include "offset/range_prefix.h" using klotski::cases::AllCases; using klotski::cases::BasicRanges; -/// ------------------------- ShortCode to CommonCode ------------------------- - -//CommonCode ShortCode::to_common_code() const noexcept { -// if (ShortCode::mode() == ShortCode::NORMAL) { -// return CommonCode::unsafe_create(tiny_decode(code_)); // normal mode -// } -// return CommonCode::unsafe_create(fast_decode(code_)); // fast mode -//} - -/// ------------------------- ShortCode to CommonCode ------------------------- - -ShortCode::ShortCode(CommonCode common_code) noexcept { -// if (ShortCode::mode() == ShortCode::NORMAL) { -// code_ = tiny_encode(common_code.unwrap()); // normal mode -// } else { - code_ = fast_encode(common_code.unwrap()); // fast mode -// } -} - -//ShortCode ShortCode::from_common_code(uint64_t common_code) { -// return ShortCode(CommonCode(common_code)); -//} +using klotski::codec::offset::ALL_CASES_OFFSET; +using klotski::codec::offset::BASIC_RANGES_OFFSET; +using klotski::codec::offset::RANGE_PREFIX_OFFSET; -ShortCode ShortCode::from_common_code(CommonCode common_code) noexcept { - return ShortCode(std::forward(common_code)); -} - -//ShortCode ShortCode::from_common_code(std::string &&common_code) { -// return ShortCode(std::forward( -// CommonCode(std::forward(common_code)) -// )); -//} - -//ShortCode ShortCode::from_common_code(const CommonCode &common_code) noexcept { -// return ShortCode(common_code); -//} - -//ShortCode ShortCode::from_common_code(const std::string &common_code) { -// return ShortCode(CommonCode(common_code)); -//} - -/// ----------------------------- Basic Functions ----------------------------- +namespace klotski { +namespace codec { -/// NOTE: ensure that input common code is valid! -uint32_t ShortCode::fast_encode(uint64_t common_code) noexcept { // common code --> short code - auto head = common_code >> 32; // head index - const auto &ranges = AllCases::instance().fetch()[head]; // available ranges - auto offset = std::lower_bound(ranges.begin(), ranges.end(), (uint32_t)common_code) - ranges.begin(); - return ALL_CASES_OFFSET[head] + offset; // release short code +/// Convert CommonCode to ShortCode based on AllCases data. +uint32_t ShortCode::fast_encode(uint64_t common_code) noexcept { + auto head = common_code >> 32; + auto &ranges = AllCases::instance().fetch()[head]; // match available ranges + auto target = std::lower_bound(ranges.begin(), ranges.end(), (uint32_t)common_code); + return ALL_CASES_OFFSET[head] + (target - ranges.begin()); } -/// NOTE: ensure that input short code is valid! -uint64_t ShortCode::fast_decode(uint32_t short_code) noexcept { // short code --> common code - auto offset = std::upper_bound( // using binary search - ALL_CASES_OFFSET, ALL_CASES_OFFSET + 16, short_code - ) - 1; - uint64_t head = offset - ALL_CASES_OFFSET; // head index - return (head << 32) | AllCases::instance().fetch()[head][short_code - *offset]; // release common code +/// Convert ShortCode to CommonCode based on AllCases data. +uint64_t ShortCode::fast_decode(uint32_t short_code) noexcept { + auto offset = std::upper_bound(ALL_CASES_OFFSET, ALL_CASES_OFFSET + 16, short_code) - 1; + uint64_t head = offset - ALL_CASES_OFFSET; + return (head << 32) | AllCases::instance().fetch()[head][short_code - *offset]; } /// NOTE: ensure that input common code is valid! diff --git a/src/core/short_code/inline_impl.h b/src/core/short_code/inline_impl.h new file mode 100644 index 0000000..8eda2d7 --- /dev/null +++ b/src/core/short_code/inline_impl.h @@ -0,0 +1,56 @@ +#pragma once + +namespace klotski { +namespace codec { + +/// Get the original 32-bit code. +inline uint32_t ShortCode::unwrap() const noexcept { + return code_; +} + +/// Implicit conversion to 32-bit code. +inline ShortCode::operator uint32_t() const noexcept { + return code_; +} + +/// Equality comparison between ShortCode and numbers. +inline bool operator==(ShortCode s1, uint32_t s2) noexcept { + return s1.unwrap() == s2; +} + +/// ShortCode equal comparison implement. +inline bool operator==(ShortCode s1, ShortCode s2) noexcept { + return s1.unwrap() == s2.unwrap(); +} + +/// ShortCode less than comparison implement. +inline bool operator<(ShortCode s1, ShortCode s2) noexcept { + return s1.unwrap() < s2.unwrap(); +} + +/// ShortCode greater than comparison implement. +inline bool operator>(ShortCode s1, ShortCode s2) noexcept { + return s1.unwrap() > s2.unwrap(); +} + +/// ShortCode create without any check. +inline ShortCode ShortCode::unsafe_create(uint32_t short_code) noexcept { + return *reinterpret_cast(&short_code); // init directly +} + +/// ShortCode create with valid check. +inline std::optional ShortCode::create(uint32_t short_code) noexcept { + if (!ShortCode::check(short_code)) { + return std::nullopt; // invalid short code + } + return ShortCode::unsafe_create(short_code); +} + +/// Output string encoding of ShortCode. +inline std::ostream& operator<<(std::ostream &out, ShortCode self) { + out << ShortCode::string_encode(self.code_); + return out; +} + +} // namespace codec +} // namespace klotski diff --git a/src/core/short_code/offset/all_cases_offset.h b/src/core/short_code/offset/all_cases_offset.h deleted file mode 100644 index 60a35e9..0000000 --- a/src/core/short_code/offset/all_cases_offset.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -/// This is the head index, the offset (0 ~ 29334498) in all cases is obtained -/// according to the `head` (0 ~ 15). In other words, the short code range can be -/// obtained according to the position of the 2x2 block. - -#include - -namespace klotski { - -const uint32_t ALL_CASES_OFFSET[16] = { - 0, 2942906, 5203298, 8146204, - 8146204, 10468254, 12345199, 14667249, - 14667249, 16989299, 18866244, 21188294, - 21188294, 24131200, 26391592, 29334498, -}; - -} // namespace klotski diff --git a/src/core/short_code/offset/basic_ranges_offset.h b/src/core/short_code/offset/basic.h similarity index 98% rename from src/core/short_code/offset/basic_ranges_offset.h rename to src/core/short_code/offset/basic.h index 3c7ad66..3c9dcce 100644 --- a/src/core/short_code/offset/basic_ranges_offset.h +++ b/src/core/short_code/offset/basic.h @@ -1,13 +1,28 @@ #pragma once -/// This is the index for basic ranges, and its position (0 ~ 7311920) in all -/// basic ranges is located according to the first 12-bit (0 ~ 4095) of the -/// 32-bit `range`. - #include namespace klotski { +namespace codec { +namespace offset { + +/// This is the head index, the offset [0, 29334498) in all cases is obtained +/// according to the `head` (0 ~ 15). In other words, the short code range can +/// be obtained according to the position of the 2x2 block. + +// TODO: using std::array +const uint32_t ALL_CASES_OFFSET[16] = { + 0, 2942906, 5203298, 8146204, + 8146204, 10468254, 12345199, 14667249, + 14667249, 16989299, 18866244, 21188294, + 21188294, 24131200, 26391592, 29334498, +}; + +/// This is the index for basic ranges, and its position (0 ~ 7311920) in all +/// basic ranges is located according to the first 12-bit (0 ~ 4095) within the +/// 32-bit `range`. +// TODO: using std::array const uint32_t BASIC_RANGES_OFFSET[4096] = { 0, 18272, 24960, 31648, 49920, 56608, 59056, 61504, 68192, 74880, 77328, 79776, 86464, 104736, 111424, 118112, @@ -523,4 +538,6 @@ const uint32_t BASIC_RANGES_OFFSET[4096] = { 7253514, 7259861, 7261646, 7263431, 7268677, 7286266, 7291512, 7296758, }; +} // namespace offset +} // namespace codec } // namespace klotski diff --git a/src/core/short_code/offset/range_prefix_offset.h b/src/core/short_code/offset/range_prefix.h similarity index 73% rename from src/core/short_code/offset/range_prefix_offset.h rename to src/core/short_code/offset/range_prefix.h index 2db7b4e..a6730f3 100644 --- a/src/core/short_code/offset/range_prefix_offset.h +++ b/src/core/short_code/offset/range_prefix.h @@ -1,14 +1,17 @@ #pragma once -/// This is the index for the range prefix. Given the `head` and the first -/// 12-bit (0 ~ 4095) of the `range`, you can get the positions of all cases -/// in the current `head`. That is, according to the position of 2x2 block -/// and the `range`, the short code range is obtained. +/// This is the index for the range prefix. Given the case `head` and the first +/// 12-bit (0 ~ 4095) of the `range`, you can get the positions of all cases in +/// the current `head`. That is, according to the position of 2x2 block and the +/// `range`, the short code range is obtained. #include namespace klotski { +namespace codec { +namespace offset { +// TODO: using std::array const uint32_t RANGE_PREFIX_OFFSET[16][4096] = {{ #include "range_prefix/offset_0x0.inc" }, { @@ -43,4 +46,6 @@ const uint32_t RANGE_PREFIX_OFFSET[16][4096] = {{ /// --------------- 0xF --------------- }}; +} // namespace offset +} // namespace codec } // namespace klotski diff --git a/src/core/short_code/serialize.cc b/src/core/short_code/serialize.cc index 92923eb..2e93a9b 100644 --- a/src/core/short_code/serialize.cc +++ b/src/core/short_code/serialize.cc @@ -4,14 +4,6 @@ namespace klotski { namespace codec { -/// --------------------------- ShortCode to String --------------------------- - -std::string ShortCode::to_string() const noexcept { // encode as 5-bits string - return string_encode(code_); -} - -/// ----------------------------- Basic Functions ----------------------------- - std::string ShortCode::string_encode(uint32_t short_code) noexcept { // encode as 5-bits string char result[6]; // short code length 5 result[5] = '\0'; // string ending flag diff --git a/src/core/short_code/serialize_chars.h b/src/core/short_code/serialize_chars.h index d62ab3a..2a587da 100644 --- a/src/core/short_code/serialize_chars.h +++ b/src/core/short_code/serialize_chars.h @@ -1,19 +1,19 @@ #pragma once -/// ShortCode Convert Table -/// ------------------------------------------------- -/// | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | -/// | `1` | `2` | `3` | `4` | `5` | `6` | `7` | `8` | -/// |-----------------------------------------------| -/// | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | -/// | `9` | `A` | `B` | `C` | `D` | `E` | `F` | `G` | -/// |-----------------------------------------------| -/// | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -/// | `H` | `J` | `K` | `M` | `N` | `P` | `Q` | `R` | -/// |-----------------------------------------------| -/// | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -/// | `S` | `T` | `U` | `V` | `W` | `X` | `Y` | `Z` | -/// ------------------------------------------------- +/// ShortCode Convert Table /// +/// ------------------------------------------------- /// +/// | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | /// +/// | `1` | `2` | `3` | `4` | `5` | `6` | `7` | `8` | /// +/// |-----------------------------------------------| /// +/// | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | /// +/// | `9` | `A` | `B` | `C` | `D` | `E` | `F` | `G` | /// +/// |-----------------------------------------------| /// +/// | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | /// +/// | `H` | `J` | `K` | `M` | `N` | `P` | `Q` | `R` | /// +/// |-----------------------------------------------| /// +/// | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | /// +/// | `S` | `T` | `U` | `V` | `W` | `X` | `Y` | `Z` | /// +/// ------------------------------------------------- /// #include diff --git a/src/core/short_code/short_code.cc b/src/core/short_code/short_code.cc index 5f66ba1..9037bf3 100644 --- a/src/core/short_code/short_code.cc +++ b/src/core/short_code/short_code.cc @@ -1,23 +1,25 @@ #include "all_cases.h" #include "short_code.h" +using klotski::cases::AllCases; +using klotski::cases::BasicRanges; + namespace klotski { namespace codec { +/// Check the validity of the original ShortCode. bool ShortCode::check(uint32_t short_code) noexcept { return short_code < SHORT_CODE_LIMIT; // 0 ~ (SHORT_CODE_LIMIT - 1) } -//ShortCode::Mode ShortCode::mode() { // ensure speed up enabled and return current mode -// if (fast_mode_available_) { -// return ShortCode::FAST; // fast mode already enabled -// } -// if (normal_mode_available_) { -// return ShortCode::NORMAL; // normal mode already enabled -// } -// speed_up(ShortCode::Mode::NORMAL); // uninitialized -> enable normal mode -// return ShortCode::Mode::NORMAL; -//} +void ShortCode::speed_up(bool fast_mode) noexcept { + if (fast_mode) { + AllCases::instance().build(); + } else { + BasicRanges::instance().build(); + } + // FIXME: setting up `fast_available_` +} //void ShortCode::speed_up(ShortCode::Mode mode) { // if (fast_mode_available_) { diff --git a/src/core/short_code/short_code.h b/src/core/short_code/short_code.h index 785aa76..a4353a1 100644 --- a/src/core/short_code/short_code.h +++ b/src/core/short_code/short_code.h @@ -118,51 +118,7 @@ private: static std::optional string_decode(const std::string &short_code) noexcept; }; -/// ShortCode compare implements. -inline bool operator==(uint32_t s1, ShortCode s2) noexcept { - return s1 == s2.unwrap(); -} - -inline bool operator==(ShortCode s1, ShortCode s2) noexcept { - return s1.unwrap() == s2.unwrap(); -} - -inline bool operator<(ShortCode s1, ShortCode s2) noexcept { - return s1.unwrap() < s2.unwrap(); -} - -inline bool operator>(ShortCode s1, ShortCode s2) noexcept { - return s1.unwrap() > s2.unwrap(); -} - -/// Get the original 32-bit code. -inline uint32_t ShortCode::unwrap() const noexcept { - return code_; -} - -/// Implicit conversion to 32-bit code. -inline ShortCode::operator uint32_t() const noexcept { - return code_; -} - -/// ShortCode create without any check. -inline ShortCode ShortCode::unsafe_create(uint32_t short_code) noexcept { - return *reinterpret_cast(&short_code); // init directly -} - -/// ShortCode create with valid check. -inline std::optional ShortCode::create(uint32_t short_code) noexcept { - if (!ShortCode::check(short_code)) { - return std::nullopt; - } - return ShortCode::unsafe_create(short_code); -} - -/// Output string encoding of ShortCode. -inline std::ostream& operator<<(std::ostream &out, ShortCode self) { - out << ShortCode::string_encode(self.code_); - return out; -} - } // namespace codec } // namespace klotski + +#include "inline_impl.h" diff --git a/src/core/short_code/sundry.cc b/src/core/short_code/sundry.cc index 6fea2c0..e50daee 100644 --- a/src/core/short_code/sundry.cc +++ b/src/core/short_code/sundry.cc @@ -4,20 +4,74 @@ namespace klotski { namespace codec { -// FIXME: just for compile +// ----------------------------------------------------------------------------------------- // + +ShortCode::ShortCode(CommonCode common_code) noexcept { +// if (fast_available_) { + code_ = fast_encode(common_code.unwrap()); +// } else { +// code_ = tiny_encode(common_code.unwrap()); +// } +} + +// ----------------------------------------------------------------------------------------- // + +std::string ShortCode::to_string() const noexcept { + return string_encode(code_); +} + CommonCode ShortCode::to_common_code() const noexcept { - return CommonCode::unsafe_create(0); +// if (fast_available_) { + return CommonCode::unsafe_create(fast_decode(code_)); +// } +// return CommonCode::unsafe_create(tiny_decode(code_)); } -// FIXME: just for compile +// ----------------------------------------------------------------------------------------- // + std::optional ShortCode::from_string(std::string &&short_code) noexcept { - return std::nullopt; + return ShortCode::from_string(short_code); } -// FIXME: just for compile std::optional ShortCode::from_string(const std::string &short_code) noexcept { - return std::nullopt; + auto code = ShortCode::string_decode(short_code); + if (!code.has_value()) { + return std::nullopt; // invalid string + } + return ShortCode::unsafe_create(code.value()); } +// ----------------------------------------------------------------------------------------- // + +ShortCode ShortCode::from_common_code(CommonCode common_code) noexcept { + return common_code.to_short_code(); +} + +std::optional ShortCode::from_common_code(uint64_t common_code) noexcept { + auto code = CommonCode::create(common_code); + if (!code.has_value()) { + return std::nullopt; // invalid common code + } + return code->to_short_code(); +} + +std::optional ShortCode::from_common_code(std::string &&common_code) noexcept { + auto code = CommonCode::from_string(std::move(common_code)); + if (!code.has_value()) { + return std::nullopt; // invalid common code + } + return code->to_short_code(); +} + +std::optional ShortCode::from_common_code(const std::string &common_code) noexcept { + auto code = CommonCode::from_string(common_code); + if (!code.has_value()) { + return std::nullopt; // invalid common code + } + return code->to_short_code(); +} + +// ----------------------------------------------------------------------------------------- // + } // namespace codec } // namespace klotski