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 77fa0fbdb1acf77fbf065262bac2d652bfb1a038
parent bfd1b8cd4086e3b10cdd55185fe55e5d00774b31
Author: [email protected] <[email protected]>
Date:   Mon, 29 Aug 2016 05:53:16 +0300

Refactoring: Add slice and unpack function, remove typed and skip functions and many more

Diffstat:
Minclude/kfr/base/basic_expressions.hpp | 62++++++++++++++++++++++++++++++++------------------------------
Minclude/kfr/base/conversion.hpp | 15++++++++-------
Minclude/kfr/base/expression.hpp | 87++++++++++++++++++-------------------------------------------------------------
Minclude/kfr/base/operators.hpp | 27+++++++++++++++++++++++----
Minclude/kfr/base/pointer.hpp | 6+++---
Minclude/kfr/base/random.hpp | 8++++----
Minclude/kfr/base/reduce.hpp | 28+++++++++++++++-------------
Minclude/kfr/dft/conv.hpp | 2+-
Minclude/kfr/dsp/delay.hpp | 9+++++----
Minclude/kfr/dsp/fir.hpp | 16++++++++--------
Minclude/kfr/dsp/oscillators.hpp | 6+++---
Minclude/kfr/dsp/sample_rate_conversion.hpp | 22++++++++++++++++------
Minclude/kfr/dsp/window.hpp | 78++++++++++++++++++++++++++++++++----------------------------------------------
Minclude/kfr/io/file.hpp | 8++++----
Mtests/dft_test.cpp | 2+-
Mtests/dsp_test.cpp | 2+-
Mtests/vec_test.cpp | 2+-
17 files changed, 176 insertions(+), 204 deletions(-)

diff --git a/include/kfr/base/basic_expressions.hpp b/include/kfr/base/basic_expressions.hpp @@ -73,7 +73,7 @@ CMT_INLINE auto sequence(T x, Ts... rest) { const T seq[] = { x, static_cast<T>(rest)... }; constexpr size_t N = arraysize(seq); - return typed<T>(lambda([=](size_t index) { return seq[index % N]; })); + return lambda<T>([=](size_t index) { return seq[index % N]; }); } template <typename T = int> @@ -169,27 +169,24 @@ internal::expression_writer<T, E1> writer(E1&& e1) namespace internal { -template <typename E1, typename = void> -struct inherit_value_type -{ -}; - template <typename E1> -struct inherit_value_type<E1, void_t<typename decay<E1>::value_type>> +struct expression_slice : expression<E1> { - using value_type = typename decay<E1>::value_type; -}; - -template <typename E1> -struct expression_skip : expression<E1>, inherit_value_type<E1> -{ - expression_skip(E1&& e1, size_t count) : expression<E1>(std::forward<E1>(e1)), count(count) {} - template <typename T, size_t N> + using value_type = value_type_of<E1>; + using T = value_type; + expression_slice(E1&& e1, size_t start, size_t size) + : expression<E1>(std::forward<E1>(e1)), start(start), + new_size(minsize(size, std::get<0>(this->args).size())) + { + } + template <size_t N> CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const { - return this->argument_first(index + count, y); + return this->argument_first(index + start, y); } - size_t count; + size_t size() const { return new_size; } + size_t start; + size_t new_size; }; template <typename T, bool precise = false> @@ -210,11 +207,11 @@ struct expression_linspace<T, false> : input_expression { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N> x) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> x) const { - using UI = itype<U>; - return U(start) + (enumerate(x) + cast<U>(cast<UI>(index))) * U(offset); + using TI = itype<T>; + return T(start) + (enumerate(x) + cast<T>(cast<TI>(index))) * T(offset); } T start; @@ -236,11 +233,11 @@ struct expression_linspace<T, true> : input_expression { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N> x) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> x) const { - using UI = itype<U>; - return mix((enumerate(x) + cast<U>(cast<UI>(index))) * invsize, cast<U>(start), cast<U>(stop)); + using TI = itype<T>; + return mix((enumerate(x) + cast<T>(cast<TI>(index))) * invsize, cast<T>(start), cast<T>(stop)); } template <typename U, size_t N> CMT_INLINE static vec<U, N> mix(vec<U, N> t, U x, U y) @@ -259,6 +256,9 @@ struct expression_sequence : expression<E...> public: using base = expression<E...>; + using value_type = common_type<value_type_of<E>...>; + using T = value_type; + template <typename... Expr_> CMT_INLINE expression_sequence(const size_t (&segments)[base::size], Expr_&&... expr) noexcept : base(std::forward<Expr_>(expr)...) @@ -268,7 +268,7 @@ public: this->segments[base::size + 1] = size_t(-1); } - template <typename T, size_t N> + template <size_t N> CMT_NOINLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const { std::size_t sindex = size_t(std::upper_bound(std::begin(segments), std::end(segments), index) - 1 - @@ -290,7 +290,7 @@ public: } protected: - template <typename T, size_t N> + template <size_t N> CMT_NOINLINE vec<T, N> get(size_t index, size_t expr_index, vec_t<T, N> y) { return cswitch(indicesfor<E...>, expr_index, [&](auto val) { return this->argument(val, index, y); }, @@ -304,9 +304,11 @@ template <typename Fn, typename E> struct expression_adjacent : expression<E> { using value_type = value_type_of<E>; + using T = value_type; + expression_adjacent(Fn&& fn, E&& e) : expression<E>(std::forward<E>(e)), fn(std::forward<Fn>(fn)) {} - template <typename T, size_t N> + template <size_t N> vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const { const vec<T, N> in = this->argument_first(index, vec_t<T, N>()); @@ -320,9 +322,9 @@ struct expression_adjacent : expression<E> } template <typename E1> -CMT_INLINE internal::expression_skip<E1> skip(E1&& e1, size_t count = 1) +CMT_INLINE internal::expression_slice<E1> slice(E1&& e1, size_t start, size_t size = infinite_size) { - return internal::expression_skip<E1>(std::forward<E1>(e1), count); + return internal::expression_slice<E1>(std::forward<E1>(e1), start, size); } template <typename T1, typename T2, bool precise = false, typename TF = ftype<common_type<T1, T2>>> diff --git a/include/kfr/base/conversion.hpp b/include/kfr/base/conversion.hpp @@ -35,22 +35,23 @@ namespace kfr { namespace internal { -template <typename From, typename E> +template <typename To, typename E> struct expression_convert : expression<E> { + using value_type = To; CMT_INLINE expression_convert(E&& expr) noexcept : expression<E>(std::forward<E>(expr)) {} - template <typename T, size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const + template <size_t N> + CMT_INLINE vec<To, N> operator()(cinput_t, size_t index, vec_t<To, N>) const { - return this->argument_first(index, vec_t<From, N>()); + return this->argument_first(index, vec_t<To, N>()); } }; } -template <typename From, typename E> -CMT_INLINE internal::expression_convert<From, decay<E>> convert(E&& expr) +template <typename To, typename E> +CMT_INLINE internal::expression_convert<To, E> convert(E&& expr) { - return internal::expression_convert<From, decay<E>>(std::forward<E>(expr)); + return internal::expression_convert<To, E>(std::forward<E>(expr)); } } diff --git a/include/kfr/base/expression.hpp b/include/kfr/base/expression.hpp @@ -187,6 +187,7 @@ struct expression_function : expression<arg<Args>...> using value_type = subtype<decltype(std::declval<Fn>()(std::declval<vec<value_type_of<arg<Args>>, 1>>()...))>; + using T = value_type; expression_function(Fn&& fn, arg<Args>&&... args) noexcept : expression<arg<Args>...>(std::forward<arg<Args>>(args)...), @@ -198,11 +199,9 @@ struct expression_function : expression<arg<Args>...> fn(fn) { } - template <typename T, size_t N> + template <size_t N> CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> x) const { - static_assert(is_same<T, value_type_of<expression_function>>::value, - "Can't cast from value_type to T"); return this->call(fn, index, x); } @@ -211,17 +210,6 @@ struct expression_function : expression<arg<Args>...> protected: Fn fn; }; - -template <typename Tout, typename Tin, size_t width, typename OutFn, typename Fn> -CMT_INLINE void process_cycle(OutFn&& outfn, const Fn& fn, size_t& i, size_t size) -{ - const size_t count = size / width * width; - CMT_LOOP_NOUNROLL - for (; i < count; i += width) - { - outfn(coutput, i, fn(cinput, i, vec_t<Tin, width>())); - } -} } template <typename A> @@ -261,6 +249,21 @@ CMT_INLINE internal::expression_function<Fn, NewArgs...> rebind( return internal::expression_function<Fn, NewArgs...>(e.get_fn(), std::forward<NewArgs>(args)...); } +namespace internal +{ +template <size_t width, typename OutputExpr, typename InputExpr> +CMT_INLINE void process_cycle(OutputExpr&& outfn, const InputExpr& fn, size_t& i, size_t size) +{ + using Tin = value_type_of<InputExpr>; + const size_t count = size / width * width; + CMT_LOOP_NOUNROLL + for (; i < count; i += width) + { + outfn(coutput, i, fn(cinput, i, vec_t<Tin, width>())); + } +} +} + template <typename Tout, cpu_t c = cpu_t::native, size_t width = 0, typename OutputExpr, typename InputExpr> CMT_INLINE void process(OutputExpr&& out, const InputExpr& in, size_t size) { @@ -271,8 +274,6 @@ CMT_INLINE void process(OutputExpr&& out, const InputExpr& in, size_t size) out.output_begin_block(size); in.begin_block(size); - using Tin = value_type_of<InputExpr>; - #ifdef NDEBUG constexpr size_t w = width == 0 ? internal::get_vector_width<Tout, c>(2, 4) : width; #else @@ -280,63 +281,13 @@ CMT_INLINE void process(OutputExpr&& out, const InputExpr& in, size_t size) #endif size_t i = 0; - internal::process_cycle<Tout, Tin, w>(std::forward<OutputExpr>(out), in, i, size); - internal::process_cycle<Tout, Tin, comp>(std::forward<OutputExpr>(out), in, i, size); + internal::process_cycle<w>(std::forward<OutputExpr>(out), in, i, size); + internal::process_cycle<comp>(std::forward<OutputExpr>(out), in, i, size); in.end_block(size); out.output_end_block(size); } -namespace internal -{ - -template <typename T, typename E1> -struct expressoin_typed : input_expression -{ - using value_type = T; - - expressoin_typed(E1&& e1) : e1(std::forward<E1>(e1)) {} - - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N>) const - { - return e1(cinput, index, vec_t<T, N>()); - } - E1 e1; -}; - -template <typename T, typename E1> -struct expressoin_sized : input_expression -{ - using value_type = T; - using size_type = size_t; - - expressoin_sized(E1&& e1, size_t size) : e1(std::forward<E1>(e1)), m_size(size) {} - - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N>) const - { - auto val = e1(cinput, index, vec_t<T, N>()); - return val; - } - - constexpr size_t size() const noexcept { return m_size; } - E1 e1; - size_t m_size; -}; -} - -template <typename T, typename E1> -inline internal::expressoin_typed<T, E1> typed(E1&& e1) -{ - return internal::expressoin_typed<T, E1>(std::forward<E1>(e1)); -} -template <typename T, typename E1> -inline internal::expressoin_sized<T, E1> typed(E1&& e1, size_t size) -{ - return internal::expressoin_sized<T, E1>(std::forward<E1>(e1), size); -} - template <typename T> struct input_expression_base : input_expression { diff --git a/include/kfr/base/operators.hpp b/include/kfr/base/operators.hpp @@ -711,14 +711,26 @@ struct expression_pack : expression<E...>, output_expression expression_pack(E&&... e) : expression<E...>(std::forward<E>(e)...) {} using value_type = vec<common_type<value_type_of<E>...>, count>; + using T = value_type; using expression<E...>::size; - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N> x) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const { - return this->call(fn_packtranspose(), index, x); + return this->call(fn_packtranspose(), index, y); } +}; + +template <typename... E> +struct expression_unpack : private expression<E...>, output_expression +{ + constexpr static size_t count = sizeof...(E); + + expression_unpack(E&&... e) : expression<E...>(std::forward<E>(e)...) {} + + using expression<E...>::size; + template <typename U, size_t N> CMT_INLINE void operator()(coutput_t, size_t index, const vec<vec<U, count>, N>& x) { @@ -726,8 +738,9 @@ struct expression_pack : expression<E...>, output_expression } template <typename Input, KFR_ENABLE_IF(is_input_expression<Input>::value)> - CMT_INLINE expression_pack& operator=(Input&& input) + CMT_INLINE expression_unpack& operator=(Input&& input) { + using value_type = vec<common_type<value_type_of<E>...>, count>; process<value_type>(*this, std::forward<Input>(input), size()); return *this; } @@ -742,6 +755,12 @@ private: }; } +template <typename... E, KFR_ENABLE_IF(is_output_expressions<E...>::value)> +internal::expression_unpack<internal::arg<E>...> unpack(E&&... e) +{ + return internal::expression_unpack<internal::arg<E>...>(std::forward<E>(e)...); +} + template <typename... E, KFR_ENABLE_IF(is_input_expressions<E...>::value)> internal::expression_pack<internal::arg<E>...> pack(E&&... e) { diff --git a/include/kfr/base/pointer.hpp b/include/kfr/base/pointer.hpp @@ -76,8 +76,8 @@ struct expression_pointer : input_expression : instance(instance), vtable(vtable), resource(std::move(resource)) { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N>) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const { using func_t = simd<T, N> (*)(void*, size_t); @@ -85,7 +85,7 @@ struct expression_pointer : input_expression constexpr size_t findex = ilog2(N); static_assert(N <= maxwidth, "N is greater than maxwidth"); func_t func = reinterpret_cast<func_t>((*vtable)[2 + findex]); - vec<U, N> result = vec<T, N>(func(instance, index)); + vec<T, N> result = vec<T, N>(func(instance, index)); return result; } CMT_INLINE void begin_block(size_t size) const diff --git a/include/kfr/base/random.hpp b/include/kfr/base/random.hpp @@ -128,8 +128,8 @@ struct expression_random_uniform : input_expression { using value_type = T; constexpr expression_random_uniform(const random_bit_generator& gen) noexcept : gen(gen) {} - template <typename U, size_t N> - vec<U, N> operator()(cinput_t, size_t, vec_t<U, N>) const + template <size_t N> + vec<T, N> operator()(cinput_t, size_t, vec_t<T, N>) const { return random_uniform<T, N>(gen); } @@ -146,8 +146,8 @@ struct expression_random_range : input_expression { } - template <typename U, size_t N> - vec<U, N> operator()(cinput_t, size_t, vec_t<U, N>) const + template <size_t N> + vec<T, N> operator()(cinput_t, size_t, vec_t<T, N>) const { return random_range<N, T>(gen, min, max); } diff --git a/include/kfr/base/reduce.hpp b/include/kfr/base/reduce.hpp @@ -66,14 +66,16 @@ struct expression_reduce : output_expression { constexpr static size_t width = vector_width<T, cpu> * bitness_const(1, 2); + using value_type = T; + expression_reduce(ReduceFn&& reducefn, TransformFn&& transformfn, FinalFn&& finalfn) : counter(0), reducefn(std::move(reducefn)), transformfn(std::move(transformfn)), finalfn(std::move(finalfn)), value(resize<width>(make_vector(reducefn(initialvalue<T>{})))) { } - template <typename U, size_t N> - CMT_INLINE void operator()(coutput_t, size_t, const vec<U, N>& x) const + template <size_t N> + CMT_INLINE void operator()(coutput_t, size_t, const vec<T, N>& x) const { counter += N; process(x); @@ -110,7 +112,7 @@ template <typename ReduceFn, typename TransformFn = fn_pass_through, typename Fi KFR_SINTRIN T reduce(E1&& e1, ReduceFn&& reducefn, TransformFn&& transformfn = fn_pass_through(), FinalFn&& finalfn = fn_pass_through()) { - static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())"); + static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use slice())"); const size_t size = e1.size(); using reducer_t = expression_reduce<T, decay<ReduceFn>, decay<TransformFn>, decay<FinalFn>>; reducer_t red(std::forward<ReduceFn>(reducefn), std::forward<TransformFn>(transformfn), @@ -134,7 +136,7 @@ KFR_FN(reduce) template <typename E1, typename T = value_type_of<E1>, KFR_ENABLE_IF(is_input_expression<E1>::value)> KFR_SINTRIN T sum(E1&& x) { - static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())"); + static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use slice())"); return internal::reduce(std::forward<E1>(x), fn_add()); } @@ -149,7 +151,7 @@ KFR_SINTRIN T sum(E1&& x) template <typename E1, typename T = value_type_of<E1>, KFR_ENABLE_IF(is_input_expression<E1>::value)> KFR_SINTRIN T mean(E1&& x) { - static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())"); + static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use slice())"); return internal::reduce(std::forward<E1>(x), fn_add(), fn_pass_through(), fn_final_mean()); } @@ -161,7 +163,7 @@ KFR_SINTRIN T mean(E1&& x) template <typename E1, typename T = value_type_of<E1>, KFR_ENABLE_IF(is_input_expression<E1>::value)> KFR_SINTRIN T minof(E1&& x) { - static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())"); + static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use slice())"); return internal::reduce(std::forward<E1>(x), fn::min()); } @@ -173,7 +175,7 @@ KFR_SINTRIN T minof(E1&& x) template <typename E1, typename T = value_type_of<E1>, KFR_ENABLE_IF(is_input_expression<E1>::value)> KFR_SINTRIN T maxof(E1&& x) { - static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())"); + static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use slice())"); return internal::reduce(std::forward<E1>(x), fn::max()); } @@ -185,7 +187,7 @@ KFR_SINTRIN T maxof(E1&& x) template <typename E1, typename T = value_type_of<E1>, KFR_ENABLE_IF(is_input_expression<E1>::value)> KFR_SINTRIN T absminof(E1&& x) { - static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())"); + static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use slice())"); return internal::reduce(std::forward<E1>(x), fn::absmin()); } @@ -197,7 +199,7 @@ KFR_SINTRIN T absminof(E1&& x) template <typename E1, typename T = value_type_of<E1>, KFR_ENABLE_IF(is_input_expression<E1>::value)> KFR_SINTRIN T absmaxof(E1&& x) { - static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())"); + static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use slice())"); return internal::reduce(std::forward<E1>(x), fn::absmax()); } @@ -215,7 +217,7 @@ KFR_SINTRIN T dotproduct(E1&& x, E2&& y) { auto m = std::forward<E1>(x) * std::forward<E2>(y); using E12 = decltype(m); - static_assert(!is_infinite<E12>::value, "e1 must be a sized expression (use typed<T>())"); + static_assert(!is_infinite<E12>::value, "e1 must be a sized expression (use slice())"); return internal::reduce(std::move(m), fn_add()); } @@ -230,7 +232,7 @@ KFR_SINTRIN T dotproduct(E1&& x, E2&& y) template <typename E1, typename T = value_type_of<E1>, KFR_ENABLE_IF(is_input_expression<E1>::value)> KFR_SINTRIN T rms(E1&& x) { - static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())"); + static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use slice())"); return internal::reduce(std::forward<E1>(x), fn_add(), fn_sqr(), fn_final_rootmean()); } @@ -245,7 +247,7 @@ KFR_SINTRIN T rms(E1&& x) template <typename E1, typename T = value_type_of<E1>, KFR_ENABLE_IF(is_input_expression<E1>::value)> KFR_SINTRIN T sumsqr(E1&& x) { - static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())"); + static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use slice())"); return internal::reduce(std::forward<E1>(x), fn_add(), fn_sqr()); } @@ -260,7 +262,7 @@ KFR_SINTRIN T sumsqr(E1&& x) template <typename E1, typename T = value_type_of<E1>, KFR_ENABLE_IF(is_input_expression<E1>::value)> KFR_SINTRIN T product(E1&& x) { - static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())"); + static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use slice())"); return internal::reduce(std::forward<E1>(x), fn_mul()); } } diff --git a/include/kfr/dft/conv.hpp b/include/kfr/dft/conv.hpp @@ -55,7 +55,7 @@ KFR_INTRIN univector<T> convolve(const univector<T, Tag1>& src1, const univector plan.execute(src2padded, src2padded, temp); src1padded = src1padded * src2padded; plan.execute(src1padded, src1padded, temp, true); - return typed<T>(real(src1padded), src1.size() + src2.size() - 1) / T(size); + return slice(real(src1padded), 0, src1.size() + src2.size() - 1) / T(size); } } #pragma clang diagnostic pop diff --git a/include/kfr/dsp/delay.hpp b/include/kfr/dsp/delay.hpp @@ -37,9 +37,10 @@ template <size_t delay, typename E> struct expression_delay : expression<E> { using value_type = value_type_of<E>; + using T = value_type; using expression<E>::expression; - template <typename T, size_t N, KFR_ENABLE_IF(N <= delay)> + template <size_t N, KFR_ENABLE_IF(N <= delay)> vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const { vec<T, N> out; @@ -49,7 +50,6 @@ struct expression_delay : expression<E> data.ringbuf_write(cursor, in); return out; } - template <typename T> vec<T, 1> operator()(cinput_t, size_t index, vec_t<T, 1>) const { T out; @@ -59,7 +59,7 @@ struct expression_delay : expression<E> data.ringbuf_write(cursor, in); return out; } - template <typename T, size_t N, KFR_ENABLE_IF(N > delay)> + template <size_t N, KFR_ENABLE_IF(N > delay)> vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const { vec<T, delay> out; @@ -78,9 +78,10 @@ template <typename E> struct expression_delay<1, E> : expression<E> { using value_type = value_type_of<E>; + using T = value_type; using expression<E>::expression; - template <typename T, size_t N> + template <size_t N> vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const { const vec<T, N> in = this->argument_first(index, vec_t<T, N>()); diff --git a/include/kfr/dsp/fir.hpp b/include/kfr/dsp/fir.hpp @@ -54,17 +54,17 @@ struct expression_short_fir : expression<E1> : expression<E1>(std::forward<E1>(e1)), taps(taps), delayline(0) { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N> x) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> x) const { - vec<T, N> in = cast<T>(this->argument_first(index, x)); + vec<T, N> in = this->argument_first(index, x); vec<T, N> out = in * taps[0]; cfor(csize<1>, csize<tapcount>, [&](auto I) { out = out + concat_and_slice<tapcount - 1 - I, N>(delayline, in) * taps[I]; }); delayline = concat_and_slice<N, tapcount - 1>(delayline, in); - return cast<U>(out); + return out; } vec<T, tapcount> taps; mutable vec<T, tapcount - 1> delayline; @@ -77,11 +77,11 @@ struct expression_fir : expression<E1> : expression<E1>(std::forward<E1>(e1)), taps(taps), delayline(taps.size(), T()), delayline_cursor(0) { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N> x) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> x) const { const size_t tapcount = taps.size(); - const vec<T, N> input = cast<T>(this->argument_first(index, x)); + const vec<T, N> input = this->argument_first(index, x); vec<T, N> output; size_t cursor = delayline_cursor; @@ -93,7 +93,7 @@ struct expression_fir : expression<E1> dotproduct(taps.slice(tapcount - cursor), delayline /*, cursor*/); } delayline_cursor = cursor; - return cast<U>(output); + return output; } univector_dyn<T> taps; mutable univector_dyn<T> delayline; diff --git a/include/kfr/dsp/oscillators.hpp b/include/kfr/dsp/oscillators.hpp @@ -34,15 +34,15 @@ namespace kfr template <typename T = fbase> auto jaehne(identity<T> magn, size_t size) { - return typed<T>(magn * sin(c_pi<T, 1, 2> * sqr(linspace(T(0), T(size), size, false)) / size), size); + return slice(magn * sin(c_pi<T, 1, 2> * sqr(linspace(T(0), T(size), size, false)) / size), 0, size); } template <typename T = fbase> auto swept(identity<T> magn, size_t size) { - return typed<T>( + return slice( magn * sin(c_pi<T, 1, 4> * sqr(sqr(linspace(T(0), T(size), size, false)) / sqr(T(size))) * T(size)), - size); + 0, size); } template <typename T = fbase> diff --git a/include/kfr/dsp/sample_rate_conversion.hpp b/include/kfr/dsp/sample_rate_conversion.hpp @@ -211,13 +211,15 @@ template <typename E> struct expression_upsample<2, E> : expression<E> { using expression<E>::expression; - template <typename T, size_t N> + using value_type = value_type_of<E>; + using T = value_type; + + template <size_t N> vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const { const vec<T, N / 2> x = this->argument_first(index / 2, vec_t<T, N / 2>()); return interleave(x, zerovector(x)); } - template <typename T> vec<T, 1> operator()(cinput_t, size_t index, vec_t<T, 1>) const { if (index & 1) @@ -231,14 +233,16 @@ template <typename E> struct expression_upsample<4, E> : expression<E> { using expression<E>::expression; - template <typename T, size_t N> + using value_type = value_type_of<E>; + using T = value_type; + + template <size_t N> vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const { const vec<T, N / 4> x = this->argument_first(index / 4, vec_t<T, N / 4>()); const vec<T, N / 2> xx = interleave(x, zerovector(x)); return interleave(xx, zerovector(xx)); } - template <typename T> vec<T, 2> operator()(cinput_t, size_t index, vec_t<T, 2>) const { switch (index & 3) @@ -265,7 +269,10 @@ template <typename E, size_t offset> struct expression_downsample<2, offset, E> : expression<E> { using expression<E>::expression; - template <typename T, size_t N> + using value_type = value_type_of<E>; + using T = value_type; + + template <size_t N> vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const { const vec<T, N* 2> x = this->argument_first(index * 2, vec_t<T, N * 2>()); @@ -277,7 +284,10 @@ template <typename E, size_t offset> struct expression_downsample<4, offset, E> : expression<E> { using expression<E>::expression; - template <typename T, size_t N> + using value_type = value_type_of<E>; + using T = value_type; + + template <size_t N> vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const { const vec<T, N* 4> x = this->argument_first(index * 4, vec_t<T, N * 4>()); diff --git a/include/kfr/dsp/window.hpp b/include/kfr/dsp/window.hpp @@ -124,12 +124,12 @@ struct expression_rectangular : input_expression expression_rectangular(size_t size, T = T(), window_symmetry = window_symmetry::symmetric) : m_size(size) { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N>) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const { - using UI = utype<U>; - const vec<UI, N> i = enumerate(vec<UI, N>()) + cast<UI>(index); - return select(i < cast<UI>(m_size), U(1), U(0)); + 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)); } size_t size() const { return m_size; } @@ -146,10 +146,9 @@ struct expression_triangular : input_expression : linspace(size, symmetry), m_size(size) { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N>) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const { - constexpr vec_t<T, N> y{}; return 1 - abs(linspace(cinput, index, y)); } size_t size() const { return m_size; } @@ -168,10 +167,9 @@ struct expression_bartlett : input_expression : linspace(size, symmetry), m_size(size) { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N>) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const { - constexpr vec_t<T, N> y{}; return 1 - abs(linspace(cinput, index, y)); } size_t size() const { return m_size; } @@ -190,10 +188,9 @@ struct expression_cosine : input_expression : linspace(size, symmetry), m_size(size) { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N>) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const { - constexpr vec_t<T, N> y{}; return sin(c_pi<T> * linspace(cinput, index, y)); } size_t size() const { return m_size; } @@ -212,10 +209,9 @@ struct expression_hann : input_expression : linspace(size, symmetry), m_size(size) { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N>) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const { - constexpr vec_t<T, N> y{}; return T(0.5) * (T(1) - cos(c_pi<T, 2> * linspace(cinput, index, y))); } size_t size() const { return m_size; } @@ -234,10 +230,9 @@ struct expression_bartlett_hann : input_expression : linspace(size, symmetry), m_size(size) { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N>) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const { - constexpr vec_t<T, N> y{}; const vec<T, N> xx = linspace(cinput, index, y); return T(0.62) - T(0.48) * abs(xx - T(0.5)) + T(0.38) * cos(c_pi<T, 2> * (xx - T(0.5))); } @@ -257,10 +252,9 @@ struct expression_hamming : input_expression : linspace(size, symmetry), alpha(alpha), m_size(size) { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N>) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const { - constexpr vec_t<T, N> y{}; return alpha - (1.0 - alpha) * (cos(c_pi<T, 2> * linspace(cinput, index, y))); } size_t size() const { return m_size; } @@ -280,11 +274,10 @@ struct expression_bohman : input_expression : linspace(size, symmetry), m_size(size) { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N>) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const { - constexpr vec_t<T, N> y{}; - const vec<U, N> n = abs(linspace(cinput, index, y)); + const vec<T, N> n = abs(linspace(cinput, index, y)); return (T(1) - n) * cos(c_pi<T> * n) + (T(1) / c_pi<T>)*sin(c_pi<T> * n); } size_t size() const { return m_size; } @@ -303,10 +296,9 @@ struct expression_blackman : input_expression : linspace(size, symmetry), a0((1 - alpha) * 0.5), a1(0.5), a2(alpha * 0.5), m_size(size) { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N>) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const { - constexpr vec_t<T, N> y{}; const vec<T, N> n = linspace(cinput, index, y); return a0 - a1 * cos(c_pi<T, 2> * n) + a2 * cos(c_pi<T, 4> * n); } @@ -327,12 +319,10 @@ struct expression_blackman_harris : input_expression : linspace(size, symmetry), m_size(size) { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N>) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const { - constexpr vec_t<T, N> y{}; const vec<T, N> n = linspace(cinput, index, y) * c_pi<T, 2>; - return T(0.35875) - T(0.48829) * cos(n) + T(0.14128) * cos(2 * n) - T(0.01168) * cos(3 * n); } size_t size() const { return m_size; } @@ -352,10 +342,9 @@ struct expression_kaiser : input_expression m_size(size) { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N>) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const { - constexpr vec_t<T, N> y{}; return modzerobessel(beta * sqrt(1 - sqr(linspace(cinput, index, y)))) * m; } size_t size() const { return m_size; } @@ -376,10 +365,9 @@ struct expression_flattop : input_expression : linspace(size, symmetry), m_size(size) { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N>) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const { - constexpr vec_t<T, N> y{}; const vec<T, N> n = linspace(cinput, index, y) * c_pi<T, 2>; constexpr T a0 = 1; constexpr T a1 = 1.93; @@ -404,10 +392,9 @@ struct expression_gaussian : input_expression : linspace(size, symmetry), alpha(alpha), m_size(size) { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N>) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const { - constexpr vec_t<T, N> y{}; return exp(-0.5 * sqr(alpha * linspace(cinput, index, y))); } @@ -427,10 +414,9 @@ struct expression_lanczos : input_expression : linspace(size, symmetry), alpha(alpha), m_size(size) { } - template <typename U, size_t N> - CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N>) const + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const { - constexpr vec_t<T, N> y{}; return sinc(linspace(cinput, index, y)); } size_t size() const { return m_size; } diff --git a/include/kfr/io/file.hpp b/include/kfr/io/file.hpp @@ -83,8 +83,8 @@ template <typename T> struct expression_file_writer : expression_file_base, output_expression { using expression_file_base::expression_file_base; - template <typename U, size_t N> - void operator()(coutput_t, size_t index, const vec<U, N>& value) + template <size_t N> + void operator()(coutput_t, size_t index, const vec<T, N>& value) { if (position != index) fseeko(file, static_cast<off_t>(index * sizeof(T)), SEEK_SET); @@ -99,8 +99,8 @@ template <typename T> struct expression_file_reader : expression_file_base, input_expression { using expression_file_base::expression_file_base; - template <typename U, size_t N> - vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N>) const + template <size_t N> + vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const { if (position != index) fseeko(file, static_cast<off_t>(index * sizeof(T)), SEEK_SET); diff --git a/tests/dft_test.cpp b/tests/dft_test.cpp @@ -51,7 +51,7 @@ TEST(fft_accuracy) const size_t size = 1 << log2size; univector<complex<float_type>> in = - typed<float_type>(gen_random_range(gen, -1.0, +1.0), size * 2); + slice(gen_random_range<float_type>(gen, -1.0, +1.0), 0, size * 2); univector<complex<float_type>> out = in; univector<complex<float_type>> refout = out; const dft_plan<float_type> dft(size); diff --git a/tests/dsp_test.cpp b/tests/dsp_test.cpp @@ -62,7 +62,7 @@ TEST(mixdown_stereo) const univector<double, 21> right = counter() * 2 + 100; univector<double, 21> mid; univector<double, 21> side; - pack(mid, side) = mixdown_stereo(left, right, matrix_sum_diff()); + unpack(mid, side) = mixdown_stereo(left, right, matrix_sum_diff()); CHECK(mid[0] == 100); CHECK(side[0] == -100); diff --git a/tests/vec_test.cpp b/tests/vec_test.cpp @@ -281,7 +281,7 @@ TEST(test_delay) TEST(test_adjacent) { - univector<int, 20> v1 = adjacent(fn_mul(), typed<int>(counter())); + univector<int, 20> v1 = adjacent(fn_mul(), counter()); CHECK(v1[0] == 0); CHECK(v1[1] == 0); CHECK(v1[2] == 2);