diff --git a/src/core/group/internal/group.cc b/src/core/group/internal/group.cc index c6bd3f0..9604736 100644 --- a/src/core/group/internal/group.cc +++ b/src/core/group/internal/group.cc @@ -1,11 +1,9 @@ #include #include +#include #include "group/group.h" - -#include - -#include +#include "mover/mover.h" using klotski::codec::RawCode; using klotski::codec::CommonCode; @@ -19,76 +17,45 @@ using klotski::mover::MaskMover; using klotski::group::GROUP_DATA; using klotski::group::PATTERN_DATA; -// NOTE: This code implements two time-consuming functions: -// 1. Calculate all cases included in Group based on type_id/pattern_id/toward. -// 2. Calculate the Group information it belongs to based on RawCode. - -/// Spawn all the unsorted codes of the current group. -// static std::vector Group_extend_for_cases(RawCode raw_code, uint32_t reserve) { -// std::vector codes; -// phmap::flat_hash_map cases; // -// codes.reserve(reserve); -// cases.reserve(reserve * 1.56); -// -// auto core = MaskMover([&codes, &cases](RawCode code, uint64_t mask) { -// if (const auto match = cases.find(code.unwrap()); match != cases.end()) { -// match->second |= mask; // update mask -// return; -// } -// cases.emplace(code, mask); -// codes.emplace_back(code); // new case -// }); -// -// uint64_t offset = 0; -// codes.emplace_back(raw_code); -// cases.emplace(raw_code, 0); // without mask -// while (offset != codes.size()) { -// auto curr = codes[offset++].unwrap(); -// core.next_cases(RawCode::unsafe_create(curr), cases.find(curr)->second); -// } -// return codes; -// } - -template -static RangesUnion extend_next_(RawCode seed, size_t reserve, R func) { +template +KLSK_NOINLINE static RangesUnion group_extend(RawCode seed, const size_t reserve, Func add_mirror) { std::vector codes; std::vector mirrors; phmap::flat_hash_map cases; // codes.reserve(reserve); mirrors.reserve(reserve); // TODO: cal max size-coff - cases.reserve(reserve * 1.56); + cases.reserve(static_cast(reserve * 1.56)); - auto core = MaskMover([&codes, &cases, &mirrors, func](RawCode code, uint64_t hint) { + auto core = MaskMover([&codes, &cases, &mirrors, add_mirror](RawCode code, uint64_t hint) { if (const auto [iter, ret] = cases.try_emplace(code, hint); !ret) { iter->second |= hint; // update hint return; } - codes.emplace_back(code); // new case - - func(code, [&cases, &mirrors](RawCode kk) { - cases.emplace(kk, 0); // TODO: contain check - mirrors.emplace_back(kk); + codes.emplace_back(code); + add_mirror(code, [&cases, &mirrors](RawCode mirror) { + cases.emplace(mirror, 0); + mirrors.emplace_back(mirror); }); }); uint64_t offset = 0; codes.emplace_back(seed); cases.emplace(seed, 0); // without hint - - func(seed, [&mirrors, &cases](RawCode pp) { - cases.emplace(pp, 0); - mirrors.emplace_back(pp); + add_mirror(seed, [&mirrors, &cases](RawCode mirror) { + cases.emplace(mirror, 0); + mirrors.emplace_back(mirror); }); - while (offset != codes.size()) { - auto curr = codes[offset++]; + const auto curr = codes[offset++]; core.next_cases(curr, cases.find(curr)->second); } + // std::cout << std::format("{:.5f}\n", static_cast(codes.size()) / reserve); + RangesUnion result {}; // TODO: how to reserve - for (auto raw_code : codes) { // TODO: using `std::views::concat` in new std library + for (auto raw_code : codes) { const auto code = raw_code.to_common_code().unwrap(); result.ranges(code >> 32).emplace_back(static_cast(code)); } @@ -99,132 +66,70 @@ static RangesUnion extend_next_(RawCode seed, size_t reserve, R func) { return result; } -__attribute__((noinline)) static RangesUnion extend_type_common(RawCode seed, size_t reserve) { - return extend_next_(seed, reserve, [](RawCode code, auto callback) {}); +static RangesUnion extend_type_common(RawCode seed, size_t reserve) { + return group_extend(seed, reserve, [](RawCode, auto) {}); } -// TODO: without `__attribute__((noinline))` will make it faster static RangesUnion extend_type_hor(RawCode seed, size_t reserve) { - return extend_next_(seed, reserve, [](RawCode code, auto callback) { - const auto k1 = code.to_horizontal_mirror(); - if (k1 != code) { - callback(k1); + return group_extend(seed, reserve, [](const RawCode code, auto callback) { + if (const auto mirror = code.to_horizontal_mirror(); mirror != code) { + callback(mirror); } }); } -__attribute__((noinline)) static RangesUnion extend_type_ver(RawCode seed, size_t reserve) { - return extend_next_(seed, reserve, [](RawCode code, auto callback) { - const auto k1 = code.to_vertical_mirror(); - // if (k1 != code) { - callback(k1); - // } +static RangesUnion extend_type_ver(RawCode seed, size_t reserve) { + return group_extend(seed, reserve, [](const RawCode code, auto callback) { + callback(code.to_vertical_mirror()); }); } -__attribute__((noinline)) static RangesUnion extend_type_diag(RawCode seed, size_t reserve) { - return extend_next_(seed, reserve, [](RawCode code, auto callback) { - const auto k1 = code.to_vertical_mirror().to_horizontal_mirror(); - if (k1 != code) { - callback(k1); +static RangesUnion extend_type_diag(RawCode seed, size_t reserve) { + return group_extend(seed, reserve, [](const RawCode code, auto callback) { + if (const auto mirror = code.to_diagonal_mirror(); mirror != code) { + callback(mirror); } }); } -__attribute__((noinline)) static RangesUnion extend_type_x(RawCode seed, size_t reserve) { - return extend_next_(seed, reserve, [](RawCode code, auto callback) { - const auto k1 = code.to_vertical_mirror(); - callback(k1); - const auto k2 = code.to_horizontal_mirror(); - if (k2 != code) { - callback(k2); - const auto p3 = k1.to_horizontal_mirror(); - callback(p3); +static RangesUnion extend_type_x(RawCode seed, size_t reserve) { + return group_extend(seed, reserve, [](const RawCode code, auto callback) { + const auto mirror_1 = code.to_vertical_mirror(); + callback(mirror_1); + if (const auto mirror_2 = code.to_horizontal_mirror(); mirror_2 != code) { + callback(mirror_2); + callback(mirror_1.to_horizontal_mirror()); } }); } RangesUnion Group::cases() const { - - // TODO: add white list for single-group unions - // return GroupUnion::cases directly + if (const auto gu = GroupUnion::unsafe_create(type_id()); gu.group_num() == 1) { + return gu.cases(); + } auto seed = CommonCode::unsafe_create(PATTERN_DATA[flat_id()] >> 23).to_raw_code(); - - // NOTE: convert as RawCode directly if (toward_ == Toward::B) { seed = seed.to_horizontal_mirror(); } else if (toward_ == Toward::C) { seed = seed.to_vertical_mirror(); } else if (toward_ == Toward::D) { - // NOTE: avoid multi convert - seed = seed.to_vertical_mirror().to_horizontal_mirror(); + seed = seed.to_diagonal_mirror(); } RangesUnion data; if (mirror_type() == MirrorType::Full) { data = extend_type_x(seed, size()); - } else if (mirror_type() == MirrorType::Horizontal) { data = extend_type_hor(seed, size()); - - // auto lambda = [](RawCode code, phmap::flat_hash_map &cases, std::vector &mirrors) { - // const auto k1 = code.to_horizontal_mirror(); - // if (k1 != code) { - // cases.emplace(k1, 0); // TODO: contain check - // mirrors.emplace_back(k1); - // } - // }; - // - // data = extend_next(seed, size()); - - // data = extend_next(seed, size(), [](RawCode code, phmap::flat_hash_map &cases, std::vector &mirrors) { - // const auto k1 = code.to_horizontal_mirror(); - // if (k1 != code) { - // cases.emplace(k1, 0); // TODO: contain check - // mirrors.emplace_back(k1); - // } - // }); - - // data = extend_next(seed, size(), [](RawCode code, auto callback) { - // const auto k1 = code.to_horizontal_mirror(); - // if (k1 != code) { - // callback(k1); - // } - // }); - } else if (mirror_type() == MirrorType::Vertical) { data = extend_type_ver(seed, size()); - - // data = extend_next_(seed, size(), [](RawCode code, auto callback) { - // const auto k1 = code.to_vertical_mirror(); - // if (k1 != code) { // TODO: without check - // callback(k1); - // } - // }); - } else if (mirror_type() == MirrorType::Centro) { data = extend_type_diag(seed, size()); - - // data = extend_next_(seed, size(), [](RawCode code, auto callback) { - // const auto k1 = code.to_vertical_mirror().to_horizontal_mirror(); - // if (k1 != code) { - // callback(k1); - // } - // }); - } else { data = extend_type_common(seed, size()); - } - // auto raw_data = Group_extend_for_cases(seed, size()); - // RangesUnion data {}; - // for (auto raw_code : raw_data) { - // auto common_code = raw_code.to_common_code().unwrap(); - // data.ranges(common_code >> 32).emplace_back(static_cast(common_code)); - // } - for (int head = 0; head < 16; ++head) { std::stable_sort(data.ranges(head).begin(), data.ranges(head).end()); } diff --git a/src/core/main.cc b/src/core/main.cc index 3c2cd0b..2726f82 100644 --- a/src/core/main.cc +++ b/src/core/main.cc @@ -62,6 +62,8 @@ int main() { for (auto group : GroupUnion::unsafe_create(type_id).groups()) { // if (group.is_horizontal_mirror()) { // if (group.is_vertical_mirror()) { + // if (group.mirror_type() == Group::MirrorType::Horizontal) { + // if (group.mirror_type() == Group::MirrorType::Vertical) { // if (group.mirror_type() == Group::MirrorType::Centro) { // if (group.mirror_type() == Group::MirrorType::Full) { // if (group.mirror_type() == Group::MirrorType::Ordinary) { diff --git a/src/core/utils/utility.h b/src/core/utils/utility.h index 5938c32..628134e 100644 --- a/src/core/utils/utility.h +++ b/src/core/utils/utility.h @@ -36,8 +36,10 @@ /// Force function declaration to be inline. #if defined(__clang__) #define KLSK_INLINE __attribute__ ((always_inline)) + #define KLSK_NOINLINE __attribute__((noinline)) #else #define KLSK_INLINE // NOTE: make sure that function can be inline + #define KLSK_NOINLINE #endif #define KLSK_INLINE_H KLSK_INLINE inline #define KLSK_INLINE_CE KLSK_INLINE constexpr