Browse Source

update: enhance `Ranges` and `RangesUnion` interfaces

master
Dnomd343 2 months ago
parent
commit
ac4c10b765
  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(RangesUnionExport)->Unit(benchmark::kMillisecond);
BENCHMARK(RangesSize);
// BENCHMARK(RangesSize);
BENCHMARK(RangesAt);
BENCHMARK_MAIN();

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

@ -5,24 +5,8 @@ using klotski::cases::Ranges;
using klotski::codec::CommonCode;
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) {
for (const auto head : heads) {
for (const auto head : Heads) {
// (*this)[head] += ranges_union[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> codes;
codes.reserve(size());
for (const auto head : heads) {
for (const auto head : Heads) {
// for (const auto range : (*this)[head]) {
for (const auto range : ranges(head)) {
codes.emplace_back(CommonCode::unsafe_create(head << 32 | range));
@ -42,25 +26,108 @@ std::vector<CommonCode> RangesUnion::codes() const {
return codes;
}
// TODO: move to `.inl` file
size_t RangesUnion::size() const {
size_type size = 0;
for (const auto head : heads) {
size += std::array<Ranges, 16>::operator[](head).size();
// size += (*this)[head].size();
KLSK_INLINE CommonCode RangesUnion::operator[](size_type n) const {
uint64_t head = 0;
while (n >= ranges(head).size()) {
n -= ranges(head).size();
++head;
}
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;
template<int N>
static void spawn_ranges(std::vector<uint32_t> &ranges, int n_10, int n_11) {
int n_01 = N - n_10;
int n_00 = 16 - N * 2 - n_11;
static KLSK_INLINE void spawn_ranges(std::vector<uint32_t> &ranges, int n_10, int n_11) {
const int n_01 = N - n_10;
const int n_00 = 16 - N * 2 - n_11;
std::array<int, 16 - N> series {};
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 6: return spawn_ranges<6>(*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> {
public:
// ------------------------------------------------------------------------------------- //
/// Append the ranges from another instance.
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.
void spawn(int n, int n_2x1, int n_1x1);
/// Flip the klotski-ranges every two bits in low-high symmetry.
void reverse();
/// Derive the legal klotski-ranges from reversed ranges with specified head.
/// Derive the legal ranges from reversed ranges with specified head.
void derive(int head, Ranges &output) const;
/// Check whether the combination of head and reversed range is valid.
static KLSK_INLINE int check(int head, uint32_t range);
// ------------------------------------------------------------------------------------- //
};
class RangesUnion final : public std::array<Ranges, 16> {
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]] 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) {
return std::array<Ranges, 16>::operator[](head);
}
/// Append the ranges from another instance.
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
#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.
#define KLSK_INLINE __attribute__ ((always_inline))
#define KLSK_INLINE_H KLSK_INLINE inline
#define KLSK_INLINE_CE KLSK_INLINE constexpr
/// Prevent reordering for both compiler and processor.

Loading…
Cancel
Save