Browse Source

update: add constexpr support of ShortCode

legacy
Dnomd343 3 weeks ago
parent
commit
76099d7069
  1. 2
      src/core/CMakeLists.txt
  2. 15
      src/core/short_code/internal/convert.cc
  3. 22
      src/core/short_code/internal/convert.inl
  4. 14
      src/core/short_code/internal/serialize.inl
  5. 10
      src/core/short_code/internal/short_code.inl
  6. 27
      src/core/short_code/short_code.h

2
src/core/CMakeLists.txt

@ -19,7 +19,7 @@ set(KLSK_CORE_SRC
# raw_code/internal/mirror.cc
short_code/internal/convert.cc
short_code/internal/serialize.cc
# short_code/internal/serialize.cc
mover/internal/mover.cc

15
src/core/short_code/internal/convert.cc

@ -50,21 +50,6 @@ static uint32_t check_range(uint32_t head, uint32_t range) noexcept {
return 0; // pass check
}
uint32_t ShortCode::fast_encode(uint64_t common_code) {
auto head = common_code >> 32;
const auto &ranges = (*cases_).ranges(head); // match available ranges
// TODO: try to narrow the scope by prefix
auto target = std::lower_bound(ranges.begin(), ranges.end(), (uint32_t)common_code);
return ALL_CASES_OFFSET[head] + (target - ranges.begin());
}
uint64_t ShortCode::fast_decode(uint32_t short_code) {
auto offset = std::upper_bound(ALL_CASES_OFFSET.begin(), ALL_CASES_OFFSET.end(), short_code) - 1;
uint64_t head = offset - ALL_CASES_OFFSET.begin();
// return (head << 32) | AllCases::instance().fetch()[head][short_code - *offset];
return (head << 32) | (*cases_).ranges(head)[short_code - *offset];
}
uint32_t ShortCode::tiny_encode(uint64_t common_code) {
uint32_t head = common_code >> 32;
uint32_t prefix = (common_code >> 20) & 0xFFF;

22
src/core/short_code/internal/convert.inl

@ -0,0 +1,22 @@
#pragma once
#include <algorithm>
namespace klotski::codec {
KLSK_INLINE_H uint32_t ShortCode::fast_encode(uint64_t common_code) {
auto head = common_code >> 32;
const auto &ranges = (*cases_).ranges(head); // match available ranges
// TODO: try to narrow the scope by prefix
auto target = std::lower_bound(ranges.begin(), ranges.end(), (uint32_t)common_code);
return cases::ALL_CASES_OFFSET[head] + (target - ranges.begin());
}
KLSK_INLINE_H uint64_t ShortCode::fast_decode(uint32_t short_code) {
auto offset = std::upper_bound(cases::ALL_CASES_OFFSET.begin(), cases::ALL_CASES_OFFSET.end(), short_code) - 1;
uint64_t head = offset - cases::ALL_CASES_OFFSET.begin();
// return (head << 32) | AllCases::instance().fetch()[head][short_code - *offset];
return (head << 32) | (*cases_).ranges(head)[short_code - *offset];
}
} // namespace klotski::codec

14
src/core/short_code/internal/serialize.cc → src/core/short_code/internal/serialize.inl

@ -1,13 +1,13 @@
#pragma once
#include <ranges>
#include "serialize_chars.h"
#include "short_code/short_code.h"
using klotski::codec::ShortCode;
using klotski::cases::ALL_CASES_NUM_;
namespace klotski::codec {
std::string ShortCode::string_encode(uint32_t short_code) {
KLSK_ASSUME(short_code < ALL_CASES_NUM_);
KLSK_INLINE_H std::string ShortCode::string_encode(uint32_t short_code) {
KLSK_ASSUME(short_code < cases::ALL_CASES_NUM_);
std::array<char, 5> arr {};
for (auto &c : arr | std::views::reverse) {
c = SHORT_CODE_TABLE[short_code & 0b11111]; // table convert
@ -16,7 +16,7 @@ std::string ShortCode::string_encode(uint32_t short_code) {
return {arr.begin(), arr.end()};
}
std::optional<uint32_t> ShortCode::string_decode(const std::string_view short_code) {
KLSK_INLINE_H std::optional<uint32_t> ShortCode::string_decode(const std::string_view short_code) {
if (short_code.length() != 5) {
return std::nullopt; // invalid string length
}
@ -36,3 +36,5 @@ std::optional<uint32_t> ShortCode::string_decode(const std::string_view short_co
}
return code; // apply convert result
}
} // namespace klotski::codec

10
src/core/short_code/internal/short_code.inl

@ -15,11 +15,11 @@ inline ShortCode::ShortCode(const CommonCode common_code) {
}
}
inline ShortCode ShortCode::unsafe_create(const uint32_t short_code) {
constexpr ShortCode ShortCode::unsafe_create(const uint32_t short_code) {
return std::bit_cast<ShortCode>(short_code); // init directly
}
inline std::optional<ShortCode> ShortCode::create(const uint32_t short_code) {
constexpr std::optional<ShortCode> ShortCode::create(const uint32_t short_code) {
if (!check(short_code)) {
return std::nullopt; // invalid short code
}
@ -28,11 +28,11 @@ inline std::optional<ShortCode> ShortCode::create(const uint32_t short_code) {
// ----------------------------------------------------------------------------------------- //
inline ShortCode::operator uint32_t() const {
constexpr ShortCode::operator uint32_t() const {
return code_;
}
inline bool ShortCode::check(const uint32_t short_code) {
constexpr bool ShortCode::check(const uint32_t short_code) {
return short_code < SHORT_CODE_LIMIT; // [0, SHORT_CODE_LIMIT)
}
@ -55,7 +55,7 @@ inline std::ostream& operator<<(std::ostream &out, const ShortCode self) {
// ----------------------------------------------------------------------------------------- //
inline uint32_t ShortCode::unwrap() const {
constexpr uint32_t ShortCode::unwrap() const {
return code_;
}

27
src/core/short_code/short_code.h

@ -66,20 +66,13 @@
#include <optional>
#include "utils/utility.h"
// #include "all_cases/all_cases.h"
namespace klotski::cases {
class AllCases;
class Ranges;
class RangesUnion;
} // namespace klotski::cases
#include "ranges/ranges_fwd.h"
#include "all_cases/all_cases_fwd.h"
#include "common_code/common_code_fwd.h"
namespace klotski::codec {
constexpr uint32_t SHORT_CODE_LIMIT = 29334498;
// constexpr uint32_t SHORT_CODE_LIMIT = cases::ALL_CASES_NUM_;
class CommonCode;
constexpr uint32_t SHORT_CODE_LIMIT = cases::ALL_CASES_NUM_;
class ShortCode {
public:
@ -91,18 +84,18 @@ public:
explicit ShortCode(CommonCode common_code);
/// Create ShortCode without any check.
static ShortCode unsafe_create(uint32_t short_code);
static constexpr ShortCode unsafe_create(uint32_t short_code);
/// Create ShortCode with validity check.
static std::optional<ShortCode> create(uint32_t short_code);
static constexpr std::optional<ShortCode> create(uint32_t short_code);
// ------------------------------------------------------------------------------------- //
/// Explicit conversion to u32 code.
explicit operator uint32_t() const;
explicit constexpr operator uint32_t() const;
/// Check the validity of the original ShortCode.
static bool check(uint32_t short_code);
static constexpr bool check(uint32_t short_code);
/// Build the conversion index for ShortCode.
static void speed_up(bool fast_mode = false);
@ -115,7 +108,7 @@ public:
// ------------------------------------------------------------------------------------- //
/// Get the original u32 code.
[[nodiscard]] uint32_t unwrap() const;
[[nodiscard]] constexpr uint32_t unwrap() const;
/// Convert ShortCode to string form.
[[nodiscard]] std::string to_string() const;
@ -200,3 +193,5 @@ static_assert(std::is_trivially_copyable_v<ShortCode>);
} // namespace klotski::codec
#include "internal/short_code.inl"
#include "internal/serialize.inl"
#include "internal/convert.inl"

Loading…
Cancel
Save