Browse Source

update: using macros to simplify cases mirror

master
Dnomd343 1 month ago
parent
commit
cb37a775de
  1. 284
      src/core/group/internal/group_cases.cc

284
src/core/group/internal/group_cases.cc

@ -1,3 +1,4 @@
#include <cstdint>
#include <iostream>
#include <algorithm>
@ -14,6 +15,8 @@ using klotski::codec::CommonCode;
using klotski::group::Group;
using klotski::group::GroupCases;
using klotski::group::GroupUnion;
using klotski::cases::Ranges;
using klotski::cases::RangesUnion;
using klotski::group::CaseInfo;
@ -30,6 +33,16 @@ using klotski::group::PATTERN_DATA;
using klotski::group::PATTERN_OFFSET;
using klotski::group::ALL_PATTERN_NUM;
using klotski::group::BLOCK_NUM;
using klotski::cases::BASIC_RANGES_NUM;
using klotski::group::GROUP_UNION_CASES_NUM;
#define RANGE_RESERVE(HEAD, SIZE) cases.ranges(HEAD).reserve(SIZE)
#define RANGE_DERIVE_WITHOUT(HEAD) ranges.derive_without(HEAD, cases.ranges(HEAD), data.ranges(HEAD))
using MirrorType = Group::MirrorType;
struct case_info_t {
uint32_t pattern_id : 10;
uint32_t toward_id : 2;
@ -42,12 +55,6 @@ static std::array<RangesUnion, ALL_PATTERN_NUM * 4> *ru_data_array = nullptr;
static std::vector<case_info_t> *rev_data = nullptr;
// #define RELEASE_INTO(RU) \
// [&RU](const RawCode raw_code) { \
// const auto code = raw_code.to_common_code().unwrap(); \
// RU.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code)); \
// }
#define EMPLACE_INTO_IMPL(RU, VAR, EXPR) \
const auto VAR = (EXPR).to_common_code().unwrap(); \
RU.ranges(VAR >> 32).emplace_back(static_cast<uint32_t>(VAR));
@ -55,8 +62,32 @@ static std::vector<case_info_t> *rev_data = nullptr;
#define EMPLACE_INTO(RU, EXPR) \
EMPLACE_INTO_IMPL(RU, KLSK_UNIQUE(tmp), EXPR)
#define NO_MIRROR \
[](RawCode, auto) {}
#define NO_MIRROR [](RawCode, auto) {}
#define CTR_MIRROR \
[](const RawCode code, auto spawn) { \
spawn(code.to_diagonal_mirror()); \
}
#define HOR_MIRROR \
[](const RawCode code, auto spawn) { \
if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) { \
spawn(m_hor); \
} \
}
#define VRT_MIRROR \
[](const RawCode code, auto spawn) { \
spawn(code.to_vertical_mirror()); \
}
#define FULL_MIRROR \
[](const RawCode code, auto spawn) { \
const auto m_vrt = code.to_vertical_mirror(); spawn(m_vrt); \
if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) { \
spawn(m_hor); spawn(m_vrt.to_horizontal_mirror()); \
} \
}
template <typename MF, typename RF>
KLSK_NOINLINE static void extend(const RawCode seed, const size_t reserve, MF add_mirror, RF release) {
@ -94,197 +125,162 @@ KLSK_NOINLINE static void extend(const RawCode seed, const size_t reserve, MF ad
for (const auto code : mirrors) { release(code); }
}
template <Group::MirrorType TYPE>
static void extend_pattern(RawCode seed, size_t size, RangesUnion *kk) {
using MirrorType = Group::MirrorType;
// #define RELEASE_TO(A, B, C, D) \
// [&data_a, &data_b, &data_c, &data_d](const RawCode code) { \
// if constexpr(A == 'A') { EMPLACE_INTO(data_a, code); } \
// if constexpr(B == 'B') { EMPLACE_INTO(data_b, code.to_horizontal_mirror()); } \
// if constexpr(C == 'C') { EMPLACE_INTO(data_c, code.to_vertical_mirror()); } \
// if constexpr(D == 'D') { EMPLACE_INTO(data_d, code.to_diagonal_mirror()); } \
// }
RangesUnion &a = kk[0];
RangesUnion &b = kk[1];
RangesUnion &c = kk[2];
RangesUnion &d = kk[3];
template <MirrorType TYPE>
static void spawn_pattern(RawCode seed, size_t size, RangesUnion *data) {
RangesUnion &ga = data[0];
RangesUnion &gb = data[1];
RangesUnion &gc = data[2];
RangesUnion &gd = data[3];
if constexpr(TYPE == MirrorType::Full) {
const auto mirror_func = [](const RawCode code, auto spawn) {
const auto m_vrt = code.to_vertical_mirror();
spawn(m_vrt);
if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) {
spawn(m_hor);
spawn(m_vrt.to_horizontal_mirror());
}
};
extend(seed, size, mirror_func, [&a](const RawCode raw_code) {
// const auto code = raw_code.to_common_code().unwrap();
// a.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code));
EMPLACE_INTO(a, raw_code);
extend(seed, size, FULL_MIRROR, [&ga](const RawCode code) {
EMPLACE_INTO(ga, code);
});
// extend(seed, size, HOR_MIRROR, RELEASE_TO('A', 0, 0, 0));
}
if constexpr(TYPE == MirrorType::Horizontal) {
const auto mirror_func = [](const RawCode code, auto spawn) {
if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) {
spawn(m_hor);
}
};
extend(seed, size, mirror_func, [&a, &c](const RawCode raw_code) {
// const auto code = raw_code.to_common_code().unwrap();
// a.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code));
EMPLACE_INTO(a, raw_code);
// const auto code_ = raw_code.to_vertical_mirror().to_common_code().unwrap();
// c.ranges(code_ >> 32).emplace_back(static_cast<uint32_t>(code_));
EMPLACE_INTO(c, raw_code.to_vertical_mirror());
extend(seed, size, HOR_MIRROR, [&ga, &gc](const RawCode code) {
EMPLACE_INTO(ga, code);
EMPLACE_INTO(gc, code.to_vertical_mirror());
});
// extend(seed, size, HOR_MIRROR, RELEASE_TO('A', 0, 'C', 0));
}
if constexpr(TYPE == MirrorType::Centro) {
const auto mirror_func = [](const RawCode code, auto spawn) {
spawn(code.to_diagonal_mirror());
};
extend(seed, size, mirror_func, [&a, &b](const RawCode raw_code) {
// const auto code = raw_code.to_common_code().unwrap();
// a.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code));
EMPLACE_INTO(a, raw_code);
// const auto code_ = raw_code.to_horizontal_mirror().to_common_code().unwrap();
// b.ranges(code_ >> 32).emplace_back(static_cast<uint32_t>(code_));
EMPLACE_INTO(b, raw_code.to_horizontal_mirror());
extend(seed, size, CTR_MIRROR, [&ga, &gb](const RawCode code) {
EMPLACE_INTO(ga, code);
EMPLACE_INTO(gb, code.to_horizontal_mirror());
});
// extend(seed, size, CTR_MIRROR, RELEASE_TO('A', 'B', 0, 0));
}
if constexpr(TYPE == MirrorType::Vertical) {
const auto mirror_func = [](const RawCode code, auto spawn) {
spawn(code.to_vertical_mirror());
};
extend(seed, size, mirror_func, [&a, &b](const RawCode raw_code) {
// const auto code = raw_code.to_common_code().unwrap();
// a.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code));
EMPLACE_INTO(a, raw_code);
// const auto code_ = raw_code.to_horizontal_mirror().to_common_code().unwrap();
// b.ranges(code_ >> 32).emplace_back(static_cast<uint32_t>(code_));
EMPLACE_INTO(b, raw_code.to_horizontal_mirror());
extend(seed, size, VRT_MIRROR, [&ga, &gb](const RawCode code) {
EMPLACE_INTO(ga, code);
EMPLACE_INTO(gb, code.to_horizontal_mirror());
});
// extend(seed, size, VRT_MIRROR, RELEASE_TO('A', 'B', 0, 0));
}
if constexpr(TYPE == MirrorType::Ordinary) {
extend(seed, size, NO_MIRROR, [&a, &b, &c, &d](const RawCode raw_code) {
// const auto code = raw_code.to_common_code().unwrap();
// a.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code));
EMPLACE_INTO(a, raw_code);
// const auto code_1 = raw_code.to_horizontal_mirror().to_common_code().unwrap();
// b.ranges(code_1 >> 32).emplace_back(static_cast<uint32_t>(code_1));
EMPLACE_INTO(b, raw_code.to_horizontal_mirror());
// const auto code_2 = raw_code.to_vertical_mirror().to_common_code().unwrap();
// c.ranges(code_2 >> 32).emplace_back(static_cast<uint32_t>(code_2));
EMPLACE_INTO(c, raw_code.to_vertical_mirror());
// const auto code_3 = raw_code.to_diagonal_mirror().to_common_code().unwrap();
// d.ranges(code_3 >> 32).emplace_back(static_cast<uint32_t>(code_3));
EMPLACE_INTO(d, raw_code.to_diagonal_mirror());
extend(seed, size, NO_MIRROR, [&ga, &gb, &gc, &gd](const RawCode code) {
EMPLACE_INTO(ga, code);
EMPLACE_INTO(gb, code.to_horizontal_mirror());
EMPLACE_INTO(gc, code.to_vertical_mirror());
EMPLACE_INTO(gd, code.to_diagonal_mirror());
});
// extend(seed, size, NO_MIRROR, RELEASE_TO('A', 'B', 'C', 'D'));
}
for (auto head : RangesUnion::Heads) {
std::stable_sort(a.ranges(head).begin(), a.ranges(head).end());
for (const auto head : RangesUnion::Heads) {
std::stable_sort(ga.ranges(head).begin(), ga.ranges(head).end());
if constexpr(TYPE == MirrorType::Centro || TYPE == MirrorType::Vertical || TYPE == MirrorType::Ordinary) {
std::stable_sort(b.ranges(head).begin(), b.ranges(head).end());
std::stable_sort(gb.ranges(head).begin(), gb.ranges(head).end());
}
if constexpr(TYPE == MirrorType::Horizontal || TYPE == MirrorType::Ordinary) {
std::stable_sort(c.ranges(head).begin(), c.ranges(head).end());
std::stable_sort(gc.ranges(head).begin(), gc.ranges(head).end());
}
if constexpr(TYPE == MirrorType::Ordinary) {
std::stable_sort(d.ranges(head).begin(), d.ranges(head).end());
std::stable_sort(gd.ranges(head).begin(), gd.ranges(head).end());
}
}
}
// static void build_ru_arr(uint8_t type_id, std::array<RangesUnion, ALL_PATTERN_NUM * 4> &data) {
static void build_ru_arr(uint8_t type_id, RangesUnion *offset) {
auto group_union = GroupUnion::unsafe_create(type_id);
// auto offset = &data[PATTERN_OFFSET[type_id] * 4];
// KLSK_INLINE static std::tuple<MirrorType, RawCode, size_t> get_info(uint8_t type_id, uint16_t pattern_id) {
// const auto flat_id = PATTERN_OFFSET[type_id] + pattern_id;
// const auto mirror_type = static_cast<MirrorType>(PATTERN_DATA[flat_id] & 0b111);
// const auto seed_val = PATTERN_DATA[flat_id] >> 23;
// auto seed = CommonCode::unsafe_create(seed_val).to_raw_code();
// const auto size = (PATTERN_DATA[flat_id] >> 3) & 0xFFFFF;
// return {mirror_type, seed, size};
// }
static RangesUnion cases_without(uint8_t type_id, const RangesUnion &data) {
Ranges ranges {};
ranges.reserve(BASIC_RANGES_NUM[type_id]);
const auto [n, n_2x1, n_1x1] = BLOCK_NUM[type_id];
ranges.spawn(n, n_2x1, n_1x1);
ranges.reverse();
RangesUnion cases;
const auto [na, nb, nc, nd] = GROUP_UNION_CASES_NUM[type_id];
RANGE_RESERVE(0x0, na); RANGE_RESERVE(0x1, nb); RANGE_RESERVE(0x2, na);
RANGE_RESERVE(0x4, nc); RANGE_RESERVE(0x5, nd); RANGE_RESERVE(0x6, nc);
RANGE_RESERVE(0x8, nc); RANGE_RESERVE(0x9, nd); RANGE_RESERVE(0xA, nc);
RANGE_RESERVE(0xC, na); RANGE_RESERVE(0xD, nb); RANGE_RESERVE(0xE, na);
RANGE_DERIVE_WITHOUT(0x0); RANGE_DERIVE_WITHOUT(0x1); RANGE_DERIVE_WITHOUT(0x2);
RANGE_DERIVE_WITHOUT(0x4); RANGE_DERIVE_WITHOUT(0x5); RANGE_DERIVE_WITHOUT(0x6);
RANGE_DERIVE_WITHOUT(0x8); RANGE_DERIVE_WITHOUT(0x9); RANGE_DERIVE_WITHOUT(0xA);
RANGE_DERIVE_WITHOUT(0xC); RANGE_DERIVE_WITHOUT(0xD); RANGE_DERIVE_WITHOUT(0xE);
return cases;
}
if (group_union.group_num() == 1) { // only single group
// data[PATTERN_OFFSET[type_id] * 4] = group_union.cases();
*offset = group_union.cases();
static void build_ru_arr(uint8_t type_id, RangesUnion *output) {
const auto gu = GroupUnion::unsafe_create(type_id);
if (gu.group_num() == 1) { // with single group
*output = gu.cases();
return;
}
uint32_t pattern_id_begin = 0;
if ((PATTERN_DATA[PATTERN_OFFSET[type_id]] & 0b111) == 0) { // first pattern is `x`
pattern_id_begin = 1;
}
const bool ff_mode = (PATTERN_DATA[PATTERN_OFFSET[type_id]] & 0b111) == 0;
for (uint32_t pattern_id = pattern_id_begin; pattern_id < group_union.pattern_num(); ++pattern_id) {
// uint32_t pattern_id_begin = 0;
// if ((PATTERN_DATA[PATTERN_OFFSET[type_id]] & 0b111) == 0) { // first pattern type `Full`
// pattern_id_begin = 1;
// }
for (uint16_t pattern_id = ff_mode ? 1 : 0; pattern_id < gu.pattern_num(); ++pattern_id) {
const auto flat_id = PATTERN_OFFSET[type_id] + pattern_id;
const auto mirror_type = static_cast<Group::MirrorType>(PATTERN_DATA[flat_id] & 0b111);
const auto mirror_type = static_cast<MirrorType>(PATTERN_DATA[flat_id] & 0b111);
const auto seed_val = PATTERN_DATA[flat_id] >> 23;
auto seed = CommonCode::unsafe_create(seed_val).to_raw_code();
const auto size = (PATTERN_DATA[flat_id] >> 3) & 0xFFFFF;
// auto kk = &data[flat_id * 4];
const auto kk = offset + pattern_id * 4;
if (mirror_type == Group::MirrorType::Full) {
extend_pattern<Group::MirrorType::Full>(seed, size, kk);
} else if (mirror_type == Group::MirrorType::Horizontal) {
extend_pattern<Group::MirrorType::Horizontal>(seed, size, kk);
} else if (mirror_type == Group::MirrorType::Centro) {
extend_pattern<Group::MirrorType::Centro>(seed, size, kk);
} else if (mirror_type == Group::MirrorType::Vertical) {
extend_pattern<Group::MirrorType::Vertical>(seed, size, kk);
} else if (mirror_type == Group::MirrorType::Ordinary) {
extend_pattern<Group::MirrorType::Ordinary>(seed, size, kk);
}
// const auto [mirror_type, seed, size] = get_info(type_id, pattern_id);
// RangesUnion &a = kk[0];
// RangesUnion &b = kk[1];
// RangesUnion &c = kk[2];
// RangesUnion &d = kk[3];
//
// for (auto head : RangesUnion::Heads) {
// std::stable_sort(a.ranges(head).begin(), a.ranges(head).end());
// std::stable_sort(b.ranges(head).begin(), b.ranges(head).end());
// std::stable_sort(c.ranges(head).begin(), c.ranges(head).end());
// std::stable_sort(d.ranges(head).begin(), d.ranges(head).end());
// }
const auto kk = output + pattern_id * 4;
if (mirror_type == MirrorType::Full) {
spawn_pattern<MirrorType::Full>(seed, size, kk);
} else if (mirror_type == MirrorType::Horizontal) {
spawn_pattern<MirrorType::Horizontal>(seed, size, kk);
} else if (mirror_type == MirrorType::Centro) {
spawn_pattern<MirrorType::Centro>(seed, size, kk);
} else if (mirror_type == MirrorType::Vertical) {
spawn_pattern<MirrorType::Vertical>(seed, size, kk);
} else if (mirror_type == MirrorType::Ordinary) {
spawn_pattern<MirrorType::Ordinary>(seed, size, kk);
}
}
if (pattern_id_begin == 1) { // first pattern is `x`
if (ff_mode) {
RangesUnion others;
// size_t index_begin = (PATTERN_OFFSET[type_id] + 1) * 4;
// size_t index_end = (PATTERN_OFFSET[type_id] + group_union.pattern_num()) * 4;
//
// for (size_t index = index_begin; index < index_end; ++index) {
// others += data[index];
// }
// TODO: try to reserve
for (auto *ptr = offset + 4; ptr < offset + group_union.pattern_num() * 4; ++ptr) {
for (auto *ptr = output + 4; ptr < output + gu.pattern_num() * 4; ++ptr) {
others += *ptr;
}
// for (size_t index = 4; index < group_union.pattern_num() * 4; ++index) {
// others += *(offset + index);
// }
// RangesUnion init;
// auto others = std::accumulate(offset + 4, offset + group_union.pattern_num() * 4, init, [](RangesUnion a, RangesUnion b) { return a += b; });
for (auto head : RangesUnion::Heads) {
for (const auto head : RangesUnion::Heads) {
std::stable_sort(others.ranges(head).begin(), others.ranges(head).end());
}
// data[PATTERN_OFFSET[type_id] * 4] = group_union.cases_without(others);
*offset = group_union.cases_without(others);
// *output = gu.cases_without(others);
*output = cases_without(type_id, others);
}
}

Loading…
Cancel
Save