Porytiles
Loading...
Searching...
No Matches
color_set.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <bitset>
4#include <cstddef>
5#include <cstdint>
6#include <functional>
7#include <string>
8
11
12namespace porytiles {
13
15inline constexpr std::size_t num_colors = palette::max_size * palette::num_palettes;
16
22class ColorSet {
23 public:
24 ColorSet() = default;
25
26 [[nodiscard]] bool test(ColorIndex index) const;
27
28 void set(ColorIndex index, bool value = true);
29
30 void reset(ColorIndex index);
31
32 [[nodiscard]] const std::bitset<num_colors> &colors() const
33 {
34 return colors_;
35 }
36
37 [[nodiscard]] bool operator==(const ColorSet &other) const = default;
38
39 private:
40 std::bitset<num_colors> colors_;
41};
42
51[[nodiscard]] ColorSet color_set_union(const ColorSet &a, const ColorSet &b);
52
61[[nodiscard]] ColorSet color_set_intersection(const ColorSet &a, const ColorSet &b);
62
70[[nodiscard]] std::size_t color_set_count(const ColorSet &set);
71
80[[nodiscard]] bool is_subset(const ColorSet &a, const ColorSet &b);
81
90[[nodiscard]] std::size_t intersection_size(const ColorSet &a, const ColorSet &b);
91
100[[nodiscard]] std::size_t union_size(const ColorSet &a, const ColorSet &b);
101
114template <typename Func>
115void for_each_color(const ColorSet &set, Func &&func)
116{
117 static_assert(num_colors % 64 == 0, "num_colors must be a multiple of 64 for efficient word-aligned bit scanning");
118
119 const auto &bits = set.colors();
120
121 // Process 64 bits at a time using efficient bit scanning:
122 //
123 // num_colors = 256, so we have 4 64-bit words
124 //
125 // Note: The +63 ceiling division is a defensive pattern; not strictly necessary due to the static_assert above.
126 constexpr std::size_t words = (num_colors + 63) / 64;
127
128 for (std::size_t word = 0; word < words; ++word) {
129 // Extract 64-bit chunk from bitset
130 std::uint64_t chunk = 0;
131 const std::size_t base = word * 64;
132 for (std::size_t b = 0; b < 64 && (base + b) < num_colors; ++b) {
133 if (bits.test(base + b)) {
134 chunk |= (1ULL << b);
135 }
136 }
137
138 // Process only set bits - skip zeros efficiently using Brian Kernighan's technique
139 while (chunk != 0) {
140 // GCC/Clang builtin to find lowest set bit position (count trailing zeros)
141 const int bit = __builtin_ctzll(chunk);
142 func(base + static_cast<std::size_t>(bit));
143 chunk &= chunk - 1; // Clear lowest set bit
144 }
145 }
146}
147
148} // namespace porytiles
149
155template <>
156struct std::hash<porytiles::ColorSet> {
164 [[nodiscard]] std::size_t operator()(const porytiles::ColorSet &color_set) const noexcept
165 {
166 return std::hash<std::string>{}(color_set.colors().to_string());
167 }
168};
Represents a color index value for palette operations.
A set of colors represented as a bitset.
Definition color_set.hpp:22
const std::bitset< num_colors > & colors() const
Definition color_set.hpp:32
void reset(ColorIndex index)
Definition color_set.cpp:15
bool operator==(const ColorSet &other) const =default
void set(ColorIndex index, bool value=true)
Definition color_set.cpp:10
bool test(ColorIndex index) const
Definition color_set.cpp:5
constexpr std::size_t max_size
Definition palette.hpp:19
constexpr std::size_t num_palettes
Definition palette.hpp:21
void for_each_color(const ColorSet &set, Func &&func)
Iterates over each color index in a ColorSet.
bool is_subset(const ColorSet &a, const ColorSet &b)
Checks if one ColorSet is a subset of another.
Definition color_set.cpp:49
ColorSet color_set_union(const ColorSet &a, const ColorSet &b)
Computes the union of two ColorSets.
Definition color_set.cpp:20
constexpr std::size_t num_colors
Maximum allowable color count for GBA hardware.
Definition color_set.hpp:15
ColorSet color_set_intersection(const ColorSet &a, const ColorSet &b)
Computes the intersection of two ColorSets.
Definition color_set.cpp:32
std::size_t intersection_size(const ColorSet &a, const ColorSet &b)
Computes the intersection size between two ColorSets.
Definition color_set.cpp:58
std::size_t color_set_count(const ColorSet &set)
Counts the number of colors in a ColorSet.
Definition color_set.cpp:44
std::size_t union_size(const ColorSet &a, const ColorSet &b)
Computes the union size of two ColorSets.
Definition color_set.cpp:63
std::size_t operator()(const porytiles::ColorSet &color_set) const noexcept
Computes the hash value for a ColorSet.