1 #ifndef KISSFFT_CLASS_HH
2 #define KISSFFT_CLASS_HH
8 template <
typename T_scalar>
13 void fill_twiddles( std::complex<T_scalar> * dst ,
int nfft,
bool inverse)
15 T_scalar phinc = (inverse?2:-2)* acos( (T_scalar) -1) / nfft;
16 for (
int i=0;i<nfft;++i)
17 dst[i] = exp( std::complex<T_scalar>(0,i*phinc) );
21 std::vector< std::complex<T_scalar> > & dst,
22 int nfft,
bool inverse,
23 std::vector<int> & stageRadix,
24 std::vector<int> & stageRemainder )
39 default: p += 2;
break;
45 stageRadix.push_back(p);
46 stageRemainder.push_back(n);
57 template <
typename T_Scalar,
65 typedef typename traits_type::cpx_type
cpx_type;
89 f += fstride*in_stride;
90 }
while(++Fout != Fout_end );
97 kf_work(stage+1, Fout , f, fstride*p,in_stride);
98 f += fstride*in_stride;
99 }
while( (Fout += m) != Fout_end );
106 case 2:
kf_bfly2(Fout,fstride,m);
break;
107 case 3:
kf_bfly3(Fout,fstride,m);
break;
108 case 4:
kf_bfly4(Fout,fstride,m);
break;
109 case 5:
kf_bfly5(Fout,fstride,m);
break;
126 for (
int k=0;k<m;++k) {
128 Fout[m+k] = Fout[k] - t;
136 int negative_if_inverse =
_inverse * -2 +1;
137 for (
size_t k=0;k<m;++k) {
138 scratch[0] = Fout[k+m] *
_traits.twiddle(k*fstride);
139 scratch[1] = Fout[k+2*m] *
_traits.twiddle(k*fstride*2);
140 scratch[2] = Fout[k+3*m] *
_traits.twiddle(k*fstride*3);
141 scratch[5] = Fout[k] - scratch[1];
143 Fout[k] += scratch[1];
144 scratch[3] = scratch[0] + scratch[2];
145 scratch[4] = scratch[0] - scratch[2];
146 scratch[4] =
cpx_type( scratch[4].imag()*negative_if_inverse , -scratch[4].real()* negative_if_inverse );
148 Fout[k+2*m] = Fout[k] - scratch[3];
149 Fout[k] += scratch[3];
150 Fout[k+m] = scratch[5] + scratch[4];
151 Fout[k+3*m] = scratch[5] - scratch[4];
158 const size_t m2 = 2*m;
169 C_MUL(scratch[1],Fout[m] , *tw1);
170 C_MUL(scratch[2],Fout[m2] , *tw2);
172 C_ADD(scratch[3],scratch[1],scratch[2]);
173 C_SUB(scratch[0],scratch[1],scratch[2]);
177 Fout[m] =
cpx_type( Fout->real() -
HALF_OF(scratch[3].real() ) , Fout->imag() -
HALF_OF(scratch[3].imag() ) );
183 Fout[m2] =
cpx_type( Fout[m].real() + scratch[0].imag() , Fout[m].imag() - scratch[0].real() );
192 cpx_type *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
198 ya = twiddles[fstride*m];
199 yb = twiddles[fstride*2*m];
208 for ( u=0; u<m; ++u ) {
212 C_MUL(scratch[1] ,*Fout1, tw[u*fstride]);
213 C_MUL(scratch[2] ,*Fout2, tw[2*u*fstride]);
214 C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]);
215 C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]);
217 C_ADD( scratch[7],scratch[1],scratch[4]);
218 C_SUB( scratch[10],scratch[1],scratch[4]);
219 C_ADD( scratch[8],scratch[2],scratch[3]);
220 C_SUB( scratch[9],scratch[2],scratch[3]);
226 S_MUL(scratch[7].real(),ya.real() ) +
S_MUL(scratch[8].real() ,yb.real() ),
227 S_MUL(scratch[7].imag(),ya.real()) +
S_MUL(scratch[8].imag(),yb.real())
231 S_MUL(scratch[10].imag(),ya.imag()) +
S_MUL(scratch[9].imag(),yb.imag()),
232 -
S_MUL(scratch[10].real(),ya.imag()) -
S_MUL(scratch[9].real(),yb.imag())
235 C_SUB(*Fout1,scratch[5],scratch[6]);
236 C_ADD(*Fout4,scratch[5],scratch[6]);
238 scratch[11] = scratch[0] +
240 S_MUL(scratch[7].real(),yb.real()) +
S_MUL(scratch[8].real(),ya.real()),
241 S_MUL(scratch[7].imag(),yb.real()) +
S_MUL(scratch[8].imag(),ya.real())
245 -
S_MUL(scratch[10].imag(),yb.imag()) +
S_MUL(scratch[9].imag(),ya.imag()),
246 S_MUL(scratch[10].real(),yb.imag()) -
S_MUL(scratch[9].real(),ya.imag())
249 C_ADD(*Fout2,scratch[11],scratch[12]);
250 C_SUB(*Fout3,scratch[11],scratch[12]);
252 ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
259 const size_t fstride,
270 for ( u=0; u<m; ++u ) {
272 for ( q1=0 ; q1<p ; ++q1 ) {
273 scratchbuf[q1] = Fout[ k ];
279 for ( q1=0 ; q1<p ; ++q1 ) {
281 Fout[ k ] = scratchbuf[0];
283 twidx += fstride * k;
284 if (twidx>=Norig) twidx-=Norig;
285 C_MUL(t,scratchbuf[q] , twiddles[twidx] );
traits_type::scalar_type scalar_type
std::vector< int > _stageRemainder
scalar_type S_MUL(const scalar_type &a, const scalar_type &b)
void C_ADDTO(cpx_type &c, const cpx_type &a)
void C_SUB(cpx_type &c, const cpx_type &a, const cpx_type &b)
void C_MULBYSCALAR(cpx_type &c, const scalar_type &a)
void kf_work(int stage, cpx_type *Fout, const cpx_type *f, size_t fstride, size_t in_stride)
void C_ADD(cpx_type &c, const cpx_type &a, const cpx_type &b)
void kf_bfly3(cpx_type *Fout, const size_t fstride, const size_t m)
void kf_bfly4(cpx_type *Fout, const size_t fstride, const size_t m)
void kf_bfly2(cpx_type *Fout, const size_t fstride, int m)
std::vector< int > _stageRadix
kissfft(int nfft, bool inverse, const traits_type &traits=traits_type())
std::vector< cpx_type > _twiddles
void kf_bfly_generic(cpx_type *Fout, const size_t fstride, int m, int p)
scalar_type HALF_OF(const scalar_type &a)
void transform(const cpx_type *src, cpx_type *dst)
void C_FIXDIV(cpx_type &, int)
traits_type::cpx_type cpx_type
void kf_bfly5(cpx_type *Fout, const size_t fstride, const size_t m)
void C_MUL(cpx_type &c, const cpx_type &a, const cpx_type &b)
void fill_twiddles(std::complex< T_scalar > *dst, int nfft, bool inverse)
const cpx_type twiddle(int i)
void prepare(std::vector< std::complex< T_scalar > > &dst, int nfft, bool inverse, std::vector< int > &stageRadix, std::vector< int > &stageRemainder)
std::complex< scalar_type > cpx_type
std::vector< cpx_type > _twiddles