|
|
@ -1,10 +1,7 @@ |
|
|
|
#include <algorithm> |
|
|
|
#include <functional> |
|
|
|
#include "common.h" |
|
|
|
#include "short_code.h" |
|
|
|
#include "basic_ranges.h" |
|
|
|
|
|
|
|
#include "all_cases.h" |
|
|
|
#include "short_code.h" |
|
|
|
#include "all_cases_offset.h" |
|
|
|
#include "basic_ranges_offset.h" |
|
|
|
#include "range_prefix_offset.h" |
|
|
@ -24,14 +21,7 @@ ShortCode::ShortCode(const CommonCode &common_code) { // convert from common cod |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
uint64_t ShortCode::fast_decode(uint32_t short_code) { // 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::fetch()[head][short_code - *offset]; // release common code
|
|
|
|
} |
|
|
|
|
|
|
|
/// NOTE: ensure that input common code is valid !!!
|
|
|
|
uint32_t ShortCode::fast_encode(uint64_t common_code) { // common code --> short code
|
|
|
|
auto head = common_code >> 32; // head index
|
|
|
|
const auto &ranges = AllCases::fetch()[head]; // available ranges
|
|
|
@ -39,170 +29,71 @@ uint32_t ShortCode::fast_encode(uint64_t common_code) { // common code --> short |
|
|
|
return ALL_CASES_OFFSET[head] + offset; // release short code
|
|
|
|
} |
|
|
|
|
|
|
|
void run(uint32_t head, uint32_t prefix, const std::function<bool(uint32_t)>& f) { |
|
|
|
/// NOTE: ensure that input short code is valid !!!
|
|
|
|
uint64_t ShortCode::fast_decode(uint32_t short_code) { // 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::fetch()[head][short_code - *offset]; // release common code
|
|
|
|
} |
|
|
|
|
|
|
|
/// NOTE: ensure that input common code is valid !!!
|
|
|
|
uint32_t ShortCode::tiny_encode(uint64_t common_code) { // common code --> short code
|
|
|
|
/// load head index and range prefix
|
|
|
|
uint32_t head = common_code >> 32; |
|
|
|
uint32_t prefix = (common_code >> 20) & 0xFFF; |
|
|
|
|
|
|
|
/// search for target range
|
|
|
|
uint32_t offset = 0; |
|
|
|
auto index = BASIC_RANGES_OFFSET[prefix]; |
|
|
|
const auto &basic_ranges = BasicRanges::fetch(); |
|
|
|
for (auto index = BASIC_RANGES_OFFSET[prefix]; index < basic_ranges.size(); ++index) { |
|
|
|
|
|
|
|
auto target = Common::range_reverse((uint32_t)common_code); // target range
|
|
|
|
for (; index < basic_ranges.size(); ++index) { |
|
|
|
auto broken_offset = Common::check_range(head, basic_ranges[index]); |
|
|
|
if (broken_offset) { // case invalid
|
|
|
|
if (!broken_offset) { // valid case
|
|
|
|
if (basic_ranges[index] == target) { |
|
|
|
break; // found target range
|
|
|
|
} |
|
|
|
++offset; // record sub offset
|
|
|
|
} else { |
|
|
|
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 { |
|
|
|
|
|
|
|
if (f(basic_ranges[index])) { |
|
|
|
|
|
|
|
// printf("ret -> %09lX\n", (uint64_t)head << 32 | Common::range_reverse(basic_ranges[index]));
|
|
|
|
|
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
return ALL_CASES_OFFSET[head] + RANGE_PREFIX_OFFSET[head][prefix] + offset; |
|
|
|
} |
|
|
|
|
|
|
|
#include <iostream> |
|
|
|
|
|
|
|
/// NOTE: ensure that input short code is valid
|
|
|
|
/// NOTE: ensure that input short code is valid !!!
|
|
|
|
uint64_t ShortCode::tiny_decode(uint32_t short_code) { // short code --> common code
|
|
|
|
/// match head index
|
|
|
|
auto offset = std::upper_bound( // binary search
|
|
|
|
ALL_CASES_OFFSET, ALL_CASES_OFFSET + 16, short_code |
|
|
|
) - 1; |
|
|
|
uint64_t head = offset - ALL_CASES_OFFSET; // head index
|
|
|
|
auto head = offset - ALL_CASES_OFFSET; // head index
|
|
|
|
short_code -= *offset; |
|
|
|
|
|
|
|
/// match range prefix
|
|
|
|
offset = std::upper_bound( // binary search
|
|
|
|
RANGE_PREFIX_OFFSET[head], RANGE_PREFIX_OFFSET[head] + 4096, short_code |
|
|
|
) - 1; |
|
|
|
uint32_t prefix = offset - RANGE_PREFIX_OFFSET[head]; // range prefix
|
|
|
|
auto prefix = offset - RANGE_PREFIX_OFFSET[head]; // range prefix
|
|
|
|
short_code -= *offset; |
|
|
|
|
|
|
|
/// search target range
|
|
|
|
// const auto &basic_ranges = BasicRanges::fetch();
|
|
|
|
// for (auto index = BASIC_RANGES_OFFSET[prefix]; index < basic_ranges.size(); ++index) {
|
|
|
|
//
|
|
|
|
// 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 {
|
|
|
|
//
|
|
|
|
// if (!short_code--) { // short code approximate
|
|
|
|
//
|
|
|
|
// /// found target range
|
|
|
|
// return head << 32 | Common::range_reverse(basic_ranges[index]);
|
|
|
|
//
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// }
|
|
|
|
|
|
|
|
// std::cout << "short code = " << short_code << std::endl;
|
|
|
|
// return 0;
|
|
|
|
|
|
|
|
uint32_t range; |
|
|
|
|
|
|
|
auto lambda = [&short_code, &range](uint32_t dat) -> bool { |
|
|
|
|
|
|
|
// return (!short_code--);
|
|
|
|
|
|
|
|
// std::cout << "short code = " << short_code << std::endl;
|
|
|
|
if (!short_code--) { // short code approximate
|
|
|
|
// std::cout << "short code reach 0" << std::endl;
|
|
|
|
range = dat; |
|
|
|
return true; |
|
|
|
/// found target range
|
|
|
|
// return head << 32 | Common::range_reverse(basic_ranges[index]);
|
|
|
|
|
|
|
|
} |
|
|
|
return false; |
|
|
|
}; |
|
|
|
run(head, prefix, lambda); |
|
|
|
|
|
|
|
return (uint64_t)head << 32 | Common::range_reverse(range); |
|
|
|
printf("ret -> %09lX\n", (uint64_t)head << 32 | Common::range_reverse(range)); |
|
|
|
|
|
|
|
|
|
|
|
printf("error\n"); |
|
|
|
|
|
|
|
return 0; // never reach when input valid
|
|
|
|
} |
|
|
|
|
|
|
|
/// NOTE: ensure that input common code is valid
|
|
|
|
uint32_t ShortCode::tiny_encode(uint64_t common_code) { // common code --> short code
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// printf("%09lX\n", common_code);
|
|
|
|
|
|
|
|
// uint64_t raw = common_code;
|
|
|
|
|
|
|
|
uint32_t head = common_code >> 32; |
|
|
|
uint32_t prefix = (common_code >> 20) & 0xFFF; |
|
|
|
|
|
|
|
// printf("head = %d\n", head);
|
|
|
|
// printf("prefix = %X\n", prefix);
|
|
|
|
|
|
|
|
uint32_t offset = 0; |
|
|
|
auto target = Common::range_reverse((uint32_t)common_code); // target range
|
|
|
|
|
|
|
|
// printf("target range: %08X\n", target);
|
|
|
|
// printf("start search at %d\n", BASIC_RANGES_OFFSET[prefix]);
|
|
|
|
//
|
|
|
|
/// search for target range
|
|
|
|
auto index = BASIC_RANGES_OFFSET[prefix]; |
|
|
|
const auto &basic_ranges = BasicRanges::fetch(); |
|
|
|
|
|
|
|
// auto true_index = std::find(basic_ranges.begin(), basic_ranges.end(), 0x0FF00F34) - basic_ranges.begin();
|
|
|
|
|
|
|
|
// printf("true index: %td\n", true_index);
|
|
|
|
// printf("basic_ranges[1294828] = %08X\n", basic_ranges[1294828]);
|
|
|
|
|
|
|
|
for (auto index = BASIC_RANGES_OFFSET[prefix]; index < basic_ranges.size(); ++index) { // traverse basic ranges
|
|
|
|
|
|
|
|
uint32_t range = basic_ranges[index]; |
|
|
|
|
|
|
|
// bool flag = false;
|
|
|
|
// if (range == 0x0FF00F34) {
|
|
|
|
// flag = true;
|
|
|
|
// std::cout << "get target range" << std::endl;
|
|
|
|
// std::cout << "check result -> " << Common::check_case(head, range) << std::endl;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// TODO: using Common::check_range
|
|
|
|
if (Common::check_case(head, range)) { // search for valid cases
|
|
|
|
|
|
|
|
// if (flag) {
|
|
|
|
// std::cout << "check ok" << std::endl;
|
|
|
|
// }
|
|
|
|
|
|
|
|
if (range == target) { // found target range
|
|
|
|
// std::cout << "sum = " << sum << std::endl;
|
|
|
|
return ALL_CASES_OFFSET[head] + RANGE_PREFIX_OFFSET[head][prefix] + offset; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
++offset; // record sub offset
|
|
|
|
|
|
|
|
for (; index < basic_ranges.size(); ++index) { // traverse basic ranges
|
|
|
|
auto broken_offset = Common::check_range(head, basic_ranges[index]); |
|
|
|
if (!broken_offset && !short_code--) { // valid case -> short code approximate
|
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
auto delta = (uint32_t)1 << (32 - broken_offset * 2); // delta to next possible range
|
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
|
printf("error\n"); |
|
|
|
|
|
|
|
return 0; |
|
|
|
return (uint64_t)head << 32 | Common::range_reverse(basic_ranges[index]); |
|
|
|
} |
|
|
|