Browse Source

update: enhance `Ranges` and `RangesUnion` interfaces

master
Dnomd343 4 days ago
parent
commit
0f74a1da14
  1. 18
      src/core/benchmark/ranges.cc
  2. 141
      src/core/ranges/internal/ranges.cc
  3. 16
      src/core/ranges/internal/ranges.inl
  4. 35
      src/core/ranges/internal/ranges_union.inl
  5. 7
      src/core/ranges/internal/spawn.cc
  6. 48
      src/core/ranges/ranges.h
  7. 1
      src/core/utils/utility.h

18
src/core/benchmark/ranges.cc

@ -55,10 +55,26 @@ static void RangesSize(benchmark::State &state) {
} }
} }
static void RangesAt(benchmark::State &state) {
auto &all_cases = AllCases::instance().fetch();
for (auto _ : state) {
volatile auto k0 = all_cases[1035968];
volatile auto k1 = all_cases[3778871];
volatile auto k2 = all_cases[7489354];
volatile auto k3 = all_cases[10398492];
volatile auto k4 = all_cases[19091276];
volatile auto k5 = all_cases[21373726];
volatile auto k6 = all_cases[27296711];
volatile auto k7 = all_cases[28214648];
}
}
// BENCHMARK(SpawnRanges)->Unit(benchmark::kMillisecond); // BENCHMARK(SpawnRanges)->Unit(benchmark::kMillisecond);
// BENCHMARK(RangesUnionExport)->Unit(benchmark::kMillisecond); // BENCHMARK(RangesUnionExport)->Unit(benchmark::kMillisecond);
BENCHMARK(RangesSize); // BENCHMARK(RangesSize);
BENCHMARK(RangesAt);
BENCHMARK_MAIN(); BENCHMARK_MAIN();

141
src/core/ranges/internal/ranges.cc

@ -5,24 +5,8 @@ using klotski::cases::Ranges;
using klotski::codec::CommonCode; using klotski::codec::CommonCode;
using klotski::cases::RangesUnion; using klotski::cases::RangesUnion;
static constexpr auto heads = std::to_array<uint64_t>({
0x0, 0x1, 0x2, 0x4, 0x5, 0x6,
0x8, 0x9, 0xA, 0xC, 0xD, 0xE,
});
void Ranges::reverse() {
for (auto &x : *this) {
x = range_reverse(x);
}
}
Ranges& Ranges::operator+=(const Ranges &ranges) {
this->insert(this->end(), ranges.begin(), ranges.end());
return *this;
}
RangesUnion& RangesUnion::operator+=(const RangesUnion &ranges_union) { RangesUnion& RangesUnion::operator+=(const RangesUnion &ranges_union) {
for (const auto head : heads) { for (const auto head : Heads) {
// (*this)[head] += ranges_union[head]; // (*this)[head] += ranges_union[head];
std::array<Ranges, 16>::operator[](head) += ranges_union.std::array<Ranges, 16>::operator[](head); std::array<Ranges, 16>::operator[](head) += ranges_union.std::array<Ranges, 16>::operator[](head);
} }
@ -32,7 +16,7 @@ RangesUnion& RangesUnion::operator+=(const RangesUnion &ranges_union) {
std::vector<CommonCode> RangesUnion::codes() const { std::vector<CommonCode> RangesUnion::codes() const {
std::vector<CommonCode> codes; std::vector<CommonCode> codes;
codes.reserve(size()); codes.reserve(size());
for (const auto head : heads) { for (const auto head : Heads) {
// for (const auto range : (*this)[head]) { // for (const auto range : (*this)[head]) {
for (const auto range : ranges(head)) { for (const auto range : ranges(head)) {
codes.emplace_back(CommonCode::unsafe_create(head << 32 | range)); codes.emplace_back(CommonCode::unsafe_create(head << 32 | range));
@ -42,25 +26,108 @@ std::vector<CommonCode> RangesUnion::codes() const {
return codes; return codes;
} }
// TODO: move to `.inl` file KLSK_INLINE CommonCode RangesUnion::operator[](size_type n) const {
size_t RangesUnion::size() const { uint64_t head = 0;
size_type size = 0; while (n >= ranges(head).size()) {
for (const auto head : heads) { n -= ranges(head).size();
size += std::array<Ranges, 16>::operator[](head).size(); ++head;
// size += (*this)[head].size();
} }
return size; KLSK_ASSUME(head < 16);
} return CommonCode::unsafe_create(head << 32 | ranges(head)[n]);
// size_t head = 0;
// if (n < ranges(head).size()) {
// return CommonCode::unsafe_create(head << 32 | ranges(head)[n]); // 0
// }
//
// n -= ranges(head).size();
// ++head;
// if (n < ranges(head).size()) {
// return ranges(head)[n]; // 1
// }
//
// n -= ranges(head).size();
// ++head;
// if (n < ranges(head).size()) {
// return ranges(head)[n]; // 2
// }
//
// n -= ranges(head).size();
// ++head;
// if (n < ranges(head).size()) {
// return ranges(head)[n]; // 3
// }
//
// n -= ranges(head).size();
// ++head;
// if (n < ranges(head).size()) {
// return ranges(head)[n]; // 4
// }
//
// n -= ranges(head).size();
// ++head;
// if (n < ranges(head).size()) {
// return ranges(head)[n]; // 5
// }
//
// n -= ranges(head).size();
// ++head;
// if (n < ranges(head).size()) {
// return ranges(head)[n]; // 6
// }
//
// n -= ranges(head).size();
// ++head;
// if (n < ranges(head).size()) {
// return ranges(head)[n]; // 7
// }
//
// n -= ranges(head).size();
// ++head;
// if (n < ranges(head).size()) {
// return ranges(head)[n]; // 8
// }
//
// n -= ranges(head).size();
// ++head;
// if (n < ranges(head).size()) {
// return ranges(head)[n]; // 9
// }
//
// n -= ranges(head).size();
// ++head;
// if (n < ranges(head).size()) {
// return ranges(head)[n]; // 10
// }
//
// n -= ranges(head).size();
// ++head;
// if (n < ranges(head).size()) {
// return ranges(head)[n]; // 11
// }
//
// n -= ranges(head).size();
// ++head;
// if (n < ranges(head).size()) {
// return ranges(head)[n]; // 12
// }
//
// n -= ranges(head).size();
// ++head;
// if (n < ranges(head).size()) {
// return ranges(head)[n]; // 13
// }
//
// n -= ranges(head).size();
// ++head;
// if (n < ranges(head).size()) {
// return ranges(head)[n]; // 14
// }
//
// n -= ranges(head).size();
// ++head;
// if (n < ranges(head).size()) {
// return ranges(head)[n]; // 15
// }
uint32_t RangesUnion::operator[](size_type index) const {
size_t head = 0;
for (;;) {
if (index >= std::array<Ranges, 16>::operator[](head).size()) {
index -= std::array<Ranges, 16>::operator[](head).size();
++head;
} else {
break;
}
}
return std::array<Ranges, 16>::operator[](head)[index];
} }

16
src/core/ranges/internal/ranges.inl

@ -0,0 +1,16 @@
#pragma once
namespace klotski::cases {
KLSK_INLINE_H void Ranges::reverse() {
for (auto &x : *this) {
x = range_reverse(x);
}
}
inline Ranges& Ranges::operator+=(const Ranges &ranges) {
this->insert(this->end(), ranges.begin(), ranges.end());
return *this;
}
} // namespace klotski::cases

35
src/core/ranges/internal/ranges_union.inl

@ -0,0 +1,35 @@
#pragma once
namespace klotski::cases {
inline Ranges& RangesUnion::ranges(const size_t head) {
return std::array<Ranges, 16>::operator[](head);
}
inline const Ranges& RangesUnion::ranges(const size_t head) const {
return std::array<Ranges, 16>::operator[](head);
}
KLSK_INLINE_H size_t RangesUnion::size() const {
size_type size = 0;
#pragma unroll
for (const auto head : Heads) {
size += ranges(head).size();
}
return size;
}
// KLSK_INLINE_H uint32_t RangesUnion::operator[](size_type n) const {
// size_t head = 0;
// for (;;) {
// if (n >= ranges(head).size()) {
// n -= ranges(head).size();
// ++head;
// } else {
// break;
// }
// }
// return ranges(head)[n];
// }
} // namespace klotski::cases

7
src/core/ranges/internal/spawn.cc

@ -6,9 +6,9 @@
using klotski::cases::Ranges; using klotski::cases::Ranges;
template<int N> template<int N>
static void spawn_ranges(std::vector<uint32_t> &ranges, int n_10, int n_11) { static KLSK_INLINE void spawn_ranges(std::vector<uint32_t> &ranges, int n_10, int n_11) {
int n_01 = N - n_10; const int n_01 = N - n_10;
int n_00 = 16 - N * 2 - n_11; const int n_00 = 16 - N * 2 - n_11;
std::array<int, 16 - N> series {}; std::array<int, 16 - N> series {};
std::fill_n(series.begin() + n_00, n_01, 0b01); std::fill_n(series.begin() + n_00, n_01, 0b01);
@ -36,5 +36,6 @@ void Ranges::spawn(const int n, const int n_2x1, const int n_1x1) {
case 5: return spawn_ranges<5>(*this, n_2x1, n_1x1); case 5: return spawn_ranges<5>(*this, n_2x1, n_1x1);
case 6: return spawn_ranges<6>(*this, n_2x1, n_1x1); case 6: return spawn_ranges<6>(*this, n_2x1, n_1x1);
case 7: return spawn_ranges<7>(*this, n_2x1, n_1x1); case 7: return spawn_ranges<7>(*this, n_2x1, n_1x1);
default: std::unreachable();
} }
} }

48
src/core/ranges/ranges.h

@ -18,41 +18,59 @@ namespace klotski::cases {
class Ranges final : public std::vector<uint32_t> { class Ranges final : public std::vector<uint32_t> {
public: public:
// ------------------------------------------------------------------------------------- //
/// Append the ranges from another instance. /// Append the ranges from another instance.
Ranges& operator+=(const Ranges &ranges); Ranges& operator+=(const Ranges &ranges);
/// Flip the ranges every two bits in low-high symmetry.
KLSK_INLINE void reverse();
/// Spawn klotski-ranges that match the specified block numbers. /// Spawn klotski-ranges that match the specified block numbers.
void spawn(int n, int n_2x1, int n_1x1); void spawn(int n, int n_2x1, int n_1x1);
/// Flip the klotski-ranges every two bits in low-high symmetry. /// Derive the legal ranges from reversed ranges with specified head.
void reverse();
/// Derive the legal klotski-ranges from reversed ranges with specified head.
void derive(int head, Ranges &output) const; void derive(int head, Ranges &output) const;
/// Check whether the combination of head and reversed range is valid. /// Check whether the combination of head and reversed range is valid.
static KLSK_INLINE int check(int head, uint32_t range); static KLSK_INLINE int check(int head, uint32_t range);
// ------------------------------------------------------------------------------------- //
}; };
class RangesUnion final : public std::array<Ranges, 16> { class RangesUnion final : public std::array<Ranges, 16> {
public: public:
/// Append the ranges from another instance. // ------------------------------------------------------------------------------------- //
RangesUnion& operator+=(const RangesUnion &ranges_union);
/// Get the Ranges of specified head.
Ranges& ranges(size_t head);
/// Export the RangesUnion as CommonCode list. /// Get the const Ranges of specified head.
[[nodiscard]] const Ranges& ranges(size_t head) const;
/// Export the RangesUnion as a CommonCode list.
[[nodiscard]] std::vector<codec::CommonCode> codes() const; [[nodiscard]] std::vector<codec::CommonCode> codes() const;
[[nodiscard]] const Ranges& ranges(const size_t head) const { // ------------------------------------------------------------------------------------- //
return std::array<Ranges, 16>::operator[](head);
} /// Get the number of ranges contained.
[[nodiscard]] KLSK_INLINE size_t size() const;
Ranges& ranges(const size_t head) { /// Append the ranges from another instance.
return std::array<Ranges, 16>::operator[](head); RangesUnion& KLSK_INLINE operator+=(const RangesUnion &ranges_union);
}
[[nodiscard]] size_t size() const; /// Obtain the CommonCode of the specified index.
[[nodiscard]] KLSK_INLINE codec::CommonCode operator[](size_type n) const;
[[nodiscard]] uint32_t operator[](size_type) const; // ------------------------------------------------------------------------------------- //
private:
static constexpr auto Heads = std::to_array<uint64_t>({
0x0, 0x1, 0x2, 0x4, 0x5, 0x6, 0x8, 0x9, 0xA, 0xC, 0xD, 0xE,
});
}; };
} // namespace klotski::cases } // namespace klotski::cases
#include "internal/ranges.inl"
#include "internal/ranges_union.inl"

1
src/core/utils/utility.h

@ -33,6 +33,7 @@
/// Force function declaration to be inline. /// Force function declaration to be inline.
#define KLSK_INLINE __attribute__ ((always_inline)) #define KLSK_INLINE __attribute__ ((always_inline))
#define KLSK_INLINE_H KLSK_INLINE inline
#define KLSK_INLINE_CE KLSK_INLINE constexpr #define KLSK_INLINE_CE KLSK_INLINE constexpr
/// Prevent reordering for both compiler and processor. /// Prevent reordering for both compiler and processor.

Loading…
Cancel
Save