implement very slow puzzle space exploration
This commit is contained in:
192
include/util.hpp
192
include/util.hpp
@ -4,81 +4,8 @@
|
||||
#include <iostream>
|
||||
#include <raylib.h>
|
||||
|
||||
// Bit shifting + masking
|
||||
|
||||
template <class T>
|
||||
requires std::unsigned_integral<T>
|
||||
auto create_mask(const uint8_t first, const uint8_t last) -> T
|
||||
{
|
||||
// If the mask width is equal the type width return all 1s instead of shifting
|
||||
// as shifting by type-width is undefined behavior.
|
||||
if (static_cast<size_t>(last - first + 1) >= sizeof(T) * 8) {
|
||||
return ~T{0};
|
||||
}
|
||||
|
||||
// Example: first=4, last=7, 7-4+1=4
|
||||
// 1 << 4 = 0b00010000
|
||||
// 32 - 1 = 0b00001111
|
||||
// 31 << 4 = 0b11110000
|
||||
// Subtracting 1 generates a consecutive mask.
|
||||
return ((T{1} << (last - first + 1)) - 1) << first;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
requires std::unsigned_integral<T>
|
||||
auto clear_bits(T& bits, const uint8_t first, const uint8_t last) -> void
|
||||
{
|
||||
const T mask = create_mask<T>(first, last);
|
||||
|
||||
bits = bits & ~mask;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
requires std::unsigned_integral<T> && std::unsigned_integral<U>
|
||||
auto set_bits(T& bits, const uint8_t first, const uint8_t last, const U value) -> void
|
||||
{
|
||||
const T mask = create_mask<T>(first, last);
|
||||
|
||||
// Example: first=4, last=6, value=0b1110, bits = 0b 01111110
|
||||
// mask = 0b 01110000
|
||||
// bits & ~mask = 0b 00001110
|
||||
// value << 4 = 0b 11100000
|
||||
// (value << 4) & mask = 0b 01100000
|
||||
// (bits & ~mask) | (value << 4) & mask = 0b 01101110
|
||||
// Insert position: ^^^
|
||||
// First clear the bits, then | with the value positioned at the insertion point.
|
||||
// The value may be larger than [first, last], extra bits are ignored.
|
||||
bits = (bits & ~mask) | ((static_cast<T>(value) << first) & mask);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
requires std::unsigned_integral<T>
|
||||
auto get_bits(const T bits, const uint8_t first, const uint8_t last) -> T
|
||||
{
|
||||
const T mask = create_mask<T>(first, last);
|
||||
|
||||
// We can >> without sign extension because T is unsigned_integral
|
||||
return (bits & mask) >> first;
|
||||
}
|
||||
|
||||
// std::variant visitor
|
||||
|
||||
// https://en.cppreference.com/w/cpp/utility/variant/visit
|
||||
template <class... Ts>
|
||||
struct overloads : Ts...
|
||||
{
|
||||
using Ts::operator()...;
|
||||
};
|
||||
|
||||
// Enums
|
||||
|
||||
enum direction
|
||||
{
|
||||
nor = 1 << 0,
|
||||
eas = 1 << 1,
|
||||
sou = 1 << 2,
|
||||
wes = 1 << 3,
|
||||
};
|
||||
#define INLINE __attribute__((always_inline))
|
||||
#define PACKED __attribute__((packed))
|
||||
|
||||
enum ctrl
|
||||
{
|
||||
@ -115,6 +42,96 @@ enum bg
|
||||
bg_white = 47
|
||||
};
|
||||
|
||||
inline auto ansi_bold_fg(const fg color) -> std::string
|
||||
{
|
||||
return std::format("\033[{};{}m", static_cast<int>(bold_bright), static_cast<int>(color));
|
||||
}
|
||||
|
||||
inline auto ansi_reset() -> std::string
|
||||
{
|
||||
return std::format("\033[{}m", static_cast<int>(reset));
|
||||
}
|
||||
|
||||
// Bit shifting + masking
|
||||
|
||||
template <class T>
|
||||
requires std::unsigned_integral<T>
|
||||
// ReSharper disable once CppRedundantInlineSpecifier
|
||||
INLINE inline auto create_mask(const uint8_t first, const uint8_t last) -> T
|
||||
{
|
||||
// If the mask width is equal the type width return all 1s instead of shifting
|
||||
// as shifting by type-width is undefined behavior.
|
||||
if (static_cast<size_t>(last - first + 1) >= sizeof(T) * 8) {
|
||||
return ~T{0};
|
||||
}
|
||||
|
||||
// Example: first=4, last=7, 7-4+1=4
|
||||
// 1 << 4 = 0b00010000
|
||||
// 32 - 1 = 0b00001111
|
||||
// 31 << 4 = 0b11110000
|
||||
// Subtracting 1 generates a consecutive mask.
|
||||
return ((T{1} << (last - first + 1)) - 1) << first;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
requires std::unsigned_integral<T>
|
||||
// ReSharper disable once CppRedundantInlineSpecifier
|
||||
INLINE inline auto clear_bits(T& bits, const uint8_t first, const uint8_t last) -> void
|
||||
{
|
||||
const T mask = create_mask<T>(first, last);
|
||||
|
||||
bits = bits & ~mask;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
requires std::unsigned_integral<T> && std::unsigned_integral<U>
|
||||
// ReSharper disable once CppRedundantInlineSpecifier
|
||||
INLINE inline auto set_bits(T& bits, const uint8_t first, const uint8_t last, const U value) -> void
|
||||
{
|
||||
const T mask = create_mask<T>(first, last);
|
||||
|
||||
// Example: first=4, last=6, value=0b1110, bits = 0b 01111110
|
||||
// mask = 0b 01110000
|
||||
// bits & ~mask = 0b 00001110
|
||||
// value << 4 = 0b 11100000
|
||||
// (value << 4) & mask = 0b 01100000
|
||||
// (bits & ~mask) | (value << 4) & mask = 0b 01101110
|
||||
// Insert position: ^^^
|
||||
// First clear the bits, then | with the value positioned at the insertion point.
|
||||
// The value may be larger than [first, last], extra bits are ignored.
|
||||
bits = (bits & ~mask) | ((static_cast<T>(value) << first) & mask);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
requires std::unsigned_integral<T>
|
||||
// ReSharper disable once CppRedundantInlineSpecifier
|
||||
INLINE inline auto get_bits(const T bits, const uint8_t first, const uint8_t last) -> T
|
||||
{
|
||||
const T mask = create_mask<T>(first, last);
|
||||
|
||||
// We can >> without sign extension because T is unsigned_integral
|
||||
return (bits & mask) >> first;
|
||||
}
|
||||
|
||||
// std::variant visitor
|
||||
|
||||
// https://en.cppreference.com/w/cpp/utility/variant/visit
|
||||
template <class... Ts>
|
||||
struct overloads : Ts...
|
||||
{
|
||||
using Ts::operator()...;
|
||||
};
|
||||
|
||||
// Enums
|
||||
|
||||
enum direction
|
||||
{
|
||||
nor = 1 << 0,
|
||||
eas = 1 << 1,
|
||||
sou = 1 << 2,
|
||||
wes = 1 << 3,
|
||||
};
|
||||
|
||||
// Output
|
||||
|
||||
inline auto operator<<(std::ostream& os, const Vector2& v) -> std::ostream&
|
||||
@ -129,16 +146,6 @@ inline auto operator<<(std::ostream& os, const Vector3& v) -> std::ostream&
|
||||
return os;
|
||||
}
|
||||
|
||||
inline auto ansi_bold_fg(const fg color) -> std::string
|
||||
{
|
||||
return std::format("\033[1;{}m", static_cast<int>(color));
|
||||
}
|
||||
|
||||
inline auto ansi_reset() -> std::string
|
||||
{
|
||||
return "\033[0m";
|
||||
}
|
||||
|
||||
// std::println doesn't work with mingw
|
||||
template <typename... Args>
|
||||
auto traceln(std::format_string<Args...> fmt, Args&&... args) -> void
|
||||
@ -168,4 +175,19 @@ auto errln(std::format_string<Args...> fmt, Args&&... args) -> void
|
||||
fmt, std::forward<Args>(args)...) << std::endl;
|
||||
}
|
||||
|
||||
inline auto print_bitmap(const uint64_t bitmap, const uint8_t w, const uint8_t h, const std::string& title) -> void
|
||||
{
|
||||
traceln("{}:", title);
|
||||
traceln("{}", std::string(2 * w - 1, '='));
|
||||
for (size_t y = 0; y < w; ++y) {
|
||||
std::cout << " ";
|
||||
for (size_t x = 0; x < h; ++x) {
|
||||
std::cout << static_cast<int>(get_bits(bitmap, y * w + x, y * h + x)) << " ";
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
std::cout << std::flush;
|
||||
traceln("{}", std::string(2 * w - 1, '='));
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user