Generative Fast Fourier Transforms (GFFT)  0.3
gfftspec.h
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2006-2014 by Vladimir Mirnyy *
3  * *
4  * This program is free software; you can redistribute it and/or modify *
5  * it under the terms of the GNU General Public License as published by *
6  * the Free Software Foundation; either version 2 of the License, or *
7  * (at your option) any later version. *
8  * *
9  * This program is distributed in the hope that it will be useful, *
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12  * GNU General Public License for more details. *
13  ***************************************************************************/
14 
15 #ifndef __gfftspec_h
16 #define __gfftspec_h
17 
22 #include "metafunc.h"
23 
24 namespace GFFT {
25 
26 using namespace MF;
27 
29 
38 template<typename T, int_t N, int S, int_t K>
40 {
41  static const int_t K2 = K*2;
42 
43  static void apply(T* c, T* s)
44  {
46  c[K-1] = Cos<N,K2,T>::value();
47  s[K-1] = S*Sin<N,K2,T>::value();
48  }
49 };
50 
51 template<typename T, int_t N, int S>
52 struct ComputeTwiddles<T,N,S,1>
53 {
54  static void apply(T* c, T* s)
55  {
56  c[0] = Cos<N,2,T>::value();
57  s[0] = S*Sin<N,2,T>::value();
58  }
59 };
60 
62 
71 template<int_t N, int_t M, typename T, int S>
72 class DFTk_inp
73 {
74  // N is assumed odd, otherwise compiler would not come here
75 
76  typedef typename TempTypeTrait<T>::Result LocalVType;
77  static const int_t K = (N-1)/2;
78  static const int_t NM = N*M;
79 
80  LocalVType m_c[K], m_s[K];
81 
82 public:
83  DFTk_inp()
84  {
86  }
87 
88  void apply(T* data)
89  {
90  T sr[K], si[K], dr[K], di[K];
91  for (int_t i=0; i<K; ++i) {
92  const int_t k = (i+1)*M;
93  sr[i] = data[k] + data[NM-k];
94  si[i] = data[k+1] + data[NM-k+1];
95  dr[i] = data[k] - data[NM-k];
96  di[i] = data[k+1] - data[NM-k+1];
97  }
98 
99  for (int_t i=1; i<K+1; ++i) {
100  T re1(0), re2(0), im1(0), im2(0);
101  for (int_t j=0; j<K; ++j) {
102  const bool sign_change = (i*(j+1) % N) > K;
103  const int_t kk = (i+j*i)%N;
104  const int_t k = (kk>K) ? N-kk-1 : kk-1;
105  const T s1 = m_s[k]*di[j];
106  const T s2 = m_s[k]*dr[j];
107  re1 += m_c[k]*sr[j];
108  im1 += m_c[k]*si[j];
109  re2 += sign_change ? -s1 : s1;
110  im2 -= sign_change ? -s2 : s2;
111  }
112  const int_t k = i*M;
113  data[k] = data[0] + re1 + re2;
114  data[k+1] = data[1] + im1 + im2;
115  data[NM-k] = data[0] + re1 - re2;
116  data[NM-k+1] = data[1] + im1 - im2;
117  }
118 
119  for (int_t i=0; i<K; ++i) {
120  data[0] += sr[i];
121  data[1] += si[i];
122  }
123  }
124 
125  template<class LT>
126  void apply(T* data, const LT* wr, const LT* wi)
127  {
128  T sr[K], si[K], dr[K], di[K];
129  for (int_t i=0; i<K; ++i) {
130  const int_t k = (i+1)*M;
131  const T tr1 = data[k]*wr[i] - data[k+1]*wi[i];
132  const T ti1 = data[k]*wi[i] + data[k+1]*wr[i];
133  const T tr2 = data[NM-k]*wr[N-i-2] - data[NM-k+1]*wi[N-i-2];
134  const T ti2 = data[NM-k]*wi[N-i-2] + data[NM-k+1]*wr[N-i-2];
135  sr[i] = tr1 + tr2;
136  si[i] = ti1 + ti2;
137  dr[i] = tr1 - tr2;
138  di[i] = ti1 - ti2;
139  }
140 
141  for (int_t i=1; i<K+1; ++i) {
142  T re1(0), re2(0), im1(0), im2(0);
143  for (int_t j=0; j<K; ++j) {
144  const bool sign_change = (i*(j+1) % N) > K;
145  const int_t kk = (i+j*i)%N;
146  const int_t k = (kk>K) ? N-kk-1 : kk-1;
147  const T s1 = m_s[k]*di[j];
148  const T s2 = m_s[k]*dr[j];
149  re1 += m_c[k]*sr[j];
150  im1 += m_c[k]*si[j];
151  re2 += sign_change ? -s1 : s1;
152  im2 -= sign_change ? -s2 : s2;
153  }
154  const int_t k = i*M;
155  data[k] = data[0] + re1 + re2;
156  data[k+1] = data[1] + im1 + im2;
157  data[NM-k] = data[0] + re1 - re2;
158  data[NM-k+1] = data[1] + im1 - im2;
159  }
160 
161  for (int_t i=0; i<K; ++i) {
162  data[0] += sr[i];
163  data[1] += si[i];
164  }
165  }
166 
167  template<class LT>
168  void apply(const LT* wr, const LT* wi, T* data)
169  {
170  T sr[K], si[K], dr[K], di[K];
171  for (int_t i=0; i<K; ++i) {
172  const int_t k = (i+1)*M;
173  sr[i] = data[k] + data[NM-k];
174  si[i] = data[k+1] + data[NM-k+1];
175  dr[i] = data[k] - data[NM-k];
176  di[i] = data[k+1] - data[NM-k+1];
177  }
178 
179  for (int_t i=1; i<K+1; ++i) {
180  T re1(0), re2(0), im1(0), im2(0);
181  for (int_t j=0; j<K; ++j) {
182  const bool sign_change = (i*(j+1) % N) > K;
183  const int_t kk = (i+j*i)%N;
184  const int_t k = (kk>K) ? N-kk-1 : kk-1;
185  const T s1 = m_s[k]*di[j];
186  const T s2 = m_s[k]*dr[j];
187  re1 += m_c[k]*sr[j];
188  im1 += m_c[k]*si[j];
189  re2 += sign_change ? -s1 : s1;
190  im2 -= sign_change ? -s2 : s2;
191  }
192  const int_t k = i*M;
193  const T tr1 = data[0] + re1 + re2;
194  const T ti1 = data[1] + im1 + im2;
195  const T tr2 = data[0] + re1 - re2;
196  const T ti2 = data[1] + im1 - im2;
197  data[k] = tr1*wr[i-1] - ti1*wi[i-1];
198  data[k+1] = tr1*wi[i-1] + ti1*wr[i-1];
199  data[NM-k] = tr2*wr[K-i+1] - ti2*wi[K-i+1];
200  data[NM-k+1] = tr2*wi[K-i+1] + ti2*wr[K-i+1];
201  }
202 
203  for (int_t i=0; i<K; ++i) {
204  data[0] += sr[i];
205  data[1] += si[i];
206  }
207  }
208 };
209 /*
210 template<int_t M, typename T, int S>
211 class DFTk_inp<4,M,T,S>
212 {
213  static const int_t I10 = M;
214  static const int_t I11 = M+1;
215  static const int_t I20 = M+M;
216  static const int_t I21 = I20+1;
217  static const int_t I30 = I20+M;
218  static const int_t I31 = I30+1;
219 
220 public:
221  DFTk_inp() { }
222 
223  void apply(T* data)
224  {
225  T tr = data[I20];
226  T ti = data[I21];
227  data[I20] = data[0]-tr;
228  data[I21] = data[1]-ti;
229  data[0] += tr;
230  data[1] += ti;
231  tr = data[I30];
232  ti = data[I31];
233  data[I30] = S*(data[I11]-ti);
234  data[I31] = S*(tr-data[I10]);
235  data[I10] += tr;
236  data[I11] += ti;
237 
238  tr = data[I10];
239  ti = data[I11];
240  data[I10] = data[0]-tr;
241  data[I11] = data[1]-ti;
242  data[0] += tr;
243  data[1] += ti;
244  tr = data[I30];
245  ti = data[I31];
246  data[I30] = data[I20]-tr;
247  data[I31] = data[I21]-ti;
248  data[I20] += tr;
249  data[I21] += ti;
250  }
251  template<class LT>
252  void apply(T* data, const LT* wr, const LT* wi)
253  {
254  }
255  template<class LT>
256  void apply(const LT* wr, const LT* wi, T* data)
257  {
258  }
259 };
260 */
261 
262 // Specialization for N=3
263 template<int_t M, typename T, int S>
264 class DFTk_inp<3,M,T,S>
265 {
266  static const int_t I10 = M;
267  static const int_t I11 = M+1;
268  static const int_t I20 = M+M;
269  static const int_t I21 = I20+1;
270 
271  T m_coef;
272 
273 public:
274  DFTk_inp() : m_coef(S * Sqrt<3, T>::value() * 0.5) { }
275 
276  void apply(T* data)
277  {
278  const T sum_r = data[I10] + data[I20];
279  const T dif_r = m_coef * (data[I10] - data[I20]);
280  const T sum_i = data[I11] + data[I21];
281  const T dif_i = m_coef * (data[I11] - data[I21]);
282  const T tr = data[0] - 0.5*sum_r;
283  const T ti = data[1] - 0.5*sum_i;
284  data[0] += sum_r;
285  data[1] += sum_i;
286  data[I10] = tr + dif_i;
287  data[I11] = ti - dif_r;
288  data[I20] = tr - dif_i;
289  data[I21] = ti + dif_r;
290  }
291  template<class LT>
292  void apply(T* data, const LT* wr, const LT* wi)
293  {
294  const T tr1 = data[I10]*wr[0] - data[I11]*wi[0];
295  const T ti1 = data[I10]*wi[0] + data[I11]*wr[0];
296  const T tr2 = data[I20]*wr[1] - data[I21]*wi[1];
297  const T ti2 = data[I20]*wi[1] + data[I21]*wr[1];
298 
299  const T sum_r = tr1 + tr2;
300  const T dif_r = m_coef * (tr1 - tr2);
301  const T sum_i = ti1 + ti2;
302  const T dif_i = m_coef * (ti1 - ti2);
303  const T tr = data[0] - 0.5*sum_r;
304  const T ti = data[1] - 0.5*sum_i;
305  data[0] += sum_r;
306  data[1] += sum_i;
307  data[I10] = tr + dif_i;
308  data[I11] = ti - dif_r;
309  data[I20] = tr - dif_i;
310  data[I21] = ti + dif_r;
311  }
312  template<class LT>
313  void apply(const LT* wr, const LT* wi, T* data)
314  {
315  const T sum_r = data[I10] + data[I20];
316  const T dif_r = m_coef * (data[I10] - data[I20]);
317  const T sum_i = data[I11] + data[I21];
318  const T dif_i = m_coef * (data[I11] - data[I21]);
319  const T tr = data[0] - 0.5*sum_r;
320  const T ti = data[1] - 0.5*sum_i;
321  const T trpdi = tr + dif_i;
322  const T trmdi = tr - dif_i;
323  const T tipdr = ti + dif_r;
324  const T timdr = ti - dif_r;
325  data[0] += sum_r;
326  data[1] += sum_i;
327  data[I10] = trpdi*wr[0] - timdr*wi[0];
328  data[I11] = trpdi*wi[0] + timdr*wr[0];
329  data[I20] = trmdi*wr[1] - tipdr*wi[1];
330  data[I21] = trmdi*wi[1] + tipdr*wr[1];
331  }
332 };
333 
334 // Specialization for N=2
335 template<int_t M, typename T, int S>
336 class DFTk_inp<2,M,T,S>
337 {
338 public:
339  void apply(T* data)
340  {
341  const T tr = data[M];
342  const T ti = data[M+1];
343  data[M] = data[0]-tr;
344  data[M+1] = data[1]-ti;
345  data[0] += tr;
346  data[1] += ti;
347 // To test
348 // const T tr = data[0] - data[M];
349 // const T ti = data[1] - data[M+1];
350 // data[0] += data[M];
351 // data[1] += data[M+1];
352 // data[M] = tr;
353 // data[M+1] = ti;
354  }
355  // For decimation-in-time
356  template<class LT>
357  void apply(T* data, const LT* wr, const LT* wi)
358  {
359  const T tr = data[M] * (*wr) - data[M+1] * (*wi);
360  const T ti = data[M] * (*wi) + data[M+1] * (*wr);
361  data[M] = data[0]-tr;
362  data[M+1] = data[1]-ti;
363  data[0] += tr;
364  data[1] += ti;
365  }
366  // For decimation-in-frequency
367  template<class LT>
368  void apply(const LT* wr, const LT* wi, T* data)
369  {
370  const T tr = data[0] - data[M];
371  const T ti = data[1] - data[M+1];
372  data[0] += data[M];
373  data[1] += data[M+1];
374  data[M] = tr * (*wr) - ti * (*wi);
375  data[M+1] = ti * (*wr) + tr * (*wi);
376  }
377 };
378 
379 
381 
391 template<int_t N, int_t SI, int_t DI, typename T, int S>
392 class DFTk
393 {
394  //GFFT_STATIC_ASSERT(N%2 == 1) // N is assumed odd, otherwise compiler would not come here
395 
396  typedef typename TempTypeTrait<T>::Result LocalVType;
397  static const int_t K = (N-1)/2;
398  static const int_t NSI = N*SI;
399  static const int_t NDI = N*DI;
400 
401  LocalVType m_c[K], m_s[K];
402 
403 public:
404  DFTk()
405  {
407  }
408 
409  void apply(const T* src, T* dst)
410  {
411  T sr[K], si[K], dr[K], di[K];
412  for (int_t i=0; i<K; ++i) {
413  const int_t k = (i+1)*SI;
414  sr[i] = src[k] + src[NSI-k];
415  si[i] = src[k+1] + src[NSI-k+1];
416  dr[i] = src[k] - src[NSI-k];
417  di[i] = src[k+1] - src[NSI-k+1];
418  }
419 
420  for (int_t i=1; i<K+1; ++i) {
421  T re1(0), re2(0), im1(0), im2(0);
422  for (int_t j=0; j<K; ++j) {
423  const bool sign_change = (i*(j+1) % N) > K;
424  const int_t kk = (i+j*i)%N;
425  const int_t k = (kk>K) ? N-kk-1 : kk-1;
426  const T s1 = m_s[k]*di[j];
427  const T s2 = m_s[k]*dr[j];
428  re1 += m_c[k]*sr[j];
429  im1 += m_c[k]*si[j];
430  re2 += sign_change ? -s1 : s1;
431  im2 -= sign_change ? -s2 : s2;
432  }
433  const int_t k = i*DI;
434  dst[k] = src[0] + re1 + re2;
435  dst[k+1] = src[1] + im1 + im2;
436  dst[NDI-k] = src[0] + re1 - re2;
437  dst[NDI-k+1] = src[1] + im1 - im2;
438  }
439 
440  dst[0] = src[0];
441  dst[1] = src[1];
442  for (int_t i=0; i<K; ++i) {
443  dst[0] += sr[i];
444  dst[1] += si[i];
445  }
446  }
447 };
448 
449 template<int_t SI, int_t DI, typename T, int S>
450 class DFTk<3,SI,DI,T,S>
451 {
452  static const int_t SI2 = SI+SI;
453  static const int_t DI2 = DI+DI;
454  T m_coef;
455 
456 public:
457  DFTk() : m_coef(S * Sqrt<3, T>::value() * 0.5) { } // sqrt(3)/2 = sin(2pi/3)
458 
459  void apply(const T* src, T* dst)
460  {
461  // 4 mult, 12 add
462  const T sr = src[SI] + src[SI2];
463  const T dr = m_coef * (src[SI] - src[SI2]);
464  const T si = src[SI+1] + src[SI2+1];
465  const T di = m_coef * (src[SI+1] - src[SI2+1]);
466  const T tr = src[0] - 0.5*sr;
467  const T ti = src[1] - 0.5*si;
468  dst[0] = src[0] + sr;
469  dst[1] = src[1] + si;
470  dst[DI] = tr + di;
471  dst[DI+1] = ti - dr;
472  dst[DI2] = tr - di;
473  dst[DI2+1] = ti + dr;
474  }
475 /*
476  template<class LT>
477  void apply(const LT* wr, const LT* wi, const T* src, T* dst)
478  {
479  // 4 mult, 12 add
480  const T sr = src[SI] + src[SI2];
481  const T dr = m_coef * (src[SI] - src[SI2]);
482  const T si = src[SI+1] + src[SI2+1];
483  const T di = m_coef * (src[SI+1] - src[SI2+1]);
484  const T tr = src[0] - 0.5*sr;
485  const T ti = src[1] - 0.5*si;
486  const T trpdi = tr + di;
487  const T trmdi = tr - di;
488  const T tipdr = ti + dr;
489  const T timdr = ti - dr;
490  dst[0] = src[0] + sr;
491  dst[1] = src[1] + si;
492  dst[DI] = trpdi*wr[0] - timdr*wi[0];
493  dst[DI+1] = trpdi*wi[0] + timdr*wr[0];
494  dst[DI2] = trmdi*wr[1] - tipdr*wi[1];
495  dst[DI2+1] = trmdi*wi[1] + tipdr*wr[1];
496  }
497  */
498 };
499 
500 template<int_t SI, int_t DI, typename T, int S>
501 class DFTk<2,SI,DI,T,S>
502 {
503 public:
504  void apply(const T* src, T* dst)
505  {
506  // the temporaries tr, ti are necessary, because may happen src == dst
507  const T tr = src[0] - src[SI];
508  const T ti = src[1] - src[SI+1];
509  dst[0] = src[0] + src[SI];
510  dst[1] = src[1] + src[SI+1];
511  dst[DI] = tr;
512  dst[DI+1] = ti;
513  }
514  /*
515  template<class LT>
516  void apply(const LT* wr, const LT* wi, const T* src, T* dst)
517  {
518  const T tr = src[0] - src[SI];
519  const T ti = src[1] - src[SI+1];
520  dst[0] = src[0] + src[SI];
521  dst[1] = src[1] + src[SI+1];
522  dst[DI] = tr * (*wr) - ti * (*wi);
523  dst[DI+1] = ti * (*wr) + tr * (*wi);
524  }
525  */
526 };
527 
531 template<typename T>
532 inline void _spec2(T* data)
533 {
534  const T tr = data[2];
535  const T ti = data[3];
536  data[2] = data[0]-tr;
537  data[3] = data[1]-ti;
538  data[0] += tr;
539  data[1] += ti;
540 }
541 
545 template<typename T>
546 inline void _spec2(const T* src, T* dst)
547 {
548  const T v1(src[1]), v2(src[2]), v3(src[3]);
549  dst[0] = (*src + v2);
550  dst[1] = (v1 + v3);
551  dst[2] = (*src - v2);
552  dst[3] = (v1 - v3);
553 }
554 
555 
556 } //namespace DFT
557 
558 #endif /*__gfftspec_h*/

Generated on Mon Feb 10 2014 for Generative Fast Fourier Transforms (GFFT) by DoxyGen 1.8.3.1