File indexing completed on 2025-01-18 09:57:03
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 namespace Eigen {
0011
0012 namespace internal {
0013
0014
0015
0016
0017 template <typename _Scalar>
0018 struct kiss_cpx_fft
0019 {
0020 typedef _Scalar Scalar;
0021 typedef std::complex<Scalar> Complex;
0022 std::vector<Complex> m_twiddles;
0023 std::vector<int> m_stageRadix;
0024 std::vector<int> m_stageRemainder;
0025 std::vector<Complex> m_scratchBuf;
0026 bool m_inverse;
0027
0028 inline void make_twiddles(int nfft, bool inverse)
0029 {
0030 using numext::sin;
0031 using numext::cos;
0032 m_inverse = inverse;
0033 m_twiddles.resize(nfft);
0034 double phinc = 0.25 * double(EIGEN_PI) / nfft;
0035 Scalar flip = inverse ? Scalar(1) : Scalar(-1);
0036 m_twiddles[0] = Complex(Scalar(1), Scalar(0));
0037 if ((nfft&1)==0)
0038 m_twiddles[nfft/2] = Complex(Scalar(-1), Scalar(0));
0039 int i=1;
0040 for (;i*8<nfft;++i)
0041 {
0042 Scalar c = Scalar(cos(i*8*phinc));
0043 Scalar s = Scalar(sin(i*8*phinc));
0044 m_twiddles[i] = Complex(c, s*flip);
0045 m_twiddles[nfft-i] = Complex(c, -s*flip);
0046 }
0047 for (;i*4<nfft;++i)
0048 {
0049 Scalar c = Scalar(cos((2*nfft-8*i)*phinc));
0050 Scalar s = Scalar(sin((2*nfft-8*i)*phinc));
0051 m_twiddles[i] = Complex(s, c*flip);
0052 m_twiddles[nfft-i] = Complex(s, -c*flip);
0053 }
0054 for (;i*8<3*nfft;++i)
0055 {
0056 Scalar c = Scalar(cos((8*i-2*nfft)*phinc));
0057 Scalar s = Scalar(sin((8*i-2*nfft)*phinc));
0058 m_twiddles[i] = Complex(-s, c*flip);
0059 m_twiddles[nfft-i] = Complex(-s, -c*flip);
0060 }
0061 for (;i*2<nfft;++i)
0062 {
0063 Scalar c = Scalar(cos((4*nfft-8*i)*phinc));
0064 Scalar s = Scalar(sin((4*nfft-8*i)*phinc));
0065 m_twiddles[i] = Complex(-c, s*flip);
0066 m_twiddles[nfft-i] = Complex(-c, -s*flip);
0067 }
0068 }
0069
0070 void factorize(int nfft)
0071 {
0072
0073 int n= nfft;
0074 int p=4;
0075 do {
0076 while (n % p) {
0077 switch (p) {
0078 case 4: p = 2; break;
0079 case 2: p = 3; break;
0080 default: p += 2; break;
0081 }
0082 if (p*p>n)
0083 p=n;
0084 }
0085 n /= p;
0086 m_stageRadix.push_back(p);
0087 m_stageRemainder.push_back(n);
0088 if ( p > 5 )
0089 m_scratchBuf.resize(p);
0090 }while(n>1);
0091 }
0092
0093 template <typename _Src>
0094 inline
0095 void work( int stage,Complex * xout, const _Src * xin, size_t fstride,size_t in_stride)
0096 {
0097 int p = m_stageRadix[stage];
0098 int m = m_stageRemainder[stage];
0099 Complex * Fout_beg = xout;
0100 Complex * Fout_end = xout + p*m;
0101
0102 if (m>1) {
0103 do{
0104
0105
0106
0107
0108 work(stage+1, xout , xin, fstride*p,in_stride);
0109 xin += fstride*in_stride;
0110 }while( (xout += m) != Fout_end );
0111 }else{
0112 do{
0113 *xout = *xin;
0114 xin += fstride*in_stride;
0115 }while(++xout != Fout_end );
0116 }
0117 xout=Fout_beg;
0118
0119
0120 switch (p) {
0121 case 2: bfly2(xout,fstride,m); break;
0122 case 3: bfly3(xout,fstride,m); break;
0123 case 4: bfly4(xout,fstride,m); break;
0124 case 5: bfly5(xout,fstride,m); break;
0125 default: bfly_generic(xout,fstride,m,p); break;
0126 }
0127 }
0128
0129 inline
0130 void bfly2( Complex * Fout, const size_t fstride, int m)
0131 {
0132 for (int k=0;k<m;++k) {
0133 Complex t = Fout[m+k] * m_twiddles[k*fstride];
0134 Fout[m+k] = Fout[k] - t;
0135 Fout[k] += t;
0136 }
0137 }
0138
0139 inline
0140 void bfly4( Complex * Fout, const size_t fstride, const size_t m)
0141 {
0142 Complex scratch[6];
0143 int negative_if_inverse = m_inverse * -2 +1;
0144 for (size_t k=0;k<m;++k) {
0145 scratch[0] = Fout[k+m] * m_twiddles[k*fstride];
0146 scratch[1] = Fout[k+2*m] * m_twiddles[k*fstride*2];
0147 scratch[2] = Fout[k+3*m] * m_twiddles[k*fstride*3];
0148 scratch[5] = Fout[k] - scratch[1];
0149
0150 Fout[k] += scratch[1];
0151 scratch[3] = scratch[0] + scratch[2];
0152 scratch[4] = scratch[0] - scratch[2];
0153 scratch[4] = Complex( scratch[4].imag()*negative_if_inverse , -scratch[4].real()* negative_if_inverse );
0154
0155 Fout[k+2*m] = Fout[k] - scratch[3];
0156 Fout[k] += scratch[3];
0157 Fout[k+m] = scratch[5] + scratch[4];
0158 Fout[k+3*m] = scratch[5] - scratch[4];
0159 }
0160 }
0161
0162 inline
0163 void bfly3( Complex * Fout, const size_t fstride, const size_t m)
0164 {
0165 size_t k=m;
0166 const size_t m2 = 2*m;
0167 Complex *tw1,*tw2;
0168 Complex scratch[5];
0169 Complex epi3;
0170 epi3 = m_twiddles[fstride*m];
0171
0172 tw1=tw2=&m_twiddles[0];
0173
0174 do{
0175 scratch[1]=Fout[m] * *tw1;
0176 scratch[2]=Fout[m2] * *tw2;
0177
0178 scratch[3]=scratch[1]+scratch[2];
0179 scratch[0]=scratch[1]-scratch[2];
0180 tw1 += fstride;
0181 tw2 += fstride*2;
0182 Fout[m] = Complex( Fout->real() - Scalar(.5)*scratch[3].real() , Fout->imag() - Scalar(.5)*scratch[3].imag() );
0183 scratch[0] *= epi3.imag();
0184 *Fout += scratch[3];
0185 Fout[m2] = Complex( Fout[m].real() + scratch[0].imag() , Fout[m].imag() - scratch[0].real() );
0186 Fout[m] += Complex( -scratch[0].imag(),scratch[0].real() );
0187 ++Fout;
0188 }while(--k);
0189 }
0190
0191 inline
0192 void bfly5( Complex * Fout, const size_t fstride, const size_t m)
0193 {
0194 Complex *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
0195 size_t u;
0196 Complex scratch[13];
0197 Complex * twiddles = &m_twiddles[0];
0198 Complex *tw;
0199 Complex ya,yb;
0200 ya = twiddles[fstride*m];
0201 yb = twiddles[fstride*2*m];
0202
0203 Fout0=Fout;
0204 Fout1=Fout0+m;
0205 Fout2=Fout0+2*m;
0206 Fout3=Fout0+3*m;
0207 Fout4=Fout0+4*m;
0208
0209 tw=twiddles;
0210 for ( u=0; u<m; ++u ) {
0211 scratch[0] = *Fout0;
0212
0213 scratch[1] = *Fout1 * tw[u*fstride];
0214 scratch[2] = *Fout2 * tw[2*u*fstride];
0215 scratch[3] = *Fout3 * tw[3*u*fstride];
0216 scratch[4] = *Fout4 * tw[4*u*fstride];
0217
0218 scratch[7] = scratch[1] + scratch[4];
0219 scratch[10] = scratch[1] - scratch[4];
0220 scratch[8] = scratch[2] + scratch[3];
0221 scratch[9] = scratch[2] - scratch[3];
0222
0223 *Fout0 += scratch[7];
0224 *Fout0 += scratch[8];
0225
0226 scratch[5] = scratch[0] + Complex(
0227 (scratch[7].real()*ya.real() ) + (scratch[8].real() *yb.real() ),
0228 (scratch[7].imag()*ya.real()) + (scratch[8].imag()*yb.real())
0229 );
0230
0231 scratch[6] = Complex(
0232 (scratch[10].imag()*ya.imag()) + (scratch[9].imag()*yb.imag()),
0233 -(scratch[10].real()*ya.imag()) - (scratch[9].real()*yb.imag())
0234 );
0235
0236 *Fout1 = scratch[5] - scratch[6];
0237 *Fout4 = scratch[5] + scratch[6];
0238
0239 scratch[11] = scratch[0] +
0240 Complex(
0241 (scratch[7].real()*yb.real()) + (scratch[8].real()*ya.real()),
0242 (scratch[7].imag()*yb.real()) + (scratch[8].imag()*ya.real())
0243 );
0244
0245 scratch[12] = Complex(
0246 -(scratch[10].imag()*yb.imag()) + (scratch[9].imag()*ya.imag()),
0247 (scratch[10].real()*yb.imag()) - (scratch[9].real()*ya.imag())
0248 );
0249
0250 *Fout2=scratch[11]+scratch[12];
0251 *Fout3=scratch[11]-scratch[12];
0252
0253 ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
0254 }
0255 }
0256
0257
0258 inline
0259 void bfly_generic(
0260 Complex * Fout,
0261 const size_t fstride,
0262 int m,
0263 int p
0264 )
0265 {
0266 int u,k,q1,q;
0267 Complex * twiddles = &m_twiddles[0];
0268 Complex t;
0269 int Norig = static_cast<int>(m_twiddles.size());
0270 Complex * scratchbuf = &m_scratchBuf[0];
0271
0272 for ( u=0; u<m; ++u ) {
0273 k=u;
0274 for ( q1=0 ; q1<p ; ++q1 ) {
0275 scratchbuf[q1] = Fout[ k ];
0276 k += m;
0277 }
0278
0279 k=u;
0280 for ( q1=0 ; q1<p ; ++q1 ) {
0281 int twidx=0;
0282 Fout[ k ] = scratchbuf[0];
0283 for (q=1;q<p;++q ) {
0284 twidx += static_cast<int>(fstride) * k;
0285 if (twidx>=Norig) twidx-=Norig;
0286 t=scratchbuf[q] * twiddles[twidx];
0287 Fout[ k ] += t;
0288 }
0289 k += m;
0290 }
0291 }
0292 }
0293 };
0294
0295 template <typename _Scalar>
0296 struct kissfft_impl
0297 {
0298 typedef _Scalar Scalar;
0299 typedef std::complex<Scalar> Complex;
0300
0301 void clear()
0302 {
0303 m_plans.clear();
0304 m_realTwiddles.clear();
0305 }
0306
0307 inline
0308 void fwd( Complex * dst,const Complex *src,int nfft)
0309 {
0310 get_plan(nfft,false).work(0, dst, src, 1,1);
0311 }
0312
0313 inline
0314 void fwd2( Complex * dst,const Complex *src,int n0,int n1)
0315 {
0316 EIGEN_UNUSED_VARIABLE(dst);
0317 EIGEN_UNUSED_VARIABLE(src);
0318 EIGEN_UNUSED_VARIABLE(n0);
0319 EIGEN_UNUSED_VARIABLE(n1);
0320 }
0321
0322 inline
0323 void inv2( Complex * dst,const Complex *src,int n0,int n1)
0324 {
0325 EIGEN_UNUSED_VARIABLE(dst);
0326 EIGEN_UNUSED_VARIABLE(src);
0327 EIGEN_UNUSED_VARIABLE(n0);
0328 EIGEN_UNUSED_VARIABLE(n1);
0329 }
0330
0331
0332
0333
0334
0335 inline
0336 void fwd( Complex * dst,const Scalar * src,int nfft)
0337 {
0338 if ( nfft&3 ) {
0339
0340 m_tmpBuf1.resize(nfft);
0341 get_plan(nfft,false).work(0, &m_tmpBuf1[0], src, 1,1);
0342 std::copy(m_tmpBuf1.begin(),m_tmpBuf1.begin()+(nfft>>1)+1,dst );
0343 }else{
0344 int ncfft = nfft>>1;
0345 int ncfft2 = nfft>>2;
0346 Complex * rtw = real_twiddles(ncfft2);
0347
0348
0349 fwd( dst, reinterpret_cast<const Complex*> (src), ncfft);
0350 Complex dc(dst[0].real() + dst[0].imag());
0351 Complex nyquist(dst[0].real() - dst[0].imag());
0352 int k;
0353 for ( k=1;k <= ncfft2 ; ++k ) {
0354 Complex fpk = dst[k];
0355 Complex fpnk = conj(dst[ncfft-k]);
0356 Complex f1k = fpk + fpnk;
0357 Complex f2k = fpk - fpnk;
0358 Complex tw= f2k * rtw[k-1];
0359 dst[k] = (f1k + tw) * Scalar(.5);
0360 dst[ncfft-k] = conj(f1k -tw)*Scalar(.5);
0361 }
0362 dst[0] = dc;
0363 dst[ncfft] = nyquist;
0364 }
0365 }
0366
0367
0368 inline
0369 void inv(Complex * dst,const Complex *src,int nfft)
0370 {
0371 get_plan(nfft,true).work(0, dst, src, 1,1);
0372 }
0373
0374
0375 inline
0376 void inv( Scalar * dst,const Complex * src,int nfft)
0377 {
0378 if (nfft&3) {
0379 m_tmpBuf1.resize(nfft);
0380 m_tmpBuf2.resize(nfft);
0381 std::copy(src,src+(nfft>>1)+1,m_tmpBuf1.begin() );
0382 for (int k=1;k<(nfft>>1)+1;++k)
0383 m_tmpBuf1[nfft-k] = conj(m_tmpBuf1[k]);
0384 inv(&m_tmpBuf2[0],&m_tmpBuf1[0],nfft);
0385 for (int k=0;k<nfft;++k)
0386 dst[k] = m_tmpBuf2[k].real();
0387 }else{
0388
0389 int ncfft = nfft>>1;
0390 int ncfft2 = nfft>>2;
0391 Complex * rtw = real_twiddles(ncfft2);
0392 m_tmpBuf1.resize(ncfft);
0393 m_tmpBuf1[0] = Complex( src[0].real() + src[ncfft].real(), src[0].real() - src[ncfft].real() );
0394 for (int k = 1; k <= ncfft / 2; ++k) {
0395 Complex fk = src[k];
0396 Complex fnkc = conj(src[ncfft-k]);
0397 Complex fek = fk + fnkc;
0398 Complex tmp = fk - fnkc;
0399 Complex fok = tmp * conj(rtw[k-1]);
0400 m_tmpBuf1[k] = fek + fok;
0401 m_tmpBuf1[ncfft-k] = conj(fek - fok);
0402 }
0403 get_plan(ncfft,true).work(0, reinterpret_cast<Complex*>(dst), &m_tmpBuf1[0], 1,1);
0404 }
0405 }
0406
0407 protected:
0408 typedef kiss_cpx_fft<Scalar> PlanData;
0409 typedef std::map<int,PlanData> PlanMap;
0410
0411 PlanMap m_plans;
0412 std::map<int, std::vector<Complex> > m_realTwiddles;
0413 std::vector<Complex> m_tmpBuf1;
0414 std::vector<Complex> m_tmpBuf2;
0415
0416 inline
0417 int PlanKey(int nfft, bool isinverse) const { return (nfft<<1) | int(isinverse); }
0418
0419 inline
0420 PlanData & get_plan(int nfft, bool inverse)
0421 {
0422
0423 PlanData & pd = m_plans[ PlanKey(nfft,inverse) ];
0424 if ( pd.m_twiddles.size() == 0 ) {
0425 pd.make_twiddles(nfft,inverse);
0426 pd.factorize(nfft);
0427 }
0428 return pd;
0429 }
0430
0431 inline
0432 Complex * real_twiddles(int ncfft2)
0433 {
0434 using std::acos;
0435 std::vector<Complex> & twidref = m_realTwiddles[ncfft2];
0436 if ( (int)twidref.size() != ncfft2 ) {
0437 twidref.resize(ncfft2);
0438 int ncfft= ncfft2<<1;
0439 Scalar pi = acos( Scalar(-1) );
0440 for (int k=1;k<=ncfft2;++k)
0441 twidref[k-1] = exp( Complex(0,-pi * (Scalar(k) / ncfft + Scalar(.5)) ) );
0442 }
0443 return &twidref[0];
0444 }
0445 };
0446
0447 }
0448
0449 }