[core] Add sign_extend helper (#20933)

This commit is contained in:
J. Nick Koston
2026-10-16 21:17:59 -04:00
committed by GitHub
parent 36ba2f6106
commit 1147b024d6
2 changed files with 21 additions and 0 deletions
+6
View File
@@ -990,6 +990,12 @@ constexpr uint32_t encode_uint32(uint8_t byte1, uint8_t byte2, uint8_t byte3, ui
(static_cast<uint32_t>(byte3) << 8) | (static_cast<uint32_t>(byte4));
}
/// Sign-extend the low \p BITS bits of \p value, e.g. sign_extend<24>(0xFFFFFE) == -2. Higher bits are ignored.
template<unsigned BITS> constexpr int32_t sign_extend(uint32_t value) {
static_assert(BITS > 0 && BITS <= 32, "BITS must be 1 to 32");
return static_cast<int32_t>(value << (32 - BITS)) >> (32 - BITS);
}
/// Encode a value from its constituent bytes (from most to least significant) in an array with length sizeof(T).
template<typename T, enable_if_t<std::is_unsigned<T>::value, int> = 0> constexpr T encode_value(const uint8_t *bytes) {
T val = 0;
+15
View File
@@ -55,6 +55,21 @@ TEST(HelpersTest, Ilog10RoundTripMatchesLog10) {
}
}
TEST(HelpersTest, SignExtend) {
EXPECT_EQ(sign_extend<24>(0x000000), 0);
EXPECT_EQ(sign_extend<24>(0x7FFFFF), 8388607);
EXPECT_EQ(sign_extend<24>(0x800000), -8388608);
EXPECT_EQ(sign_extend<24>(0xFFFFFE), -2);
EXPECT_EQ(sign_extend<24>(0xAB000001), 1); // bits above BITS are ignored
EXPECT_EQ(sign_extend<12>(0x7FF), 2047);
EXPECT_EQ(sign_extend<12>(0x800), -2048);
EXPECT_EQ(sign_extend<16>(0xFF38), -200);
EXPECT_EQ(sign_extend<1>(1), -1);
EXPECT_EQ(sign_extend<32>(0xFFFFFFFF), -1);
EXPECT_EQ(sign_extend<32>(0x7FFFFFFF), INT32_MAX);
static_assert(sign_extend<12>(0xFFF) == -1, "usable in constant expressions");
}
TEST(HelpersTest, SumBytes) {
static constexpr uint8_t FRAME[] = {0x11, 0xDA, 0x27, 0x00, 0xC5, 0x00, 0x10};
EXPECT_EQ(sum_bytes(FRAME, sizeof(FRAME)), 0xE7); // the Daikin comfort frame checksum