Skip to content

Commit

Permalink
optimal specialization
Browse files Browse the repository at this point in the history
  • Loading branch information
thinkyhead committed Jul 22, 2024
1 parent b3ead0a commit 85a84cc
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 3 deletions.
46 changes: 43 additions & 3 deletions Marlin/src/core/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,53 @@ template <class L, class R> struct IF<true, L, R> { typedef L type; };
#define FI FORCE_INLINE

// Define types based on largest bit width stored value required
#define bits_t(W) typename IF<((W)> 16), uint32_t, typename IF<((W)> 8), uint16_t, uint8_t>::type>::type
#define bits_t(W) typename IF<((W)> 32), uint64_t, typename IF<((W)> 16), uint32_t, typename IF<((W)>8), uint16_t, uint8_t>::type>::type>::type
#define uvalue_t(V) typename IF<((V)>65535), uint32_t, typename IF<((V)>255), uint16_t, uint8_t>::type>::type
#define value_t(V) typename IF<((V)>32767), int32_t, typename IF<((V)>127), int16_t, int8_t>::type>::type

// General Flags for some number of states
// Define a template for a bit field of N bits, using the smallest type that can hold N bits
template<size_t N, bool UseArray = (N > 64)>
struct Flags;

// Flag bits for <= 64 states
template<size_t N>
struct Flags<N, false> {
typedef bits_t(N) flagbits_t;
flagbits_t b;

class BitProxy {
public:
BitProxy(flagbits_t& data, int bit) : data_(data), bit_(bit) {}

BitProxy& operator=(const bool value) {
if (value)
data_ |= _BV(bit_);
else
data_ &= ~_BV(bit_);
return *this;
}

operator bool() const { return TEST(data_, bit_); }

private:
flagbits_t& data_;
uint8_t bit_;
};

FI void reset() { b = 0; }
FI void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); }
FI void set(const int n) { b |= _BV(n); }
FI void clear(const int n) { b &= ~_BV(n); }
FI bool test(const int n) const { return TEST(b, n); }
FI BitProxy operator[](const int n) { return BitProxy(b, n); }
FI bool operator[](const int n) const { return test(n); }
FI int size() const { return sizeof(b); }
FI operator bool() const { return b != 0; }
};

// Flag bits for more than 64 states
template<size_t N>
struct Flags {
struct Flags<N, true> {
uint8_t bitmask[(N+7)>>3];
// Proxy class for handling bit assignment
class BitProxy {
Expand Down
29 changes: 29 additions & 0 deletions Marlin/tests/core/test_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,35 @@ MARLIN_TEST(types, Flags_32) {
TEST_ASSERT_EQUAL(4, flags.size());
}

MARLIN_TEST(types, Flags_64) {
Flags<64> flags;

flags.reset();
TEST_ASSERT_EQUAL(0, flags.b);

flags.set(0, true);
flags.set(63, true);
TEST_ASSERT_EQUAL(9223372036854775809, flags.b);

flags.clear(0);
flags.clear(63);
TEST_ASSERT_EQUAL(0, flags.b);

flags.set(0, true);
flags.set(63, true);
TEST_ASSERT_EQUAL(true, flags.test(0));
TEST_ASSERT_EQUAL(true, flags.test(63));
TEST_ASSERT_EQUAL(false, flags.test(1));
TEST_ASSERT_EQUAL(false, flags.test(62));

TEST_ASSERT_EQUAL(true, flags[0]);
TEST_ASSERT_EQUAL(true, flags[63]);
TEST_ASSERT_EQUAL(false, flags[1]);
TEST_ASSERT_EQUAL(false, flags[62]);

TEST_ASSERT_EQUAL(8, flags.size());
}

MARLIN_TEST(types, AxisFlags_const_as_bools) {
const AxisFlags axis_flags_const_false = {0};
TEST_ASSERT_FALSE(axis_flags_const_false);
Expand Down

0 comments on commit 85a84cc

Please sign in to comment.