From f536d8d93f014825699b4387a9a927d655571bfa Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Sun, 8 Dec 2024 15:54:17 +0800 Subject: [PATCH] feat: add constexpr support of codec module --- src/core/CMakeLists.txt | 10 ++--- src/core/common_code/common_code.h | 40 +++++++++--------- .../internal/{common_code.cc => check.inl} | 9 ++-- src/core/common_code/internal/common_code.inl | 22 +++++----- .../internal/{mirror.cc => mirror.inl} | 14 +++---- src/core/group/internal/group.inl | 2 + src/core/group/internal/group_union.inl | 1 + src/core/main.cc | 34 +++++++++++++++ .../internal/{raw_code.cc => check.inl} | 15 +++++-- .../internal/{convert.cc => convert.inl} | 11 +++-- .../internal/{mirror.cc => mirror.inl} | 27 ++++++------ src/core/raw_code/internal/raw_code.inl | 20 ++++----- src/core/raw_code/raw_code.h | 41 ++++++++++--------- src/core/raw_code/raw_code_fwd.h | 9 ++++ src/core/short_code/short_code.h | 2 +- src/core/short_code/short_code_fwd.h | 9 ++++ 16 files changed, 168 insertions(+), 98 deletions(-) rename src/core/common_code/internal/{common_code.cc => check.inl} (93%) rename src/core/common_code/internal/{mirror.cc => mirror.inl} (93%) rename src/core/raw_code/internal/{raw_code.cc => check.inl} (89%) rename src/core/raw_code/internal/{convert.cc => convert.inl} (90%) rename src/core/raw_code/internal/{mirror.cc => mirror.inl} (84%) create mode 100644 src/core/raw_code/raw_code_fwd.h create mode 100644 src/core/short_code/short_code_fwd.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index fdd95e0..16429c3 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -10,13 +10,13 @@ set(KLSK_CORE_SRC all_cases/internal/basic_ranges.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/mirror.cc +# common_code/internal/mirror.cc - raw_code/internal/raw_code.cc - raw_code/internal/convert.cc - raw_code/internal/mirror.cc +# raw_code/internal/raw_code.cc +# raw_code/internal/convert.cc +# raw_code/internal/mirror.cc short_code/internal/convert.cc short_code/internal/serialize.cc diff --git a/src/core/common_code/common_code.h b/src/core/common_code/common_code.h index 26a2dc1..24159e7 100644 --- a/src/core/common_code/common_code.h +++ b/src/core/common_code/common_code.h @@ -62,13 +62,12 @@ #include #include -#include #include -namespace klotski::codec { +#include "raw_code/raw_code_fwd.h" +#include "short_code/short_code_fwd.h" -class RawCode; -class ShortCode; +namespace klotski::codec { class CommonCode { public: @@ -77,24 +76,24 @@ public: CommonCode() = delete; /// Construct CommonCode from RawCode. - explicit CommonCode(RawCode raw_code); + explicit constexpr CommonCode(RawCode raw_code); /// Construct CommonCode from ShortCode. explicit CommonCode(ShortCode short_code); /// 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. - static std::optional create(uint64_t common_code); + static constexpr std::optional create(uint64_t common_code); // ------------------------------------------------------------------------------------- // /// Explicit conversion to u64 code. - explicit operator uint64_t() const; + explicit constexpr operator uint64_t() const; /// 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 /// Output string encoding of CommonCode only for debug. @@ -107,7 +106,7 @@ public: [[nodiscard]] constexpr uint64_t unwrap() const; /// Convert CommonCode to RawCode. - [[nodiscard]] RawCode to_raw_code() const; + [[nodiscard]] constexpr RawCode to_raw_code() const; /// Convert CommonCode to ShortCode. [[nodiscard]] ShortCode to_short_code() const; @@ -123,10 +122,10 @@ public: // ------------------------------------------------------------------------------------- // /// 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. - static std::optional from_raw_code(uint64_t raw_code); + static constexpr std::optional from_raw_code(uint64_t raw_code); // ------------------------------------------------------------------------------------- // @@ -142,16 +141,16 @@ public: // ------------------------------------------------------------------------------------- // /// 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. - [[nodiscard]] bool is_horizontal_mirror() const; + [[nodiscard]] constexpr bool is_horizontal_mirror() const; /// 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. - [[nodiscard]] CommonCode to_horizontal_mirror() const; + [[nodiscard]] constexpr CommonCode to_horizontal_mirror() const; // ------------------------------------------------------------------------------------- // @@ -182,20 +181,23 @@ private: // ------------------------------------------------------------------------------------- // /// 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. - 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. - 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); static_assert(std::is_trivially_copyable_v); } // namespace klotski::codec #include "internal/common_code.inl" +#include "internal/mirror.inl" +#include "internal/check.inl" diff --git a/src/core/common_code/internal/common_code.cc b/src/core/common_code/internal/check.inl similarity index 93% rename from src/core/common_code/internal/common_code.cc rename to src/core/common_code/internal/check.inl index 24af763..2a96acb 100644 --- a/src/core/common_code/internal/common_code.cc +++ b/src/core/common_code/internal/check.inl @@ -1,9 +1,10 @@ +#pragma once + #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. /// M_1x1 | M_1x2 | M_2x1 | M_2x2 @@ -56,3 +57,5 @@ bool CommonCode::check(const uint64_t common_code) { } } } + +} // namespace klotski::codec diff --git a/src/core/common_code/internal/common_code.inl b/src/core/common_code/internal/common_code.inl index 575bdb2..de55de5 100644 --- a/src/core/common_code/internal/common_code.inl +++ b/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_; } @@ -15,11 +15,11 @@ inline CommonCode::CommonCode(const ShortCode short_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(common_code); // init directly } -inline std::optional CommonCode::create(const uint64_t common_code) { +constexpr std::optional CommonCode::create(const uint64_t common_code) { if (!check(common_code)) { return std::nullopt; // invalid common code } @@ -28,7 +28,7 @@ inline std::optional CommonCode::create(const uint64_t common_code) // ----------------------------------------------------------------------------------------- // -inline CommonCode::operator uint64_t() const { +constexpr CommonCode::operator uint64_t() const { return code_; } @@ -45,7 +45,7 @@ constexpr uint64_t CommonCode::unwrap() const { return code_; } -inline RawCode CommonCode::to_raw_code() const { +constexpr RawCode CommonCode::to_raw_code() const { return RawCode(*this); } @@ -68,11 +68,11 @@ inline std::optional 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(); } -inline std::optional CommonCode::from_raw_code(const uint64_t raw_code) { +constexpr std::optional CommonCode::from_raw_code(const uint64_t raw_code) { const auto convert = [](const RawCode code) { return code.to_common_code(); }; @@ -101,19 +101,19 @@ inline std::optional CommonCode::from_short_code(const std::string_v // ----------------------------------------------------------------------------------------- // -inline bool CommonCode::is_vertical_mirror() const { +constexpr bool CommonCode::is_vertical_mirror() const { return false; } -inline bool CommonCode::is_horizontal_mirror() const { +constexpr bool CommonCode::is_horizontal_mirror() const { 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_)); } -inline CommonCode CommonCode::to_horizontal_mirror() const { +constexpr CommonCode CommonCode::to_horizontal_mirror() const { return unsafe_create(get_horizontal_mirror(code_)); } diff --git a/src/core/common_code/internal/mirror.cc b/src/core/common_code/internal/mirror.inl similarity index 93% rename from src/core/common_code/internal/mirror.cc rename to src/core/common_code/internal/mirror.inl index 1e8b338..54590ec 100644 --- a/src/core/common_code/internal/mirror.cc +++ b/src/core/common_code/internal/mirror.inl @@ -1,11 +1,9 @@ -#include +#pragma once -#include "common_code/common_code.h" - -using klotski::codec::CommonCode; +namespace klotski::codec { // 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; uint32_t ranges = range_reverse(common_code); @@ -134,13 +132,15 @@ bool CommonCode::check_mirror(uint64_t common_code) { } // 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(); return raw_code.to_vertical_mirror().to_common_code().unwrap(); } // 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(); return raw_code.to_horizontal_mirror().to_common_code().unwrap(); } + +} // namespace klotski::codec diff --git a/src/core/group/internal/group.inl b/src/core/group/internal/group.inl index 8fe869a..fbb8883 100644 --- a/src/core/group/internal/group.inl +++ b/src/core/group/internal/group.inl @@ -1,5 +1,7 @@ #pragma once +#include + #include "constant/group.h" namespace klotski::group { diff --git a/src/core/group/internal/group_union.inl b/src/core/group/internal/group_union.inl index 72064eb..0f9b480 100644 --- a/src/core/group/internal/group_union.inl +++ b/src/core/group/internal/group_union.inl @@ -1,6 +1,7 @@ #pragma once #include +#include // TODO: only for debug output namespace klotski::group { diff --git a/src/core/main.cc b/src/core/main.cc index a4f45b0..8540fa5 100644 --- a/src/core/main.cc +++ b/src/core/main.cc @@ -45,6 +45,40 @@ int main() { 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(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(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(0x4FEA13400).to_raw_code(); // FastCal fc {code}; diff --git a/src/core/raw_code/internal/raw_code.cc b/src/core/raw_code/internal/check.inl similarity index 89% rename from src/core/raw_code/internal/raw_code.cc rename to src/core/raw_code/internal/check.inl index bcca2c1..f8a6759 100644 --- a/src/core/raw_code/internal/raw_code.cc +++ b/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 +#include +#endif #include "utils/common.h" -#include "raw_code/raw_code.h" -using klotski::codec::RawCode; +namespace klotski::codec { #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({ '.', // space '~', '|', // 1x2 | 2x1 @@ -23,7 +28,7 @@ std::ostream& klotski::codec::operator<<(std::ostream &out, const RawCode self) } #endif -bool RawCode::check(uint64_t raw_code) { +constexpr bool RawCode::check(uint64_t raw_code) { /// MASK_1x1 | MASK_1x2 | MASK_2x1 | MASK_2x2 /// 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 @@ -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 } + +} // namespace klotski::codec diff --git a/src/core/raw_code/internal/convert.cc b/src/core/raw_code/internal/convert.inl similarity index 90% rename from src/core/raw_code/internal/convert.cc rename to src/core/raw_code/internal/convert.inl index bb2d613..f505080 100644 --- a/src/core/raw_code/internal/convert.cc +++ b/src/core/raw_code/internal/convert.inl @@ -1,10 +1,11 @@ +#pragma once + #include "utils/common.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; uint64_t head = 0; // 2x2 block address 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 } -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 range = range_reverse((uint32_t)common_code); // reversed range @@ -57,3 +58,5 @@ uint64_t RawCode::extract(uint64_t common_code) { } return code; } + +} // namespace klotski::codec diff --git a/src/core/raw_code/internal/mirror.cc b/src/core/raw_code/internal/mirror.inl similarity index 84% rename from src/core/raw_code/internal/mirror.cc rename to src/core/raw_code/internal/mirror.inl index 536ead1..7df6ea9 100644 --- a/src/core/raw_code/internal/mirror.cc +++ b/src/core/raw_code/internal/mirror.inl @@ -1,7 +1,8 @@ +#pragma once + #include "utils/common.h" -#include "raw_code/raw_code.h" -using klotski::codec::RawCode; +namespace klotski::codec { /// MASK_MIRROR_H1 | MASK_MIRROR_H2 /// 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_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; for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bit 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 switch ((raw_code >> addr) & 0b111) { 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 switch ((raw_code >> addr) & 0b111) { 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 switch ((raw_code >> addr) & 0b111) { 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); raw_code = (raw_code & MASK_MIRROR_V3) | ((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; } -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); 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 @@ -97,14 +98,10 @@ uint64_t RawCode::get_horizontal_mirror(uint64_t raw_code) { return raw_code; } -// bool RawCode::check_vertical_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) { +constexpr bool RawCode::check_mirror(uint64_t raw_code) { horizontal_fill(raw_code); return !(MASK_MIRROR_H1 & ((raw_code >> 9) ^ raw_code)) && !(MASK_MIRROR_H2 & ((raw_code >> 3) ^ raw_code)); } + +} // namespace klotski::codec diff --git a/src/core/raw_code/internal/raw_code.inl b/src/core/raw_code/internal/raw_code.inl index 7b13e65..8ae3f1c 100644 --- a/src/core/raw_code/internal/raw_code.inl +++ b/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()); } @@ -14,7 +14,7 @@ constexpr RawCode RawCode::unsafe_create(const uint64_t raw_code) { return std::bit_cast(raw_code); // init directly } -inline std::optional RawCode::create(const uint64_t raw_code) { +constexpr std::optional RawCode::create(const uint64_t raw_code) { if (!check(raw_code)) { return std::nullopt; // invalid raw code } @@ -23,7 +23,7 @@ inline std::optional RawCode::create(const uint64_t raw_code) { // ----------------------------------------------------------------------------------------- // -inline RawCode::operator uint64_t() const { +constexpr RawCode::operator uint64_t() const { return code_; } @@ -31,17 +31,17 @@ constexpr uint64_t RawCode::unwrap() const { return code_; } -inline CommonCode RawCode::to_common_code() const { +constexpr CommonCode RawCode::to_common_code() const { 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(); } -inline std::optional RawCode::from_common_code(const uint64_t common_code) { +constexpr std::optional RawCode::from_common_code(const uint64_t common_code) { const auto convert = [](const CommonCode code) { return code.to_raw_code(); }; @@ -57,19 +57,19 @@ inline std::optional 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; } -inline bool RawCode::is_horizontal_mirror() const { +constexpr bool RawCode::is_horizontal_mirror() const { 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_)); } -inline RawCode RawCode::to_horizontal_mirror() const { +constexpr RawCode RawCode::to_horizontal_mirror() const { return unsafe_create(get_horizontal_mirror(code_)); } diff --git a/src/core/raw_code/raw_code.h b/src/core/raw_code/raw_code.h index bf51ceb..6bb82d8 100644 --- a/src/core/raw_code/raw_code.h +++ b/src/core/raw_code/raw_code.h @@ -64,13 +64,12 @@ #pragma once #include -#include #include #include -namespace klotski::codec { +#include "common_code/common_code_fwd.h" -class CommonCode; +namespace klotski::codec { class RawCode { public: @@ -79,21 +78,21 @@ public: RawCode() = delete; /// Construct RawCode from CommonCode. - explicit RawCode(CommonCode common_code); + explicit constexpr RawCode(CommonCode common_code); /// Create RawCode without any check. static constexpr RawCode unsafe_create(uint64_t raw_code); /// Create RawCode with validity check. - static std::optional create(uint64_t raw_code); + static constexpr std::optional create(uint64_t raw_code); // ------------------------------------------------------------------------------------- // /// Explicit conversion to u64 code. - explicit operator uint64_t() const; + explicit constexpr operator uint64_t() const; /// 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 /// Output string encoding of RawCode only for debug. @@ -106,15 +105,15 @@ public: [[nodiscard]] constexpr uint64_t unwrap() const; /// Convert RawCode to CommonCode. - [[nodiscard]] CommonCode to_common_code() const; + [[nodiscard]] constexpr CommonCode to_common_code() const; // ------------------------------------------------------------------------------------- // /// 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. - static std::optional from_common_code(uint64_t common_code); + static constexpr std::optional from_common_code(uint64_t common_code); /// Create RawCode from CommonCode in string form. static std::optional from_common_code(std::string_view common_code); @@ -122,16 +121,16 @@ public: // ------------------------------------------------------------------------------------- // /// 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. - [[nodiscard]] bool is_horizontal_mirror() const; + [[nodiscard]] constexpr bool is_horizontal_mirror() const; /// 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. - [[nodiscard]] RawCode to_horizontal_mirror() const; + [[nodiscard]] constexpr RawCode to_horizontal_mirror() const; // ------------------------------------------------------------------------------------- // @@ -151,28 +150,32 @@ private: // ------------------------------------------------------------------------------------- // /// 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. - static uint64_t extract(uint64_t common_code); + static constexpr uint64_t extract(uint64_t common_code); // ------------------------------------------------------------------------------------- // /// 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. - 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. - 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); static_assert(std::is_trivially_copyable_v); } // namespace klotski::codec #include "internal/raw_code.inl" +#include "internal/convert.inl" +#include "internal/mirror.inl" +#include "internal/check.inl" diff --git a/src/core/raw_code/raw_code_fwd.h b/src/core/raw_code/raw_code_fwd.h new file mode 100644 index 0000000..3e165c4 --- /dev/null +++ b/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 diff --git a/src/core/short_code/short_code.h b/src/core/short_code/short_code.h index c386e8d..72ff239 100644 --- a/src/core/short_code/short_code.h +++ b/src/core/short_code/short_code.h @@ -63,7 +63,6 @@ #include #include #include -#include #include #include "utils/utility.h" @@ -194,6 +193,7 @@ private: // ------------------------------------------------------------------------------------- // }; +static_assert(sizeof(ShortCode) == 4); static_assert(std::is_standard_layout_v); static_assert(std::is_trivially_copyable_v); diff --git a/src/core/short_code/short_code_fwd.h b/src/core/short_code/short_code_fwd.h new file mode 100644 index 0000000..c2bb45a --- /dev/null +++ b/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