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 83fb4650b693397fef1d412d4e1c476864126964
parent 02d5d16b48c41e5d0271054983738b4a6b100989
Author: d.levin256@gmail.com <d.levin256@gmail.com>
Date:   Thu, 14 Jul 2022 19:38:11 +0100

Output expressions must use set_elements functions

Diffstat:
Minclude/kfr/base/basic_expressions.hpp | 21+++++++++++----------
Minclude/kfr/base/expression.hpp | 25++++++++++++++-----------
Minclude/kfr/base/reduce.hpp | 6+++---
Minclude/kfr/base/univector.hpp | 15++++++++-------
Minclude/kfr/dsp/goertzel.hpp | 17+++++++++--------
Minclude/kfr/io/tostring.hpp | 6++++--
6 files changed, 49 insertions(+), 41 deletions(-)

diff --git a/include/kfr/base/basic_expressions.hpp b/include/kfr/base/basic_expressions.hpp @@ -117,9 +117,8 @@ KFR_INTRINSIC internal::expression_iterator<T, E1> to_iterator(E1&& e1) template <typename... Ts, typename T = common_type<Ts...>> inline auto sequence(const Ts&... list) { - return lambda<T>([seq = std::array<T, sizeof...(Ts)>{ { static_cast<T>(list)... } }](size_t index) { - return seq[index % seq.size()]; - }); + return lambda<T>([seq = std::array<T, sizeof...(Ts)>{ { static_cast<T>(list)... } }](size_t index) + { return seq[index % seq.size()]; }); } template <typename T = int> @@ -148,8 +147,8 @@ KFR_INTRINSIC auto counter(T1 start) template <typename T1, typename T2> KFR_INTRINSIC auto counter(T1 start, T2 step) { - return lambda<common_type<T1, T2>>( - [start, step](cinput_t, size_t index, auto x) { return (enumerate(x) + index) * step + start; }); + return lambda<common_type<T1, T2>>([start, step](cinput_t, size_t index, auto x) + { return (enumerate(x) + index) * step + start; }); } template <typename Gen> @@ -534,10 +533,11 @@ struct multioutput : output_expression { } template <typename T, size_t N> - void operator()(coutput_t coutput, size_t index, const vec<T, N>& x) + KFR_INTRINSIC friend void set_elements(multioutput& self, coutput_t coutput, size_t index, + const vec<T, N>& x) { cfor(csize_t<0>(), csize_t<sizeof...(E)>(), - [&](auto n) { std::get<val_of(decltype(n)())>(outputs)(coutput, index, x); }); + [&](auto n) { set_elements(std::get<val_of(decltype(n)())>(self.outputs), coutput, index, x); }); } std::tuple<E...> outputs; @@ -577,9 +577,10 @@ struct expression_unpack : private expression_with_arguments<E...>, output_expre using expression_with_arguments<E...>::size; template <typename U, size_t N> - KFR_MEM_INTRINSIC void operator()(coutput_t coutput, size_t index, const vec<vec<U, count>, N>& x) + KFR_INTRINSIC friend void set_elements(expression_unpack& self, coutput_t coutput, size_t index, + const vec<vec<U, count>, N>& x) { - output(coutput, index, x, csizeseq<count>); + self.output(coutput, index, x, csizeseq<count>); } template <typename Input, KFR_ENABLE_IF(is_input_expression<Input>)> @@ -594,7 +595,7 @@ private: void output(coutput_t coutput, size_t index, const vec<vec<U, count>, N>& x, csizes_t<indices...>) { const vec<vec<U, N>, count> xx = vec<vec<U, N>, count>::from_flatten(transpose<count>(flatten(x))); - swallow{ (std::get<indices>(this->args)(coutput, index, xx[indices]), void(), 0)... }; + swallow{ (set_elements(std::get<indices>(this->args), coutput, index, xx[indices]), void(), 0)... }; } }; } // namespace internal diff --git a/include/kfr/base/expression.hpp b/include/kfr/base/expression.hpp @@ -171,13 +171,15 @@ void test_expression(const E& expr, size_t size, Fn&& fn, const char* expression if (g > (1 << (maxsize - 1))) g = 1; - cswitch(csize<1> << csizeseq<maxsize>, next_size, [&](auto x) { - constexpr size_t nsize = val_of(decltype(x)()); - ::testo::scope s(as_string("i = ", i, " width = ", nsize)); - test->check(c <= get_elements(expr, cinput, i, vec_shape<T, nsize>()) == - internal::get_fn_value<T, nsize>(i, fn), - expression); - }); + cswitch(csize<1> << csizeseq<maxsize>, next_size, + [&](auto x) + { + constexpr size_t nsize = val_of(decltype(x)()); + ::testo::scope s(as_string("i = ", i, " width = ", nsize)); + test->check(c <= get_elements(expr, cinput, i, vec_shape<T, nsize>()) == + internal::get_fn_value<T, nsize>(i, fn), + expression); + }); i += next_size; } } @@ -451,10 +453,10 @@ CMT_INTRINSIC static size_t process(OutputExpr&& out, const InputExpr& in, size_ CMT_LOOP_NOUNROLL for (; i < start + size / w * w; i += w) - out(coutput, i, get_elements(in, cinput, i, vec_shape<Tin, w>())); + set_elements(out, coutput, i, get_elements(in, cinput, i, vec_shape<Tin, w>())); CMT_LOOP_NOUNROLL for (; i < start + size / groupsize * groupsize; i += groupsize) - out(coutput, i, get_elements(in, cinput, i, vec_shape<Tin, groupsize>())); + set_elements(out, coutput, i, get_elements(in, cinput, i, vec_shape<Tin, groupsize>())); in.end_block(cinput, size); out.end_block(coutput, size); @@ -484,10 +486,11 @@ struct output_expression_base : output_expression virtual void output(size_t index, const T& value) = 0; template <typename U, size_t N> - KFR_MEM_INTRINSIC void operator()(coutput_t, size_t index, const vec<U, N>& value) + friend KFR_INTRINSIC void set_elements(const output_expression_base& self, coutput_t, size_t index, + const vec<U, N>& value) { for (size_t i = 0; i < N; i++) - output(index + i, static_cast<T>(value[i])); + self.output(index + i, static_cast<T>(value[i])); } }; diff --git a/include/kfr/base/reduce.hpp b/include/kfr/base/reduce.hpp @@ -79,10 +79,10 @@ struct expression_reduce : output_expression } template <size_t N> - KFR_MEM_INTRINSIC void operator()(coutput_t, size_t, const vec<Tin, N>& x) const + KFR_INTRINSIC friend void set_elements(expression_reduce& self, coutput_t, size_t, const vec<Tin, N>& x) { - counter += N; - process(x); + self.counter += N; + self.process(x); } KFR_MEM_INTRINSIC Tout get() diff --git a/include/kfr/base/univector.hpp b/include/kfr/base/univector.hpp @@ -99,13 +99,6 @@ struct univector_base<T, Class, true> : input_expression, output_expression using output_expression::begin_block; using output_expression::end_block; - template <typename U, size_t N> - KFR_MEM_INTRINSIC void operator()(coutput_t, size_t index, const vec<U, N>& value) - { - T* data = derived_cast<Class>(this)->data(); - write(ptr_cast<T>(data) + index, vec<T, N>(value)); - } - template <typename Input, KFR_ENABLE_IF(is_input_expression<Input>)> KFR_MEM_INTRINSIC Class& operator=(Input&& input) { @@ -604,6 +597,14 @@ KFR_INTRINSIC vec<U, N> get_elements(const univector<T, Tag>& self, cinput_t, si return static_cast<vec<U, N>>(read<N>(ptr_cast<T>(data) + index)); } +template <typename T, univector_tag Tag, typename U, size_t N> +KFR_INTRINSIC void set_elements(univector<T, Tag>& self, coutput_t, size_t index, + const vec<U, N>& value) +{ + T* data = self.data(); + write(ptr_cast<T>(data) + index, vec<T, N>(value)); +} + /// @brief Converts an expression to univector template <typename Expr, typename T = value_type_of<Expr>> KFR_INTRINSIC univector<T> render(Expr&& expr) diff --git a/include/kfr/dsp/goertzel.hpp b/include/kfr/dsp/goertzel.hpp @@ -51,15 +51,15 @@ struct expression_goertzel : output_expression result.imag(q2 * sin(omega)); } template <typename U, size_t N> - KFR_MEM_INTRINSIC void operator()(coutput_t, size_t, const vec<U, N>& x) + KFR_INTRINSIC friend void set_elements(expression_goertzel& self, coutput_t, size_t, const vec<U, N>& x) { vec<T, N> in = x; CMT_LOOP_UNROLL for (size_t i = 0; i < N; i++) { - q0 = coeff * q1 - q2 + in[i]; - q2 = q1; - q1 = q0; + self.q0 = self.coeff * self.q1 - self.q2 + in[i]; + self.q2 = self.q1; + self.q1 = self.q0; } } complex<T>& result; @@ -88,15 +88,16 @@ struct expression_parallel_goertzel : output_expression } } template <typename U, size_t N> - KFR_MEM_INTRINSIC void operator()(coutput_t, size_t, const vec<U, N>& x) + KFR_INTRINSIC friend void set_elements(expression_parallel_goertzel& self, coutput_t, size_t, + const vec<U, N>& x) { const vec<T, N> in = x; CMT_LOOP_UNROLL for (size_t i = 0; i < N; i++) { - q0 = coeff * q1 - q2 + in[i]; - q2 = q1; - q1 = q0; + self.q0 = self.coeff * self.q1 - self.q2 + in[i]; + self.q2 = self.q1; + self.q1 = self.q0; } } complex<T>* result; diff --git a/include/kfr/io/tostring.hpp b/include/kfr/io/tostring.hpp @@ -236,7 +236,8 @@ namespace internal struct expression_printer : output_expression { template <typename T, size_t N> - void operator()(coutput_t, size_t index, const vec<T, N>& value) + KFR_INTRINSIC friend void set_elements(expression_printer& self, coutput_t, size_t index, + const vec<T, N>& value) { for (size_t i = 0; i < N; i++) { @@ -256,7 +257,8 @@ struct expression_printer : output_expression struct expression_debug_printer : output_expression { template <typename T, size_t N> - void operator()(coutput_t, size_t index, const vec<T, N>& value) + KFR_INTRINSIC friend void set_elements(expression_debug_printer& self, coutput_t, size_t index, + const vec<T, N>& value) { println(fmtwidth<7>(index), ": (", value, ")"); }