summaryrefslogtreecommitdiff
path: root/gr-blocks/lib/peak_detector_impl.cc
diff options
context:
space:
mode:
authorThomas Habets <thomas@habets.se>2020-05-18 22:02:30 +0100
committerMartin Braun <martin@gnuradio.org>2020-05-21 10:46:58 -0700
commitde5c0123e81329e1a8f6611edeac14062114af0c (patch)
tree80d7e6891675ac0d398e3e0453645023882af00b /gr-blocks/lib/peak_detector_impl.cc
parent4aa2ff61959a0005f50d9f591a76e69c2d3cbc34 (diff)
gr-blocks/peak_detector: Remove UB on infinities
This code fixes two issues: 1. The code used `::min()` in one place, and "minus infinity" in another, for the same purpose. 2. It used minus infinity on integer types, which is undefined behavior. (1) seems to have been accidentally left out of 9d9ea63c45b5f314eb344a69340ef49e8edafdfa. (2) Section 4.9: > The behavior is undefined if the truncated value cannot be > represented in the destination type. And trunc() on infinity is still infinity, which can't be represented in integer types.
Diffstat (limited to 'gr-blocks/lib/peak_detector_impl.cc')
-rw-r--r--gr-blocks/lib/peak_detector_impl.cc27
1 files changed, 25 insertions, 2 deletions
diff --git a/gr-blocks/lib/peak_detector_impl.cc b/gr-blocks/lib/peak_detector_impl.cc
index c10a977b1a..1967e4416e 100644
--- a/gr-blocks/lib/peak_detector_impl.cc
+++ b/gr-blocks/lib/peak_detector_impl.cc
@@ -15,11 +15,34 @@
#include "peak_detector_impl.h"
#include <gnuradio/io_signature.h>
#include <string.h>
+#include <type_traits>
#include <limits>
namespace gr {
namespace blocks {
+namespace {
+
+// lowest_value() returns -infinity if the type has a concept of
+// infinity. Otherwise it returns the lowest possible value.
+//
+// Positive infinity is guaranteed by std::numeric_limits<T>::has_infinity, but
+// since we want negative infinity let's use IEEE754.
+template <typename T,
+ typename std::enable_if<std::numeric_limits<T>::is_iec559, int>::type = 0>
+constexpr T lowest_value() noexcept
+{
+ return -std::numeric_limits<T>::infinity();
+}
+
+template <typename T,
+ typename std::enable_if<!std::numeric_limits<T>::is_iec559, int>::type = 0>
+constexpr T lowest_value() noexcept
+{
+ return std::numeric_limits<T>::lowest();
+}
+} // namespace
+
template <class T>
typename peak_detector<T>::sptr peak_detector<T>::make(float threshold_factor_rise,
float threshold_factor_fall,
@@ -61,7 +84,7 @@ int peak_detector_impl<T>::work(int noutput_items,
memset(optr, 0, noutput_items * sizeof(char));
- T peak_val = std::numeric_limits<T>::min();
+ T peak_val = lowest_value<T>();
int peak_ind = 0;
unsigned char state = 0;
int i = 0;
@@ -89,7 +112,7 @@ int peak_detector_impl<T>::work(int noutput_items,
} else {
optr[peak_ind] = 1;
state = 0;
- peak_val = -(T)INFINITY;
+ peak_val = lowest_value<T>();
// printf("Leaving State 1: Peak: %f Peak Ind: %d i: %d noutput_items:
// %d\n", peak_val, peak_ind, i, noutput_items);
}