kfr

Fast, modern C++ DSP framework, FFT, Sample Rate Conversion, FIR/IIR/Biquad Filters (SSE, AVX, AVX-512, ARM NEON)
Log | Files | Refs | README

commit 49ee6ce02cc9a457293cfebd99ee3852b9adef86
parent 279015634881c47020a484c09b5221cdf1a61993
Author: d.levin256@gmail.com <d.levin256@gmail.com>
Date:   Sun, 21 Oct 2018 19:31:06 +0300

safe_cast, small fixes

Diffstat:
Minclude/kfr/base/types.hpp | 2+-
Minclude/kfr/dsp/weighting.hpp | 6+++---
Minclude/kfr/dsp/window.hpp | 21+++++++++++----------
Minclude/kfr/testo/assert.hpp | 36+++++++++++++++++++++++++++++++++++-
4 files changed, 50 insertions(+), 15 deletions(-)

diff --git a/include/kfr/base/types.hpp b/include/kfr/base/types.hpp @@ -184,7 +184,7 @@ inline datatype operator|(datatype x, datatype y) inline datatype operator&(datatype x, datatype y) { using type = underlying_type<datatype>; - return static_cast<datatype>(static_cast<type>(x) | static_cast<type>(y)); + return static_cast<datatype>(static_cast<type>(x) & static_cast<type>(y)); } template <typename T> diff --git a/include/kfr/dsp/weighting.hpp b/include/kfr/dsp/weighting.hpp @@ -43,7 +43,7 @@ KFR_SINTRIN T weight_a_unnorm(T f) } template <typename T> -constexpr static T weight_a_gain = reciprocal(weight_a_unnorm(T(1000.0))); +const static T weight_a_gain = reciprocal(weight_a_unnorm(T(1000.0))); template <typename T> KFR_SINTRIN T aweighting(T f) @@ -62,7 +62,7 @@ KFR_SINTRIN T weight_b_unnorm(T f) } template <typename T> -constexpr static T weight_b_gain = reciprocal(weight_b_unnorm(T(1000.0))); +const static T weight_b_gain = reciprocal(weight_b_unnorm(T(1000.0))); template <typename T> KFR_SINTRIN T bweighting(T f) @@ -81,7 +81,7 @@ KFR_SINTRIN T weight_c_unnorm(T f) } template <typename T> -constexpr static T weight_c_gain = reciprocal(weight_c_unnorm(T(1000.0))); +const static T weight_c_gain = reciprocal(weight_c_unnorm(T(1000.0))); template <typename T> KFR_SINTRIN T cweighting(T f) diff --git a/include/kfr/dsp/window.hpp b/include/kfr/dsp/window.hpp @@ -127,7 +127,7 @@ struct expression_rectangular : input_expression template <size_t N> CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const { - using TI = utype<T>; + using TI = utype<T>; const vec<TI, N> i = enumerate(vec<TI, N>()) + cast<TI>(index); return select(i < cast<TI>(m_size), T(1), T(0)); } @@ -369,11 +369,11 @@ struct expression_flattop : input_expression CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { const vec<T, N> n = linspace(cinput, index, y) * c_pi<T, 2>; - constexpr T a0 = 1; - constexpr T a1 = 1.93; - constexpr T a2 = 1.29; - constexpr T a3 = 0.388; - constexpr T a4 = 0.028; + constexpr T a0 = 1; + constexpr T a1 = 1.93; + constexpr T a2 = 1.29; + constexpr T a3 = 0.388; + constexpr T a4 = 0.028; return a0 - a1 * cos(n) + a2 * cos(2 * n) - a3 * cos(3 * n) + a4 * cos(4 * n); } size_t size() const { return m_size; } @@ -399,6 +399,7 @@ struct expression_gaussian : input_expression } size_t size() const { return m_size; } + private: window_linspace_m1_1_trunc<T> linspace; T alpha; @@ -452,7 +453,7 @@ KFR_WINDOW_BY_TYPE(flattop) KFR_WINDOW_BY_TYPE(gaussian) KFR_WINDOW_BY_TYPE(lanczos) #undef KFR_WINDOW_BY_TYPE -} +} // namespace internal /** * @brief Returns template expression that generates Rrectangular window of length @c size @@ -609,11 +610,11 @@ CMT_NOINLINE expression_pointer<T> window(size_t size, window_type type, identit window_type::bohman, window_type::blackman, window_type::blackman_harris, window_type::kaiser, window_type::flattop, window_type::gaussian, window_type::lanczos>(), type, - [=](auto win) { + [size, win_param, symmetry](auto win) { constexpr window_type window = val_of(decltype(win)()); - return to_pointer<T>( + return to_pointer( typename internal::window_by_type<window>::template type<T>(size, win_param, symmetry)); }, fn::returns<expression_pointer<T>>()); } -} +} // namespace kfr diff --git a/include/kfr/testo/assert.hpp b/include/kfr/testo/assert.hpp @@ -21,8 +21,11 @@ inline void assertion_failed(const std::string& string, const char* file, int li errorln("Assertion failed at ", file, ":", line); errorln(string); errorln(); + std::fflush(stderr); } +bool check_assertion(...); + template <typename Op, typename L, typename R> bool check_assertion(const comparison<Op, L, R>& comparison, const char* expr, const char* file, int line) { @@ -44,7 +47,7 @@ bool check_assertion(const half_comparison<L>& comparison, const char* expr, con { assertion_failed(as_string(padleft(22, expr), " | ", comparison.left), file, line); } - return false; + return result; } #if defined(TESTO_ASSERTION_ON) || !(defined(NDEBUG) || defined(TESTO_ASSERTION_OFF)) @@ -67,4 +70,35 @@ bool check_assertion(const half_comparison<L>& comparison, const char* expr, con #ifndef TESTO_NO_SHORT_MACROS #define ASSERT TESTO_ASSERT #endif + +template <typename OutType, typename InType> +inline OutType safe_cast(const InType& val) +{ + static_assert(std::is_integral<InType>::value && std::is_integral<OutType>::value, + "safe_cast is for numeric types only"); + if (std::is_signed<InType>::value && std::is_signed<OutType>::value) // S->S + { + ASSERT(val >= std::numeric_limits<OutType>::min()); + ASSERT(val <= std::numeric_limits<OutType>::max()); + } + else if (!std::is_signed<InType>::value && !std::is_signed<OutType>::value) // U->U + { + ASSERT(val <= std::numeric_limits<OutType>::max()); + } + else if (std::is_signed<InType>::value && !std::is_signed<OutType>::value) // S->U + { + ASSERT(val >= 0); + ASSERT(val <= std::numeric_limits<OutType>::max()); + // val will be converted to an unsigned number for the above comparison. + // it's safe because we've already checked that it is positive + } + else // U->S + { + ASSERT(val <= std::numeric_limits<OutType>::max()); + // std::numeric_limits<OutType>::max() will be converted to an unsigned number for the above + // comparison. it's also safe here + } + return static_cast<OutType>(val); } + +} // namespace testo