Browse Source

feat: add constexpr support of codec module

master
Dnomd343 3 weeks ago
parent
commit
f536d8d93f
  1. 10
      src/core/CMakeLists.txt
  2. 40
      src/core/common_code/common_code.h
  3. 9
      src/core/common_code/internal/check.inl
  4. 22
      src/core/common_code/internal/common_code.inl
  5. 14
      src/core/common_code/internal/mirror.inl
  6. 2
      src/core/group/internal/group.inl
  7. 1
      src/core/group/internal/group_union.inl
  8. 34
      src/core/main.cc
  9. 15
      src/core/raw_code/internal/check.inl
  10. 11
      src/core/raw_code/internal/convert.inl
  11. 27
      src/core/raw_code/internal/mirror.inl
  12. 20
      src/core/raw_code/internal/raw_code.inl
  13. 41
      src/core/raw_code/raw_code.h
  14. 9
      src/core/raw_code/raw_code_fwd.h
  15. 2
      src/core/short_code/short_code.h
  16. 9
      src/core/short_code/short_code_fwd.h

10
src/core/CMakeLists.txt

@ -10,13 +10,13 @@ set(KLSK_CORE_SRC
all_cases/internal/basic_ranges.cc all_cases/internal/basic_ranges.cc
all_cases/internal/all_cases.cc all_cases/internal/all_cases.cc
common_code/internal/common_code.cc # common_code/internal/common_code.cc
common_code/internal/serialize.cc common_code/internal/serialize.cc
common_code/internal/mirror.cc # common_code/internal/mirror.cc
raw_code/internal/raw_code.cc # raw_code/internal/raw_code.cc
raw_code/internal/convert.cc # raw_code/internal/convert.cc
raw_code/internal/mirror.cc # raw_code/internal/mirror.cc
short_code/internal/convert.cc short_code/internal/convert.cc
short_code/internal/serialize.cc short_code/internal/serialize.cc

40
src/core/common_code/common_code.h

@ -62,13 +62,12 @@
#include <string> #include <string>
#include <cstdint> #include <cstdint>
#include <ostream>
#include <optional> #include <optional>
namespace klotski::codec { #include "raw_code/raw_code_fwd.h"
#include "short_code/short_code_fwd.h"
class RawCode; namespace klotski::codec {
class ShortCode;
class CommonCode { class CommonCode {
public: public:
@ -77,24 +76,24 @@ public:
CommonCode() = delete; CommonCode() = delete;
/// Construct CommonCode from RawCode. /// Construct CommonCode from RawCode.
explicit CommonCode(RawCode raw_code); explicit constexpr CommonCode(RawCode raw_code);
/// Construct CommonCode from ShortCode. /// Construct CommonCode from ShortCode.
explicit CommonCode(ShortCode short_code); explicit CommonCode(ShortCode short_code);
/// Create CommonCode without any check. /// Create CommonCode without any check.
static CommonCode unsafe_create(uint64_t common_code); static constexpr CommonCode unsafe_create(uint64_t common_code);
/// Create CommonCode with validity check. /// Create CommonCode with validity check.
static std::optional<CommonCode> create(uint64_t common_code); static constexpr std::optional<CommonCode> create(uint64_t common_code);
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
/// Explicit conversion to u64 code. /// Explicit conversion to u64 code.
explicit operator uint64_t() const; explicit constexpr operator uint64_t() const;
/// Check the validity of the original CommonCode. /// Check the validity of the original CommonCode.
static bool check(uint64_t common_code); static constexpr bool check(uint64_t common_code);
#ifndef KLSK_NDEBUG #ifndef KLSK_NDEBUG
/// Output string encoding of CommonCode only for debug. /// Output string encoding of CommonCode only for debug.
@ -107,7 +106,7 @@ public:
[[nodiscard]] constexpr uint64_t unwrap() const; [[nodiscard]] constexpr uint64_t unwrap() const;
/// Convert CommonCode to RawCode. /// Convert CommonCode to RawCode.
[[nodiscard]] RawCode to_raw_code() const; [[nodiscard]] constexpr RawCode to_raw_code() const;
/// Convert CommonCode to ShortCode. /// Convert CommonCode to ShortCode.
[[nodiscard]] ShortCode to_short_code() const; [[nodiscard]] ShortCode to_short_code() const;
@ -123,10 +122,10 @@ public:
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
/// Create CommonCode from RawCode. /// Create CommonCode from RawCode.
static CommonCode from_raw_code(RawCode raw_code); static constexpr CommonCode from_raw_code(RawCode raw_code);
/// Create CommonCode from RawCode in u64. /// Create CommonCode from RawCode in u64.
static std::optional<CommonCode> from_raw_code(uint64_t raw_code); static constexpr std::optional<CommonCode> from_raw_code(uint64_t raw_code);
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
@ -142,16 +141,16 @@ public:
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
/// Whether the layout is vertically symmetrical. /// Whether the layout is vertically symmetrical.
[[nodiscard]] bool is_vertical_mirror() const; [[nodiscard]] constexpr bool is_vertical_mirror() const;
/// Whether the layout is horizontally symmetrical. /// Whether the layout is horizontally symmetrical.
[[nodiscard]] bool is_horizontal_mirror() const; [[nodiscard]] constexpr bool is_horizontal_mirror() const;
/// Calculate the vertically symmetrical klotski layout. /// Calculate the vertically symmetrical klotski layout.
[[nodiscard]] CommonCode to_vertical_mirror() const; [[nodiscard]] constexpr CommonCode to_vertical_mirror() const;
/// Calculate the horizontally symmetrical klotski layout. /// Calculate the horizontally symmetrical klotski layout.
[[nodiscard]] CommonCode to_horizontal_mirror() const; [[nodiscard]] constexpr CommonCode to_horizontal_mirror() const;
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
@ -182,20 +181,23 @@ private:
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
/// Check the horizontally symmetrical. /// Check the horizontally symmetrical.
static bool check_mirror(uint64_t common_code); static constexpr bool check_mirror(uint64_t common_code);
/// Get the vertically symmetrical layout. /// Get the vertically symmetrical layout.
static uint64_t get_vertical_mirror(uint64_t common_code); static constexpr uint64_t get_vertical_mirror(uint64_t common_code);
/// Get the horizontally symmetrical layout. /// Get the horizontally symmetrical layout.
static uint64_t get_horizontal_mirror(uint64_t common_code); static constexpr uint64_t get_horizontal_mirror(uint64_t common_code);
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
}; };
static_assert(sizeof(CommonCode) == 8);
static_assert(std::is_standard_layout_v<CommonCode>); static_assert(std::is_standard_layout_v<CommonCode>);
static_assert(std::is_trivially_copyable_v<CommonCode>); static_assert(std::is_trivially_copyable_v<CommonCode>);
} // namespace klotski::codec } // namespace klotski::codec
#include "internal/common_code.inl" #include "internal/common_code.inl"
#include "internal/mirror.inl"
#include "internal/check.inl"

9
src/core/common_code/internal/common_code.cc → src/core/common_code/internal/check.inl

@ -1,9 +1,10 @@
#pragma once
#include "utils/utility.h" #include "utils/utility.h"
#include "common_code/common_code.h"
using klotski::codec::CommonCode; namespace klotski::codec {
bool CommonCode::check(const uint64_t common_code) { constexpr bool CommonCode::check(const uint64_t common_code) {
// TODO: optimization of synchronizing all_cases. // TODO: optimization of synchronizing all_cases.
/// M_1x1 | M_1x2 | M_2x1 | M_2x2 /// M_1x1 | M_1x2 | M_2x1 | M_2x2
@ -56,3 +57,5 @@ bool CommonCode::check(const uint64_t common_code) {
} }
} }
} }
} // namespace klotski::codec

22
src/core/common_code/internal/common_code.inl

@ -7,7 +7,7 @@ namespace klotski::codec {
// ----------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------- //
inline CommonCode::CommonCode(const RawCode raw_code) { constexpr CommonCode::CommonCode(const RawCode raw_code) {
code_ = raw_code.to_common_code().code_; code_ = raw_code.to_common_code().code_;
} }
@ -15,11 +15,11 @@ inline CommonCode::CommonCode(const ShortCode short_code) {
code_ = short_code.to_common_code().code_; code_ = short_code.to_common_code().code_;
} }
inline CommonCode CommonCode::unsafe_create(const uint64_t common_code) { constexpr CommonCode CommonCode::unsafe_create(const uint64_t common_code) {
return std::bit_cast<CommonCode>(common_code); // init directly return std::bit_cast<CommonCode>(common_code); // init directly
} }
inline std::optional<CommonCode> CommonCode::create(const uint64_t common_code) { constexpr std::optional<CommonCode> CommonCode::create(const uint64_t common_code) {
if (!check(common_code)) { if (!check(common_code)) {
return std::nullopt; // invalid common code return std::nullopt; // invalid common code
} }
@ -28,7 +28,7 @@ inline std::optional<CommonCode> CommonCode::create(const uint64_t common_code)
// ----------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------- //
inline CommonCode::operator uint64_t() const { constexpr CommonCode::operator uint64_t() const {
return code_; return code_;
} }
@ -45,7 +45,7 @@ constexpr uint64_t CommonCode::unwrap() const {
return code_; return code_;
} }
inline RawCode CommonCode::to_raw_code() const { constexpr RawCode CommonCode::to_raw_code() const {
return RawCode(*this); return RawCode(*this);
} }
@ -68,11 +68,11 @@ inline std::optional<CommonCode> CommonCode::from_string(const std::string_view
// ----------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------- //
inline CommonCode CommonCode::from_raw_code(const RawCode raw_code) { constexpr CommonCode CommonCode::from_raw_code(const RawCode raw_code) {
return raw_code.to_common_code(); return raw_code.to_common_code();
} }
inline std::optional<CommonCode> CommonCode::from_raw_code(const uint64_t raw_code) { constexpr std::optional<CommonCode> CommonCode::from_raw_code(const uint64_t raw_code) {
const auto convert = [](const RawCode code) { const auto convert = [](const RawCode code) {
return code.to_common_code(); return code.to_common_code();
}; };
@ -101,19 +101,19 @@ inline std::optional<CommonCode> CommonCode::from_short_code(const std::string_v
// ----------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------- //
inline bool CommonCode::is_vertical_mirror() const { constexpr bool CommonCode::is_vertical_mirror() const {
return false; return false;
} }
inline bool CommonCode::is_horizontal_mirror() const { constexpr bool CommonCode::is_horizontal_mirror() const {
return check_mirror(code_); return check_mirror(code_);
} }
inline CommonCode CommonCode::to_vertical_mirror() const { constexpr CommonCode CommonCode::to_vertical_mirror() const {
return unsafe_create(get_vertical_mirror(code_)); return unsafe_create(get_vertical_mirror(code_));
} }
inline CommonCode CommonCode::to_horizontal_mirror() const { constexpr CommonCode CommonCode::to_horizontal_mirror() const {
return unsafe_create(get_horizontal_mirror(code_)); return unsafe_create(get_horizontal_mirror(code_));
} }

14
src/core/common_code/internal/mirror.cc → src/core/common_code/internal/mirror.inl

@ -1,11 +1,9 @@
#include <format> #pragma once
#include "common_code/common_code.h" namespace klotski::codec {
using klotski::codec::CommonCode;
// TODO: performance optimization. // TODO: performance optimization.
bool CommonCode::check_mirror(uint64_t common_code) { constexpr bool CommonCode::check_mirror(uint64_t common_code) {
int head = common_code >> 32; int head = common_code >> 32;
uint32_t ranges = range_reverse(common_code); uint32_t ranges = range_reverse(common_code);
@ -134,13 +132,15 @@ bool CommonCode::check_mirror(uint64_t common_code) {
} }
// TODO: temporarily use RawCode conversion. // TODO: temporarily use RawCode conversion.
uint64_t CommonCode::get_vertical_mirror(uint64_t common_code) { constexpr uint64_t CommonCode::get_vertical_mirror(uint64_t common_code) {
auto raw_code = unsafe_create(common_code).to_raw_code(); auto raw_code = unsafe_create(common_code).to_raw_code();
return raw_code.to_vertical_mirror().to_common_code().unwrap(); return raw_code.to_vertical_mirror().to_common_code().unwrap();
} }
// TODO: temporarily use RawCode conversion. // TODO: temporarily use RawCode conversion.
uint64_t CommonCode::get_horizontal_mirror(uint64_t common_code) { constexpr uint64_t CommonCode::get_horizontal_mirror(uint64_t common_code) {
auto raw_code = unsafe_create(common_code).to_raw_code(); auto raw_code = unsafe_create(common_code).to_raw_code();
return raw_code.to_horizontal_mirror().to_common_code().unwrap(); return raw_code.to_horizontal_mirror().to_common_code().unwrap();
} }
} // namespace klotski::codec

2
src/core/group/internal/group.inl

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <format>
#include "constant/group.h" #include "constant/group.h"
namespace klotski::group { namespace klotski::group {

1
src/core/group/internal/group_union.inl

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <ranges> #include <ranges>
#include <ostream> // TODO: only for debug output
namespace klotski::group { namespace klotski::group {

34
src/core/main.cc

@ -45,6 +45,40 @@ int main() {
const auto start = std::chrono::system_clock::now(); const auto start = std::chrono::system_clock::now();
static_assert(CommonCode::check(0x1A9BF0C00));
constexpr auto common_code = CommonCode::unsafe_create(0x1A9BF0C00);
static_assert(common_code.unwrap() == 0x1A9BF0C00);
static_assert(static_cast<uint64_t>(common_code) == 0x1A9BF0C00);
static_assert(common_code == CommonCode::create(0x1A9BF0C00)->unwrap());
static_assert(common_code.to_raw_code() == 0x603EDF5CAFFF5E2);
static_assert(CommonCode::from_raw_code(0x603EDF5CAFFF5E2).value() == 0x1A9BF0C00);
static_assert(CommonCode(RawCode::unsafe_create(0x603EDF5CAFFF5E2)) == 0x1A9BF0C00);
static_assert(CommonCode::from_raw_code(RawCode::unsafe_create(0x603EDF5CAFFF5E2)) == 0x1A9BF0C00);
static_assert(!common_code.is_vertical_mirror());
static_assert(common_code.is_horizontal_mirror());
static_assert(common_code.to_vertical_mirror() == 0xDC3BE6800);
static_assert(common_code.to_horizontal_mirror() == 0x1A9BF0C00);
static_assert(RawCode::check(0x603EDF5CAFFF5E2));
constexpr auto raw_code = RawCode::unsafe_create(0x603EDF5CAFFF5E2);
static_assert(raw_code.unwrap() == 0x603EDF5CAFFF5E2);
static_assert(static_cast<uint64_t>(raw_code) == 0x603EDF5CAFFF5E2);
static_assert(raw_code == RawCode::create(0x603EDF5CAFFF5E2)->unwrap());
static_assert(raw_code.to_common_code() == 0x1A9BF0C00);
static_assert(RawCode::from_common_code(0x1A9BF0C00).value() == 0x603EDF5CAFFF5E2);
static_assert(RawCode(CommonCode::unsafe_create(0x1A9BF0C00)) == 0x603EDF5CAFFF5E2);
static_assert(RawCode::from_common_code(CommonCode::unsafe_create(0x1A9BF0C00)) == 0x603EDF5CAFFF5E2);
static_assert(!raw_code.is_vertical_mirror());
static_assert(raw_code.is_horizontal_mirror());
static_assert(raw_code.to_vertical_mirror() == 0xFFF5E2FCF4DA603);
static_assert(raw_code.to_horizontal_mirror() == 0x603EDF5CAFFF5E2);
// const auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code(); // const auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code();
// const auto code = CommonCode::unsafe_create(0x4FEA13400).to_raw_code(); // const auto code = CommonCode::unsafe_create(0x4FEA13400).to_raw_code();
// FastCal fc {code}; // FastCal fc {code};

15
src/core/raw_code/internal/raw_code.cc → src/core/raw_code/internal/check.inl

@ -1,12 +1,17 @@
#pragma once
#ifndef KLSK_NDEBUG
// TODO: only for debug output -> move to other header
#include <format> #include <format>
#include <ostream>
#endif
#include "utils/common.h" #include "utils/common.h"
#include "raw_code/raw_code.h"
using klotski::codec::RawCode; namespace klotski::codec {
#ifndef KLSK_NDEBUG #ifndef KLSK_NDEBUG
std::ostream& klotski::codec::operator<<(std::ostream &out, const RawCode self) { inline std::ostream& operator<<(std::ostream &out, const RawCode self) {
constexpr auto char_map = std::to_array({ constexpr auto char_map = std::to_array({
'.', // space '.', // space
'~', '|', // 1x2 | 2x1 '~', '|', // 1x2 | 2x1
@ -23,7 +28,7 @@ std::ostream& klotski::codec::operator<<(std::ostream &out, const RawCode self)
} }
#endif #endif
bool RawCode::check(uint64_t raw_code) { constexpr bool RawCode::check(uint64_t raw_code) {
/// MASK_1x1 | MASK_1x2 | MASK_2x1 | MASK_2x2 /// MASK_1x1 | MASK_1x2 | MASK_2x1 | MASK_2x2
/// 100 000 000 000 | 000 100 000 000 | 000 000 000 000 | 000 100 000 000 /// 100 000 000 000 | 000 100 000 000 | 000 000 000 000 | 000 100 000 000
/// 000 000 000 000 | 000 000 000 000 | 100 000 000 000 | 100 100 000 000 /// 000 000 000 000 | 000 000 000 000 | 100 000 000 000 | 100 100 000 000
@ -71,3 +76,5 @@ bool RawCode::check(uint64_t raw_code) {
} }
return head_num == 1 && space_num >= 2; // one head and at least 2 space return head_num == 1 && space_num >= 2; // one head and at least 2 space
} }
} // namespace klotski::codec

11
src/core/raw_code/internal/convert.cc → src/core/raw_code/internal/convert.inl

@ -1,10 +1,11 @@
#pragma once
#include "utils/common.h" #include "utils/common.h"
#include "utils/utility.h" #include "utils/utility.h"
#include "raw_code/raw_code.h"
using klotski::codec::RawCode; namespace klotski::codec {
uint64_t RawCode::compact(uint64_t raw_code) { constexpr uint64_t RawCode::compact(uint64_t raw_code) {
int unfilled = 16; int unfilled = 16;
uint64_t head = 0; // 2x2 block address uint64_t head = 0; // 2x2 block address
uint32_t range = 0; uint32_t range = 0;
@ -32,7 +33,7 @@ uint64_t RawCode::compact(uint64_t raw_code) {
return head | (range << (unfilled << 1)); // fill low bits as zero return head | (range << (unfilled << 1)); // fill low bits as zero
} }
uint64_t RawCode::extract(uint64_t common_code) { constexpr uint64_t RawCode::extract(uint64_t common_code) {
auto code = K_MASK_2x2 << (common_code >> 32) * 3; // flag for 2x2 block auto code = K_MASK_2x2 << (common_code >> 32) * 3; // flag for 2x2 block
auto range = range_reverse((uint32_t)common_code); // reversed range auto range = range_reverse((uint32_t)common_code); // reversed range
@ -57,3 +58,5 @@ uint64_t RawCode::extract(uint64_t common_code) {
} }
return code; return code;
} }
} // namespace klotski::codec

27
src/core/raw_code/internal/mirror.cc → src/core/raw_code/internal/mirror.inl

@ -1,7 +1,8 @@
#pragma once
#include "utils/common.h" #include "utils/common.h"
#include "raw_code/raw_code.h"
using klotski::codec::RawCode; namespace klotski::codec {
/// MASK_MIRROR_H1 | MASK_MIRROR_H2 /// MASK_MIRROR_H1 | MASK_MIRROR_H2
/// 111 000 000 000 | 000 111 000 000 /// 111 000 000 000 | 000 111 000 000
@ -24,7 +25,7 @@ constexpr uint64_t MASK_MIRROR_V1 = 0x0'000'000'000'000'FFF;
constexpr uint64_t MASK_MIRROR_V2 = 0x0'000'000'000'FFF'000; constexpr uint64_t MASK_MIRROR_V2 = 0x0'000'000'000'FFF'000;
constexpr uint64_t MASK_MIRROR_V3 = 0x0'000'000'FFF'000'000; constexpr uint64_t MASK_MIRROR_V3 = 0x0'000'000'FFF'000'000;
static void vertical_fill(uint64_t &raw_code) { static constexpr void vertical_fill(uint64_t &raw_code) {
uint64_t mask = 0; uint64_t mask = 0;
for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bit for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bit
switch ((raw_code >> addr) & 0b111) { switch ((raw_code >> addr) & 0b111) {
@ -45,7 +46,7 @@ static void vertical_fill(uint64_t &raw_code) {
} }
} }
static void horizontal_fill(uint64_t &raw_code) { static constexpr void horizontal_fill(uint64_t &raw_code) {
for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bit for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bit
switch ((raw_code >> addr) & 0b111) { switch ((raw_code >> addr) & 0b111) {
case BLOCK_1x2: case BLOCK_1x2:
@ -60,7 +61,7 @@ static void horizontal_fill(uint64_t &raw_code) {
} }
} }
static void vertical_clear(uint64_t &raw_code) { static constexpr void vertical_clear(uint64_t &raw_code) {
for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bit for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bit
switch ((raw_code >> addr) & 0b111) { switch ((raw_code >> addr) & 0b111) {
case BLOCK_2x1: case BLOCK_2x1:
@ -70,7 +71,7 @@ static void vertical_clear(uint64_t &raw_code) {
} }
} }
static void horizontal_clear(uint64_t &raw_code) { static constexpr void horizontal_clear(uint64_t &raw_code) {
for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bit for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bit
switch ((raw_code >> addr) & 0b111) { switch ((raw_code >> addr) & 0b111) {
case BLOCK_1x2: case BLOCK_1x2:
@ -80,7 +81,7 @@ static void horizontal_clear(uint64_t &raw_code) {
} }
} }
uint64_t RawCode::get_vertical_mirror(uint64_t raw_code) { constexpr uint64_t RawCode::get_vertical_mirror(uint64_t raw_code) {
vertical_fill(raw_code); vertical_fill(raw_code);
raw_code = (raw_code & MASK_MIRROR_V3) raw_code = (raw_code & MASK_MIRROR_V3)
| ((raw_code >> 48) & MASK_MIRROR_V1) | ((raw_code >> 24) & MASK_MIRROR_V2) | ((raw_code >> 48) & MASK_MIRROR_V1) | ((raw_code >> 24) & MASK_MIRROR_V2)
@ -89,7 +90,7 @@ uint64_t RawCode::get_vertical_mirror(uint64_t raw_code) {
return raw_code; return raw_code;
} }
uint64_t RawCode::get_horizontal_mirror(uint64_t raw_code) { constexpr uint64_t RawCode::get_horizontal_mirror(uint64_t raw_code) {
horizontal_fill(raw_code); horizontal_fill(raw_code);
raw_code = ((raw_code >> 9) & MASK_MIRROR_H1) | ((raw_code >> 3) & MASK_MIRROR_H2) raw_code = ((raw_code >> 9) & MASK_MIRROR_H1) | ((raw_code >> 3) & MASK_MIRROR_H2)
| ((raw_code & MASK_MIRROR_H2) << 3) | ((raw_code & MASK_MIRROR_H1) << 9); // flip raw code | ((raw_code & MASK_MIRROR_H2) << 3) | ((raw_code & MASK_MIRROR_H1) << 9); // flip raw code
@ -97,14 +98,10 @@ uint64_t RawCode::get_horizontal_mirror(uint64_t raw_code) {
return raw_code; return raw_code;
} }
// bool RawCode::check_vertical_mirror(uint64_t raw_code) { constexpr bool RawCode::check_mirror(uint64_t raw_code) {
// vertical_fill(raw_code);
// return !(MASK_MIRROR_V1 & ((raw_code >> 48) ^ raw_code))
// && !(MASK_MIRROR_V2 & ((raw_code >> 24) ^ raw_code));
// }
bool RawCode::check_mirror(uint64_t raw_code) {
horizontal_fill(raw_code); horizontal_fill(raw_code);
return !(MASK_MIRROR_H1 & ((raw_code >> 9) ^ raw_code)) return !(MASK_MIRROR_H1 & ((raw_code >> 9) ^ raw_code))
&& !(MASK_MIRROR_H2 & ((raw_code >> 3) ^ raw_code)); && !(MASK_MIRROR_H2 & ((raw_code >> 3) ^ raw_code));
} }
} // namespace klotski::codec

20
src/core/raw_code/internal/raw_code.inl

@ -6,7 +6,7 @@ namespace klotski::codec {
// ----------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------- //
inline RawCode::RawCode(const CommonCode common_code) { constexpr RawCode::RawCode(const CommonCode common_code) {
code_ = extract(common_code.unwrap()); code_ = extract(common_code.unwrap());
} }
@ -14,7 +14,7 @@ constexpr RawCode RawCode::unsafe_create(const uint64_t raw_code) {
return std::bit_cast<RawCode>(raw_code); // init directly return std::bit_cast<RawCode>(raw_code); // init directly
} }
inline std::optional<RawCode> RawCode::create(const uint64_t raw_code) { constexpr std::optional<RawCode> RawCode::create(const uint64_t raw_code) {
if (!check(raw_code)) { if (!check(raw_code)) {
return std::nullopt; // invalid raw code return std::nullopt; // invalid raw code
} }
@ -23,7 +23,7 @@ inline std::optional<RawCode> RawCode::create(const uint64_t raw_code) {
// ----------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------- //
inline RawCode::operator uint64_t() const { constexpr RawCode::operator uint64_t() const {
return code_; return code_;
} }
@ -31,17 +31,17 @@ constexpr uint64_t RawCode::unwrap() const {
return code_; return code_;
} }
inline CommonCode RawCode::to_common_code() const { constexpr CommonCode RawCode::to_common_code() const {
return CommonCode::unsafe_create(compact(code_)); return CommonCode::unsafe_create(compact(code_));
} }
// ----------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------- //
inline RawCode RawCode::from_common_code(const CommonCode common_code) { constexpr RawCode RawCode::from_common_code(const CommonCode common_code) {
return common_code.to_raw_code(); return common_code.to_raw_code();
} }
inline std::optional<RawCode> RawCode::from_common_code(const uint64_t common_code) { constexpr std::optional<RawCode> RawCode::from_common_code(const uint64_t common_code) {
const auto convert = [](const CommonCode code) { const auto convert = [](const CommonCode code) {
return code.to_raw_code(); return code.to_raw_code();
}; };
@ -57,19 +57,19 @@ inline std::optional<RawCode> RawCode::from_common_code(const std::string_view c
// ----------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------- //
inline bool RawCode::is_vertical_mirror() const { constexpr bool RawCode::is_vertical_mirror() const {
return false; return false;
} }
inline bool RawCode::is_horizontal_mirror() const { constexpr bool RawCode::is_horizontal_mirror() const {
return check_mirror(code_); return check_mirror(code_);
} }
inline RawCode RawCode::to_vertical_mirror() const { constexpr RawCode RawCode::to_vertical_mirror() const {
return unsafe_create(get_vertical_mirror(code_)); return unsafe_create(get_vertical_mirror(code_));
} }
inline RawCode RawCode::to_horizontal_mirror() const { constexpr RawCode RawCode::to_horizontal_mirror() const {
return unsafe_create(get_horizontal_mirror(code_)); return unsafe_create(get_horizontal_mirror(code_));
} }

41
src/core/raw_code/raw_code.h

@ -64,13 +64,12 @@
#pragma once #pragma once
#include <string> #include <string>
#include <ostream>
#include <cstdint> #include <cstdint>
#include <optional> #include <optional>
namespace klotski::codec { #include "common_code/common_code_fwd.h"
class CommonCode; namespace klotski::codec {
class RawCode { class RawCode {
public: public:
@ -79,21 +78,21 @@ public:
RawCode() = delete; RawCode() = delete;
/// Construct RawCode from CommonCode. /// Construct RawCode from CommonCode.
explicit RawCode(CommonCode common_code); explicit constexpr RawCode(CommonCode common_code);
/// Create RawCode without any check. /// Create RawCode without any check.
static constexpr RawCode unsafe_create(uint64_t raw_code); static constexpr RawCode unsafe_create(uint64_t raw_code);
/// Create RawCode with validity check. /// Create RawCode with validity check.
static std::optional<RawCode> create(uint64_t raw_code); static constexpr std::optional<RawCode> create(uint64_t raw_code);
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
/// Explicit conversion to u64 code. /// Explicit conversion to u64 code.
explicit operator uint64_t() const; explicit constexpr operator uint64_t() const;
/// Check the validity of the original RawCode. /// Check the validity of the original RawCode.
static bool check(uint64_t raw_code); static constexpr bool check(uint64_t raw_code);
#ifndef KLSK_NDEBUG #ifndef KLSK_NDEBUG
/// Output string encoding of RawCode only for debug. /// Output string encoding of RawCode only for debug.
@ -106,15 +105,15 @@ public:
[[nodiscard]] constexpr uint64_t unwrap() const; [[nodiscard]] constexpr uint64_t unwrap() const;
/// Convert RawCode to CommonCode. /// Convert RawCode to CommonCode.
[[nodiscard]] CommonCode to_common_code() const; [[nodiscard]] constexpr CommonCode to_common_code() const;
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
/// Create RawCode from CommonCode. /// Create RawCode from CommonCode.
static RawCode from_common_code(CommonCode common_code); static constexpr RawCode from_common_code(CommonCode common_code);
/// Create RawCode from CommonCode in u64. /// Create RawCode from CommonCode in u64.
static std::optional<RawCode> from_common_code(uint64_t common_code); static constexpr std::optional<RawCode> from_common_code(uint64_t common_code);
/// Create RawCode from CommonCode in string form. /// Create RawCode from CommonCode in string form.
static std::optional<RawCode> from_common_code(std::string_view common_code); static std::optional<RawCode> from_common_code(std::string_view common_code);
@ -122,16 +121,16 @@ public:
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
/// Whether the layout is vertically symmetrical. /// Whether the layout is vertically symmetrical.
[[nodiscard]] bool is_vertical_mirror() const; [[nodiscard]] constexpr bool is_vertical_mirror() const;
/// Whether the layout is horizontally symmetrical. /// Whether the layout is horizontally symmetrical.
[[nodiscard]] bool is_horizontal_mirror() const; [[nodiscard]] constexpr bool is_horizontal_mirror() const;
/// Calculate the vertically symmetrical klotski layout. /// Calculate the vertically symmetrical klotski layout.
[[nodiscard]] RawCode to_vertical_mirror() const; [[nodiscard]] constexpr RawCode to_vertical_mirror() const;
/// Calculate the horizontally symmetrical klotski layout. /// Calculate the horizontally symmetrical klotski layout.
[[nodiscard]] RawCode to_horizontal_mirror() const; [[nodiscard]] constexpr RawCode to_horizontal_mirror() const;
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
@ -151,28 +150,32 @@ private:
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
/// Compact RawCode as CommonCode. /// Compact RawCode as CommonCode.
static uint64_t compact(uint64_t raw_code); static constexpr uint64_t compact(uint64_t raw_code);
/// Extract CommonCode as RawCode. /// Extract CommonCode as RawCode.
static uint64_t extract(uint64_t common_code); static constexpr uint64_t extract(uint64_t common_code);
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
/// Check the horizontally symmetrical. /// Check the horizontally symmetrical.
static bool check_mirror(uint64_t raw_code); static constexpr bool check_mirror(uint64_t raw_code);
/// Get the vertically symmetrical layout. /// Get the vertically symmetrical layout.
static uint64_t get_vertical_mirror(uint64_t raw_code); static constexpr uint64_t get_vertical_mirror(uint64_t raw_code);
/// Get the horizontally symmetrical layout. /// Get the horizontally symmetrical layout.
static uint64_t get_horizontal_mirror(uint64_t raw_code); static constexpr uint64_t get_horizontal_mirror(uint64_t raw_code);
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
}; };
static_assert(sizeof(RawCode) == 8);
static_assert(std::is_standard_layout_v<RawCode>); static_assert(std::is_standard_layout_v<RawCode>);
static_assert(std::is_trivially_copyable_v<RawCode>); static_assert(std::is_trivially_copyable_v<RawCode>);
} // namespace klotski::codec } // namespace klotski::codec
#include "internal/raw_code.inl" #include "internal/raw_code.inl"
#include "internal/convert.inl"
#include "internal/mirror.inl"
#include "internal/check.inl"

9
src/core/raw_code/raw_code_fwd.h

@ -0,0 +1,9 @@
/// Klotski Engine by Dnomd343 @2024
#pragma once
namespace klotski::codec {
class RawCode;
} // namespace klotski::codec

2
src/core/short_code/short_code.h

@ -63,7 +63,6 @@
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <cstdint> #include <cstdint>
#include <ostream>
#include <optional> #include <optional>
#include "utils/utility.h" #include "utils/utility.h"
@ -194,6 +193,7 @@ private:
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
}; };
static_assert(sizeof(ShortCode) == 4);
static_assert(std::is_standard_layout_v<ShortCode>); static_assert(std::is_standard_layout_v<ShortCode>);
static_assert(std::is_trivially_copyable_v<ShortCode>); static_assert(std::is_trivially_copyable_v<ShortCode>);

9
src/core/short_code/short_code_fwd.h

@ -0,0 +1,9 @@
/// Klotski Engine by Dnomd343 @2024
#pragma once
namespace klotski::codec {
class ShortCode;
} // namespace klotski::codec
Loading…
Cancel
Save