From c530c3f65c565e9e25ff03859675f0b0b3f87d9e Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Mon, 16 Jan 2023 16:20:53 +0800 Subject: [PATCH] update: check case range function --- src/all_cases/all_cases.cc | 51 ++++++++--------------------------- src/all_cases/all_cases.h | 3 +-- src/main.cc | 17 ++++++------ src/short_code/data_loader.cc | 2 +- src/utils/common.cc | 40 +++++++++++++++++++++++++++ src/utils/common.h | 3 +++ 6 files changed, 64 insertions(+), 52 deletions(-) diff --git a/src/all_cases/all_cases.cc b/src/all_cases/all_cases.cc index 27b52ba..d5fa6d1 100644 --- a/src/all_cases/all_cases.cc +++ b/src/all_cases/all_cases.cc @@ -43,51 +43,22 @@ void AllCases::build_data() { // find all cases } /// head -> 0/1/2 / 4/5/6 / 8/9/10 / 12/13/14 data[head].reserve(ALL_CASES_SIZE[head]); // memory pre-allocated + /// head(4-bits) + basic ranges(32-bits) ==check==> release valid cases for (auto index = 0; index < basic_ranges.size(); ++index) { - uint32_t broken = check_case(head, basic_ranges[index]); // check and get broken address - auto range_rev = Common::range_reverse(basic_ranges[index]); // reversed range - if (broken) { // invalid case - auto delta = (uint32_t)1 << (32 - broken * 2); // this --delta--> next possible range - auto next_min = (range_rev & ~(delta - 1)) + delta; + auto broken_offset = Common::check_range(head, basic_ranges[index]); + if (broken_offset) { // case invalid + auto delta = (uint32_t)1 << (32 - broken_offset * 2); // delta to next possible range + /// !! -> broken + /// ( xx xx xx ) xx xx xx ... (reversed range) + /// +1 00 00 00 ... (delta) + auto next_min = (Common::range_reverse(basic_ranges[index]) & ~(delta - 1)) + delta; while (Common::range_reverse(basic_ranges[++index]) < next_min); // located next range --index; } else { - AllCases::data[head].emplace_back(range_rev); // release valid cases + AllCases::data[head].emplace_back( + Common::range_reverse(basic_ranges[index]) // release valid cases + ); } } } } - -int AllCases::check_case(uint32_t head, uint32_t range) { // check the head and range - constexpr uint32_t M_1x1 = 0b1; - constexpr uint32_t M_1x2 = 0b11; - constexpr uint32_t M_2x1 = 0b10001; - constexpr uint32_t M_2x2 = 0b110011; - - int block_num = 1; - uint32_t cache = M_2x2 << head; // fill 2x2 block - for (int addr = 0; range; range >>= 2, ++block_num) { // traverse every 2-bits - while (cache >> addr & 0b1) { - ++addr; // search next not filled block - } - switch (range & 0b11) { - case 0b00: // space - case 0b11: // 1x1 block - cache |= M_1x1 << addr; // fill space or 1x1 block - break; - case 0b10: // 2x1 block - if (addr > 15 || cache >> (addr + 4) & 0b1) { // invalid address - return block_num; // broken block number - } - cache |= M_2x1 << addr; // fill 2x1 block - break; - case 0b01: // 1x2 block - if ((addr & 0b11) == 0b11 || cache >> (addr + 1) & 0b1) { // invalid address - return block_num; // broken block number - } - cache |= M_1x2 << addr; // fill 1x2 block - break; - } - } - return 0; // pass check -} diff --git a/src/all_cases/all_cases.h b/src/all_cases/all_cases.h index 4904717..ae47baf 100644 --- a/src/all_cases/all_cases.h +++ b/src/all_cases/all_cases.h @@ -18,8 +18,7 @@ public: static enum Status status(); static const std::vector (&fetch())[16]; - // TODO: only for test - static int check_case(uint32_t head, uint32_t range); +// static int check_case(uint32_t head, uint32_t range); private: static bool available; diff --git a/src/main.cc b/src/main.cc index 9196f97..b5da5fd 100644 --- a/src/main.cc +++ b/src/main.cc @@ -245,7 +245,7 @@ int main() { // } - BasicRanges::build(); +// BasicRanges::build(); // const auto &br = BasicRanges::fetch(); // br.push_back(123); // std::cout << "size: " << BasicRanges::fetch().size() << std::endl; @@ -254,14 +254,13 @@ int main() { // printf("%08X\n", range); // } -// AllCases::build(); - -// for (auto head = 0; head < 16; ++head) { -// uint64_t prefix = (uint64_t)head << 32; -// for (const auto &range : AllCases::fetch()[head]) { -// printf("%09lX\n", prefix | range); -// } -// } + AllCases::build(); + for (auto head = 0; head < 16; ++head) { + uint64_t prefix = (uint64_t)head << 32; + for (const auto &range : AllCases::fetch()[head]) { + printf("%09lX\n", prefix | range); + } + } // for (uint32_t i = 0; i < 29334498; ++i) { // if (ShortCode::fast_encode(ShortCode::fast_decode(i)) != i) { diff --git a/src/short_code/data_loader.cc b/src/short_code/data_loader.cc index 351d1b9..6b0d9da 100644 --- a/src/short_code/data_loader.cc +++ b/src/short_code/data_loader.cc @@ -94,7 +94,7 @@ uint64_t ShortCode::tiny_decode_demo(uint32_t short_code) { uint32_t range = basic_ranges[index]; // traverse basic ranges - uint32_t broken = AllCases::check_case(head, basic_ranges[index]); // check and get broken address + uint32_t broken = Common::check_range(head, basic_ranges[index]); // check and get broken address auto range_rev = Common::range_reverse(basic_ranges[index]); // reversed range diff --git a/src/utils/common.cc b/src/utils/common.cc index 13bc5a6..bd845e3 100644 --- a/src/utils/common.cc +++ b/src/utils/common.cc @@ -7,6 +7,7 @@ uint32_t Common::range_reverse(uint32_t bin) { // reverse binary every 2-bits return ((bin << 2) & 0xCCCCCCCC) | ((bin >> 2) & 0x33333333); } +// TODO: remove legacy function -> combine as single function in CommonCode bool Common::check_case(uint32_t head, uint32_t range) { // whether the head and range is valid uint32_t mask = 0b110011 << head; // fill 2x2 block for (int addr = 0; range; range >>= 2) { // traverse every 2-bits @@ -37,3 +38,42 @@ bool Common::check_case(uint32_t head, uint32_t range) { // whether the head and } return true; // valid case } + +/// NOTE: don't check unknown ranges +uint8_t Common::check_range(uint32_t head, uint32_t range) { // check generated range + /// M_1x1 M_1x2 M_2x1 M_2x2 + /// 1 0 0 0 1 1 0 0 1 0 0 0 1 1 0 0 + /// 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 + /// ... ... ... ... + constexpr uint32_t M_1x1 = 0b1; + constexpr uint32_t M_1x2 = 0b11; + constexpr uint32_t M_2x1 = 0b10001; + constexpr uint32_t M_2x2 = 0b110011; + + int block_offset = 1; + uint32_t cache = M_2x2 << head; // fill 2x2 block + for (int addr = 0; range; range >>= 2, ++block_offset) { // traverse every 2-bits + while (cache >> addr & 0b1) { + ++addr; // search next unfilled block + } + switch (range & 0b11) { + case 0b00: // space + case 0b11: // 1x1 block + cache |= M_1x1 << addr; // fill space or 1x1 block + break; + case 0b10: // 2x1 block + if (addr > 15 || cache >> (addr + 4) & 0b1) { // invalid address + return block_offset; // broken block number + } + cache |= M_2x1 << addr; // fill 2x1 block + break; + case 0b01: // 1x2 block + if ((addr & 0b11) == 0b11 || cache >> (addr + 1) & 0b1) { // invalid address + return block_offset; // broken block number + } + cache |= M_1x2 << addr; // fill 1x2 block + break; + } + } + return 0; // pass check +} diff --git a/src/utils/common.h b/src/utils/common.h index 50dc979..2f2c4dc 100644 --- a/src/utils/common.h +++ b/src/utils/common.h @@ -43,4 +43,7 @@ class Common { public: static uint32_t range_reverse(uint32_t bin); static bool check_case(uint32_t head, uint32_t range); + + // TODO: with broken block offset return + static uint8_t check_range(uint32_t head, uint32_t range); };