From 3f018ee1a76f2627cfcdf695690ef071794f01dd Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 8 Aug 2024 22:58:22 +0100 Subject: [PATCH] Fixed floating point etl::unaligned_type --- include/etl/unaligned_type.h | 315 +++++++++++++++++++++++++++-------- support/Release notes.txt | 4 + test/test_unaligned_type.cpp | 201 ++++++++++++++++++++++ 3 files changed, 452 insertions(+), 68 deletions(-) diff --git a/include/etl/unaligned_type.h b/include/etl/unaligned_type.h index 87204d4d6..067d81e1a 100644 --- a/include/etl/unaligned_type.h +++ b/include/etl/unaligned_type.h @@ -40,6 +40,7 @@ SOFTWARE. #include "endianness.h" #include "iterator.h" #include "algorithm.h" +#include "bit.h" #include @@ -367,7 +368,7 @@ namespace etl //************************************************************************* /// Unaligned copy //************************************************************************* - template + template struct unaligned_copy; //******************************************* @@ -375,7 +376,7 @@ namespace etl /// Size == 1 //******************************************* template - struct unaligned_copy + struct unaligned_copy { //******************************* static ETL_CONSTEXPR14 void copy(T value, pointer store) @@ -401,7 +402,7 @@ namespace etl /// Size == 2 //******************************************* template - struct unaligned_copy + struct unaligned_copy::value>::type> { //******************************* static ETL_CONSTEXPR14 void copy(T value, unsigned char* store) @@ -452,9 +453,10 @@ namespace etl //******************************************* /// Unaligned copy /// Size == 4 + /// Integrals //******************************************* template - struct unaligned_copy + struct unaligned_copy::value>::type> { static ETL_CONSTEXPR14 void copy(T value, unsigned char* store) { @@ -513,12 +515,57 @@ namespace etl } }; + //******************************************* + /// Unaligned copy + /// Size == 4 + /// Floating point + //******************************************* + template + struct unaligned_copy::value>::type> + { + static void copy(T value, unsigned char* store) + { + memcpy(store, &value, 4U); + + if (Endian != etl::endianness::value()) + { + etl::reverse(store, store + 4U); + } + } + + //******************************* + static void copy(const_pointer store, T& value) + { + unsigned char temp[4U]; + memcpy(temp, store, 4U); + + if (Endian != etl::endianness::value()) + { + etl::reverse(temp, temp + 4U); + } + + memcpy(&value, temp, 4U); + } + + //******************************* + static ETL_CONSTEXPR14 void copy(const_pointer src, int endian_src, unsigned char* dst) + { + memcpy(dst, src, 4U); + + if (Endian != endian_src) + { + etl::reverse(dst, dst + 4U); + } + } + }; + //******************************************* /// Unaligned copy /// Size == 8 + /// Integrals //******************************************* template - struct unaligned_copy + struct unaligned_copy::value>::type> { static ETL_CONSTEXPR14 void copy(T value, unsigned char* store) { @@ -600,6 +647,138 @@ namespace etl } } }; + + //******************************************* + /// Unaligned copy + /// Size == 8 + /// Floating point + //******************************************* + template + struct unaligned_copy::value>::type> + { + static void copy(T value, unsigned char* store) + { + memcpy(store, &value, 8U); + + if (Endian != etl::endianness::value()) + { + etl::reverse(store, store + 8U); + } + } + + //******************************* + static void copy(const_pointer store, T& value) + { + unsigned char temp[8U]; + memcpy(temp, store, 8U); + + if (Endian != etl::endianness::value()) + { + etl::reverse(temp, temp + 8U); + } + + memcpy(&value, temp, 8U); + } + + //******************************* + static ETL_CONSTEXPR14 void copy(const_pointer src, int endian_src, unsigned char* dst) + { + memcpy(dst, src, 8U); + + if (Endian != endian_src) + { + etl::reverse(dst, dst + 8U); + } + } + }; + + //******************************************* + /// Unaligned copy + /// Size == 12 + /// Floating point + //******************************************* + template + struct unaligned_copy::value>::type> + { + static void copy(T value, unsigned char* store) + { + memcpy(store, &value, 12U); + + if (Endian != etl::endianness::value()) + { + etl::reverse(store, store + 12U); + } + } + + //******************************* + static void copy(const_pointer store, T& value) + { + unsigned char temp[12U]; + memcpy(temp, store, 12U); + + if (Endian != etl::endianness::value()) + { + etl::reverse(temp, temp + 12U); + } + + memcpy(&value, temp, 12U); + } + + //******************************* + static ETL_CONSTEXPR14 void copy(const_pointer src, int endian_src, unsigned char* dst) + { + memcpy(dst, src, 12U); + + if (Endian != endian_src) + { + etl::reverse(dst, dst + 12U); + } + } + }; + + //******************************************* + /// Unaligned copy + /// Size == 16 + /// Floating point + //******************************************* + template + struct unaligned_copy::value>::type> + { + static void copy(T value, unsigned char* store) + { + memcpy(store, &value, 16U); + + if (Endian != etl::endianness::value()) + { + etl::reverse(store, store + 16U); + } + } + + //******************************* + static void copy(const_pointer store, T& value) + { + unsigned char temp[16U]; + memcpy(temp, store, 16U); + + if (Endian != etl::endianness::value()) + { + etl::reverse(temp, temp + 16U); + } + + memcpy(&value, temp, 16U); + } + + //******************************* + static ETL_CONSTEXPR14 void copy(const_pointer src, int endian_src, unsigned char* dst) + { + memcpy(dst, src, 16U); + + if (Endian != endian_src) + { + etl::reverse(dst, dst + 16U); + } + } + }; }; template @@ -610,89 +789,89 @@ namespace etl #if ETL_HAS_CONSTEXPR_ENDIANNESS // Host order - typedef unaligned_type host_char_t; - typedef unaligned_type host_schar_t; - typedef unaligned_type host_uchar_t; - typedef unaligned_type host_short_t; - typedef unaligned_type host_ushort_t; - typedef unaligned_type host_int_t; - typedef unaligned_type host_uint_t; - typedef unaligned_type host_long_t; - typedef unaligned_type host_ulong_t; - typedef unaligned_type host_long_long_t; + typedef unaligned_type host_char_t; + typedef unaligned_type host_schar_t; + typedef unaligned_type host_uchar_t; + typedef unaligned_type host_short_t; + typedef unaligned_type host_ushort_t; + typedef unaligned_type host_int_t; + typedef unaligned_type host_uint_t; + typedef unaligned_type host_long_t; + typedef unaligned_type host_ulong_t; + typedef unaligned_type host_long_long_t; typedef unaligned_type host_ulong_long_t; #if ETL_USING_8BIT_TYPES - typedef unaligned_type host_int8_t; - typedef unaligned_type host_uint8_t; + typedef unaligned_type host_int8_t; + typedef unaligned_type host_uint8_t; #endif - typedef unaligned_type host_int16_t; - typedef unaligned_type host_uint16_t; - typedef unaligned_type host_int32_t; - typedef unaligned_type host_uint32_t; + typedef unaligned_type host_int16_t; + typedef unaligned_type host_uint16_t; + typedef unaligned_type host_int32_t; + typedef unaligned_type host_uint32_t; #if ETL_USING_64BIT_TYPES - typedef unaligned_type host_int64_t; - typedef unaligned_type host_uint64_t; + typedef unaligned_type host_int64_t; + typedef unaligned_type host_uint64_t; #endif - typedef unaligned_type host_float_t; - typedef unaligned_type host_double_t; - typedef unaligned_type host_long_double_t; + typedef unaligned_type host_float_t; + typedef unaligned_type host_double_t; + typedef unaligned_type host_long_double_t; #endif // Little Endian - typedef unaligned_type le_char_t; - typedef unaligned_type le_schar_t; - typedef unaligned_type le_uchar_t; - typedef unaligned_type le_short_t; - typedef unaligned_type le_ushort_t; - typedef unaligned_type le_int_t; - typedef unaligned_type le_uint_t; - typedef unaligned_type le_long_t; - typedef unaligned_type le_ulong_t; - typedef unaligned_type le_long_long_t; + typedef unaligned_type le_char_t; + typedef unaligned_type le_schar_t; + typedef unaligned_type le_uchar_t; + typedef unaligned_type le_short_t; + typedef unaligned_type le_ushort_t; + typedef unaligned_type le_int_t; + typedef unaligned_type le_uint_t; + typedef unaligned_type le_long_t; + typedef unaligned_type le_ulong_t; + typedef unaligned_type le_long_long_t; typedef unaligned_type le_ulong_long_t; #if ETL_USING_8BIT_TYPES - typedef unaligned_type le_int8_t; - typedef unaligned_type le_uint8_t; + typedef unaligned_type le_int8_t; + typedef unaligned_type le_uint8_t; #endif - typedef unaligned_type le_int16_t; - typedef unaligned_type le_uint16_t; - typedef unaligned_type le_int32_t; - typedef unaligned_type le_uint32_t; + typedef unaligned_type le_int16_t; + typedef unaligned_type le_uint16_t; + typedef unaligned_type le_int32_t; + typedef unaligned_type le_uint32_t; #if ETL_USING_64BIT_TYPES - typedef unaligned_type le_int64_t; - typedef unaligned_type le_uint64_t; + typedef unaligned_type le_int64_t; + typedef unaligned_type le_uint64_t; #endif - typedef unaligned_type le_float_t; - typedef unaligned_type le_double_t; - typedef unaligned_type le_long_double_t; + typedef unaligned_type le_float_t; + typedef unaligned_type le_double_t; + typedef unaligned_type le_long_double_t; // Big Endian - typedef unaligned_type be_char_t; - typedef unaligned_type be_schar_t; - typedef unaligned_type be_uchar_t; - typedef unaligned_type be_short_t; - typedef unaligned_type be_ushort_t; - typedef unaligned_type be_int_t; - typedef unaligned_type be_uint_t; - typedef unaligned_type be_long_t; - typedef unaligned_type be_ulong_t; - typedef unaligned_type be_long_long_t; + typedef unaligned_type be_char_t; + typedef unaligned_type be_schar_t; + typedef unaligned_type be_uchar_t; + typedef unaligned_type be_short_t; + typedef unaligned_type be_ushort_t; + typedef unaligned_type be_int_t; + typedef unaligned_type be_uint_t; + typedef unaligned_type be_long_t; + typedef unaligned_type be_ulong_t; + typedef unaligned_type be_long_long_t; typedef unaligned_type be_ulong_long_t; #if ETL_USING_8BIT_TYPES - typedef unaligned_type be_int8_t; - typedef unaligned_type be_uint8_t; + typedef unaligned_type be_int8_t; + typedef unaligned_type be_uint8_t; #endif - typedef unaligned_type be_int16_t; - typedef unaligned_type be_uint16_t; - typedef unaligned_type be_int32_t; - typedef unaligned_type be_uint32_t; + typedef unaligned_type be_int16_t; + typedef unaligned_type be_uint16_t; + typedef unaligned_type be_int32_t; + typedef unaligned_type be_uint32_t; #if ETL_USING_64BIT_TYPES - typedef unaligned_type be_int64_t; - typedef unaligned_type be_uint64_t; + typedef unaligned_type be_int64_t; + typedef unaligned_type be_uint64_t; #endif - typedef unaligned_type be_float_t; - typedef unaligned_type be_double_t; - typedef unaligned_type be_long_double_t; + typedef unaligned_type be_float_t; + typedef unaligned_type be_double_t; + typedef unaligned_type be_long_double_t; // Network Order typedef be_char_t net_char_t; diff --git a/support/Release notes.txt b/support/Release notes.txt index 52bf4b817..021938d50 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,8 +1,12 @@ =============================================================================== 20.39.3 +Updates: Removed C++11 restriction on etl::observer::notification +Fixes: +#917 unaligned_type doesn't compile with floating point types + Pull Requests: #946 Make include paths to private files relative diff --git a/test/test_unaligned_type.cpp b/test/test_unaligned_type.cpp index 3a161a3c1..8e3bc8830 100644 --- a/test/test_unaligned_type.cpp +++ b/test/test_unaligned_type.cpp @@ -101,6 +101,54 @@ namespace CHECK_EQUAL(uint64_t(0xEE23456789ABCDEF), uint64_t(be_v3)); } + //************************************************************************* + TEST(test_copy_construction_float) + { + etl::le_float_t le_v1(3.1415927f); + etl::be_float_t be_v1(3.1415927f); + etl::le_float_t le_v2(le_v1); // Copy construct le from le. + etl::be_float_t be_v2(be_v1); // Copy construct be from be. + etl::le_float_t le_v3(be_v1); // Copy construct le from be. + etl::be_float_t be_v3(le_v1); // Copy construct be from le. + + CHECK_EQUAL(3.1415927f, le_v2); + CHECK_EQUAL(3.1415927f, be_v2); + CHECK_EQUAL(3.1415927f, le_v3); + CHECK_EQUAL(3.1415927f, be_v3); + } + + //************************************************************************* + TEST(test_copy_construction_double) + { + etl::le_double_t le_v1(3.1415927); + etl::be_double_t be_v1(3.1415927); + etl::le_double_t le_v2(le_v1); // Copy construct le from le. + etl::be_double_t be_v2(be_v1); // Copy construct be from be. + etl::le_double_t le_v3(be_v1); // Copy construct le from be. + etl::be_double_t be_v3(le_v1); // Copy construct be from le. + + CHECK_EQUAL(3.1415927, le_v2); + CHECK_EQUAL(3.1415927, be_v2); + CHECK_EQUAL(3.1415927, le_v3); + CHECK_EQUAL(3.1415927, be_v3); + } + + //************************************************************************* + TEST(test_copy_construction_long_double) + { + etl::le_long_double_t le_v1(3.1415927L); + etl::be_long_double_t be_v1(3.1415927L); + etl::le_long_double_t le_v2(le_v1); // Copy construct le from le. + etl::be_long_double_t be_v2(be_v1); // Copy construct be from be. + etl::le_long_double_t le_v3(be_v1); // Copy construct le from be. + etl::be_long_double_t be_v3(le_v1); // Copy construct be from le. + + CHECK_EQUAL(3.1415927L, le_v2); + CHECK_EQUAL(3.1415927L, be_v2); + CHECK_EQUAL(3.1415927L, le_v3); + CHECK_EQUAL(3.1415927L, be_v3); + } + //************************************************************************* TEST(test_endianness) { @@ -279,6 +327,21 @@ namespace CHECK((unsigned long long)(0x0123456789ABCDEFU) == etl::le_ulong_long_t(0x0123456789ABCDEFU)); CHECK(etl::le_ulong_long_t(0x0123456789ABCDEFU) == (unsigned long long)(0x0123456789ABCDEFU)); } + + // float + CHECK(etl::le_float_t(3.1415927f) == etl::le_float_t(3.1415927f)); + CHECK(3.1415927f == etl::le_float_t(3.1415927f)); + CHECK(etl::le_float_t(3.1415927f) == 3.1415927f); + + // double + CHECK(etl::le_double_t(3.1415927) == etl::le_double_t(3.1415927)); + CHECK(3.1415927 == etl::le_double_t(3.1415927)); + CHECK(etl::le_double_t(3.1415927) == 3.1415927); + + // long double + CHECK(etl::le_long_double_t(3.1415927L) == etl::le_long_double_t(3.1415927L)); + CHECK(3.1415927L == etl::le_long_double_t(3.1415927L)); + CHECK(etl::le_long_double_t(3.1415927L) == 3.1415927L); } //************************************************************************* @@ -338,6 +401,21 @@ namespace CHECK((unsigned long long)(0x0123456789ABCDEFU) != etl::le_ulong_long_t(0x0223456789ABCDEFU)); CHECK(etl::le_ulong_long_t(0x0123456789ABCDEFU) != (unsigned long long)(0x0223456789ABCDEFU)); } + + // float + CHECK(etl::le_float_t(3.1415927f) != etl::le_float_t(2.7182818f)); + CHECK(3.1415927f != etl::le_float_t(2.7182818f)); + CHECK(etl::le_float_t(3.1415927f) != 2.7182818f); + + // double + CHECK(etl::le_double_t(3.1415927) != etl::le_double_t(2.7182818)); + CHECK(3.1415927 != etl::le_double_t(2.7182818)); + CHECK(etl::le_double_t(3.1415927) != 2.7182818); + + // long double + CHECK(etl::le_long_double_t(3.1415927L) != etl::le_long_double_t(2.7182818L)); + CHECK(3.1415927L != etl::le_long_double_t(2.7182818L)); + CHECK(etl::le_long_double_t(3.1415927L) != 2.7182818L); } //************************************************************************* @@ -397,6 +475,21 @@ namespace CHECK((unsigned long long)(0x0123456789ABCDEFU) == etl::be_ulong_long_t(0x0123456789ABCDEFU)); CHECK(etl::be_ulong_long_t(0x0123456789ABCDEFU) == (unsigned long long)(0x0123456789ABCDEFU)); } + + // float + CHECK(etl::be_float_t(3.1415927f) == etl::be_float_t(3.1415927f)); + CHECK(3.1415927f == etl::be_float_t(3.1415927f)); + CHECK(etl::be_float_t(3.1415927f) == 3.1415927f); + + // double + CHECK(etl::be_double_t(3.1415927) == etl::be_double_t(3.1415927)); + CHECK(3.1415927 == etl::be_double_t(3.1415927)); + CHECK(etl::be_double_t(3.1415927) == 3.1415927); + + // long double + CHECK(etl::be_long_double_t(3.1415927L) == etl::be_long_double_t(3.1415927L)); + CHECK(3.1415927L == etl::be_long_double_t(3.1415927L)); + CHECK(etl::be_long_double_t(3.1415927L) == 3.1415927L); } //************************************************************************* @@ -456,6 +549,21 @@ namespace CHECK((unsigned long long)(0x0123456789ABCDEFU) != etl::be_ulong_long_t(0x0223456789ABCDEFU)); CHECK(etl::be_ulong_long_t(0x0123456789ABCDEFU) != (unsigned long long)(0x0223456789ABCDEFU)); } + + // float + CHECK(etl::be_float_t(3.1415927f) != etl::be_float_t(2.7182818f)); + CHECK(3.1415927f != etl::be_float_t(2.7182818f)); + CHECK(etl::be_float_t(3.1415927f) != 2.7182818f); + + // double + CHECK(etl::be_double_t(3.1415927) != etl::be_double_t(2.7182818)); + CHECK(3.1415927 != etl::be_double_t(2.7182818)); + CHECK(etl::be_double_t(3.1415927) != 2.7182818); + + // long double + CHECK(etl::be_long_double_t(3.1415927L) != etl::be_long_double_t(2.7182818L)); + CHECK(3.1415927L != etl::be_long_double_t(2.7182818L)); + CHECK(etl::be_long_double_t(3.1415927L) != 2.7182818L); } //************************************************************************* @@ -510,6 +618,21 @@ namespace le_ulong = 0x0123456789ABCDEF; CHECK(0x0123456789ABCDEF == (unsigned long long)le_ulong); } + + // float + etl::le_float_t le_float; + le_float = 3.1415927f; + CHECK(3.1415927f == le_float); + + // double + etl::le_double_t le_double; + le_double = 3.1415927; + CHECK(3.1415927 == le_double); + + // long double + etl::le_long_double_t le_long_double; + le_long_double = 3.1415927L; + CHECK(3.1415927L == le_long_double); } //************************************************************************* @@ -564,6 +687,21 @@ namespace be_ulong = 0x0123456789ABCDEF; CHECK(0x0123456789ABCDEF == (unsigned long long)be_ulong); } + + // float + etl::be_float_t be_float; + be_float = 3.1415927f; + CHECK(3.1415927f == be_float); + + // double + etl::be_double_t be_double; + be_double = 3.1415927; + CHECK(3.1415927 == be_double); + + // long double + etl::be_long_double_t be_long_double; + be_long_double = 3.1415927L; + CHECK(3.1415927L == be_long_double); } //************************************************************************* @@ -587,6 +725,69 @@ namespace CHECK_EQUAL(int(0x01234567), int(be_v3)); } + //************************************************************************* + TEST(test_cross_assignment_float) + { + etl::le_float_t le_v1(3.1415927f); + etl::be_float_t be_v1(3.1415927f); + etl::le_float_t le_v2; + etl::be_float_t be_v2; + etl::le_float_t le_v3; + etl::be_float_t be_v3; + + le_v2 = le_v1; // Assign le from le. + be_v2 = be_v1; // Assign be from be. + le_v3 = be_v1; // Assign le from be. + be_v3 = le_v1; // Assign be from le. + + CHECK_EQUAL(3.1415927f, le_v2); + CHECK_EQUAL(3.1415927f, be_v2); + CHECK_EQUAL(3.1415927f, le_v3); + CHECK_EQUAL(3.1415927f, be_v3); + } + + //************************************************************************* + TEST(test_cross_assignment_double) + { + etl::le_double_t le_v1(3.1415927); + etl::be_double_t be_v1(3.1415927); + etl::le_double_t le_v2; + etl::be_double_t be_v2; + etl::le_double_t le_v3; + etl::be_double_t be_v3; + + le_v2 = le_v1; // Assign le from le. + be_v2 = be_v1; // Assign be from be. + le_v3 = be_v1; // Assign le from be. + be_v3 = le_v1; // Assign be from le. + + CHECK_EQUAL(3.1415927, le_v2); + CHECK_EQUAL(3.1415927, be_v2); + CHECK_EQUAL(3.1415927, le_v3); + CHECK_EQUAL(3.1415927, be_v3); + } + + //************************************************************************* + TEST(test_cross_assignment_long_double) + { + etl::le_long_double_t le_v1(3.1415927L); + etl::be_long_double_t be_v1(3.1415927L); + etl::le_long_double_t le_v2; + etl::be_long_double_t be_v2; + etl::le_long_double_t le_v3; + etl::be_long_double_t be_v3; + + le_v2 = le_v1; // Assign le from le. + be_v2 = be_v1; // Assign be from be. + le_v3 = be_v1; // Assign le from be. + be_v3 = le_v1; // Assign be from le. + + CHECK_EQUAL(3.1415927L, le_v2); + CHECK_EQUAL(3.1415927L, be_v2); + CHECK_EQUAL(3.1415927L, le_v3); + CHECK_EQUAL(3.1415927L, be_v3); + } + //************************************************************************* TEST(test_data) {