Browse Source

update: cpp style optimization of all cases

master
Dnomd343 2 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 "all_cases.h"
namespace klotski {
namespace cases {
namespace klotski::cases {
/// Calculate all possible klotski 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.
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_1x2 = 0b00000011;
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
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
flags >>= num;
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.
void AllCases::build_cases(int head, Ranges &release) noexcept {
void AllCases::build_cases(const int head, Ranges &release) noexcept {
release.clear();
release.reserve(ALL_CASES_NUM[head]);
auto &basic_ranges = BasicRanges::instance().fetch();
@ -127,5 +127,4 @@ void AllCases::build_parallel_async(Executor &&executor, Notifier &&callback) no
}
}
} // namespace cases
} // namespace klotski
} // namespace klotski::cases

17
src/core/all_cases/all_cases.h

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

11
src/core/all_cases/basic_ranges.cc

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

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

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

16
src/core/utils/utility.h

@ -2,15 +2,15 @@
#include <cstdint>
#define DISALLOW_COPY_AND_ASSIGN(T) \
T(T&&) = delete; \
T(const T&) = delete; \
T& operator=(T&&) = delete; \
T& operator=(const T&) = delete;
#define MARK_INSTANCE(T) \
T(T &&) = delete; \
T(const T &) = delete; \
T& operator=(T &&) = delete; \
T& operator=(const T &) = delete;
namespace klotski {
inline int low_zero_num(uint32_t bin) {
inline int low_zero_num(const uint32_t bin) {
return __builtin_ctzl(bin);
// 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;
}
inline int low_zero_num(uint64_t bin) {
inline int low_zero_num(const uint64_t bin) {
return __builtin_ctzll(bin);
// WARN: be aware of serious performance issues
// 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__)
bin = __builtin_bswap32(bin);
// TODO: using `std::byteswap` (c++23)

Loading…
Cancel
Save