diff --git a/src/core/group/group.h b/src/core/group/group.h index 0c188e4..39b65a5 100644 --- a/src/core/group/group.h +++ b/src/core/group/group.h @@ -72,11 +72,6 @@ namespace klotski::group { -// TODO: move constants to `.inl` file -constexpr uint32_t TYPE_ID_LIMIT = 203; -constexpr uint32_t ALL_GROUP_NUM = 25422; // TODO: from GROUP_NUM -constexpr uint32_t ALL_PATTERN_NUM = 6577; // TODO: from PATTERN_NUM - class Group; class GroupUnion { @@ -86,13 +81,13 @@ public: GroupUnion() = delete; /// Get the original type id. - [[nodiscard]] constexpr uint32_t unwrap() const; + [[nodiscard]] constexpr uint_fast8_t unwrap() const; /// Create GroupUnion without any check. - static constexpr GroupUnion unsafe_create(uint32_t type_id); + static constexpr GroupUnion unsafe_create(uint_fast8_t type_id); /// Create GroupUnion with validity check. - static constexpr std::optional create(uint32_t type_id); + static constexpr std::optional create(uint_fast8_t type_id); // ------------------------------------------------------------------------------------- // @@ -145,15 +140,15 @@ public: // ------------------------------------------------------------------------------------- // private: - uint32_t type_id_; // TODO: using uint_fast8_t + uint_fast8_t type_id_; // ------------------------------------------------------------------------------------- // /// Get the type id of RawCode. - static KLSK_INLINE uint_fast8_t type_id(codec::RawCode raw_code); + static KLSK_INLINE_CE uint_fast8_t type_id(codec::RawCode raw_code); /// Get the type id of CommonCode. - static KLSK_INLINE uint_fast8_t type_id(codec::CommonCode common_code); + static KLSK_INLINE_CE uint_fast8_t type_id(codec::CommonCode common_code); // ------------------------------------------------------------------------------------- // }; @@ -380,6 +375,7 @@ static_assert(std::is_trivially_copyable_v); } // namespace klotski::group +#include "internal/type_id.inl" #include "internal/group_union.inl" #include "internal/group_cases.inl" #include "internal/group.inl" diff --git a/src/core/group/internal/constant/group_union.h b/src/core/group/internal/constant/group_union.h index ee903f8..168be1e 100644 --- a/src/core/group/internal/constant/group_union.h +++ b/src/core/group/internal/constant/group_union.h @@ -6,6 +6,10 @@ namespace klotski::group { +constexpr uint32_t TYPE_ID_LIMIT = 203; +constexpr uint32_t ALL_GROUP_NUM = 25422; // TODO: from GROUP_NUM +constexpr uint32_t ALL_PATTERN_NUM = 6577; // TODO: from PATTERN_NUM + /// The number of groups contained in GroupUnion. constexpr auto GROUP_NUM = std::to_array({ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , diff --git a/src/core/group/internal/group_union.cc b/src/core/group/internal/group_union.cc index c9b7ea0..7e8611b 100644 --- a/src/core/group/internal/group_union.cc +++ b/src/core/group/internal/group_union.cc @@ -3,40 +3,16 @@ #include "constant/group_union.h" using klotski::cases::Ranges; -using klotski::cases::RangesUnion; - using klotski::codec::RawCode; using klotski::codec::CommonCode; using klotski::group::GroupUnion; +using klotski::cases::RangesUnion; using klotski::cases::BASIC_RANGES_NUM; #define RANGE_DERIVE(HEAD) ranges.derive(HEAD, cases[HEAD]) -static KLSK_INLINE uint_fast8_t to_type_id(const int n, const int n_2x1, const int n_1x1) { - KLSK_ASSUME(n >= 0 && n <= 7); - KLSK_ASSUME(n_2x1 >= 0 && n_2x1 <= n); - KLSK_ASSUME(n_1x1 >= 0 && n_1x1 <= (14 - n * 2)); - constexpr int offset[8] = {0, 15, 41, 74, 110, 145, 175, 196}; - return offset[n] + (15 - n * 2) * n_2x1 + n_1x1; -} - -uint_fast8_t GroupUnion::type_id(const CommonCode common_code) { - const auto range = static_cast(common_code.unwrap()); - const auto n_1x1 = std::popcount((range >> 1) & range & 0x55555555); - const auto n_2x1 = std::popcount((range >> 1) & ~range & 0x55555555); - return to_type_id(std::popcount(range) - n_1x1 * 2, n_2x1, n_1x1); -} - -uint_fast8_t GroupUnion::type_id(const RawCode raw_code) { - const auto code = raw_code.unwrap(); - const auto n = std::popcount(((code >> 1) ^ code) & 0x0249249249249249); - const auto n_2x1 = std::popcount((code >> 1) & ~code & 0x0249249249249249); - const auto n_1x1 = std::popcount((code >> 1) & code & 0x0249249249249249) - n - 3; - return to_type_id(n, n_2x1, n_1x1); -} - -klotski::cases::RangesUnion GroupUnion::cases() const { +RangesUnion GroupUnion::cases() const { auto [n, n_2x1, n_1x1] = BLOCK_NUM[type_id_]; auto [s_a, s_b, s_c, s_d] = GROUP_UNION_CASES_NUM[type_id_]; diff --git a/src/core/group/internal/group_union.inl b/src/core/group/internal/group_union.inl index 1a39631..7d9bf4e 100644 --- a/src/core/group/internal/group_union.inl +++ b/src/core/group/internal/group_union.inl @@ -8,15 +8,15 @@ namespace klotski::group { // ----------------------------------------------------------------------------------------- // -constexpr uint32_t GroupUnion::unwrap() const { +constexpr uint_fast8_t GroupUnion::unwrap() const { return type_id_; } -constexpr GroupUnion GroupUnion::unsafe_create(const uint32_t type_id) { +constexpr GroupUnion GroupUnion::unsafe_create(const uint_fast8_t type_id) { return std::bit_cast(type_id); } -constexpr std::optional GroupUnion::create(const uint32_t type_id) { +constexpr std::optional GroupUnion::create(const uint_fast8_t type_id) { if (type_id < TYPE_ID_LIMIT) { return unsafe_create(type_id); } @@ -33,26 +33,14 @@ constexpr uint32_t GroupUnion::group_num() const { return GROUP_NUM[type_id_]; } +constexpr uint32_t GroupUnion::pattern_num() const { + return PATTERN_NUM[type_id_]; +} + constexpr uint32_t GroupUnion::max_group_size() const { return MAX_GROUP_SIZE[type_id_]; } -//inline std::vector GroupUnion::groups() const { -// auto build = [this](const uint32_t group_id) { -// return Group::unsafe_create(type_id_, group_id); -// }; -// return std::views::iota(0U, group_num()) -// | std::views::transform(build) -// | std::ranges::to(); -//} - -//inline std::optional GroupUnion::group(const uint32_t group_id) const { -// if (group_id < group_num()) { -// return Group::unsafe_create(type_id_, group_id); -// } -// return std::nullopt; -//} - #ifndef KLSK_NDEBUG inline std::ostream& operator<<(std::ostream &out, GroupUnion self) { out << self.type_id_; // TODO: benchmark using `std::format` @@ -66,9 +54,14 @@ constexpr auto operator==(const GroupUnion &lhs, const GroupUnion &rhs) { // ----------------------------------------------------------------------------------------- // -constexpr uint32_t GroupUnion::pattern_num() const { - return PATTERN_NUM[type_id_]; -} +//inline std::vector GroupUnion::groups() const { +// auto build = [this](const uint32_t group_id) { +// return Group::unsafe_create(type_id_, group_id); +// }; +// return std::views::iota(0U, group_num()) +// | std::views::transform(build) +// | std::ranges::to(); +//} constexpr std::vector GroupUnion::groups() const { std::vector groups; diff --git a/src/core/group/internal/type_id.inl b/src/core/group/internal/type_id.inl new file mode 100644 index 0000000..e0f7f56 --- /dev/null +++ b/src/core/group/internal/type_id.inl @@ -0,0 +1,28 @@ +#pragma once + +namespace klotski::group { + +KLSK_INLINE_CE uint_fast8_t to_type_id(const int n, const int n_2x1, const int n_1x1) { + KLSK_ASSUME(n >= 0 && n <= 7); + KLSK_ASSUME(n_2x1 >= 0 && n_2x1 <= n); + KLSK_ASSUME(n_1x1 >= 0 && n_1x1 <= (14 - n * 2)); + constexpr int offset[8] = {0, 15, 41, 74, 110, 145, 175, 196}; + return offset[n] + (15 - n * 2) * n_2x1 + n_1x1; +} + +KLSK_INLINE_CE uint_fast8_t GroupUnion::type_id(const codec::CommonCode common_code) { + const auto range = static_cast(common_code.unwrap()); + const auto n_1x1 = std::popcount((range >> 1) & range & 0x55555555); + const auto n_2x1 = std::popcount((range >> 1) & ~range & 0x55555555); + return to_type_id(std::popcount(range) - n_1x1 * 2, n_2x1, n_1x1); +} + +KLSK_INLINE_CE uint_fast8_t GroupUnion::type_id(const codec::RawCode raw_code) { + const auto code = raw_code.unwrap(); + const auto n = std::popcount(((code >> 1) ^ code) & 0x0249249249249249); + const auto n_2x1 = std::popcount((code >> 1) & ~code & 0x0249249249249249); + const auto n_1x1 = std::popcount((code >> 1) & code & 0x0249249249249249) - n - 3; + return to_type_id(n, n_2x1, n_1x1); +} + +} // namespace klotski::group diff --git a/src/core/utils/utility.h b/src/core/utils/utility.h index 73bf1bb..55933af 100644 --- a/src/core/utils/utility.h +++ b/src/core/utils/utility.h @@ -31,6 +31,7 @@ /// Force function declaration to be inline. #define KLSK_INLINE __attribute__ ((always_inline)) +#define KLSK_INLINE_CE KLSK_INLINE constexpr /// Prevent reordering for both compiler and processor. #define KLSK_MEM_BARRIER std::atomic_thread_fence(std::memory_order_seq_cst)