From ec21c73e5459d4a2e671e537e91b77663e88666b Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Fri, 6 Jan 2023 16:26:59 +0800 Subject: [PATCH] perf: ShortCode module --- klotski/main.cc | 25 +-------- klotski/short_code.cc | 118 +++++++++++++++++++----------------------- klotski/short_code.h | 27 +++------- 3 files changed, 61 insertions(+), 109 deletions(-) diff --git a/klotski/main.cc b/klotski/main.cc index 2d5ad5b..5e1b229 100644 --- a/klotski/main.cc +++ b/klotski/main.cc @@ -18,37 +18,16 @@ int main() { // std::cout << temp.size() << std::endl; // } -// auto s = ShortCode(); -// auto s = ShortCode(ShortCode::Mode::NORMAL); -// auto s = ShortCode(ShortCode::Mode::FAST); - -// s.speed_up(ShortCode::Mode::FAST); -// std::cout << s.all_cases_list.size() << std::endl; -// std::cout << s.all_cases_dict.size() << std::endl; - -// printf("%d\n", s.fast_encode(0x6EC0F8800)); -// printf("%09lX\n", s.fast_decode(14323231)); - -// s.speed_up(ShortCode::Mode::NORMAL); -// std::cout << s.basic_ranges.size() << std::endl; - -// auto s = ShortCode(); -// s.speed_up(ShortCode::Mode::NORMAL); // enter normal mode first -// -// printf("%d\n", s.tiny_encode(0x6EC0F8800)); -// printf("%09lX\n", s.tiny_decode(14323231)); auto s = ShortCode(); // auto s = ShortCode(ShortCode::Mode::NORMAL); // auto s = ShortCode(ShortCode::Mode::FAST); -// std::cout << "start" << std::endl; -// std::cout << s.zip_short_code(0x6EC0F8800) << std::endl; -// std::cout << "complete" << std::endl; +// s.speed_up(ShortCode::Mode::NORMAL); + s.speed_up(ShortCode::Mode::FAST); printf("%d\n", s.zip_short_code(0x6EC0F8800)); printf("%09lX\n", s.unzip_short_code(14323231)); -// printf("%09lX\n", s.unzip_short_code(87654321)); return 0; } diff --git a/klotski/short_code.cc b/klotski/short_code.cc index 995d4c7..b00b661 100644 --- a/klotski/short_code.cc +++ b/klotski/short_code.cc @@ -46,64 +46,15 @@ void ShortCode::build_mappings() { // build fast search mappings } } -uint64_t ShortCode::fast_decode(uint32_t short_code) { // short_code --fast--> common_code - // TODO: ensure input short_code < SHORT_CODE_LIMIT - return all_cases_list[short_code]; -} - -uint32_t ShortCode::fast_encode(uint64_t common_code) { // common_code --fast--> short_code - // TODO: ensure input common_code valid - return all_cases_dict[common_code]; -} - -// TODO: load basic ranges before tiny_decode -// TODO: ensure input short_code < SHORT_CODE_LIMIT -uint64_t ShortCode::tiny_decode(uint32_t short_code) { // short_code --low-mem--> common_code - uint32_t head = 0, prefix = 0; - for (; head < 16; ++head) { - if (short_code < ALL_CASES_INDEX[head]) { // match head - break; - } - short_code -= ALL_CASES_INDEX[head]; // short code approximate - } - for (; prefix < 256; ++prefix) { - if (short_code < RANGE_PREFIX_INDEX[head][prefix]) { // match range prefix - break; - } - short_code -= RANGE_PREFIX_INDEX[head][prefix]; // short code approximate - } - - uint32_t range; - for (int index = 0; index < BASIC_RANGES_INDEX[prefix]; ++index) { // traverse basic ranges - range = basic_ranges[index + BASIC_RANGES_OFFSET[prefix]]; - if (Common::check_case(head, range)) { // search for valid cases - if (short_code == 0) { - break; // found target range - } - --short_code; // short code approximate - } +enum ShortCode::Mode ShortCode::check_mode() { // ensure speed up enabled and return current mode + if (!all_cases_list.empty()) { + return ShortCode::Mode::FAST; // fast mode already enabled } - return (uint64_t)head << 32 | Common::range_reverse(range); // release common code -} - -// TODO: ensure input common_code valid -// TODO: load basic ranges before tiny_encode -uint32_t ShortCode::tiny_encode(uint64_t common_code) { - uint32_t offset = 0; - uint32_t head = common_code >> 32; // common code head - uint32_t prefix = (common_code >> 24) & 0xFF; // common code range prefix - auto target = Common::range_reverse((uint32_t)common_code); // target range - - for (int index = 0; index < BASIC_RANGES_INDEX[prefix]; ++index) { // traverse basic ranges - uint32_t range = basic_ranges[index + BASIC_RANGES_OFFSET[prefix]]; - if (range == target) { - break; // found target range - } - if (Common::check_case(head, range)) { // search for valid cases - ++offset; // record sub offset - } + if (!basic_ranges.empty()) { + return ShortCode::Mode::NORMAL; // normal mode already enabled } - return ALL_CASES_OFFSET[head] + RANGE_PREFIX_OFFSET[head][prefix] + offset; + speed_up(ShortCode::Mode::NORMAL); // class without initialized -> enter normal mode + return ShortCode::Mode::NORMAL; // use normal mode } uint32_t ShortCode::zip_short_code(uint64_t common_code) { // common_code --zip--> short_code @@ -114,33 +65,68 @@ uint32_t ShortCode::zip_short_code(uint64_t common_code) { // common_code --zip- case ShortCode::Mode::NORMAL: return tiny_encode(common_code); case ShortCode::Mode::FAST: - return fast_encode(common_code); + return all_cases_dict[common_code]; default: throw std::runtime_error("unknown error"); } } uint64_t ShortCode::unzip_short_code(uint32_t short_code) { // short_code --unzip--> common_code - if (!check(short_code)) { + if (!ShortCode::check(short_code)) { throw std::runtime_error("invalid short code"); } switch (check_mode()) { case ShortCode::Mode::NORMAL: return tiny_decode(short_code); case ShortCode::Mode::FAST: - return fast_decode(short_code); + return all_cases_list[short_code]; default: throw std::runtime_error("unknown error"); } } -enum ShortCode::Mode ShortCode::check_mode() { // ensure speed up enabled and return current mode - if (!all_cases_list.empty()) { - return ShortCode::Mode::FAST; // fast mode already enabled +uint32_t ShortCode::tiny_encode(uint64_t common_code) { // common_code --low-memory--> short_code + uint32_t offset = 0; + uint32_t head = common_code >> 32; // common code head + uint32_t prefix = (common_code >> 24) & 0xFF; // common code range prefix + auto target = Common::range_reverse((uint32_t)common_code); // target range + + for (int index = 0; index < BASIC_RANGES_INDEX[prefix]; ++index) { // traverse basic ranges + uint32_t range = basic_ranges[index + BASIC_RANGES_OFFSET[prefix]]; + if (range == target) { + break; // found target range + } + if (Common::check_case(head, range)) { // search for valid cases + ++offset; // record sub offset + } } - if (!basic_ranges.empty()) { - return ShortCode::Mode::NORMAL; // normal mode already enabled + return ALL_CASES_OFFSET[head] + RANGE_PREFIX_OFFSET[head][prefix] + offset; +} + +uint64_t ShortCode::tiny_decode(uint32_t short_code) { // short_code --low-memory--> common_code + uint32_t head = 0, prefix = 0; + for (; head < 16; ++head) { + if (short_code < ALL_CASES_INDEX[head]) { // match head + break; + } + short_code -= ALL_CASES_INDEX[head]; // short code approximate } - speed_up(ShortCode::Mode::NORMAL); // class without initialized -> enter normal mode - return ShortCode::Mode::NORMAL; // use normal mode + for (; prefix < 256; ++prefix) { + if (short_code < RANGE_PREFIX_INDEX[head][prefix]) { // match range prefix + break; + } + short_code -= RANGE_PREFIX_INDEX[head][prefix]; // short code approximate + } + + uint32_t range; + for (int index = 0; index < BASIC_RANGES_INDEX[prefix]; ++index) { // traverse basic ranges + range = basic_ranges[index + BASIC_RANGES_OFFSET[prefix]]; + if (Common::check_case(head, range)) { // search for valid cases + if (short_code == 0) { + break; // found target range + } + --short_code; // short code approximate + } + } + return (uint64_t)head << 32 | Common::range_reverse(range); // release common code } diff --git a/klotski/short_code.h b/klotski/short_code.h index 24480c1..d91c3da 100644 --- a/klotski/short_code.h +++ b/klotski/short_code.h @@ -6,38 +6,25 @@ class ShortCode { public: - enum Mode {NORMAL, FAST}; - std::vector basic_ranges; - - std::vector all_cases_list; // short_code -> common_code - std::unordered_map all_cases_dict; // common_code -> short_code - ShortCode() = default; void speed_up(enum Mode mode); explicit ShortCode(enum Mode mode); - + static bool check(uint32_t short_code); uint32_t zip_short_code(uint64_t common_code); uint64_t unzip_short_code(uint32_t short_code); - enum Mode check_mode(); - - static bool check(uint32_t short_code); - private: -// std::vector all_cases_list; // short_code -> common_code -// std::unordered_map all_cases_dict; // common_code -> short_code - static const uint32_t SHORT_CODE_LIMIT = 29334498; - uint64_t fast_decode(uint32_t short_code); - uint32_t fast_encode(uint64_t common_code); - - uint64_t tiny_decode(uint32_t short_code); - uint32_t tiny_encode(uint64_t common_code); + std::vector basic_ranges; + std::vector all_cases_list; // short_code -> common_code + std::unordered_map all_cases_dict; // common_code -> short_code void build_mappings(); + enum Mode check_mode(); void build_base_ranges(); - + uint64_t tiny_decode(uint32_t short_code); + uint32_t tiny_encode(uint64_t common_code); };