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
17inline constexpr std::size_t num_colors = pal::max_size * pal::num_pals;
18
26class ColorSet {
27 public:
28 ColorSet() = default;
29
30 [[nodiscard]] bool test(ColorIndex index) const;
31
32 void set(ColorIndex index, bool value = true);
33
34 void reset(ColorIndex index);
35
36 [[nodiscard]] const std::bitset<num_colors> &colors() const
37 {
38 return colors_;
39 }
40
41 [[nodiscard]] bool operator==(const ColorSet &other) const = default;
42
43 private:
44 std::bitset<num_colors> colors_;
45};
46
57[[nodiscard]] ColorSet color_set_union(const ColorSet &a, const ColorSet &b);
58
69[[nodiscard]] ColorSet color_set_intersection(const ColorSet &a, const ColorSet &b);
70
80[[nodiscard]] std::size_t color_set_count(const ColorSet &set);
81
92[[nodiscard]] bool is_subset(const ColorSet &a, const ColorSet &b);
93
104[[nodiscard]] std::size_t intersection_size(const ColorSet &a, const ColorSet &b);
105
116[[nodiscard]] std::size_t union_size(const ColorSet &a, const ColorSet &b);
117
132template <typename Func>
133void for_each_color(const ColorSet &set, Func &&func)
134{
135 static_assert(num_colors % 64 == 0, "num_colors must be a multiple of 64 for efficient word-aligned bit scanning");
136
137 const auto &bits = set.colors();
138
139 /*
140 * Process 64 bits at a time using efficient bit scanning:
141 *
142 * num_colors = 256, so we have 4 64-bit words
143 *
144 * Note: The +63 ceiling division is a defensive pattern; not strictly necessary due to the static_assert above.
145 */
146 constexpr std::size_t words = (num_colors + 63) / 64;
147
148 for (std::size_t word = 0; word < words; ++word) {
149 // Extract 64-bit chunk from bitset
150 std::uint64_t chunk = 0;
151 const std::size_t base = word * 64;
152 for (std::size_t b = 0; b < 64 && (base + b) < num_colors; ++b) {
153 if (bits.test(base + b)) {
154 chunk |= (1ULL << b);
155 }
156 }
157
158 // Process only set bits - skip zeros efficiently using Brian Kernighan's technique
159 while (chunk != 0) {
160 // GCC/Clang builtin to find lowest set bit position (count trailing zeros)
161 const int bit = __builtin_ctzll(chunk);
162 func(base + static_cast<std::size_t>(bit));
163 chunk &= chunk - 1; // Clear lowest set bit
164 }
165 }
166}
167
168} // namespace porytiles
169
177template <>
178struct std::hash<porytiles::ColorSet> {
188 [[nodiscard]] std::size_t operator()(const porytiles::ColorSet &color_set) const noexcept
189 {
190 return std::hash<std::string>{}(color_set.colors().to_string());
191 }
192};
Represents a color index value for palette operations.
A set of colors represented as a bitset.
Definition color_set.hpp:26
const std::bitset< num_colors > & colors() const
Definition color_set.hpp:36
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 num_pals
Definition palette.hpp:21
constexpr std::size_t max_size
Definition palette.hpp:19
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:17
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.