diff --git a/include/etl/absolute.h b/include/etl/absolute.h index d473b3ec..9dc7b347 100644 --- a/include/etl/absolute.h +++ b/include/etl/absolute.h @@ -32,6 +32,7 @@ SOFTWARE. #define ETL_ABSOLUTE_INCLUDED #include "type_traits.h" +#include "integral_limits.h" namespace etl { @@ -54,6 +55,29 @@ namespace etl { return value; } + + //*************************************************************************** + // For signed types. + // Returns the result as the unsigned type. + //*************************************************************************** + template ::type> + ETL_CONSTEXPR typename etl::enable_if::value, TReturn>::type + absolute_unsigned(T value) + { + return (value == etl::integral_limits::min) ? etl::integral_limits::max / 2U + : (value < T(0)) ? TReturn(-value) : TReturn(value); + } + + //*************************************************************************** + // For unsigned types. + // Returns the result as the unsigned type. + //*************************************************************************** + template + ETL_CONSTEXPR typename etl::enable_if::value, T>::type + absolute_unsigned(T value) + { + return etl::absolute(value); + } } #endif diff --git a/include/etl/binary.h b/include/etl/binary.h index 91058967..51860943 100644 --- a/include/etl/binary.h +++ b/include/etl/binary.h @@ -120,7 +120,7 @@ namespace etl #else ETL_STATIC_ASSERT(etl::is_integral::value, "Not an integral type"); - const size_t SHIFT = etl::integral_limits::type>::bits - 1; + ETL_CONSTANT size_t SHIFT = etl::integral_limits::type>::bits - 1U; return (value << 1U) | (value >> SHIFT); #endif @@ -138,11 +138,18 @@ namespace etl #else ETL_STATIC_ASSERT(etl::is_integral::value, "Not an integral type"); - const size_t BITS = etl::integral_limits::type>::bits; + ETL_CONSTANT size_t BITS = etl::integral_limits::type>::bits; distance %= BITS; const size_t SHIFT = BITS - distance; - return (value << distance) | (value >> SHIFT); + if (SHIFT == BITS) + { + return value; + } + else + { + return (value << distance) | (value >> SHIFT); + } #endif } @@ -158,7 +165,7 @@ namespace etl #else ETL_STATIC_ASSERT(etl::is_integral::value, "Not an integral type"); - const size_t SHIFT = etl::integral_limits::type>::bits - 1; + ETL_CONSTANT size_t SHIFT = etl::integral_limits::type>::bits - 1U; return (value >> 1U) | (value << SHIFT); #endif @@ -176,11 +183,18 @@ namespace etl #else ETL_STATIC_ASSERT(etl::is_integral::value, "Not an integral type"); - const size_t BITS = etl::integral_limits::type>::bits; + ETL_CONSTANT size_t BITS = etl::integral_limits::type>::bits; distance %= BITS; const size_t SHIFT = BITS - distance; - return (value >> distance) | (value << SHIFT); + if (SHIFT == BITS) + { + return value; + } + else + { + return (value >> distance) | (value << SHIFT); + } #endif } @@ -224,13 +238,13 @@ namespace etl /// Fold a binary number down to a set number of bits using XOR. ///\ingroup binary //*************************************************************************** - template + template ETL_CONSTEXPR14 TReturn fold_bits(TValue value) { ETL_STATIC_ASSERT(integral_limits::bits >= NBITS, "Return type too small to hold result"); - const TValue mask = etl::power<2, NBITS>::value - 1U; - const size_t shift = NBITS; + ETL_CONSTANT TValue mask = etl::power<2, NBITS>::value - 1U; + ETL_CONSTANT size_t shift = NBITS; // Fold the value down to fit the width. TReturn folded_value = 0; @@ -253,7 +267,7 @@ namespace etl /// Converts an N bit binary number, where bit N-1 is the sign bit, to a signed integral type. ///\ingroup binary //*************************************************************************** - template + template ETL_CONSTEXPR14 TReturn sign_extend(TValue value) { ETL_STATIC_ASSERT(etl::is_integral::value, "TValue not an integral type"); @@ -274,7 +288,7 @@ namespace etl /// is the right shift amount, to a signed integral type. ///\ingroup binary //*************************************************************************** - template + template ETL_CONSTEXPR14 TReturn sign_extend(TValue value) { ETL_STATIC_ASSERT(etl::is_integral::value, "TValue not an integral type"); @@ -296,7 +310,7 @@ namespace etl ///\ingroup binary //*************************************************************************** template - ETL_CONSTEXPR14 TReturn sign_extend(TValue value, const size_t NBITS) + ETL_CONSTEXPR14 TReturn sign_extend(TValue value, size_t NBITS) { ETL_STATIC_ASSERT(etl::is_integral::value, "TValue not an integral type"); ETL_STATIC_ASSERT(etl::is_integral::value, "TReturn not an integral type"); @@ -316,7 +330,7 @@ namespace etl ///\ingroup binary //*************************************************************************** template - ETL_CONSTEXPR14 TReturn sign_extend(TValue value, const size_t NBITS, const size_t SHIFT) + ETL_CONSTEXPR14 TReturn sign_extend(TValue value, size_t NBITS, size_t SHIFT) { ETL_STATIC_ASSERT(etl::is_integral::value, "TValue not an integral type"); ETL_STATIC_ASSERT(etl::is_integral::value, "TReturn not an integral type"); @@ -398,7 +412,7 @@ namespace etl ETL_STATIC_ASSERT(sizeof(TResult) >= sizeof(TValue), "Result must be at least as large as the fill value"); typedef typename etl::make_unsigned::type unsigned_r_t; - typedef typename etl::make_unsigned::type unsigned_v_t; + typedef typename etl::make_unsigned::type unsigned_v_t; return TResult(unsigned_v_t(value) * (unsigned_r_t(~unsigned_r_t(0U)) / unsigned_v_t(~unsigned_v_t(0U)))); } @@ -407,13 +421,13 @@ namespace etl /// Fills a value with a bit pattern. Partial compile time. ///\ingroup binary //*************************************************************************** - template + template ETL_CONSTEXPR TResult binary_fill() { ETL_STATIC_ASSERT(sizeof(TResult) >= sizeof(TValue), "Result must be at least as large as the fill value"); typedef typename etl::make_unsigned::type unsigned_r_t; - typedef typename etl::make_unsigned::type unsigned_v_t; + typedef typename etl::make_unsigned::type unsigned_v_t; return TResult(unsigned_v_t(N) * (unsigned_r_t(~unsigned_r_t(0U)) / unsigned_v_t(~unsigned_v_t(0U)))); } @@ -424,7 +438,7 @@ namespace etl ///\ingroup binary //*************************************************************************** template - ETL_CONSTEXPR14 bool has_zero_byte(const TValue value) + ETL_CONSTEXPR14 bool has_zero_byte(TValue value) { typedef typename etl::make_unsigned::type unsigned_t; const unsigned_t mask = etl::binary_fill(0x7FU); @@ -437,7 +451,7 @@ namespace etl /// Detects the presence of zero bytes. Partial compile time. ///\ingroup binary //*************************************************************************** - template + template ETL_CONSTEXPR14 bool has_zero_byte() { typedef typename etl::make_unsigned::type unsigned_t; @@ -461,7 +475,7 @@ namespace etl /// Detects the presence of a byte of value N. Partial compile time. ///\ingroup binary //*************************************************************************** - template + template ETL_CONSTEXPR14 bool has_byte_n(TValue value) { return etl::has_zero_byte(TValue(value ^ etl::binary_fill(N))); @@ -475,7 +489,7 @@ namespace etl ///\ingroup binary //*************************************************************************** template - ETL_CONSTEXPR T binary_merge(const T first, const T second, const T mask) + ETL_CONSTEXPR T binary_merge(T first, T second, T mask) { return second ^ ((second ^ first) & mask); } @@ -486,8 +500,8 @@ namespace etl /// Mask is a template parameter. ///\ingroup binary //*************************************************************************** - template - ETL_CONSTEXPR T binary_merge(const T first, const T second) + template + ETL_CONSTEXPR T binary_merge(T first, T second) { return second ^ ((second ^ first) & MASK); } @@ -2151,7 +2165,7 @@ namespace etl //*************************************************************************** template ETL_CONSTEXPR typename etl::enable_if::value, bool>::type - is_odd(const T value) + is_odd(T value) { return ((static_cast::type>(value) & 1U) != 0U); } @@ -2162,7 +2176,7 @@ namespace etl //*************************************************************************** template ETL_CONSTEXPR typename etl::enable_if::value, bool>::type - is_even(const T value) + is_even(T value) { return ((static_cast::type>(value) & 1U) == 0U); } diff --git a/include/etl/bit_stream.h b/include/etl/bit_stream.h index f820314b..2894d1cf 100644 --- a/include/etl/bit_stream.h +++ b/include/etl/bit_stream.h @@ -231,10 +231,12 @@ namespace etl while (width != 0) { unsigned char mask_width = static_cast(etl::min(width, bits_in_byte)); - unsigned char chunk = get_chunk(mask_width); + + typedef typename etl::make_unsigned::type chunk_t; + chunk_t chunk = get_chunk(mask_width); width -= mask_width; - value |= static_cast(chunk) << width; + value |= static_cast(chunk << width); } success = true; diff --git a/include/etl/bitset.h b/include/etl/bitset.h index 7da2c4bb..dac84ac9 100644 --- a/include/etl/bitset.h +++ b/include/etl/bitset.h @@ -447,12 +447,12 @@ namespace etl if (OK) { - T shift = T(0); + uint_least8_t shift = 0U; for (size_t i = 0UL; i < SIZE; ++i) { - v |= T(pdata[i]) << shift; - shift += T(BITS_PER_ELEMENT); + v |= T(typename etl::make_unsigned::type(pdata[i]) << shift); + shift += uint_least8_t(BITS_PER_ELEMENT); } } diff --git a/include/etl/nullptr.h b/include/etl/nullptr.h index 0820c6f8..4c1b5c8a 100644 --- a/include/etl/nullptr.h +++ b/include/etl/nullptr.h @@ -35,7 +35,7 @@ SOFTWARE. #include -#if ETL_CPP11_NOT_SUPPORTED || ETL_NOT_USING_STL +#if ETL_CPP11_NOT_SUPPORTED // Use the old style C++ NULL definition. #define ETL_NULLPTR 0 #else diff --git a/include/etl/private/to_string_helper.h b/include/etl/private/to_string_helper.h index 0d7ef7a6..8137b226 100644 --- a/include/etl/private/to_string_helper.h +++ b/include/etl/private/to_string_helper.h @@ -385,7 +385,8 @@ namespace etl denominator *= 10U; } - working_t abs_value = etl::absolute(value); + // Get the absolute value, taking care of minimum negative values. + working_t abs_value = etl::absolute_unsigned(value); // Figure out how many decimal digits we have in the value. const uint32_t& original_decimal_digits = denominator_exponent; diff --git a/test/data.h b/test/data.h index 503476c6..99fd7807 100644 --- a/test/data.h +++ b/test/data.h @@ -189,15 +189,15 @@ public: } TestDataM(TestDataM&& other) noexcept - : value(other.value) + : value(std::move(other.value);) , valid(true) { - other.value = std::move(T()); other.valid = false; } virtual ~TestDataM() { + valid = false; } TestDataM& operator =(TestDataM&& other) noexcept @@ -205,7 +205,6 @@ public: value = std::move(other.value); valid = true; - other.value = T(); other.valid = false; return *this;