From 67478d43167c9e03751f63daf7359616566291f1 Mon Sep 17 00:00:00 2001 From: Aaron Rossetto Date: Wed, 19 Jan 2022 13:43:26 -0600 Subject: convert: Make narrowing conversions saturate This commit modifies the explicitly written narrowing conversions to clamp the results to the limits of the signed integer type. --- host/lib/convert/convert_common.hpp | 33 +++++++++++++++++++++------------ host/lib/convert/gen_convert_general.py | 5 +++-- 2 files changed, 24 insertions(+), 14 deletions(-) (limited to 'host') diff --git a/host/lib/convert/convert_common.hpp b/host/lib/convert/convert_common.hpp index 6ee9a651a..112fe3afc 100644 --- a/host/lib/convert/convert_common.hpp +++ b/host/lib/convert/convert_common.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #define _DECLARE_CONVERTER(name, in_form, num_in, out_form, num_out, prio) \ @@ -96,6 +97,14 @@ typedef uint32_t item32_t; typedef item32_t (*xtox_t)(item32_t); +template +const T clamp(const U v) +{ + constexpr T min_t = std::numeric_limits::min(); + constexpr T max_t = std::numeric_limits::max(); + return (v < min_t) ? min_t : (v > max_t) ? max_t : T(v); +} + /*********************************************************************** * Convert xx to items32 sc16 buffer **********************************************************************/ @@ -103,8 +112,8 @@ template UHD_INLINE item32_t xx_to_item32_sc16_x1( const std::complex& num, const double scale_factor) { - uint16_t real = int16_t(num.real() * float(scale_factor)); - uint16_t imag = int16_t(num.imag() * float(scale_factor)); + uint16_t real = clamp(num.real() * float(scale_factor)); + uint16_t imag = clamp(num.imag() * float(scale_factor)); return (item32_t(real) << 16) | (item32_t(imag) << 0); } @@ -132,8 +141,8 @@ template UHD_FORCE_INLINE sc16_t xx_to_sc16_x1( const std::complex& num, const double scale_factor) { - uint16_t real = int16_t(num.real() * T(scale_factor)); - uint16_t imag = int16_t(num.imag() * T(scale_factor)); + uint16_t real = clamp(num.real() * float(scale_factor)); + uint16_t imag = clamp(num.imag() * float(scale_factor)); return sc16_t(real, imag); } @@ -203,10 +212,10 @@ template UHD_INLINE item32_t xx_to_item32_sc8_x1( const std::complex& in0, const std::complex& in1, const double scale_factor) { - uint8_t real1 = int8_t(in0.real() * float(scale_factor)); - uint8_t imag1 = int8_t(in0.imag() * float(scale_factor)); - uint8_t real0 = int8_t(in1.real() * float(scale_factor)); - uint8_t imag0 = int8_t(in1.imag() * float(scale_factor)); + uint8_t real1 = clamp(in0.real() * float(scale_factor)); + uint8_t imag1 = clamp(in0.imag() * float(scale_factor)); + uint8_t real0 = clamp(in1.real() * float(scale_factor)); + uint8_t imag0 = clamp(in1.imag() * float(scale_factor)); return (item32_t(real0) << 8) | (item32_t(imag0) << 0) | (item32_t(real1) << 24) | (item32_t(imag1) << 16); } @@ -215,10 +224,10 @@ template <> UHD_INLINE item32_t xx_to_item32_sc8_x1( const sc16_t& in0, const sc16_t& in1, const double) { - uint8_t real1 = int8_t(in0.real()); - uint8_t imag1 = int8_t(in0.imag()); - uint8_t real0 = int8_t(in1.real()); - uint8_t imag0 = int8_t(in1.imag()); + uint8_t real1 = clamp(in0.real()); + uint8_t imag1 = clamp(in0.imag()); + uint8_t real0 = clamp(in1.real()); + uint8_t imag0 = clamp(in1.imag()); return (item32_t(real0) << 8) | (item32_t(imag0) << 0) | (item32_t(real1) << 24) | (item32_t(imag1) << 16); } diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py index 40ea1c7ba..eb4330119 100644 --- a/host/lib/convert/gen_convert_general.py +++ b/host/lib/convert/gen_convert_general.py @@ -43,8 +43,9 @@ DECLARE_CONVERTER({fctype}, 1, sc16_chdr, 1, PRIORITY_GENERAL) {{ int16_t* output = reinterpret_cast(outputs[0]); for (size_t i = 0; i < nsamps * 2; i += 2) {{ - output[i] = static_cast(input[i] * {fptype}(scale_factor)); - output[i+1] = static_cast(input[i+1] * {fptype}(scale_factor)); + output[i] = clamp(input[i] * {fptype}(scale_factor)); + output[i+1] = clamp(input[i + 1] * {fptype}(scale_factor)); + }} }} -- cgit v1.2.3