Browse Source

perf: optimize range check speed

master
Dnomd343 4 weeks ago
parent
commit
736d619463
  1. 16
      src/core/ranges/internal/check.inl

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

@ -4,11 +4,12 @@ namespace klotski::cases {
KLSK_INLINE_CE int Ranges::check(const int head, uint32_t range) { KLSK_INLINE_CE int Ranges::check(const int head, uint32_t range) {
KLSK_ASSUME(head >= 0 && head < 16 && head % 4 != 3); KLSK_ASSUME(head >= 0 && head < 16 && head % 4 != 3);
const int limit = 16 - (std::countl_zero(range) >> 1);
uint32_t flags = 0b110011 << head; // fill 2x2 block uint32_t flags = 0b110011 << head; // fill 2x2 block
for (int addr = 0, offset = 1; range; range >>= 2, ++offset) { // traverse every 2-bit
const auto num = std::countr_one(flags); for (int offset = 0, addr = 0; offset < limit; ++offset, range >>= 2) { // traverse every 2-bit
addr += num; // next unfilled block addr += std::countr_one(flags); // next unfilled block
flags >>= num; flags >>= std::countr_one(flags);
switch (range & 0b11) { switch (range & 0b11) {
case 0b00: // space case 0b00: // space
case 0b11: // 1x1 block case 0b11: // 1x1 block
@ -16,15 +17,18 @@ KLSK_INLINE_CE int Ranges::check(const int head, uint32_t range) {
continue; continue;
case 0b01: // 1x2 block case 0b01: // 1x2 block
if (flags & 0b10 || addr % 4 == 3) { // invalid case if (flags & 0b10 || addr % 4 == 3) { // invalid case
return offset; // broken offset return offset + 1; // broken offset
} }
flags |= 0b11; flags |= 0b11;
continue; continue;
case 0b10: // 2x1 block case 0b10: // 2x1 block
if (flags & 0b10000 || addr > 15) { // invalid case if (flags & 0b10000 || addr > 15) { // invalid case
return offset; // broken offset return offset + 1; // broken offset
} }
flags |= 0b10001; flags |= 0b10001;
continue;
default:
std::unreachable();
} }
} }
return 0; // pass check return 0; // pass check

Loading…
Cancel
Save