From ea9a1e51c9d1cddcbae353b0287f0c80bc780dd7 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 16 Apr 2018 19:17:41 +0100 Subject: [PATCH] More efficient implementations of sign_extend --- include/etl/binary.h | 56 ++++++++++++++------------------------------ 1 file changed, 18 insertions(+), 38 deletions(-) diff --git a/include/etl/binary.h b/include/etl/binary.h index df7f73b9..7a363d1c 100644 --- a/include/etl/binary.h +++ b/include/etl/binary.h @@ -270,16 +270,12 @@ namespace etl STATIC_ASSERT(etl::is_signed::value, "TReturn not a signed type"); STATIC_ASSERT(NBITS <= std::numeric_limits::digits, "NBITS too large for return type"); - const TReturn negative = (TReturn(1) << (NBITS - 1)); - TReturn signed_value = value & ((1 << NBITS) - 1); - - if ((signed_value & negative) != 0) + struct S { - const TReturn sign_bits = ~((TReturn(1) << NBITS) - 1); - signed_value |= sign_bits; - } + signed value : NBITS; + } s; - return signed_value; + return (s.value = value); } //*************************************************************************** @@ -290,22 +286,18 @@ namespace etl template TReturn sign_extend(TValue value) { - STATIC_ASSERT(etl::is_integral::value, "TValue not an integral type"); + STATIC_ASSERT(etl::is_integral::value, "TValue not an integral type"); STATIC_ASSERT(etl::is_integral::value, "TReturn not an integral type"); - STATIC_ASSERT(etl::is_signed::value, "TReturn not a signed type"); + STATIC_ASSERT(etl::is_signed::value, "TReturn not a signed type"); STATIC_ASSERT(NBITS <= std::numeric_limits::digits, "NBITS too large for return type"); STATIC_ASSERT(SHIFT <= std::numeric_limits::digits, "SHIFT too large"); - const TReturn negative = (TReturn(1) << (NBITS - 1)); - TReturn signed_value = (value >> SHIFT) & ((1 << NBITS) - 1); - - if ((signed_value & negative) != 0) + struct S { - const TReturn sign_bits = ~((TReturn(1) << NBITS) - 1); - signed_value |= sign_bits; - } + signed value : NBITS; + } s; - return signed_value; + return (s.value = (value >> SHIFT)); } //*************************************************************************** @@ -320,16 +312,10 @@ namespace etl STATIC_ASSERT(etl::is_signed::value, "TReturn not a signed type"); assert(NBITS <= std::numeric_limits::digits); - const TReturn negative = (TReturn(1) << (NBITS - 1)); - TReturn signed_value = value & ((1 << NBITS) - 1); + TReturn mask = TReturn(1U) << (NBITS - 1); + value = value & ((1U << NBITS) - 1); - if ((signed_value & negative) != 0) - { - const TReturn sign_bits = ~((TReturn(1) << NBITS) - 1); - signed_value |= sign_bits; - } - - return signed_value; + return TReturn((value ^ mask) - mask); } //*************************************************************************** @@ -340,21 +326,15 @@ namespace etl template TReturn sign_extend(TValue value, const size_t NBITS, const size_t SHIFT) { - STATIC_ASSERT(etl::is_integral::value, "TValue not an integral type"); + STATIC_ASSERT(etl::is_integral::value, "TValue not an integral type"); STATIC_ASSERT(etl::is_integral::value, "TReturn not an integral type"); - STATIC_ASSERT(etl::is_signed::value, "TReturn not a signed type"); + STATIC_ASSERT(etl::is_signed::value, "TReturn not a signed type"); assert(NBITS <= std::numeric_limits::digits); - const TReturn negative = (TReturn(1) << (NBITS - 1)); - TReturn signed_value = (value >> SHIFT) & ((1 << NBITS) - 1); + TReturn mask = TReturn(1U) << (NBITS - 1); + value = (value >> SHIFT) & ((1U << NBITS) - 1); - if ((signed_value & negative) != 0) - { - const TReturn sign_bits = ~((TReturn(1) << NBITS) - 1); - signed_value |= sign_bits; - } - - return signed_value; + return TReturn((value ^ mask) - mask); } //***************************************************************************