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