Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify some C++ abstractions #1518

Merged
merged 10 commits into from
Sep 26, 2024
File renamed without changes.
20 changes: 9 additions & 11 deletions include/gfx/main.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,20 +107,18 @@ struct Palette {
uint8_t size() const;
};

namespace detail {
template<typename T, T... i>
static constexpr auto flipTable(std::integer_sequence<T, i...>) {
return std::array{[](uint8_t byte) {
// Flipping tends to happen fairly often, so take a bite out of dcache to speed it up
static constexpr auto flipTable = ([]() constexpr {
std::array<uint16_t, 256> table{};
for (uint16_t i = 0; i < table.size(); i++) {
// To flip all the bits, we'll flip both nibbles, then each nibble half, etc.
uint16_t byte = i;
byte = (byte & 0b0000'1111) << 4 | (byte & 0b1111'0000) >> 4;
byte = (byte & 0b0011'0011) << 2 | (byte & 0b1100'1100) >> 2;
byte = (byte & 0b0101'0101) << 1 | (byte & 0b1010'1010) >> 1;
return byte;
}(i)...};
}
} // namespace detail

// Flipping tends to happen fairly often, so take a bite out of dcache to speed it up
static constexpr auto flipTable = detail::flipTable(std::make_integer_sequence<uint16_t, 256>());
table[i] = byte;
}
return table;
})();

#endif // RGBDS_GFX_MAIN_HPP
6 changes: 1 addition & 5 deletions include/gfx/pal_packing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,15 @@
#include <tuple>
#include <vector>

#include "defaultinitalloc.hpp"
#include "defaultinitvec.hpp"

struct Palette;
class ProtoPalette;

namespace packing {

/*
* Returns which palette each proto-palette maps to, and how many palettes are necessary
*/
std::tuple<DefaultInitVec<size_t>, size_t>
overloadAndRemove(std::vector<ProtoPalette> const &protoPalettes);

} // namespace packing

#endif // RGBDS_GFX_PAL_PACKING_HPP
10 changes: 3 additions & 7 deletions include/gfx/pal_sorting.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,16 @@

struct Palette;

namespace sorting {

void indexed(
void sortIndexed(
std::vector<Palette> &palettes,
int palSize,
png_color const *palRGB,
int palAlphaSize,
png_byte *palAlpha
);
void grayscale(
void sortGrayscale(
std::vector<Palette> &palettes, std::array<std::optional<Rgba>, 0x8001> const &colors
);
void rgb(std::vector<Palette> &palettes);

} // namespace sorting
void sortRgb(std::vector<Palette> &palettes);

#endif // RGBDS_GFX_PAL_SORTING_HPP
4 changes: 2 additions & 2 deletions include/gfx/rgba.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ struct Rgba {
auto shl = [](uint8_t val, unsigned shift) { return static_cast<uint32_t>(val) << shift; };
return shl(red, 24) | shl(green, 16) | shl(blue, 8) | shl(alpha, 0);
}
friend bool operator==(Rgba const &lhs, Rgba const &rhs) { return lhs.toCSS() == rhs.toCSS(); }
friend bool operator!=(Rgba const &lhs, Rgba const &rhs) { return lhs.toCSS() != rhs.toCSS(); }
bool operator==(Rgba const &rhs) const { return toCSS() == rhs.toCSS(); }
bool operator!=(Rgba const &rhs) const { return toCSS() != rhs.toCSS(); }

/*
* CGB colors are RGB555, so we use bit 15 to signify that the color is transparent instead
Expand Down
77 changes: 34 additions & 43 deletions include/itertools.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,45 @@
#include <utility>

template<typename T>
class EnumSeqIterator {
T _value;

public:
explicit EnumSeqIterator(T value) : _value(value) {}
class EnumSeq {
T _start;
T _stop;

EnumSeqIterator &operator++() {
_value = (T)(_value + 1);
return *this;
}
class Iterator {
T _value;

auto operator*() const { return _value; }
public:
explicit Iterator(T value) : _value(value) {}

friend auto operator==(EnumSeqIterator const &lhs, EnumSeqIterator const &rhs) {
return lhs._value == rhs._value;
}
Iterator &operator++() {
_value = (T)(_value + 1);
return *this;
}

friend auto operator!=(EnumSeqIterator const &lhs, EnumSeqIterator const &rhs) {
return lhs._value != rhs._value;
}
};
auto operator*() const { return _value; }

template<typename T>
class EnumSeq {
T _start;
T _stop;
bool operator==(Iterator const &rhs) const { return _value == rhs._value; }
bool operator!=(Iterator const &rhs) const { return _value != rhs._value; }
};

public:
explicit EnumSeq(T stop) : _start((T)0), _stop(stop) {}
explicit EnumSeq(T start, T stop) : _start(start), _stop(stop) {}

EnumSeqIterator<T> begin() { return EnumSeqIterator(_start); }
EnumSeqIterator<T> end() { return EnumSeqIterator(_stop); }
Iterator begin() { return Iterator(_start); }
Iterator end() { return Iterator(_stop); }
};

// This is not a fully generic implementation; its current use cases only require for-loop behavior.
// We also assume that all iterators have the same length.
template<typename... Iters>
class Zip {
std::tuple<Iters...> _iters;
template<typename... Ts>
class ZipIterator {
std::tuple<Ts...> _iters;

public:
explicit Zip(std::tuple<Iters...> &&iters) : _iters(iters) {}
explicit ZipIterator(std::tuple<Ts...> &&iters) : _iters(iters) {}

Zip &operator++() {
ZipIterator &operator++() {
std::apply([](auto &&...it) { (++it, ...); }, _iters);
return *this;
}
Expand All @@ -62,26 +56,24 @@ class Zip {
);
}

friend auto operator==(Zip const &lhs, Zip const &rhs) {
return std::get<0>(lhs._iters) == std::get<0>(rhs._iters);
bool operator==(ZipIterator const &rhs) const {
return std::get<0>(_iters) == std::get<0>(rhs._iters);
}

friend auto operator!=(Zip const &lhs, Zip const &rhs) {
return std::get<0>(lhs._iters) != std::get<0>(rhs._iters);
bool operator!=(ZipIterator const &rhs) const {
return std::get<0>(_iters) != std::get<0>(rhs._iters);
}
};

namespace detail {
template<typename... Containers>
template<typename... Ts>
class ZipContainer {
std::tuple<Containers...> _containers;
std::tuple<Ts...> _containers;

public:
explicit ZipContainer(Containers &&...containers)
: _containers(std::forward<Containers>(containers)...) {}
explicit ZipContainer(Ts &&...containers) : _containers(std::forward<Ts>(containers)...) {}

auto begin() {
return Zip(std::apply(
return ZipIterator(std::apply(
[](auto &&...containers) {
using std::begin;
return std::make_tuple(begin(containers)...);
Expand All @@ -91,7 +83,7 @@ class ZipContainer {
}

auto end() {
return Zip(std::apply(
return ZipIterator(std::apply(
[](auto &&...containers) {
using std::end;
return std::make_tuple(end(containers)...);
Expand All @@ -105,12 +97,11 @@ class ZipContainer {
template<typename T>
using Holder = std::
conditional_t<std::is_lvalue_reference_v<T>, T, std::remove_cv_t<std::remove_reference_t<T>>>;
} // namespace detail

// Does the same number of iterations as the first container's iterator!
template<typename... Containers>
static constexpr auto zip(Containers &&...cs) {
return detail::ZipContainer<detail::Holder<Containers>...>(std::forward<Containers>(cs)...);
template<typename... Ts>
static constexpr auto zip(Ts &&...cs) {
return ZipContainer<Holder<Ts>...>(std::forward<Ts>(cs)...);
}

#endif // RGBDS_ITERTOOLS_HPP
10 changes: 2 additions & 8 deletions src/gfx/pal_packing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@
#include "gfx/main.hpp"
#include "gfx/proto_palette.hpp"

using std::swap;

namespace packing {

// The solvers here are picked from the paper at https://arxiv.org/abs/1605.00558:
// "Algorithms for the Pagination Problem, a Bin Packing with Overlapping Items"
// Their formulation of the problem consists in packing "tiles" into "pages"; here is a
Expand Down Expand Up @@ -114,8 +110,8 @@ class AssignedProtos {
}

friend void swap(Iter &lhs, Iter &rhs) {
swap(lhs._array, rhs._array);
swap(lhs._iter, rhs._iter);
std::swap(lhs._array, rhs._array);
std::swap(lhs._iter, rhs._iter);
}
};
public:
Expand Down Expand Up @@ -537,5 +533,3 @@ std::tuple<DefaultInitVec<size_t>, size_t>
}
return {mappings, assignments.size()};
}

} // namespace packing
10 changes: 3 additions & 7 deletions src/gfx/pal_sorting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@

#include "gfx/main.hpp"

namespace sorting {

void indexed(
void sortIndexed(
std::vector<Palette> &palettes,
int palSize,
png_color const *palRGB,
Expand Down Expand Up @@ -47,7 +45,7 @@ void indexed(
}
}

void grayscale(
void sortGrayscale(
std::vector<Palette> &palettes, std::array<std::optional<Rgba>, 0x8001> const &colors
) {
options.verbosePrint(Options::VERB_LOG_ACT, "Sorting grayscale-only palette...\n");
Expand All @@ -73,7 +71,7 @@ static unsigned int legacyLuminance(uint16_t color) {
return 2126 * red + 7152 * green + 722 * blue;
}

void rgb(std::vector<Palette> &palettes) {
void sortRgb(std::vector<Palette> &palettes) {
options.verbosePrint(Options::VERB_LOG_ACT, "Sorting palettes by \"\"\"luminance\"\"\"...\n");

for (Palette &pal : palettes) {
Expand All @@ -82,5 +80,3 @@ void rgb(std::vector<Palette> &palettes) {
});
}
}

} // namespace sorting
Loading