Browse Source

update: cpp style optimization of all cases

legacy
Dnomd343 8 months ago
parent
commit
c438e2ba9b
  1. 13
      src/core/all_cases/all_cases.cc
  2. 17
      src/core/all_cases/all_cases.h
  3. 11
      src/core/all_cases/basic_ranges.cc
  4. 6
      src/core/all_cases/inline_impl.inl
  5. 16
      src/core/utils/utility.h

13
src/core/all_cases/all_cases.cc

@ -1,8 +1,8 @@
#include <future> #include <future>
#include "all_cases.h" #include "all_cases.h"
namespace klotski { namespace klotski::cases {
namespace cases {
/// Calculate all possible klotski heads. /// Calculate all possible klotski heads.
consteval static std::array<int, 12> case_heads() { consteval static std::array<int, 12> case_heads() {
@ -16,7 +16,7 @@ consteval static std::array<int, 12> case_heads() {
} }
/// Check whether the combination of head and range is valid. /// Check whether the combination of head and range is valid.
static int check_range(int head, uint32_t range) noexcept { static int check_range(const int head, uint32_t range) noexcept {
constexpr uint32_t M_1x1 = 0b00000001; constexpr uint32_t M_1x1 = 0b00000001;
constexpr uint32_t M_1x2 = 0b00000011; constexpr uint32_t M_1x2 = 0b00000011;
constexpr uint32_t M_2x1 = 0b00010001; constexpr uint32_t M_2x1 = 0b00010001;
@ -24,7 +24,7 @@ static int check_range(int head, uint32_t range) noexcept {
uint32_t flags = M_2x2 << head; // fill 2x2 block uint32_t flags = M_2x2 << head; // fill 2x2 block
for (int addr = 0, offset = 1; range; range >>= 2, ++offset) { // traverse every 2-bit for (int addr = 0, offset = 1; range; range >>= 2, ++offset) { // traverse every 2-bit
auto num = low_zero_num(~flags); const auto num = low_zero_num(~flags);
addr += num; // next unfilled block addr += num; // next unfilled block
flags >>= num; flags >>= num;
switch (range & 0b11) { switch (range & 0b11) {
@ -50,7 +50,7 @@ static int check_range(int head, uint32_t range) noexcept {
} }
/// Build all valid ranges of the specified head. /// Build all valid ranges of the specified head.
void AllCases::build_cases(int head, Ranges &release) noexcept { void AllCases::build_cases(const int head, Ranges &release) noexcept {
release.clear(); release.clear();
release.reserve(ALL_CASES_NUM[head]); release.reserve(ALL_CASES_NUM[head]);
auto &basic_ranges = BasicRanges::instance().fetch(); auto &basic_ranges = BasicRanges::instance().fetch();
@ -127,5 +127,4 @@ void AllCases::build_parallel_async(Executor &&executor, Notifier &&callback) no
} }
} }
} // namespace cases } // namespace klotski::cases
} // namespace klotski

17
src/core/all_cases/all_cases.h

@ -41,10 +41,12 @@
#include <cstdint> #include <cstdint>
#include <numeric> #include <numeric>
#include <functional> #include <functional>
#include "utility.h" #include "utility.h"
namespace klotski { namespace klotski::cases {
namespace cases {
// ----------------------------------------------------------------------------------------- //
typedef uint32_t Range; typedef uint32_t Range;
typedef std::vector<Range> Ranges; typedef std::vector<Range> Ranges;
@ -57,7 +59,7 @@ typedef std::function<void(std::function<void()>&&)> Executor;
constexpr auto BASIC_RANGES_NUM = 7311921; constexpr auto BASIC_RANGES_NUM = 7311921;
constexpr std::array<int, 16> ALL_CASES_NUM { constexpr std::array ALL_CASES_NUM {
2942906, 2260392, 2942906, 0, 2942906, 2260392, 2942906, 0,
2322050, 1876945, 2322050, 0, 2322050, 1876945, 2322050, 0,
2322050, 1876945, 2322050, 0, 2322050, 1876945, 2322050, 0,
@ -76,7 +78,7 @@ public:
const Ranges& fetch() noexcept; const Ranges& fetch() noexcept;
[[nodiscard]] bool is_available() const noexcept; [[nodiscard]] bool is_available() const noexcept;
DISALLOW_COPY_AND_ASSIGN(BasicRanges); MARK_INSTANCE(BasicRanges);
static BasicRanges& instance() noexcept; static BasicRanges& instance() noexcept;
private: private:
@ -100,7 +102,7 @@ public:
const RangesUnion& fetch() noexcept; const RangesUnion& fetch() noexcept;
[[nodiscard]] bool is_available() const noexcept; [[nodiscard]] bool is_available() const noexcept;
DISALLOW_COPY_AND_ASSIGN(AllCases); MARK_INSTANCE(AllCases);
static AllCases& instance() noexcept; static AllCases& instance() noexcept;
private: private:
@ -114,7 +116,6 @@ private:
// ----------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------- //
} // namespace cases } // namespace klotski::cases
} // namespace klotski
#include "inline_impl.h" #include "inline_impl.inl"

11
src/core/all_cases/basic_ranges.cc

@ -1,9 +1,9 @@
#include <list> #include <list>
#include <algorithm> #include <algorithm>
#include "all_cases.h" #include "all_cases.h"
namespace klotski { namespace klotski::cases {
namespace cases {
typedef std::vector<Range>::iterator RangeIter; typedef std::vector<Range>::iterator RangeIter;
typedef std::tuple<int, int, int, int> RangeType; typedef std::tuple<int, int, int, int> RangeType;
@ -52,7 +52,7 @@ void BasicRanges::spawn_ranges(Ranges &ranges, int n1, int n2, int n3, int n4) n
do { // full permutation traversal do { // full permutation traversal
uint32_t range = 0; uint32_t range = 0;
for (auto x : series) // store every 2-bit for (const auto x : series) // store every 2-bit
(range <<= 2) |= x; (range <<= 2) |= x;
ranges.emplace_back(range << offset); ranges.emplace_back(range << offset);
} while (next_permutation(series.begin(), series.end())); } while (next_permutation(series.begin(), series.end()));
@ -87,7 +87,7 @@ void BasicRanges::build() noexcept {
if (available_) { if (available_) {
return; // reduce consumption of mutex return; // reduce consumption of mutex
} }
std::lock_guard<std::mutex> guard(building_); std::lock_guard guard(building_);
if (available_) { if (available_) {
return; // data is already available return; // data is already available
} }
@ -95,5 +95,4 @@ void BasicRanges::build() noexcept {
available_ = true; available_ = true;
} }
} // namespace cases } // namespace klotski::cases
} // namespace klotski

6
src/core/all_cases/inline_impl.h → src/core/all_cases/inline_impl.inl

@ -1,7 +1,6 @@
#pragma once #pragma once
namespace klotski { namespace klotski::cases {
namespace cases {
// ----------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------- //
@ -47,5 +46,4 @@ inline bool AllCases::is_available() const noexcept {
// ----------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------- //
} // namespace codec } // namespace klotski::codec
} // namespace klotski

16
src/core/utils/utility.h

@ -2,15 +2,15 @@
#include <cstdint> #include <cstdint>
#define DISALLOW_COPY_AND_ASSIGN(T) \ #define MARK_INSTANCE(T) \
T(T&&) = delete; \ T(T &&) = delete; \
T(const T&) = delete; \ T(const T &) = delete; \
T& operator=(T&&) = delete; \ T& operator=(T &&) = delete; \
T& operator=(const T&) = delete; T& operator=(const T &) = delete;
namespace klotski { namespace klotski {
inline int low_zero_num(uint32_t bin) { inline int low_zero_num(const uint32_t bin) {
return __builtin_ctzl(bin); return __builtin_ctzl(bin);
// TODO: using (bin ^ (bin - 1)) when non-builtin // TODO: using (bin ^ (bin - 1)) when non-builtin
@ -19,14 +19,14 @@ inline int low_zero_num(uint32_t bin) {
// return __builtin_popcount(~(bin ^ -bin)) - 1; // return __builtin_popcount(~(bin ^ -bin)) - 1;
} }
inline int low_zero_num(uint64_t bin) { inline int low_zero_num(const uint64_t bin) {
return __builtin_ctzll(bin); return __builtin_ctzll(bin);
// WARN: be aware of serious performance issues // WARN: be aware of serious performance issues
// return __builtin_popcount(~(bin ^ -bin)) - 1; // return __builtin_popcount(~(bin ^ -bin)) - 1;
} }
inline uint32_t range_reverse(uint32_t bin) noexcept { inline uint32_t range_reverse(uint32_t bin) {
#if defined(__GNUC__) || defined(__clang__) #if defined(__GNUC__) || defined(__clang__)
bin = __builtin_bswap32(bin); bin = __builtin_bswap32(bin);
// TODO: using `std::byteswap` (c++23) // TODO: using `std::byteswap` (c++23)

Loading…
Cancel
Save