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 c6cf5bbf7d16472dace59b0cddaffd88964ed33f
parent 51111bd019c87aade9a268a0a3ef4975c737c875
Author: [email protected] <[email protected]>
Date:   Thu, 10 Nov 2022 16:10:37 +0000

Fixes for older compilers: counter and memory_finalizer

Diffstat:
Minclude/kfr/base/basic_expressions.hpp | 10++++++++--
Minclude/kfr/base/simd_expressions.hpp | 20++++++++++----------
Minclude/kfr/base/tensor.hpp | 40+++++++++++++++++++++++++++-------------
Mtests/unit/base/tensor.cpp | 11+++++++++++
4 files changed, 56 insertions(+), 25 deletions(-)

diff --git a/include/kfr/base/basic_expressions.hpp b/include/kfr/base/basic_expressions.hpp @@ -102,8 +102,14 @@ struct expression_traits<expression_counter<T, Dims>> : expression_traits_defaul template <typename T = int, typename Arg = T, typename... Args, typename Tout = std::common_type_t<T, Arg, Args...>> -KFR_INTRINSIC expression_counter<Tout, 1 + sizeof...(Args)> counter(T start = T(0), Arg step = 1, - Args... steps) +KFR_INTRINSIC expression_counter<Tout, 1> counter(T start = 0) +{ + return { static_cast<Tout>(std::move(start)), { static_cast<Tout>(1) } }; +} + +template <typename T = int, typename Arg = T, typename... Args, + typename Tout = std::common_type_t<T, Arg, Args...>> +KFR_INTRINSIC expression_counter<Tout, 1 + sizeof...(Args)> counter(T start, Arg step, Args... steps) { return { static_cast<Tout>(std::move(start)), { static_cast<Tout>(std::move(step)), static_cast<Tout>(std::move(steps))... } }; diff --git a/include/kfr/base/simd_expressions.hpp b/include/kfr/base/simd_expressions.hpp @@ -425,70 +425,70 @@ KFR_INTRINSIC expression_function<fn::satsub, E1, E2> satsub(E1&& x, E2&& y) template <typename E1, typename E2, enable_if_input_output_expression<E1>* = nullptr, enable_if_input_expression<E2>* = nullptr> -KFR_INTRINSIC E1& operator+=(E1& e1, E2&& e2) +KFR_INTRINSIC E1& operator+=(E1&& e1, E2&& e2) { process(e1, operator+(e1, e2)); return e1; } template <typename E1, typename E2, enable_if_input_output_expression<E1>* = nullptr, enable_if_input_expression<E2>* = nullptr> -KFR_INTRINSIC E1& operator-=(E1& e1, E2&& e2) +KFR_INTRINSIC E1& operator-=(E1&& e1, E2&& e2) { process(e1, operator-(e1, e2)); return e1; } template <typename E1, typename E2, enable_if_input_output_expression<E1>* = nullptr, enable_if_input_expression<E2>* = nullptr> -KFR_INTRINSIC E1& operator*=(E1& e1, E2&& e2) +KFR_INTRINSIC E1& operator*=(E1&& e1, E2&& e2) { process(e1, operator*(e1, e2)); return e1; } template <typename E1, typename E2, enable_if_input_output_expression<E1>* = nullptr, enable_if_input_expression<E2>* = nullptr> -KFR_INTRINSIC E1& operator/=(E1& e1, E2&& e2) +KFR_INTRINSIC E1& operator/=(E1&& e1, E2&& e2) { process(e1, operator/(e1, e2)); return e1; } template <typename E1, typename E2, enable_if_input_output_expression<E1>* = nullptr, enable_if_input_expression<E2>* = nullptr> -KFR_INTRINSIC E1& operator%=(E1& e1, E2&& e2) +KFR_INTRINSIC E1& operator%=(E1&& e1, E2&& e2) { process(e1, operator%(e1, e2)); return e1; } template <typename E1, typename E2, enable_if_input_output_expression<E1>* = nullptr, enable_if_input_expression<E2>* = nullptr> -KFR_INTRINSIC E1& operator|=(E1& e1, E2&& e2) +KFR_INTRINSIC E1& operator|=(E1&& e1, E2&& e2) { process(e1, operator|(e1, e2)); return e1; } template <typename E1, typename E2, enable_if_input_output_expression<E1>* = nullptr, enable_if_input_expression<E2>* = nullptr> -KFR_INTRINSIC E1& operator&=(E1& e1, E2&& e2) +KFR_INTRINSIC E1& operator&=(E1&& e1, E2&& e2) { process(e1, operator&(e1, e2)); return e1; } template <typename E1, typename E2, enable_if_input_output_expression<E1>* = nullptr, enable_if_input_expression<E2>* = nullptr> -KFR_INTRINSIC E1& operator^=(E1& e1, E2&& e2) +KFR_INTRINSIC E1& operator^=(E1&& e1, E2&& e2) { process(e1, operator^(e1, e2)); return e1; } template <typename E1, typename E2, enable_if_input_output_expression<E1>* = nullptr, enable_if_input_expression<E2>* = nullptr> -KFR_INTRINSIC E1& operator<<=(E1& e1, E2&& e2) +KFR_INTRINSIC E1& operator<<=(E1&& e1, E2&& e2) { process(e1, operator<<(e1, e2)); return e1; } template <typename E1, typename E2, enable_if_input_output_expression<E1>* = nullptr, enable_if_input_expression<E2>* = nullptr> -KFR_INTRINSIC E1& operator>>=(E1& e1, E2&& e2) +KFR_INTRINSIC E1& operator>>=(E1&& e1, E2&& e2) { process(e1, operator>>(e1, e2)); return e1; diff --git a/include/kfr/base/tensor.hpp b/include/kfr/base/tensor.hpp @@ -45,12 +45,32 @@ CMT_PRAGMA_MSVC(warning(disable : 4324)) namespace kfr { -using memory_finalizer = std::shared_ptr<void>; +namespace internal_generic +{ +struct memory_finalizer_base +{ + virtual ~memory_finalizer_base() {} +}; +template <typename Data> +struct memory_finalizer_data : public memory_finalizer_base +{ + constexpr KFR_INTRINSIC memory_finalizer_data(Data&& data) : data(std::move(data)) {} + Data data; +}; +template <typename Func> +struct memory_finalizer_func : public memory_finalizer_data<Func> +{ + using memory_finalizer_data<Func>::memory_finalizer_data; + KFR_INTRINSIC ~memory_finalizer_func() { this->data(); } +}; +} // namespace internal_generic + +using memory_finalizer = std::shared_ptr<internal_generic::memory_finalizer_base>; template <typename Fn> memory_finalizer KFR_INTRINSIC make_memory_finalizer(Fn&& fn) { - return std::shared_ptr<void>(nullptr, [fn = std::move(fn)](void*) { fn(); }); + return memory_finalizer(new internal_generic::memory_finalizer_func<Fn>{ std::move(fn) }); } template <typename T, typename Derived, typename Dims> @@ -842,20 +862,14 @@ private: template <typename Container, CMT_ENABLE_IF(kfr::has_data_size<Container>), typename T = typename Container::value_type> -KFR_INTRINSIC tensor<T, 1> tensor_from_container(Container vector) +KFR_INTRINSIC tensor<T, 1> tensor_from_container(Container container) { - struct vector_finalizer - { - mutable std::optional<Container> vector; - void operator()(void*) const { vector.reset(); } - }; - - vector_finalizer finalizer{ std::move(vector) }; + using container_finalizer = internal_generic::memory_finalizer_data<Container>; + memory_finalizer mem = memory_finalizer(new container_finalizer{ std::move(container) }); - memory_finalizer mem = std::shared_ptr<void>(nullptr, std::move(finalizer)); - vector_finalizer* fin = std::get_deleter<vector_finalizer>(mem); + Container* ptr = &static_cast<container_finalizer*>(mem.get())->data; - return tensor<T, 1>(fin->vector->data(), make_vector<index_t>(fin->vector->size()), std::move(mem)); + return tensor<T, 1>(ptr->data(), shape{ ptr->size() }, std::move(mem)); } template <typename T, index_t Dims> diff --git a/tests/unit/base/tensor.cpp b/tests/unit/base/tensor.cpp @@ -785,6 +785,17 @@ TEST(from_ilist) CHECK(t4 == tensor<float, 3>(shape{ 2, 2, 2 }, { 10, 20, 30, 40, 50, 60, 70, 80 })); } +TEST(tensor_from_container) +{ + std::vector<int> a{ 1, 2, 3 }; + auto t = tensor_from_container(a); + CHECK(t.shape() == shape{ 3 }); + CHECK(t == tensor<int, 1>{ 1, 2, 3 }); + auto t2 = t; // share data + t(0) = 100; + CHECK(t2 == tensor<int, 1>{ 100, 2, 3 }); +} + } // namespace CMT_ARCH_NAME } // namespace kfr