Browse Source

perf: ShortCode module

master
Dnomd343 2 years ago
parent
commit
ec21c73e54
  1. 25
      klotski/main.cc
  2. 118
      klotski/short_code.cc
  3. 27
      klotski/short_code.h

25
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;
}

118
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
}

27
klotski/short_code.h

@ -6,38 +6,25 @@
class ShortCode {
public:
enum Mode {NORMAL, FAST};
std::vector<uint32_t> basic_ranges;
std::vector<uint64_t> all_cases_list; // short_code -> common_code
std::unordered_map<uint64_t, uint32_t> 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<uint64_t> all_cases_list; // short_code -> common_code
// std::unordered_map<uint64_t, uint32_t> 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<uint32_t> basic_ranges;
std::vector<uint64_t> all_cases_list; // short_code -> common_code
std::unordered_map<uint64_t, uint32_t> 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);
};

Loading…
Cancel
Save