17 template <
typename _Scalar>
33 m_twiddles.resize(nfft);
34 Scalar phinc = (inverse?2:-2)*
acos( (Scalar) -1) / nfft;
35 for (
int i=0;i<nfft;++i)
49 default: p += 2;
break;
55 m_stageRadix.push_back(p);
56 m_stageRemainder.push_back(n);
58 m_scratchBuf.resize(p);
62 template <
typename _Src>
64 void work(
int stage,Complex * xout,
const _Src * xin,
size_t fstride,
size_t in_stride)
66 int p = m_stageRadix[stage];
67 int m = m_stageRemainder[stage];
68 Complex * Fout_beg = xout;
69 Complex * Fout_end = xout + p*m;
77 work(stage+1, xout , xin, fstride*p,in_stride);
78 xin += fstride*in_stride;
79 }
while( (xout += m) != Fout_end );
83 xin += fstride*in_stride;
84 }
while(++xout != Fout_end );
90 case 2:
bfly2(xout,fstride,m);
break;
91 case 3:
bfly3(xout,fstride,m);
break;
92 case 4:
bfly4(xout,fstride,m);
break;
93 case 5:
bfly5(xout,fstride,m);
break;
99 void bfly2( Complex * Fout,
const size_t fstride,
int m)
101 for (
int k=0;k<m;++k) {
102 Complex t = Fout[m+k] * m_twiddles[k*fstride];
103 Fout[m+k] = Fout[k] - t;
109 void bfly4( Complex * Fout,
const size_t fstride,
const size_t m)
112 int negative_if_inverse = m_inverse * -2 +1;
113 for (
size_t k=0;k<m;++k) {
114 scratch[0] = Fout[k+m] * m_twiddles[k*fstride];
115 scratch[1] = Fout[k+2*m] * m_twiddles[k*fstride*2];
116 scratch[2] = Fout[k+3*m] * m_twiddles[k*fstride*3];
117 scratch[5] = Fout[k] - scratch[1];
119 Fout[k] += scratch[1];
120 scratch[3] = scratch[0] + scratch[2];
121 scratch[4] = scratch[0] - scratch[2];
122 scratch[4] =
Complex( scratch[4].
imag()*negative_if_inverse , -scratch[4].
real()* negative_if_inverse );
124 Fout[k+2*m] = Fout[k] - scratch[3];
125 Fout[k] += scratch[3];
126 Fout[k+m] = scratch[5] + scratch[4];
127 Fout[k+3*m] = scratch[5] - scratch[4];
132 void bfly3( Complex * Fout,
const size_t fstride,
const size_t m)
135 const size_t m2 = 2*m;
139 epi3 = m_twiddles[fstride*m];
141 tw1=tw2=&m_twiddles[0];
144 scratch[1]=Fout[m] * *tw1;
145 scratch[2]=Fout[m2] * *tw2;
147 scratch[3]=scratch[1]+scratch[2];
148 scratch[0]=scratch[1]-scratch[2];
151 Fout[m] =
Complex( Fout->real() -
Scalar(.5)*scratch[3].real() , Fout->imag() -
Scalar(.5)*scratch[3].imag() );
152 scratch[0] *= epi3.imag();
161 void bfly5( Complex * Fout,
const size_t fstride,
const size_t m)
163 Complex *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
166 Complex * twiddles = &m_twiddles[0];
169 ya = twiddles[fstride*m];
170 yb = twiddles[fstride*2*m];
179 for ( u=0; u<m; ++u ) {
182 scratch[1] = *Fout1 * tw[u*fstride];
183 scratch[2] = *Fout2 * tw[2*u*fstride];
184 scratch[3] = *Fout3 * tw[3*u*fstride];
185 scratch[4] = *Fout4 * tw[4*u*fstride];
187 scratch[7] = scratch[1] + scratch[4];
188 scratch[10] = scratch[1] - scratch[4];
189 scratch[8] = scratch[2] + scratch[3];
190 scratch[9] = scratch[2] - scratch[3];
192 *Fout0 += scratch[7];
193 *Fout0 += scratch[8];
195 scratch[5] = scratch[0] +
Complex(
196 (scratch[7].
real()*ya.real() ) + (scratch[8].
real() *yb.real() ),
197 (scratch[7].
imag()*ya.real()) + (scratch[8].
imag()*yb.real())
201 (scratch[10].
imag()*ya.imag()) + (scratch[9].
imag()*yb.imag()),
202 -(scratch[10].
real()*ya.imag()) - (scratch[9].
real()*yb.imag())
205 *Fout1 = scratch[5] - scratch[6];
206 *Fout4 = scratch[5] + scratch[6];
208 scratch[11] = scratch[0] +
210 (scratch[7].
real()*yb.real()) + (scratch[8].
real()*ya.real()),
211 (scratch[7].
imag()*yb.real()) + (scratch[8].
imag()*ya.real())
215 -(scratch[10].
imag()*yb.imag()) + (scratch[9].
imag()*ya.imag()),
216 (scratch[10].
real()*yb.imag()) - (scratch[9].
real()*ya.imag())
219 *Fout2=scratch[11]+scratch[12];
220 *Fout3=scratch[11]-scratch[12];
222 ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
230 const size_t fstride,
236 Complex * twiddles = &m_twiddles[0];
238 int Norig =
static_cast<int>(m_twiddles.size());
239 Complex * scratchbuf = &m_scratchBuf[0];
241 for ( u=0; u<m; ++u ) {
243 for ( q1=0 ; q1<p ; ++q1 ) {
244 scratchbuf[q1] = Fout[ k ];
249 for ( q1=0 ; q1<p ; ++q1 ) {
251 Fout[ k ] = scratchbuf[0];
253 twidx +=
static_cast<int>(fstride) * k;
254 if (twidx>=Norig) twidx-=Norig;
255 t=scratchbuf[q] * twiddles[twidx];
264 template <
typename _Scalar>
273 m_realTwiddles.clear();
277 void fwd( Complex * dst,
const Complex *src,
int nfft)
279 get_plan(nfft,
false).work(0, dst, src, 1,1);
283 void fwd2( Complex * dst,
const Complex *src,
int n0,
int n1)
292 void inv2( Complex * dst,
const Complex *src,
int n0,
int n1)
305 void fwd( Complex * dst,
const Scalar * src,
int nfft)
309 m_tmpBuf1.resize(nfft);
310 get_plan(nfft,
false).work(0, &m_tmpBuf1[0], src, 1,1);
311 std::copy(m_tmpBuf1.begin(),m_tmpBuf1.begin()+(nfft>>1)+1,dst );
314 int ncfft2 = nfft>>2;
315 Complex * rtw = real_twiddles(ncfft2);
318 fwd( dst, reinterpret_cast<const Complex*> (src), ncfft);
319 Complex dc = dst[0].real() + dst[0].imag();
320 Complex nyquist = dst[0].real() - dst[0].imag();
322 for ( k=1;k <= ncfft2 ; ++k ) {
323 Complex fpk = dst[k];
324 Complex fpnk =
conj(dst[ncfft-k]);
325 Complex f1k = fpk + fpnk;
326 Complex f2k = fpk - fpnk;
327 Complex tw= f2k * rtw[k-1];
328 dst[k] = (f1k + tw) *
Scalar(.5);
332 dst[ncfft] = nyquist;
338 void inv(Complex * dst,
const Complex *src,
int nfft)
340 get_plan(nfft,
true).work(0, dst, src, 1,1);
345 void inv( Scalar * dst,
const Complex * src,
int nfft)
348 m_tmpBuf1.resize(nfft);
349 m_tmpBuf2.resize(nfft);
350 std::copy(src,src+(nfft>>1)+1,m_tmpBuf1.begin() );
351 for (
int k=1;k<(nfft>>1)+1;++k)
352 m_tmpBuf1[nfft-k] =
conj(m_tmpBuf1[k]);
353 inv(&m_tmpBuf2[0],&m_tmpBuf1[0],nfft);
354 for (
int k=0;k<nfft;++k)
355 dst[k] = m_tmpBuf2[k].
real();
359 int ncfft2 = nfft>>2;
360 Complex * rtw = real_twiddles(ncfft2);
361 m_tmpBuf1.resize(ncfft);
363 for (
int k = 1; k <= ncfft / 2; ++k) {
365 Complex fnkc =
conj(src[ncfft-k]);
366 Complex fek = fk + fnkc;
367 Complex tmp = fk - fnkc;
368 Complex fok = tmp *
conj(rtw[k-1]);
369 m_tmpBuf1[k] = fek + fok;
370 m_tmpBuf1[ncfft-k] =
conj(fek - fok);
372 get_plan(ncfft,
true).work(0, reinterpret_cast<Complex*>(dst), &m_tmpBuf1[0], 1,1);
386 int PlanKey(
int nfft,
bool isinverse)
const {
return (nfft<<1) | int(isinverse); }
392 PlanData & pd = m_plans[ PlanKey(nfft,inverse) ];
404 std::vector<Complex> & twidref = m_realTwiddles[ncfft2];
405 if ( (
int)twidref.size() != ncfft2 ) {
406 twidref.resize(ncfft2);
407 int ncfft= ncfft2<<1;
409 for (
int k=1;k<=ncfft2;++k)
PlanData & get_plan(int nfft, bool inverse)
const AutoDiffScalar< DerType > & conj(const AutoDiffScalar< DerType > &x)
#define EIGEN_UNUSED_VARIABLE(var)
std::complex< Scalar > Complex
std::vector< Complex > m_twiddles
iterative scaling algorithm to equilibrate rows and column norms in matrices
DerType::Scalar imag(const AutoDiffScalar< DerType > &)
void bfly_generic(Complex *Fout, const size_t fstride, int m, int p)
void inv(Scalar *dst, const Complex *src, int nfft)
void bfly5(Complex *Fout, const size_t fstride, const size_t m)
std::complex< Scalar > Complex
std::map< int, std::vector< Complex > > m_realTwiddles
void inv(Complex *dst, const Complex *src, int nfft)
const CwiseUnaryOp< internal::scalar_inverse_op< Scalar >, const Derived > inverse() const
void bfly3(Complex *Fout, const size_t fstride, const size_t m)
std::map< int, PlanData > PlanMap
IntermediateState acos(const Expression &arg)
std::vector< Complex > m_scratchBuf
std::vector< int > m_stageRemainder
void fwd(Complex *dst, const Scalar *src, int nfft)
void bfly4(Complex *Fout, const size_t fstride, const size_t m)
void make_twiddles(int nfft, bool inverse)
Complex * real_twiddles(int ncfft2)
void fwd(Complex *dst, const Complex *src, int nfft)
kiss_cpx_fft< Scalar > PlanData
void work(int stage, Complex *xout, const _Src *xin, size_t fstride, size_t in_stride)
std::vector< int > m_stageRadix
void fwd2(Complex *dst, const Complex *src, int n0, int n1)
IntermediateState exp(const Expression &arg)
int PlanKey(int nfft, bool isinverse) const
void inv2(Complex *dst, const Complex *src, int n0, int n1)
std::vector< Complex > m_tmpBuf2
const AutoDiffScalar< DerType > & real(const AutoDiffScalar< DerType > &x)
std::vector< Complex > m_tmpBuf1
void bfly2(Complex *Fout, const size_t fstride, int m)