diff --git a/bitwise.hpp b/bitwise.hpp index e79be09a..96c98022 100644 --- a/bitwise.hpp +++ b/bitwise.hpp @@ -33,13 +33,24 @@ const uint8_t BITMASK_6BITS = 0x3F; const uint8_t BITMASK_7BITS = 0x7F; const uint8_t BITMASK_8BITS = 0xFF; +#define MODT(x) ((x) % (sizeof (T) * 8)) template -T +constexpr T rotatel (const T &value, size_t magnitude) { - magnitude %= sizeof (T) * 8; - return (value << magnitude) | (value >> sizeof (value) * 8 - magnitude); + return (value << MODT (magnitude)) | + (value >> sizeof (value) * 8 - MODT (magnitude)); } + +template +constexpr T +rotater (const T &value, size_t magnitude) { + return (value >> MODT (magnitude)) | + (value << sizeof (value) * 8 - MODT (magnitude)); +} + +#undef MODT + #endif diff --git a/test/bitwise.cpp b/test/bitwise.cpp index 7085899a..5b9d7627 100644 --- a/test/bitwise.cpp +++ b/test/bitwise.cpp @@ -7,15 +7,28 @@ main (int, char**) { CHECK_EQ (rotatel (uint8_t (0xF0), 4), 0x0F); CHECK_EQ (rotatel (uint8_t (0x0F), 8), 0x0F); + CHECK_EQ (rotater (uint8_t (0x0F), 0), 0x0F); + CHECK_EQ (rotater (uint8_t (0x0F), 4), 0xF0); + CHECK_EQ (rotater (uint8_t (0xF0), 4), 0x0F); + CHECK_EQ (rotater (uint8_t (0x0F), 8), 0x0F); + CHECK_EQ (rotatel (uint16_t (0xABCD), 0), 0xABCD); CHECK_EQ (rotatel (uint16_t (0xABCD), 4), 0xBCDA); CHECK_EQ (rotatel (uint16_t (0xABCD), 8), 0xCDAB); CHECK_EQ (rotatel (uint16_t (0xABCD), 12), 0xDABC); CHECK_EQ (rotatel (uint16_t (0xABCD), 16), 0xABCD); + CHECK_EQ (rotater (uint16_t (0xABCD), 0), 0xABCD); + CHECK_EQ (rotater (uint16_t (0xABCD), 4), 0xDABC); + CHECK_EQ (rotater (uint16_t (0xABCD), 8), 0xCDAB); + CHECK_EQ (rotater (uint16_t (0xABCD), 12), 0xBCDA); + CHECK_EQ (rotater (uint16_t (0xABCD), 16), 0xABCD); + CHECK_EQ (rotatel (uint32_t (0x12345670), 12), 0x45670123); + CHECK_EQ (rotater (uint32_t (0x12345670), 12), 0x67012345); CHECK_EQ (rotatel (uint64_t (0x1234567890ABCDEF), 12), 0x4567890ABCDEF123); + CHECK_EQ (rotater (uint64_t (0x1234567890ABCDEF), 12), 0xDEF1234567890ABC); return 0; }