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 dfb5ea94d8c96e4d3384a1c7dc9fac109881a4a6
parent f3bc9bb02773324731c59ea811b8ca4c616b0212
Author: Stephen Larew <stephen@slarew.net>
Date:   Thu, 20 Feb 2020 12:28:51 -0800

add gen_expj

Diffstat:
Minclude/kfr/base/generators.hpp | 41+++++++++++++++++++++++++++++++++++++++++
Mtests/base_test.cpp | 12++++++++++++
2 files changed, 53 insertions(+), 0 deletions(-)

diff --git a/include/kfr/base/generators.hpp b/include/kfr/base/generators.hpp @@ -136,6 +136,35 @@ protected: T vstep; }; +template <typename T, size_t width = vector_width<T>* bitness_const(1, 2), + std::enable_if_t<std::is_same<complex<deep_subtype<T>>, T>::value, int> = 0> +struct generator_expj : generator<T, width, generator_expj<T, width>> +{ + using ST = deep_subtype<T>; + + generator_expj(ST start_, ST step_) + : step(step_), alpha(2 * sqr(sin(width * step / 2))), beta(-sin(width * step)) + { + this->resync(T(start_)); + } + KFR_MEM_INTRINSIC void sync(T start) const CMT_NOEXCEPT { this->value = init_cossin(step, start.real()); } + + KFR_MEM_INTRINSIC void next() const CMT_NOEXCEPT + { + this->value = ccomp(cdecom(this->value) - + subadd(alpha * cdecom(this->value), beta * swap<2>(cdecom(this->value)))); + } + +protected: + ST const step; + ST const alpha; + ST const beta; + CMT_NOINLINE static vec<T, width> init_cossin(ST w, ST phase) + { + return ccomp(cossin(dup(phase + enumerate<ST, width>() * w))); + } +}; + template <typename T, size_t width = vector_width<T>* bitness_const(1, 2)> struct generator_exp2 : generator<T, width, generator_exp2<T, width>> { @@ -255,6 +284,18 @@ KFR_FUNCTION internal::generator_exp<TF> gen_exp(T1 start, T2 step) /** * @brief Returns template expression that generates values using the following formula: * \f[ + x_i = e^{ j ( start + i \cdot step ) } + \f] + */ +template <typename T1, typename T2, typename TF = complex<ftype<common_type<T1, T2>>>> +KFR_FUNCTION internal::generator_expj<TF> gen_expj(T1 start, T2 step) +{ + return internal::generator_expj<TF>(start, step); +} + +/** + * @brief Returns template expression that generates values using the following formula: + * \f[ x_i = 2^{ start + i \cdot step } \f] */ diff --git a/tests/base_test.cpp b/tests/base_test.cpp @@ -92,6 +92,18 @@ TEST(test_basic) CHECK(inrange(pack(1, 2, 3), 1, 1) == make_mask<int>(true, false, false)); } +TEST(test_gen_expj) +{ + kfr::univector<cbase> v = kfr::truncate(kfr::gen_expj(0.f, constants<float>::pi_s(2) * 0.1f), 1000); + CHECK(rms(cabs(v.slice(990) - + univector<cbase>({ cbase(1., +0.00000000e+00), cbase(0.80901699, +5.87785252e-01), + cbase(0.30901699, +9.51056516e-01), cbase(-0.30901699, +9.51056516e-01), + cbase(-0.80901699, +5.87785252e-01), cbase(-1., +1.22464680e-16), + cbase(-0.80901699, -5.87785252e-01), + cbase(-0.30901699, -9.51056516e-01), cbase(0.30901699, -9.51056516e-01), + cbase(0.80901699, -5.87785252e-01) }))) < 0.00001); +} + } // namespace CMT_ARCH_NAME #ifndef KFR_NO_MAIN