From eb36baedc7c2008247b06fabca589de2504722e6 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 20 May 2018 10:29:28 +0100 Subject: [PATCH] Merge remote-tracking branch 'origin/development' --- include/etl/binary.h | 70 +++++++++++++++++++++++ src/binary.cpp | 128 +++++++++++++++++++++++++++++++++++++++++++ test/test_binary.cpp | 38 +++++++++++++ 3 files changed, 236 insertions(+) diff --git a/include/etl/binary.h b/include/etl/binary.h index c54bc1fc..c9fa2653 100644 --- a/include/etl/binary.h +++ b/include/etl/binary.h @@ -569,6 +569,76 @@ namespace etl }; #endif + //*************************************************************************** + /// Merges two values according to a mask. + /// Ones in the mask select bits from 'first', zeros select bits from second. + /// Mask is a function parameter. + //*************************************************************************** + template + T binary_merge(const T first, const T second, const T mask) + { + return second ^ ((second ^ first) & mask); + } + + //*************************************************************************** + /// Merges two values according to a mask. + /// Ones in the mask select bits from 'first', zeros select bits from second. + /// Mask is a template parameter. + //*************************************************************************** + template + T binary_merge(const T first, const T second) + { + return second ^ ((second ^ first) & MASK); + } + + //*************************************************************************** + /// Binary interleave + //*************************************************************************** +#if ETL_8BIT_SUPPORT + uint16_t binary_interleave(uint8_t first, uint8_t second); + inline int16_t binary_interleave(int8_t first, int8_t second) { return int16_t(binary_interleave(uint8_t(first), uint8_t(second))); } +#endif + uint32_t binary_interleave(uint16_t first, uint16_t second); + inline int32_t binary_interleave(int16_t first, int16_t second) { return int32_t(binary_interleave(uint16_t(first), uint16_t(second))); } + uint64_t binary_interleave(uint32_t first, uint32_t second); + inline int64_t binary_interleave(int32_t first, int32_t second) { return int64_t(binary_interleave(uint16_t(first), uint16_t(second))); } + + //*************************************************************************** + /// Checks if odd. + //*************************************************************************** + bool is_odd(const unsigned char value); + inline bool is_odd(const char value) { return is_odd((unsigned char)value); } + + bool is_odd(const unsigned short value); + inline bool is_odd(const short value) { return is_odd((unsigned short)value); } + + bool is_odd(const unsigned int value); + inline bool is_odd(const int value) { return is_odd((unsigned int)value); } + + bool is_odd(const unsigned long value); + inline bool is_odd(const long value) { return is_odd((unsigned long)value); } + + bool is_odd(const unsigned long long value); + inline bool is_odd(const long long value) { return is_odd((unsigned long long)value); } + + //*************************************************************************** + /// Checks if even. + //*************************************************************************** + bool is_even(const unsigned char value); + inline bool is_even(const char value) { return is_even((unsigned char)value); } + + bool is_even(const unsigned short value); + inline bool is_even(const short value) { return is_even((unsigned short)value); } + + bool is_even(const unsigned int value); + inline bool is_even(const int value) { return is_even((unsigned int)value); } + + bool is_even(const unsigned long value); + inline bool is_even(const long value) { return is_even((unsigned long)value); } + + bool is_even(const unsigned long long value); + inline bool is_even(const long long value) { return is_even((unsigned long long)value); } + //*************************************************************************** /// 8 bit binary constants. //*************************************************************************** diff --git a/src/binary.cpp b/src/binary.cpp index 52035a5c..7f676070 100644 --- a/src/binary.cpp +++ b/src/binary.cpp @@ -467,4 +467,132 @@ namespace etl return count; } + +#if ETL_8BIT_SUPPORT + //***************************************************************************** + /// Binary interleave + //***************************************************************************** + uint16_t binary_interleave(uint8_t first, uint8_t second) + { + static const uint16_t mask[] = { 0x5555, 0x3333, 0x0F0F }; + + uint16_t f = first; + uint16_t s = second; + + f = (f | (f << 4)) & mask[2]; + f = (f | (f << 2)) & mask[1]; + f = (f | (f << 1)) & mask[0]; + + s = (s | (s << 4)) & mask[2]; + s = (s | (s << 2)) & mask[1]; + s = (s | (s << 1)) & mask[0]; + + return (f | (s << 1)); + } +#endif + + //***************************************************************************** + /// Binary interleave + //***************************************************************************** + uint32_t binary_interleave(uint16_t first, uint16_t second) + { + static const uint32_t mask[] = { 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF }; + + uint32_t f = first; + uint32_t s = second; + + f = (f | (f << 8)) & mask[3]; + f = (f | (f << 4)) & mask[2]; + f = (f | (f << 2)) & mask[1]; + f = (f | (f << 1)) & mask[0]; + + s = (s | (s << 8)) & mask[3]; + s = (s | (s << 4)) & mask[2]; + s = (s | (s << 2)) & mask[1]; + s = (s | (s << 1)) & mask[0]; + + return (f | (s << 1)); + } + + //***************************************************************************** + /// Binary interleave + //***************************************************************************** + uint64_t binary_interleave(uint32_t first, uint32_t second) + { + static const uint64_t mask[] = { 0x5555555555555555, 0x3333333333333333, 0x0F0F0F0F0F0F0F0F, 0x00FF00FF00FF00FF, 0x0000FFFF0000FFFF }; + + uint64_t f = first; + uint64_t s = second; + + f = (f | (f << 16)) & mask[4]; + f = (f | (f << 8)) & mask[3]; + f = (f | (f << 4)) & mask[2]; + f = (f | (f << 2)) & mask[1]; + f = (f | (f << 1)) & mask[0]; + + s = (s | (s << 16)) & mask[4]; + s = (s | (s << 8)) & mask[3]; + s = (s | (s << 4)) & mask[2]; + s = (s | (s << 2)) & mask[1]; + s = (s | (s << 1)) & mask[0]; + + return (f | (s << 1)); + } + + //*************************************************************************** + /// Checks if odd. + //*************************************************************************** + bool is_odd(const unsigned char value) + { + return ((value & 1U) != 0U); + } + + bool is_odd(const unsigned short value) + { + return ((value & 1U) != 0U); + } + + bool is_odd(const unsigned int value) + { + return ((value & 1U) != 0U); + } + + bool is_odd(const unsigned long value) + { + return ((value & 1U) != 0U); + } + + bool is_odd(const unsigned long long value) + { + return ((value & 1U) != 0U); + } + + //*************************************************************************** + /// Checks if even. + //*************************************************************************** + bool is_even(const unsigned char value) + { + return ((value & 1U) == 0U); + } + + bool is_even(const unsigned short value) + { + return ((value & 1U) == 0U); + } + + bool is_even(const unsigned int value) + { + return ((value & 1U) == 0U); + } + + bool is_even(const unsigned long value) + { + return ((value & 1U) == 0U); + } + + bool is_even(const unsigned long long value) + { + return ((value & 1U) == 0U); + } } + diff --git a/test/test_binary.cpp b/test/test_binary.cpp index fc5ecbc4..35cd1c53 100644 --- a/test/test_binary.cpp +++ b/test/test_binary.cpp @@ -1480,6 +1480,44 @@ namespace CHECK(!(etl::has_byte_n<>::test(int64_t(0x0123456789ABCDEF), 0x12))); CHECK((etl::has_byte_n<>::test(int64_t(0x0123456789ABCDEF), 0xAB))); } + + //************************************************************************* + TEST(test_binary_merge) + { + CHECK_EQUAL((etl::binary_merge(uint8_t(0x12), uint8_t(0x34), uint8_t(0xF0))), uint8_t(0x14)); + CHECK_EQUAL((etl::binary_merge(uint8_t(0x12), uint8_t(0x34))), uint8_t(0x14)); + + CHECK_EQUAL((etl::binary_merge(uint16_t(0x1234), uint16_t(0x3456), uint16_t(0xF0F0))), uint16_t(0x1436)); + CHECK_EQUAL((etl::binary_merge(uint16_t(0x1234), uint16_t(0x3456))), uint16_t(0x1436)); + + CHECK_EQUAL((etl::binary_merge(uint32_t(0x12345678), uint32_t(0x3456789A), uint32_t(0xF0F0F0F0))), uint32_t(0x1436587A)); + CHECK_EQUAL((etl::binary_merge(uint32_t(0x12345678), uint32_t(0x3456789A))), uint32_t(0x1436587A)); + + CHECK_EQUAL((etl::binary_merge(uint64_t(0x123456789ABCDEF0), uint64_t(0x3456789ABCDEF012), uint64_t(0xF0F0F0F0F0F0F0F0))), uint64_t(0x1436587A9CBED0F2)); + CHECK_EQUAL((etl::binary_merge(uint64_t(0x123456789ABCDEF0), uint64_t(0x3456789ABCDEF012))), uint64_t(0x1436587A9CBED0F2)); + } + + //************************************************************************* + TEST(test_binary_interleave) + { + CHECK_EQUAL((etl::binary_interleave(uint8_t(0x5A), uint8_t(0xA5))), uint16_t(0x9966)); + CHECK_EQUAL((etl::binary_interleave(uint16_t(0x5A5A), uint16_t(0xA5A5))), uint32_t(0x99669966)); + CHECK_EQUAL((etl::binary_interleave(uint32_t(0x5A5A5A5A), uint32_t(0xA5A5A5A5))), uint64_t(0x9966996699669966)); + } + + //************************************************************************* + TEST(test_is_odd) + { + CHECK(etl::is_odd(1)); + CHECK(!etl::is_odd(2)); + } + + //************************************************************************* + TEST(test_is_even) + { + CHECK(!etl::is_even(1)); + CHECK(etl::is_even(2)); + } }; }