10#ifndef EIGEN_FFT_MODULE_H
11#define EIGEN_FFT_MODULE_H
16#include "../../Eigen/Core"
81#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
85#ifdef EIGEN_FFTW_DEFAULT
88#include "src/FFT/ei_fftw_impl.h"
92struct default_fft_impl :
public internal::fftw_impl<T> {};
94#elif defined EIGEN_MKL_DEFAULT
96#include "src/FFT/ei_imklfft_impl.h"
99struct default_fft_impl :
public internal::imklfft::imklfft_impl<T> {};
101#elif defined EIGEN_POCKETFFT_DEFAULT
103#include <pocketfft_hdronly.h>
104#include "src/FFT/ei_pocketfft_impl.h"
107struct default_fft_impl :
public internal::pocketfft_impl<T> {};
111#include "src/FFT/ei_kissfft_impl.h"
114struct default_fft_impl :
public internal::kissfft_impl<T> {};
123template <
typename T_SrcMat,
typename T_FftIfc>
125template <
typename T_SrcMat,
typename T_FftIfc>
129template <
typename T_SrcMat,
typename T_FftIfc>
130struct traits<fft_fwd_proxy<T_SrcMat, T_FftIfc> > {
131 typedef typename T_SrcMat::PlainObject ReturnType;
133template <
typename T_SrcMat,
typename T_FftIfc>
134struct traits<fft_inv_proxy<T_SrcMat, T_FftIfc> > {
135 typedef typename T_SrcMat::PlainObject ReturnType;
139template <
typename T_SrcMat,
typename T_FftIfc>
140struct fft_fwd_proxy :
public ReturnByValue<fft_fwd_proxy<T_SrcMat, T_FftIfc> > {
141 typedef DenseIndex Index;
143 fft_fwd_proxy(
const T_SrcMat& src, T_FftIfc& fft, Index nfft) : m_src(src), m_ifc(fft), m_nfft(nfft) {}
145 template <
typename T_DestMat>
146 void evalTo(T_DestMat& dst)
const;
148 Index rows()
const {
return m_src.rows(); }
149 Index cols()
const {
return m_src.cols(); }
152 const T_SrcMat& m_src;
157template <
typename T_SrcMat,
typename T_FftIfc>
158struct fft_inv_proxy :
public ReturnByValue<fft_inv_proxy<T_SrcMat, T_FftIfc> > {
159 typedef DenseIndex Index;
161 fft_inv_proxy(
const T_SrcMat& src, T_FftIfc& fft, Index nfft) : m_src(src), m_ifc(fft), m_nfft(nfft) {}
163 template <
typename T_DestMat>
164 void evalTo(T_DestMat& dst)
const;
166 Index rows()
const {
return m_src.rows(); }
167 Index cols()
const {
return m_src.cols(); }
170 const T_SrcMat& m_src;
175template <
typename T_Scalar,
typename T_Impl = default_fft_impl<T_Scalar> >
178 typedef T_Impl impl_type;
179 typedef DenseIndex Index;
180 typedef typename impl_type::Scalar Scalar;
181 typedef typename impl_type::Complex Complex;
184 static constexpr Flag Default = 0;
185 static constexpr Flag Unscaled = 1;
186 static constexpr Flag HalfSpectrum = 2;
187 static constexpr Flag Speedy = 32767;
189 FFT(
const impl_type& impl = impl_type(), Flag flags = Default) : m_impl(impl), m_flag(flags) {
190 eigen_assert((flags == Default || flags == Unscaled || flags == HalfSpectrum || flags == Speedy) &&
191 "invalid flags argument");
194 inline bool HasFlag(Flag f)
const {
return (m_flag & (
int)f) == f; }
196 inline void SetFlag(Flag f) { m_flag |= (int)f; }
198 inline void ClearFlag(Flag f) { m_flag &= (~(int)f); }
200 inline void fwd(Complex* dst,
const Scalar* src, Index nfft) {
201 m_impl.fwd(dst, src,
static_cast<int>(nfft));
202 if (HasFlag(HalfSpectrum) ==
false) ReflectSpectrum(dst, nfft);
205 inline void fwd(Complex* dst,
const Complex* src, Index nfft) { m_impl.fwd(dst, src,
static_cast<int>(nfft)); }
207#if defined EIGEN_FFTW_DEFAULT || defined EIGEN_POCKETFFT_DEFAULT || defined EIGEN_MKL_DEFAULT
208 inline void fwd2(Complex* dst,
const Complex* src,
int n0,
int n1) { m_impl.fwd2(dst, src, n0, n1); }
211 template <
typename Input_>
212 inline void fwd(std::vector<Complex>& dst,
const std::vector<Input_>& src) {
213 if (NumTraits<Input_>::IsComplex == 0 && HasFlag(HalfSpectrum))
214 dst.resize((src.size() >> 1) + 1);
216 dst.resize(src.size());
217 fwd(&dst[0], &src[0], src.size());
220 template <
typename InputDerived,
typename ComplexDerived>
221 inline void fwd(MatrixBase<ComplexDerived>& dst,
const MatrixBase<InputDerived>& src, Index nfft = -1) {
222 typedef typename ComplexDerived::Scalar dst_type;
223 typedef typename InputDerived::Scalar src_type;
224 EIGEN_STATIC_ASSERT_VECTOR_ONLY(InputDerived)
225 EIGEN_STATIC_ASSERT_VECTOR_ONLY(ComplexDerived)
226 EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(ComplexDerived, InputDerived)
228 (internal::is_same<dst_type, Complex>::value),
229 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
230 EIGEN_STATIC_ASSERT(
int(InputDerived::Flags) &
int(ComplexDerived::Flags) &
DirectAccessBit,
231 THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES)
233 if (nfft < 1) nfft = src.size();
235 Index dst_size = nfft;
236 if (NumTraits<src_type>::IsComplex == 0 && HasFlag(HalfSpectrum)) {
237 dst_size = (nfft >> 1) + 1;
239 dst.derived().resize(dst_size);
241 if (src.innerStride() != 1 || src.size() < nfft) {
242 Matrix<src_type, 1, Dynamic> tmp;
243 if (src.size() < nfft) {
245 tmp.block(0, 0, src.size(), 1) = src;
249 if (dst.innerStride() != 1) {
250 Matrix<dst_type, 1, Dynamic> out(1, dst_size);
251 fwd(&out[0], &tmp[0], nfft);
254 fwd(&dst[0], &tmp[0], nfft);
257 if (dst.innerStride() != 1) {
258 Matrix<dst_type, 1, Dynamic> out(1, dst_size);
259 fwd(&out[0], &src[0], nfft);
262 fwd(&dst[0], &src[0], nfft);
267 template <
typename InputDerived>
268 inline fft_fwd_proxy<MatrixBase<InputDerived>, FFT<T_Scalar, T_Impl> > fwd(
const MatrixBase<InputDerived>& src,
270 return fft_fwd_proxy<MatrixBase<InputDerived>, FFT<T_Scalar, T_Impl> >(src, *
this, nfft);
273 template <
typename InputDerived>
274 inline fft_inv_proxy<MatrixBase<InputDerived>, FFT<T_Scalar, T_Impl> > inv(
const MatrixBase<InputDerived>& src,
276 return fft_inv_proxy<MatrixBase<InputDerived>, FFT<T_Scalar, T_Impl> >(src, *
this, nfft);
279 inline void inv(Complex* dst,
const Complex* src, Index nfft) {
280 m_impl.inv(dst, src,
static_cast<int>(nfft));
281 if (HasFlag(Unscaled) ==
false) scale(dst, Scalar(1. / nfft), nfft);
284 inline void inv(Scalar* dst,
const Complex* src, Index nfft) {
285 m_impl.inv(dst, src,
static_cast<int>(nfft));
286 if (HasFlag(Unscaled) ==
false) scale(dst, Scalar(1. / nfft), nfft);
289 template <
typename OutputDerived,
typename ComplexDerived>
290 inline void inv(MatrixBase<OutputDerived>& dst,
const MatrixBase<ComplexDerived>& src, Index nfft = -1) {
291 typedef typename ComplexDerived::Scalar src_type;
292 typedef typename ComplexDerived::RealScalar real_type;
293 typedef typename OutputDerived::Scalar dst_type;
294 const bool realfft = (NumTraits<dst_type>::IsComplex == 0);
295 EIGEN_STATIC_ASSERT_VECTOR_ONLY(OutputDerived)
296 EIGEN_STATIC_ASSERT_VECTOR_ONLY(ComplexDerived)
297 EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(ComplexDerived, OutputDerived)
299 (internal::is_same<src_type, Complex>::value),
300 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
301 EIGEN_STATIC_ASSERT(
int(OutputDerived::Flags) &
int(ComplexDerived::Flags) &
DirectAccessBit,
302 THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES)
305 if (realfft && HasFlag(HalfSpectrum))
306 nfft = 2 * (src.size() - 1);
310 dst.derived().resize(nfft);
313 Index resize_input = (realfft && HasFlag(HalfSpectrum)) ? ((nfft / 2 + 1) - src.size()) : (nfft - src.size());
315 if (src.innerStride() != 1 || resize_input) {
317 Matrix<src_type, 1, Dynamic> tmp;
319 size_t ncopy = (std::min)(src.size(), src.size() + resize_input);
320 tmp.setZero(src.size() + resize_input);
321 if (realfft && HasFlag(HalfSpectrum)) {
323 tmp.head(ncopy) = src.head(ncopy);
324 tmp(ncopy - 1) =
real(tmp(ncopy - 1));
327 nhead = 1 + ncopy / 2 - 1;
328 ntail = ncopy / 2 - 1;
329 tmp.head(nhead) = src.head(nhead);
330 tmp.tail(ntail) = src.tail(ntail);
333 tmp(nhead) = (src(nfft / 2) + src(src.size() - nfft / 2)) * real_type(.5);
335 tmp(nhead) = src(nhead) * real_type(.5);
336 tmp(tmp.size() - nhead) = tmp(nhead);
343 if (dst.innerStride() != 1) {
344 Matrix<dst_type, 1, Dynamic> out(1, nfft);
345 inv(&out[0], &tmp[0], nfft);
348 inv(&dst[0], &tmp[0], nfft);
351 if (dst.innerStride() != 1) {
352 Matrix<dst_type, 1, Dynamic> out(1, nfft);
353 inv(&out[0], &src[0], nfft);
356 inv(&dst[0], &src[0], nfft);
361 template <
typename Output_>
362 inline void inv(std::vector<Output_>& dst,
const std::vector<Complex>& src, Index nfft = -1) {
364 nfft = (NumTraits<Output_>::IsComplex == 0 && HasFlag(HalfSpectrum)) ? 2 * (src.size() - 1) : src.size();
366 inv(&dst[0], &src[0], nfft);
369#if defined EIGEN_FFTW_DEFAULT || defined EIGEN_POCKETFFT_DEFAULT || defined EIGEN_MKL_DEFAULT
370 inline void inv2(Complex* dst,
const Complex* src,
int n0,
int n1) {
371 m_impl.inv2(dst, src, n0, n1);
372 if (HasFlag(Unscaled) ==
false) scale(dst, 1. / (n0 * n1), n0 * n1);
376 inline impl_type& impl() {
return m_impl; }
379 template <
typename T_Data>
380 inline void scale(T_Data* x, Scalar s, Index nx) {
382 for (
int k = 0; k < nx; ++k) *x++ *= s;
384 if (((ptrdiff_t)x) & 15)
385 Matrix<T_Data, Dynamic, 1>::Map(x, nx) *= s;
387 Matrix<T_Data, Dynamic, 1>::MapAligned(x, nx) *= s;
392 inline void ReflectSpectrum(Complex* freq, Index nfft) {
394 Index nhbins = (nfft >> 1) + 1;
395 for (Index k = nhbins; k < nfft; ++k) freq[k] =
conj(freq[nfft - k]);
402template <
typename T_SrcMat,
typename T_FftIfc>
403template <
typename T_DestMat>
404inline void fft_fwd_proxy<T_SrcMat, T_FftIfc>::evalTo(T_DestMat& dst)
const {
405 m_ifc.fwd(dst, m_src, m_nfft);
408template <
typename T_SrcMat,
typename T_FftIfc>
409template <
typename T_DestMat>
410inline void fft_inv_proxy<T_SrcMat, T_FftIfc>::evalTo(T_DestMat& dst)
const {
411 m_ifc.inv(dst, m_src, m_nfft);
416#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
const unsigned int DirectAccessBit
Namespace containing all symbols from the Eigen library.
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_real_op< typename Derived::Scalar >, const Derived > real(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_conjugate_op< typename Derived::Scalar >, const Derived > conj(const Eigen::ArrayBase< Derived > &x)