Browse Source

update: try to optimize code structure

master
Dnomd343 1 day ago
parent
commit
78c108ab1a
  1. 333
      src/core/group/internal/group.cc

333
src/core/group/internal/group.cc

@ -18,12 +18,12 @@ using klotski::group::GROUP_DATA;
using klotski::group::PATTERN_DATA; using klotski::group::PATTERN_DATA;
template <typename MF, typename RF> template <typename MF, typename RF>
KLSK_NOINLINE static void extend(RawCode seed, const size_t size, MF add_mirror, RF release) { KLSK_NOINLINE static void extend(const RawCode seed, const size_t reserve, MF add_mirror, RF release) {
std::vector<RawCode> queue, mirrors; std::vector<RawCode> queue, mirrors;
phmap::flat_hash_map<RawCode, uint64_t> cases; phmap::flat_hash_map<RawCode, uint64_t> cases;
queue.reserve(size); mirrors.reserve(size); queue.reserve(reserve); mirrors.reserve(reserve);
cases.reserve(static_cast<size_t>(static_cast<double>(size) * 1.56)); // reduce load factor cases.reserve(static_cast<size_t>(static_cast<double>(reserve) * 1.56)); // reduce load factor
auto mover = MaskMover([&queue, &cases, &mirrors, add_mirror](RawCode code, uint64_t hint) { auto mover = MaskMover([&queue, &cases, &mirrors, add_mirror](RawCode code, uint64_t hint) {
if (const auto [iter, ret] = cases.try_emplace(code, hint); !ret) { if (const auto [iter, ret] = cases.try_emplace(code, hint); !ret) {
@ -53,174 +53,204 @@ KLSK_NOINLINE static void extend(RawCode seed, const size_t size, MF add_mirror,
for (const auto code : mirrors) { release(code); } for (const auto code : mirrors) { release(code); }
} }
static RangesUnion extend_type_common(RawCode seed, size_t reserve) { #define RELEASE_TO(RU) \
RangesUnion data {}; [&data](const RawCode raw_code) { \
extend(seed, reserve, [](RawCode, auto) {}, [&data](const RawCode raw_code) { const auto code = raw_code.to_common_code().unwrap(); \
const auto code = raw_code.to_common_code().unwrap(); data.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code)); \
data.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code)); }
});
return data;
}
static RangesUnion extend_type_hor(RawCode seed, size_t reserve) { template <Group::MirrorType TYPE>
static RangesUnion extend_type_xxx(const RawCode seed, const size_t reserve) {
RangesUnion data {};
// size_t size_a = static_cast<size_t>(static_cast<double>(size) * 0.500892) + 11; if constexpr(TYPE == Group::MirrorType::Ordinary) {
// size_t size_b = static_cast<size_t>(static_cast<double>(size) * 0.499108) + 10;
RangesUnion data {}; extend(seed, reserve, [](RawCode, auto) {}, RELEASE_TO(data));
// TODO: how to reserve } else if constexpr(TYPE == Group::MirrorType::Horizontal) {
// size_t val = reserve / 8;
//
// data.ranges(0).reserve(val);
// data.ranges(1).reserve(val);
// data.ranges(2).reserve(val);
//
// data.ranges(4).reserve(val);
// data.ranges(5).reserve(val);
// data.ranges(6).reserve(val);
//
// data.ranges(8).reserve(val);
// data.ranges(9).reserve(val);
// data.ranges(10).reserve(val);
//
// data.ranges(12).reserve(val);
// data.ranges(13).reserve(val);
// data.ranges(14).reserve(val);
extend(seed, reserve, [](const RawCode code, auto callback) { extend(seed, reserve, [](const RawCode code, auto callback) {
if (const auto mirror = code.to_horizontal_mirror(); mirror != code) { if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) {
callback(mirror); callback(m_hor);
} }
}, [&data](const RawCode raw_code) { }, RELEASE_TO(data));
const auto code = raw_code.to_common_code().unwrap();
data.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code));
});
return data; } else if constexpr(TYPE == Group::MirrorType::Vertical) {
}
static RangesUnion extend_type_ver(RawCode seed, size_t reserve) {
RangesUnion data {};
extend(seed, reserve, [](const RawCode code, auto callback) { extend(seed, reserve, [](const RawCode code, auto callback) {
callback(code.to_vertical_mirror()); callback(code.to_vertical_mirror());
}, [&data](const RawCode raw_code) { }, RELEASE_TO(data));
const auto code = raw_code.to_common_code().unwrap();
data.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code)); } else if constexpr(TYPE == Group::MirrorType::Centro) {
});
return data;
}
static RangesUnion extend_type_diag(RawCode seed, size_t reserve) {
RangesUnion data {};
extend(seed, reserve, [](const RawCode code, auto callback) { extend(seed, reserve, [](const RawCode code, auto callback) {
callback(code.to_diagonal_mirror()); callback(code.to_diagonal_mirror());
}, [&data](const RawCode raw_code) { }, RELEASE_TO(data));
const auto code = raw_code.to_common_code().unwrap();
data.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code)); } else if constexpr(TYPE == Group::MirrorType::Full) {
});
return data;
}
static RangesUnion extend_type_x(RawCode seed, size_t reserve) {
RangesUnion data {};
extend(seed, reserve, [](const RawCode code, auto callback) { extend(seed, reserve, [](const RawCode code, auto callback) {
const auto mirror_1 = code.to_vertical_mirror(); const auto m_vrt = code.to_vertical_mirror();
callback(mirror_1); callback(m_vrt);
if (const auto mirror_2 = code.to_horizontal_mirror(); mirror_2 != code) { if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) {
callback(mirror_2); callback(m_hor);
callback(mirror_1.to_horizontal_mirror()); callback(m_vrt.to_horizontal_mirror());
} }
}, [&data](const RawCode raw_code) { }, RELEASE_TO(data));
const auto code = raw_code.to_common_code().unwrap();
data.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code)); }
});
return data; return data;
} }
// static RangesUnion extend_type_ord(const RawCode seed, const size_t reserve) {
// RangesUnion data {};
// extend(seed, reserve, [](RawCode, auto) {}, RELEASE_TO(data));
// return data;
// }
//
// static RangesUnion extend_type_hor(const RawCode seed, const size_t reserve) {
// RangesUnion data {};
// extend(seed, reserve, [](const RawCode code, auto callback) {
// if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) {
// callback(m_hor);
// }
// }, RELEASE_TO(data));
// return data;
// }
//
// static RangesUnion extend_type_vrt(const RawCode seed, const size_t reserve) {
// RangesUnion data {};
// extend(seed, reserve, [](const RawCode code, auto callback) {
// callback(code.to_vertical_mirror());
// }, RELEASE_TO(data));
// return data;
// }
//
// static RangesUnion extend_type_diag(const RawCode seed, const size_t reserve) {
// RangesUnion data {};
// extend(seed, reserve, [](const RawCode code, auto callback) {
// callback(code.to_diagonal_mirror());
// }, RELEASE_TO(data));
// return data;
// }
//
// static RangesUnion extend_type_full(const RawCode seed, const size_t reserve) {
// RangesUnion data {};
// extend(seed, reserve, [](const RawCode code, auto callback) {
// const auto m_vrt = code.to_vertical_mirror();
// callback(m_vrt);
// if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) {
// callback(m_hor);
// callback(m_vrt.to_horizontal_mirror());
// }
// }, RELEASE_TO(data));
// return data;
// }
template <typename MFunc, typename RFunc> template <typename MFunc, typename RFunc>
KLSK_NOINLINE static void spawn_pattern(RawCode seed, const size_t reserve, MFunc add_mirror, RFunc release) { KLSK_NOINLINE static void spawn_pattern(RawCode seed, const size_t reserve, MFunc add_mirror, RFunc release) {
std::vector<RawCode> queue;
std::vector<RawCode> codes;
std::vector<RawCode> mirrors; std::vector<RawCode> mirrors;
phmap::flat_hash_map<RawCode, uint64_t> cases; // <code, hint> phmap::flat_hash_map<RawCode, uint64_t> cases;
codes.reserve(reserve); queue.reserve(reserve);
mirrors.reserve(reserve); // TODO: cal max size-coff mirrors.reserve(reserve);
cases.reserve(static_cast<size_t>(reserve * 1.56)); cases.reserve(static_cast<size_t>(reserve * 1.56));
auto core = MaskMover([&codes, &cases, &mirrors, add_mirror](RawCode code, uint64_t hint) { auto mover = MaskMover([&queue, &cases, &mirrors, add_mirror](RawCode code, uint64_t hint) {
if (const auto [iter, ret] = cases.try_emplace(code, hint); !ret) { if (const auto [iter, ret] = cases.try_emplace(code, hint); !ret) {
iter->second |= hint; // update hint iter->second |= hint; // update hint
return; return;
} }
codes.emplace_back(code); queue.emplace_back(code);
add_mirror(code, [&cases, &mirrors](RawCode mirror) { add_mirror(code, [&cases, &mirrors](RawCode mirror) {
cases.emplace(mirror, 0); cases.emplace(mirror, 0); // without hint
mirrors.emplace_back(mirror); mirrors.emplace_back(mirror);
}); });
}); });
uint64_t offset = 0; uint64_t offset = 0;
codes.emplace_back(seed); queue.emplace_back(seed);
cases.emplace(seed, 0); // without hint cases.emplace(seed, 0);
add_mirror(seed, [&mirrors, &cases](RawCode mirror) { add_mirror(seed, [&mirrors, &cases](RawCode mirror) {
cases.emplace(mirror, 0); cases.emplace(mirror, 0); // without hint
mirrors.emplace_back(mirror); mirrors.emplace_back(mirror);
}); });
while (offset != codes.size()) { while (offset != queue.size()) {
const auto curr = codes[offset++]; const auto curr = queue[offset++];
core.next_cases(curr, cases.find(curr)->second); mover.next_cases(curr, cases.find(curr)->second);
} }
for (const auto code : codes) { for (const auto code : queue) { release(code); }
release(code); for (const auto code : mirrors) { release(code); }
}
for (const auto code : mirrors) {
release(code);
}
} }
#define OUTPUT(VAR, EXPL, OUT) \
const auto VAR = (EXPL).to_common_code().unwrap(); \
OUT.ranges(VAR >> 32).emplace_back(static_cast<uint32_t>(VAR))
#define KLSK_CONCAT_IMPL(X, Y) X##Y
#define KLSK_CONCAT(X, Y) KLSK_CONCAT_IMPL(X, Y)
#define OUTPUT_IMPL(VAR, EXPL, OUT) \
const auto VAR = (EXPL).to_common_code().unwrap(); \
OUT.ranges(VAR >> 32).emplace_back(static_cast<uint32_t>(VAR))
#define OUTPUT(EXPL, OUT) \
OUTPUT_IMPL(KLSK_CONCAT(c_, __COUNTER__), EXPL, OUT)
KLSK_NOINLINE static void spawn_full_pattern(RawCode seed, const size_t reserve, RangesUnion &output) { KLSK_NOINLINE static void spawn_full_pattern(RawCode seed, const size_t reserve, RangesUnion &output) {
spawn_pattern(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) { spawn_pattern(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) {
const auto code = raw_code.to_common_code().unwrap(); // const auto code = raw_code.to_common_code().unwrap();
output.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code)); // output.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code));
// OUTPUT(code, raw_code, output);
OUTPUT(raw_code, output);
}); });
} }
KLSK_NOINLINE static void spawn_hor_pattern(RawCode seed, const size_t reserve, RangesUnion &output) { KLSK_NOINLINE static void spawn_hor_pattern(RawCode seed, const size_t reserve, RangesUnion &output) {
spawn_pattern(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) { spawn_pattern(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) {
const auto code = raw_code.to_common_code().unwrap(); // const auto code = raw_code.to_common_code().unwrap();
output.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code)); // output.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code));
OUTPUT(raw_code, output);
const auto code_ = raw_code.to_vertical_mirror().to_common_code().unwrap(); // const auto code_ = raw_code.to_vertical_mirror().to_common_code().unwrap();
output.ranges(code_ >> 32).emplace_back(static_cast<uint32_t>(code_)); // output.ranges(code_ >> 32).emplace_back(static_cast<uint32_t>(code_));
OUTPUT(raw_code.to_vertical_mirror(), output);
}); });
} }
KLSK_NOINLINE static void spawn_ver_pattern(RawCode seed, const size_t reserve, RangesUnion &output) { KLSK_NOINLINE static void spawn_ver_pattern(RawCode seed, const size_t reserve, RangesUnion &output) {
spawn_pattern(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) { spawn_pattern(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) {
const auto code = raw_code.to_common_code().unwrap(); // const auto code = raw_code.to_common_code().unwrap();
output.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code)); // output.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code));
OUTPUT(raw_code, output);
const auto code_ = raw_code.to_horizontal_mirror().to_common_code().unwrap(); // const auto code_ = raw_code.to_horizontal_mirror().to_common_code().unwrap();
output.ranges(code_ >> 32).emplace_back(static_cast<uint32_t>(code_)); // output.ranges(code_ >> 32).emplace_back(static_cast<uint32_t>(code_));
OUTPUT(raw_code.to_horizontal_mirror(), output);
}); });
} }
KLSK_NOINLINE static void spawn_ord_pattern(RawCode seed, const size_t reserve, RangesUnion &output) { KLSK_NOINLINE static void spawn_ord_pattern(RawCode seed, const size_t reserve, RangesUnion &output) {
spawn_pattern(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) { spawn_pattern(seed, reserve, [](RawCode, auto) {}, [&output](RawCode raw_code) {
const auto code = raw_code.to_common_code().unwrap(); // const auto code = raw_code.to_common_code().unwrap();
output.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code)); // output.ranges(code >> 32).emplace_back(static_cast<uint32_t>(code));
OUTPUT(raw_code, output);
const auto code_1 = raw_code.to_vertical_mirror().to_common_code().unwrap(); // const auto code_1 = raw_code.to_vertical_mirror().to_common_code().unwrap();
output.ranges(code_1 >> 32).emplace_back(static_cast<uint32_t>(code_1)); // output.ranges(code_1 >> 32).emplace_back(static_cast<uint32_t>(code_1));
OUTPUT(raw_code.to_vertical_mirror(), output);
const auto code_2 = raw_code.to_horizontal_mirror().to_common_code().unwrap(); // const auto code_2 = raw_code.to_horizontal_mirror().to_common_code().unwrap();
output.ranges(code_2 >> 32).emplace_back(static_cast<uint32_t>(code_2)); // output.ranges(code_2 >> 32).emplace_back(static_cast<uint32_t>(code_2));
OUTPUT(raw_code.to_horizontal_mirror(), output);
const auto code_3 = raw_code.to_diagonal_mirror().to_common_code().unwrap(); // const auto code_3 = raw_code.to_diagonal_mirror().to_common_code().unwrap();
output.ranges(code_3 >> 32).emplace_back(static_cast<uint32_t>(code_3)); // output.ranges(code_3 >> 32).emplace_back(static_cast<uint32_t>(code_3));
OUTPUT(raw_code.to_diagonal_mirror(), output); // TODO: perf it
}); });
} }
@ -263,7 +293,8 @@ RangesUnion Group::cases() const {
// return GroupUnion::unsafe_create(type_id_).cases(); // return GroupUnion::unsafe_create(type_id_).cases();
} }
auto seed = CommonCode::unsafe_create(PATTERN_DATA[flat_id()] >> 23).to_raw_code(); const auto seed_val = PATTERN_DATA[flat_id()] >> 23;
auto seed = CommonCode::unsafe_create(seed_val).to_raw_code();
if (toward_ == Toward::B) { if (toward_ == Toward::B) {
seed = seed.to_horizontal_mirror(); seed = seed.to_horizontal_mirror();
} else if (toward_ == Toward::C) { } else if (toward_ == Toward::C) {
@ -272,20 +303,96 @@ RangesUnion Group::cases() const {
seed = seed.to_diagonal_mirror(); seed = seed.to_diagonal_mirror();
} }
// const auto centro_mirror = [](const RawCode code, auto callback) {
// callback(code.to_diagonal_mirror());
// };
// const auto vertical_mirror = [](const RawCode code, auto callback) {
// callback(code.to_vertical_mirror());
// };
// const auto horizontal_mirror = [](const RawCode code, auto callback) {
// if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) {
// callback(m_hor);
// }
// };
// const auto full_mirror = [](const RawCode code, auto callback) {
// const auto m_vrt = code.to_vertical_mirror();
// callback(m_vrt);
// if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) {
// callback(m_hor);
// callback(m_vrt.to_horizontal_mirror());
// }
// };
// TODO: how to reserve `data`
RangesUnion data; RangesUnion data;
// if (mirror_type() == MirrorType::Ordinary) {
// // std::println("Ordinary"); // 24892
// // extend(seed, size(), [](RawCode, auto) {}, RELEASE_TO(data));
//
// data = extend_ord(seed, size());
//
// } else if (mirror_type() == MirrorType::Horizontal) {
// // std::println("Horizontal"); // 294
// // extend(seed, size(), [](const RawCode code, auto callback) {
// // if (const auto m_hor = code.to_horizontal_mirror(); m_hor != code) {
// // callback(m_hor);
// // }
// // }, RELEASE_TO(data));
// // return extend_hor(seed, size());
//
// data = extend_hor(seed, size());
//
// } else if (mirror_type() == MirrorType::Vertical) {
// // std::println("Vertical"); // 54
// // extend(seed, size(), vertical_mirror, RELEASE_TO(data));
//
// data = extend_ver(seed, size());
//
// } else if (mirror_type() == MirrorType::Full) {
// // std::println("Full"); // 3
// // extend(seed, size(), full_mirror, RELEASE_TO(data));
//
// data = extend_type_x(seed, size());
//
// } else {
// // std::println("Centro"); // 4
// // extend(seed, size(), centro_mirror, RELEASE_TO(data));
//
// data = extend_diag(seed, size());
//
// }
if (mirror_type() == MirrorType::Full) { if (mirror_type() == MirrorType::Full) {
data = extend_type_x(seed, size()); // data = extend_type_full(seed, size());
data = extend_type_xxx<MirrorType::Full>(seed, size());
} else if (mirror_type() == MirrorType::Horizontal) { } else if (mirror_type() == MirrorType::Horizontal) {
data = extend_type_hor(seed, size()); // data = extend_type_hor(seed, size());
data = extend_type_xxx<MirrorType::Horizontal>(seed, size());
} else if (mirror_type() == MirrorType::Vertical) { } else if (mirror_type() == MirrorType::Vertical) {
data = extend_type_ver(seed, size()); // data = extend_type_vrt(seed, size());
data = extend_type_xxx<MirrorType::Vertical>(seed, size());
} else if (mirror_type() == MirrorType::Centro) { } else if (mirror_type() == MirrorType::Centro) {
data = extend_type_diag(seed, size()); // data = extend_type_diag(seed, size());
data = extend_type_xxx<MirrorType::Centro>(seed, size());
} else { } else {
data = extend_type_common(seed, size()); // data = extend_type_ord(seed, size());
data = extend_type_xxx<MirrorType::Ordinary>(seed, size());
} }
for (int head = 0; head < 16; ++head) { // if (mirror_type() == MirrorType::Ordinary) {
// data = extend_type_ord(seed, size());
// } else if (mirror_type() == MirrorType::Horizontal) {
// data = extend_type_hor(seed, size());
// } else if (mirror_type() == MirrorType::Vertical) {
// data = extend_type_vrt(seed, size());
// } else if (mirror_type() == MirrorType::Full) {
// data = extend_type_full(seed, size());
// } else {
// data = extend_type_diag(seed, size());
// }
for (const auto head : RangesUnion::Heads) {
std::stable_sort(data.ranges(head).begin(), data.ranges(head).end()); std::stable_sort(data.ranges(head).begin(), data.ranges(head).end());
} }
return data; return data;

Loading…
Cancel
Save