fftw++.h
Go to the documentation of this file.
1 /* Fast Fourier transform C++ header class for the FFTW3 Library
2  Copyright (C) 2004-16
3  John C. Bowman, University of Alberta
4  Malcolm Roberts, University of Strasbourg
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published by
8  the Free Software Foundation; either version 3 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19 
20 #ifndef __fftwpp_h__
21 #define __fftwpp_h__ 1
22 
23 #define __FFTWPP_H_VERSION__ 2.05
24 
25 #include <cstdlib>
26 #include <fstream>
27 #include <iostream>
28 #include <fftw3.h>
29 #include <cerrno>
30 #include <map>
31 
32 #ifndef _OPENMP
33 #ifndef FFTWPP_SINGLE_THREAD
34 #define FFTWPP_SINGLE_THREAD
35 #endif
36 #endif
37 
38 #ifndef FFTWPP_SINGLE_THREAD
39 #include <omp.h>
40 #endif
41 
42 inline int get_thread_num()
43 {
44 #ifdef FFTWPP_SINGLE_THREAD
45  return 0;
46 #else
47  return omp_get_thread_num();
48 #endif
49 }
50 
51 inline int get_max_threads()
52 {
53 #ifdef FFTWPP_SINGLE_THREAD
54  return 1;
55 #else
56  return omp_get_max_threads();
57 #endif
58 }
59 
60 #ifndef FFTWPP_SINGLE_THREAD
61 #define PARALLEL(code) \
62  if(threads > 1) { \
63  _Pragma("omp parallel for num_threads(threads)") \
64  code \
65  } else { \
66  code \
67  }
68 #else
69 #define PARALLEL(code) \
70  { \
71  code \
72  }
73 #endif
74 
75 #ifdef FFTWPP_SINGLE_THREAD
76 # define FFTWPP_THREADS_PAR
77 #else
78 # define FFTWPP_THREADS_PAR threads
79 #endif
80 
81 #ifndef __Complex_h__
82 #include <complex>
83 typedef std::complex<double> Complex;
84 #endif
85 
86 #include "seconds.h"
87 #include "statistics.h"
88 #include "align.h"
89 
90 namespace fftwpp {
91 
92 // Obsolete names:
93 #define FFTWComplex utils::ComplexAlign
94 #define FFTWdouble utils::doubleAlign
95 #define FFTWdelete utils::deleteAlign
96 
97 class fftw;
98 
99 extern "C" fftw_plan Planner(fftw *F, Complex *in, Complex *out);
100 void LoadWisdom();
101 void SaveWisdom();
102 
103 extern const char *inout;
104 
105 struct threaddata {
106  unsigned int threads;
107  double mean;
108  double stdev;
109  threaddata() : threads(0), mean(0.0), stdev(0.0) {}
110  threaddata(unsigned int threads, double mean, double stdev) :
111  threads(threads), mean(mean), stdev(stdev) {}
112 };
113 
114 class fftw;
115 
117 {
118 protected:
119  unsigned int threads;
120  unsigned int innerthreads;
121 public:
122  ThreadBase();
123  ThreadBase(unsigned int threads) : threads(threads) {}
124  void Threads(unsigned int nthreads) {threads=nthreads;}
125  unsigned int Threads() {return threads;}
126 
127  void multithread(unsigned int nx) {
128  if(nx >= threads) {
129  innerthreads=1;
130  } else {
132  threads=1;
133  }
134  }
135 };
136 
137 inline unsigned int realsize(unsigned int n, Complex *in, Complex *out=NULL)
138 {
139  return (!out || in == out) ? 2*(n/2+1) : n;
140 }
141 
142 inline unsigned int realsize(unsigned int n, Complex *in, double *out)
143 {
144  return realsize(n,in,(Complex *) out);
145 }
146 
147 inline unsigned int realsize(unsigned int n, double *in, Complex *out)
148 {
149  return realsize(n,(Complex *) in,out);
150 }
151 
152 // Base clase for fft routines
153 //
154 class fftw : public ThreadBase {
155 protected:
156  unsigned int doubles; // number of double precision values in dataset
157  int sign;
158  unsigned int threads;
159  double norm;
160 
161  fftw_plan plan;
162  bool inplace;
163 
164  unsigned int Dist(unsigned int n, size_t stride, size_t dist) {
165  return dist ? dist : ((stride == 1) ? n : 1);
166  }
167 
168  static const double twopi;
169 
170 public:
171  static unsigned int effort;
172  static unsigned int maxthreads;
173  static double testseconds;
174  static const char *WisdomName;
175  static fftw_plan (*planner)(fftw *f, Complex *in, Complex *out);
176 
177  virtual unsigned int Threads() {return threads;}
178 
179  static const char *oddshift;
180 
181  // Inplace shift of Fourier origin to (nx/2,0) for even nx.
182  static void Shift(Complex *data, unsigned int nx, unsigned int ny,
183  unsigned int FFTWPP_THREADS_PAR) {
184  unsigned int nyp=ny/2+1;
185  unsigned int stop=nx*nyp;
186  if(nx % 2 == 0) {
187  unsigned int inc=2*nyp;
188 #ifndef FFTWPP_SINGLE_THREAD
189 #pragma omp parallel for num_threads(threads)
190 #endif
191  for(unsigned int i=nyp; i < stop; i += inc) {
192  Complex *p=data+i;
193  for(unsigned int j=0; j < nyp; j++) p[j]=-p[j];
194  }
195  } else {
196  std::cerr << oddshift << std::endl;
197  exit(1);
198  }
199  }
200 
201  // Out-of-place shift of Fourier origin to (nx/2,0) for even nx.
202  static void Shift(double *data, unsigned int nx, unsigned int ny,
203  unsigned int FFTWPP_THREADS_PAR) {
204  if(nx % 2 == 0) {
205  unsigned int stop=nx*ny;
206  unsigned int inc=2*ny;
207 #ifndef FFTWPP_SINGLE_THREAD
208 #pragma omp parallel for num_threads(threads)
209 #endif
210  for(unsigned int i=ny; i < stop; i += inc) {
211  double *p=data+i;
212  for(unsigned int j=0; j < ny; j++) p[j]=-p[j];
213  }
214  } else {
215  std::cerr << oddshift << std::endl;
216  exit(1);
217  }
218  }
219 
220  // Inplace shift of Fourier origin to (nx/2,ny/2,0) for even nx and ny.
221  static void Shift(Complex *data, unsigned int nx, unsigned int ny,
222  unsigned int nz, unsigned int FFTWPP_THREADS_PAR) {
223  unsigned int nzp=nz/2+1;
224  unsigned int nyzp=ny*nzp;
225  if(nx % 2 == 0 && ny % 2 == 0) {
226  unsigned int pinc=2*nzp;
227 #ifndef FFTWPP_SINGLE_THREAD
228 #pragma omp parallel for num_threads(threads)
229 #endif
230  for(unsigned int i=0; i < nx; i++) {
231  Complex *pstart=data+i*nyzp;
232  Complex *pstop=pstart+nyzp;
233  for(Complex *p=pstart+(1-(i % 2))*nzp; p < pstop; p += pinc) {
234  for(unsigned int k=0; k < nzp; k++) p[k]=-p[k];
235  }
236  }
237  } else {
238  std::cerr << oddshift << " or odd ny" << std::endl;
239  exit(1);
240  }
241  }
242 
243  // Out-of-place shift of Fourier origin to (nx/2,ny/2,0) for even nx and ny.
244  static void Shift(double *data, unsigned int nx, unsigned int ny,
245  unsigned int nz, unsigned int FFTWPP_THREADS_PAR) {
246  unsigned int nyz=ny*nz;
247  if(nx % 2 == 0 && ny % 2 == 0) {
248  unsigned int pinc=2*nz;
249 #ifndef FFTWPP_SINGLE_THREAD
250 #pragma omp parallel for num_threads(threads)
251 #endif
252  for(unsigned int i=0; i < nx; i++) {
253  double *pstart=data+i*nyz;
254  double *pstop=pstart+nyz;
255  for(double *p=pstart+(1-(i % 2))*nz; p < pstop; p += pinc) {
256  for(unsigned int k=0; k < nz; k++) p[k]=-p[k];
257  }
258  }
259  } else {
260  std::cerr << oddshift << " or odd ny" << std::endl;
261  exit(1);
262  }
263  }
264 
265  fftw() : plan(NULL) {}
266  fftw(unsigned int doubles, int sign, unsigned int threads,
267  unsigned int n=0) :
268  doubles(doubles), sign(sign), threads(threads),
269  norm(1.0/(n ? n : doubles/2)), plan(NULL) {
270 #ifndef FFTWPP_SINGLE_THREAD
271  fftw_init_threads();
272 #endif
273  }
274 
275  virtual ~fftw() {
276  if(plan) fftw_destroy_plan(plan);
277  }
278 
279  virtual fftw_plan Plan(Complex* /*in*/, Complex* /*out*/) {return NULL;};
280 
281  inline void CheckAlign(Complex *p, const char *s) {
282  if((size_t) p % sizeof(Complex) == 0) return;
283  std::cerr << "WARNING: " << s << " array is not " << sizeof(Complex)
284  << "-byte aligned: address " << p << std::endl;
285  }
286 
287  void noplan() {
288  std::cerr << "Unable to construct FFTW plan" << std::endl;
289  exit(1);
290  }
291 
292  static void planThreads(unsigned int FFTWPP_THREADS_PAR) {
293 #ifndef FFTWPP_SINGLE_THREAD
294  omp_set_num_threads(threads);
295  fftw_plan_with_nthreads(threads);
296 #endif
297  }
298 
299  threaddata time(fftw_plan plan1, fftw_plan planT, Complex *in, Complex *out,
300  unsigned int Threads) {
301  utils::statistics S,ST;
302  double stop=utils::totalseconds()+testseconds;
303  threads=1;
304  plan=plan1;
305  fft(in,out);
307  plan=planT;
308  fft(in,out);
309  unsigned int N=1;
310  for(;;) {
311  double t0=utils::totalseconds();
312  threads=1;
313  plan=plan1;
314  for(unsigned int i=0; i < N; ++i)
315  fft(in,out);
316  double t1=utils::totalseconds();
318  plan=planT;
319  for(unsigned int i=0; i < N; ++i)
320  fft(in,out);
321  double t=utils::totalseconds();
322  S.add(t1-t0);
323  ST.add(t-t1);
324  if(S.mean() < 100.0/CLOCKS_PER_SEC) N *= 2;
325  if(S.count() >= 10) {
326  double error=S.stdev();
327  double diff=ST.mean()-S.mean();
328  if(diff >= 0.0 || t > stop) {
329  threads=1;
330  plan=plan1;
331  fftw_destroy_plan(planT);
332  break;
333  }
334  if(diff < -error) {
336  fftw_destroy_plan(plan1);
337  break;
338  }
339  }
340  }
341  return threaddata(threads,S.mean(),S.stdev());
342  }
343 
344  virtual threaddata lookup(bool /*inplace*/, unsigned int /*threads*/) {
345  return threaddata();
346  }
347  virtual void store(bool /*inplace*/, const threaddata& /*data*/) {}
348 
349  inline Complex *CheckAlign(Complex *in, Complex *out, bool constructor=true)
350  {
351 #ifndef NO_CHECK_ALIGN
352  CheckAlign(in,constructor ? "constructor input" : "input");
353  if(out) CheckAlign(out,constructor ? "constructor output" : "output");
354  else out=in;
355 #else
356  if(!out) out=in;
357 #endif
358  return out;
359  }
360 
362  bool alloc=!in;
363  if(alloc) in=utils::ComplexAlign((doubles+1)/2);
364  out=CheckAlign(in,out);
365  inplace=(out==in);
366 
368  unsigned int Threads=threads;
369  if(threads > 1) data=lookup(inplace,threads);
370  threads=data.threads > 0 ? data.threads : 1;
372  plan=(*planner)(this,in,out);
373  if(!plan) noplan();
374 
375  fftw_plan planT;
376  if(fftw::maxthreads > 1) {
379  planT=(*planner)(this,in,out);
380 
381  if(data.threads == 0) {
382  if(planT)
383  data=time(plan,planT,in,out,threads);
384  else noplan();
386  }
387  }
388 
389  if(alloc) Array::deleteAlign(in,(doubles+1)/2);
390  return data;
391  }
392 
393  threaddata Setup(Complex *in, double *out) {
394  return Setup(in,(Complex *) out);
395  }
396 
397  threaddata Setup(double *in, Complex *out=NULL) {
398  return Setup((Complex *) in,out);
399  }
400 
401  virtual void Execute(Complex *in, Complex *out, bool=false) {
402  fftw_execute_dft(plan,(fftw_complex *) in,(fftw_complex *) out);
403  }
404 
406  out=CheckAlign(in,out,false);
407  if(inplace ^ (out == in)) {
408  std::cerr << "ERROR: fft " << inout << std::endl;
409  exit(1);
410  }
411  return out;
412  }
413 
414  void fft(Complex *in, Complex *out=NULL) {
415  out=Setout(in,out);
416  Execute(in,out);
417  }
418 
419  void fft(double *in, Complex *out=NULL) {
420  fft((Complex *) in,out);
421  }
422 
423  void fft(Complex *in, double *out) {
424  fft(in,(Complex *) out);
425  }
426 
427  void fft0(Complex *in, Complex *out=NULL) {
428  out=Setout(in,out);
429  Execute(in,out,true);
430  }
431 
432  void fft0(double *in, Complex *out=NULL) {
433  fft0((Complex *) in,out);
434  }
435 
436  void fft0(Complex *in, double *out) {
437  fft0(in,(Complex *) out);
438  }
439 
441  unsigned int stop=doubles/2;
442 #ifndef FFTWPP_SINGLE_THREAD
443 #pragma omp parallel for num_threads(threads)
444 #endif
445  for(unsigned int i=0; i < stop; i++) out[i] *= norm;
446  }
447 
448  void Normalize(double *out) {
449 #ifndef FFTWPP_SINGLE_THREAD
450 #pragma omp parallel for num_threads(threads)
451 #endif
452  for(unsigned int i=0; i < doubles; i++) out[i] *= norm;
453  }
454 
455  virtual void fftNormalized(Complex *in, Complex *out=NULL, bool shift=false)
456  {
457  out=Setout(in,out);
458  Execute(in,out,shift);
459  Normalize(out);
460  }
461 
462  void fftNormalized(Complex *in, double *out, bool shift=false) {
463  out=(double *) Setout(in,(Complex *) out);
464  Execute(in,(Complex *) out,shift);
465  Normalize(out);
466  }
467 
468  void fftNormalized(double *in, Complex *out, bool shift=false) {
469  fftNormalized((Complex *) in,out,shift);
470  }
471 
472  template<class I, class O>
473  void fft0Normalized(I in, O out) {
474  fftNormalized(in,out,true);
475  }
476 
477  template<class O>
478  void Normalize(unsigned int nx, unsigned int M, size_t ostride,
479  size_t odist, O *out) {
480  unsigned int stop=nx*ostride;
481  O *outMdist=out+M*odist;
482 #ifndef FFTWPP_SINGLE_THREAD
483 #pragma omp parallel for num_threads(threads)
484 #endif
485  for(unsigned int i=0; i < stop; i += ostride) {
486  O *pstop=outMdist+i;
487  for(O *p=out+i; p < pstop; p += odist) {
488  *p *= norm;
489  }
490  }
491  }
492 
493  template<class I, class O>
494  void fftNormalized(unsigned int nx, unsigned int M, size_t ostride,
495  size_t odist, I *in, O *out=NULL, bool shift=false) {
496  out=(O *) Setout((Complex *) in,(Complex *) out);
497  Execute((Complex *) in,(Complex *) out,shift);
498  Normalize(nx,M,ostride,odist,out);
499  }
500 
501 }; // class fftw
502 
503 class Transpose {
504  fftw_plan plan;
505  fftw_plan plan2;
506  unsigned int a,b;
507  unsigned int nlength,mlength;
508  unsigned int ilast,jlast;
509  unsigned int rows,cols;
510 #pragma GCC diagnostic push
511 #pragma GCC diagnostic ignored "-Wattributes"
512  [[maybe_unused]] unsigned int threads;
513 #pragma GCC diagnostic pop
514  bool inplace;
515  unsigned int size;
516 public:
517  template<class T>
518  Transpose(unsigned int rows, unsigned int cols, unsigned int length,
519  T *in, T *out=NULL, unsigned int threads=fftw::maxthreads) :
520  rows(rows), cols(cols), threads(threads) {
521  size=sizeof(T);
522  if(size % sizeof(double) != 0) {
523  std::cerr << "ERROR: Transpose is not implemented for type of size "
524  << size;
525  exit(1);
526  }
527  plan=plan2=NULL;
528  if(rows == 0 || cols == 0) return;
529  size /= sizeof(double);
530  length *= size;
531 
532  if(!out) out=in;
533  inplace=(out==in);
534  if(inplace) {
536  threads=1;
537  } else fftw::planThreads(1);
538 
539  fftw_iodim dims[3];
540 
541  a=std::min(rows,threads);
542  b=std::min(cols,threads/a);
543 
544  unsigned int n=utils::ceilquotient(rows,a);
545  unsigned int m=utils::ceilquotient(cols,b);
546 
547  // If rows <= threads then a=rows and n=1.
548  // If rows >= threads then b=1 and m=cols.
549 
550  nlength=n*length;
551  mlength=m*length;
552 
553  dims[0].n=n;
554  dims[0].is=cols*length;
555  dims[0].os=length;
556 
557  dims[1].n=m;
558  dims[1].is=length;
559  dims[1].os=rows*length;
560 
561  dims[2].n=length;
562  dims[2].is=1;
563  dims[2].os=1;
564 
565  // A plan with rank=0 is a transpose.
566  plan=fftw_plan_guru_r2r(0,NULL,3,dims,(double *) in,(double *) out,
567  NULL,fftw::effort);
568  ilast=a;
569  jlast=b;
570 
571  if(n*a > rows) { // Only happens when rows > threads.
572  a=utils::ceilquotient(rows,n);
573  ilast=a-1;
574  dims[0].n=rows-n*ilast;
575  plan2=fftw_plan_guru_r2r(0,NULL,3,dims,(double *) in,(double *) out,
576  NULL,fftw::effort);
577  } else { // Only happens when rows < threads.
578  if(m*b > cols) {
579  b=utils::ceilquotient(cols,m);
580  jlast=b-1;
581  dims[1].n=cols-m*jlast;
582  plan2=fftw_plan_guru_r2r(0,NULL,3,dims,(double *) in,(double *) out,
583  NULL,fftw::effort);
584  }
585  }
586  }
587 
589  if(plan) fftw_destroy_plan(plan);
590  if(plan2) fftw_destroy_plan(plan2);
591  }
592 
593  template<class T>
594  void transpose(T *in, T *out=NULL) {
595  if(rows == 0 || cols == 0) return;
596  if(!out) out=in;
597  if(inplace ^ (out == in)) {
598  std::cerr << "ERROR: Transpose " << inout << std::endl;
599  exit(1);
600  }
601 #ifndef FFTWPP_SINGLE_THREAD
602  if(a > 1) {
603  if(b > 1) {
604  int A=a, B=b;
605 #pragma omp parallel for num_threads(A)
606  for(unsigned int i=0; i < a; ++i) {
607  unsigned int I=i*nlength;
608 #pragma omp parallel for num_threads(B)
609  for(unsigned int j=0; j < b; ++j) {
610  unsigned int J=j*mlength;
611  fftw_execute_r2r((i < ilast && j < jlast) ? plan : plan2,
612  (double *) in+cols*I+J,
613  (double *) out+rows*J+I);
614  }
615  }
616  } else {
617  int A=a;
618 #pragma omp parallel for num_threads(A)
619  for(unsigned int i=0; i < a; ++i) {
620  unsigned int I=i*nlength;
621  fftw_execute_r2r(i < ilast ? plan : plan2,
622  (double *) in+cols*I,(double *) out+I);
623  }
624  }
625  } else if(b > 1) {
626  int B=b;
627 #pragma omp parallel for num_threads(B)
628  for(unsigned int j=0; j < b; ++j) {
629  unsigned int J=j*mlength;
630  fftw_execute_r2r(j < jlast ? plan : plan2,
631  (double *) in+J,(double *) out+rows*J);
632  }
633  } else
634 #endif
635  fftw_execute_r2r(plan,(double *) in,(double*) out);
636  }
637 };
638 
639 template<class T, class L>
640 class Threadtable {
641 public:
642  typedef std::map<T,threaddata,L> Table;
643 
644  threaddata Lookup(Table& table, T key) {
645  typename Table::iterator p=table.find(key);
646  return p == table.end() ? threaddata() : p->second;
647  }
648 
649  void Store(Table& threadtable, T key, const threaddata& data) {
650  threadtable[key]=data;
651  }
652 };
653 
654 struct keytype1 {
655  unsigned int nx;
656  unsigned int threads;
657  bool inplace;
658  keytype1(unsigned int nx, unsigned int threads, bool inplace) :
659  nx(nx), threads(threads), inplace(inplace) {}
660 };
661 
662 struct keyless1 {
663  bool operator()(const keytype1& a, const keytype1& b) const {
664  return a.nx < b.nx || (a.nx == b.nx &&
665  (a.threads < b.threads || (a.threads == b.threads &&
666  a.inplace < b.inplace)));
667  }
668 };
669 
670 struct keytype2 {
671  unsigned int nx;
672  unsigned int ny;
673  unsigned int threads;
674  bool inplace;
675  keytype2(unsigned int nx, unsigned int ny, unsigned int threads,
676  bool inplace) :
677  nx(nx), ny(ny), threads(threads), inplace(inplace) {}
678 };
679 
680 struct keyless2 {
681  bool operator()(const keytype2& a, const keytype2& b) const {
682  return a.nx < b.nx || (a.nx == b.nx &&
683  (a.ny < b.ny || (a.ny == b.ny &&
684  (a.threads < b.threads ||
685  (a.threads == b.threads &&
686  a.inplace < b.inplace)))));
687  }
688 };
689 
690 struct keytype3 {
691  unsigned int nx;
692  unsigned int ny;
693  unsigned int nz;
694  unsigned int threads;
695  bool inplace;
696  keytype3(unsigned int nx, unsigned int ny, unsigned int nz,
697  unsigned int threads, bool inplace) :
698  nx(nx), ny(ny), nz(nz), threads(threads), inplace(inplace) {}
699 };
700 
701 struct keyless3 {
702  bool operator()(const keytype3& a, const keytype3& b) const {
703  return a.nx < b.nx || (a.nx == b.nx &&
704  (a.ny < b.ny || (a.ny == b.ny &&
705  (a.nz < b.nz ||
706  (a.nz == b.nz &&
707  (a.threads < b.threads ||
708  (a.threads == b.threads &&
709  a.inplace < b.inplace)))))));
710  }
711 };
712 
713 // Compute the complex Fourier transform of n complex values.
714 // Before calling fft(), the arrays in and out (which may coincide) must be
715 // allocated as Complex[n].
716 //
717 // Out-of-place usage:
718 //
719 // fft1d Forward(n,-1,in,out);
720 // Forward.fft(in,out);
721 //
722 // fft1d Backward(n,1,in,out);
723 // Backward.fft(in,out);
724 //
725 // fft1d Backward(n,1,in,out);
726 // Backward.fftNormalized(in,out); // True inverse of Forward.fft(out,in);
727 //
728 // In-place usage:
729 //
730 // fft1d Forward(n,-1);
731 // Forward.fft(in);
732 //
733 // fft1d Backward(n,1);
734 // Backward.fft(in);
735 //
736 class fft1d : public fftw, public Threadtable<keytype1,keyless1> {
737  unsigned int nx;
739 public:
740  fft1d(unsigned int nx, int sign, Complex *in=NULL, Complex *out=NULL,
741  unsigned int threads=maxthreads)
742  : fftw(2*nx,sign,threads), nx(nx) {Setup(in,out);}
743 
744 #ifdef __Array_h__
745  fft1d(int sign, const Array::array1<Complex>& in,
746  const Array::array1<Complex>& out=Array::NULL1,
747  unsigned int threads=maxthreads)
748  : fftw(2*in.Nx(),sign,threads), nx(in.Nx()) {Setup(in,out);}
749 #endif
750 
751  threaddata lookup(bool inplace, unsigned int threads) {
752  return this->Lookup(threadtable,keytype1(nx,threads,inplace));
753  }
754  void store(bool inplace, const threaddata& data) {
755  this->Store(threadtable,keytype1(nx,data.threads,inplace),data);
756  }
757 
758  fftw_plan Plan(Complex *in, Complex *out) {
759  return fftw_plan_dft_1d(nx,(fftw_complex *) in,(fftw_complex *) out,
760  sign,effort);
761  }
762 };
763 
764 template<class I, class O>
765 class fftwblock : public virtual fftw {
766 public:
767  int nx;
768  unsigned int M;
769  size_t istride,ostride;
770  size_t idist,odist;
771  fftw_plan plan1,plan2;
772  unsigned int T,Q,R;
773  fftwblock(unsigned int nx, unsigned int M,
774  size_t istride, size_t ostride, size_t idist, size_t odist,
775  Complex *in, Complex *out, unsigned int Threads)
776  : fftw(), nx(nx), M(M), istride(istride), ostride(ostride),
777  idist(Dist(nx,istride,idist)), odist(Dist(nx,ostride,odist)),
778  plan1(NULL), plan2(NULL) {
779  T=1;
780  Q=M;
781  R=0;
782 
783  threaddata S1=Setup(in,out);
784  fftw_plan planT1=plan;
785 
786  if(fftw::maxthreads > 1) {
787  if(Threads > 1) {
788  T=std::min(M,Threads);
789  Q=T > 0 ? M/T : 0;
790  R=M-Q*T;
791 
793  threaddata ST=Setup(in,out);
794 
795  if(R > 0 && threads == 1 && plan1 != plan2) {
796  fftw_destroy_plan(plan2);
797  plan2=plan1;
798  }
799 
800  if(ST.mean > S1.mean-S1.stdev) { // Use FFTW's multi-threading
801  fftw_destroy_plan(plan);
802  if(R > 0) {
803  fftw_destroy_plan(plan2);
804  plan2=NULL;
805  }
806  T=1;
807  Q=M;
808  R=0;
809  plan=planT1;
810  threads=S1.threads;
811  } else { // Do the multi-threading ourselves
812  fftw_destroy_plan(planT1);
813  threads=ST.threads;
814  }
815  } else
816  Setup(in,out); // Synchronize wisdom
817  }
818  }
819 
820  fftw_plan Plan(int Q, fftw_complex *in, fftw_complex *out) {
821  return fftw_plan_many_dft(1,&nx,Q,in,NULL,istride,idist,
822  out,NULL,ostride,odist,sign,effort);
823  }
824 
825  fftw_plan Plan(int Q, double *in, fftw_complex *out) {
826  return fftw_plan_many_dft_r2c(1,&nx,Q,in,NULL,istride,idist,
827  out,NULL,ostride,odist,effort);
828  }
829 
830  fftw_plan Plan(int Q, fftw_complex *in, double *out) {
831  return fftw_plan_many_dft_c2r(1,&nx,Q,in,NULL,istride,idist,
832  out,NULL,ostride,odist,effort);
833  }
834 
835  fftw_plan Plan(Complex *in, Complex *out) {
836  if(R > 0) {
837  plan2=Plan(Q+1,(I *) in,(O *) out);
838  if(!plan2) return NULL;
839  if(threads == 1) plan1=plan2;
840  }
841  return Plan(Q,(I *) in,(O *) out);
842  }
843 
844  void Execute(fftw_plan plan, fftw_complex *in, fftw_complex *out) {
845  fftw_execute_dft(plan,in,out);
846  }
847 
848  void Execute(fftw_plan plan, double *in, fftw_complex *out) {
849  fftw_execute_dft_r2c(plan,in,out);
850  }
851 
852  void Execute(fftw_plan plan, fftw_complex *in, double *out) {
853  fftw_execute_dft_c2r(plan,in,out);
854  }
855 
856  void Execute(Complex *in, Complex *out, bool=false) {
857  if(T == 1)
858  Execute(plan,(I *) in,(O *) out);
859  else {
860  unsigned int extra=T-R;
861 #ifndef FFTWPP_SINGLE_THREAD
862 #pragma omp parallel for num_threads(T)
863 #endif
864  for(unsigned int i=0; i < T; ++i) {
865  unsigned int iQ=i*Q;
866  if(i < extra)
867  Execute(plan,(I *) in+iQ*idist,(O *) out+iQ*odist);
868  else {
869  unsigned int offset=iQ+i-extra;
870  Execute(plan2,(I *) in+offset*idist,(O *) out+offset*odist);
871  }
872  }
873  }
874  }
875 
876  unsigned int Threads() {return std::max(T,threads);}
877 
879  if(plan2) fftw_destroy_plan(plan2);
880  }
881 };
882 
883 // Compute the complex Fourier transform of M complex vectors, each of
884 // length n.
885 // Before calling fft(), the arrays in and out (which may coincide) must be
886 // allocated as Complex[M*n].
887 //
888 // Out-of-place usage:
889 //
890 // mfft1d Forward(n,-1,M,stride,dist,in,out);
891 // Forward.fft(in,out);
892 //
893 // In-place usage:
894 //
895 // mfft1d Forward(n,-1,M,stride,dist);
896 // Forward.fft(in);
897 //
898 // Notes:
899 // stride is the spacing between the elements of each Complex vector;
900 // dist is the spacing between the first elements of the vectors.
901 //
902 //
903 class mfft1d : public fftwblock<fftw_complex,fftw_complex>,
904  public Threadtable<keytype3,keyless3> {
906 public:
907  mfft1d(unsigned int nx, int sign, unsigned int M=1, size_t stride=1,
908  size_t dist=0, Complex *in=NULL, Complex *out=NULL,
909  unsigned int threads=maxthreads) :
910  fftw(2*((nx-1)*stride+(M-1)*Dist(nx,stride,dist)+1),sign,threads,nx),
911  fftwblock<fftw_complex,fftw_complex>
912  (nx,M,stride,stride,dist,dist,in,out,threads) {}
913 
914  mfft1d(unsigned int nx, int sign, unsigned int M,
915  size_t istride, size_t ostride, size_t idist, size_t odist,
916  Complex *in=NULL, Complex *out=NULL, unsigned int threads=maxthreads):
917  fftw(std::max(2*((nx-1)*istride+(M-1)*Dist(nx,istride,idist)+1),
918  2*((nx-1)*ostride+(M-1)*Dist(nx,ostride,odist)+1)),sign,
919  threads, nx),
920  fftwblock<fftw_complex,fftw_complex>(nx,M,istride,ostride,idist,odist,in,
921  out,threads) {}
922 
923  threaddata lookup(bool inplace, unsigned int threads) {
924  return Lookup(threadtable,keytype3(nx,Q,R,threads,inplace));
925  }
926  void store(bool inplace, const threaddata& data) {
927  Store(threadtable,keytype3(nx,Q,R,data.threads,inplace),data);
928  }
929 };
930 
931 // Compute the complex Fourier transform of n real values, using phase sign -1.
932 // Before calling fft(), the array in must be allocated as double[n] and
933 // the array out must be allocated as Complex[n/2+1]. The arrays in and out
934 // may coincide, allocated as Complex[n/2+1].
935 //
936 // Out-of-place usage:
937 //
938 // rcfft1d Forward(n,in,out);
939 // Forward.fft(in,out);
940 //
941 // In-place usage:
942 //
943 // rcfft1d Forward(n);
944 // Forward.fft(out);
945 //
946 // Notes:
947 // in contains the n real values stored as a Complex array;
948 // out contains the first n/2+1 Complex Fourier values.
949 //
950 class rcfft1d : public fftw, public Threadtable<keytype1,keyless1> {
951  unsigned int nx;
953 public:
954  rcfft1d(unsigned int nx, Complex *out=NULL, unsigned int threads=maxthreads)
955  : fftw(2*(nx/2+1),-1,threads,nx), nx(nx) {Setup(out,(double*) NULL);}
956 
957  rcfft1d(unsigned int nx, double *in, Complex *out=NULL,
958  unsigned int threads=maxthreads)
959  : fftw(2*(nx/2+1),-1,threads,nx), nx(nx) {Setup(in,out);}
960 
961  threaddata lookup(bool inplace, unsigned int threads) {
962  return Lookup(threadtable,keytype1(nx,threads,inplace));
963  }
964  void store(bool inplace, const threaddata& data) {
965  Store(threadtable,keytype1(nx,data.threads,inplace),data);
966  }
967 
968  fftw_plan Plan(Complex *in, Complex *out) {
969  return fftw_plan_dft_r2c_1d(nx,(double *) in,(fftw_complex *) out, effort);
970  }
971 
972  void Execute(Complex *in, Complex *out, bool=false) {
973  fftw_execute_dft_r2c(plan,(double *) in,(fftw_complex *) out);
974  }
975 };
976 
977 // Compute the real inverse Fourier transform of the n/2+1 Complex values
978 // corresponding to the non-negative part of the frequency spectrum, using
979 // phase sign +1.
980 // Before calling fft(), the array in must be allocated as Complex[n/2+1]
981 // and the array out must be allocated as double[n]. The arrays in and out
982 // may coincide, allocated as Complex[n/2+1].
983 //
984 // Out-of-place usage (input destroyed):
985 //
986 // crfft1d Backward(n,in,out);
987 // Backward.fft(in,out);
988 //
989 // In-place usage:
990 //
991 // crfft1d Backward(n);
992 // Backward.fft(in);
993 //
994 // Notes:
995 // in contains the first n/2+1 Complex Fourier values.
996 // out contains the n real values stored as a Complex array;
997 //
998 class crfft1d : public fftw, public Threadtable<keytype1,keyless1> {
999  unsigned int nx;
1001 public:
1002  crfft1d(unsigned int nx, double *out=NULL, unsigned int threads=maxthreads)
1003  : fftw(2*(nx/2+1),1,threads,nx), nx(nx) {Setup(out);}
1004 
1005  crfft1d(unsigned int nx, Complex *in, double *out=NULL,
1006  unsigned int threads=maxthreads)
1007  : fftw(realsize(nx,in,out),1,threads,nx), nx(nx) {Setup(in,out);}
1008 
1009  threaddata lookup(bool inplace, unsigned int threads) {
1010  return Lookup(threadtable,keytype1(nx,threads,inplace));
1011  }
1012  void store(bool inplace, const threaddata& data) {
1013  Store(threadtable,keytype1(nx,data.threads,inplace),data);
1014  }
1015 
1016  fftw_plan Plan(Complex *in, Complex *out) {
1017  return fftw_plan_dft_c2r_1d(nx,(fftw_complex *) in,(double *) out,effort);
1018  }
1019 
1020  void Execute(Complex *in, Complex *out, bool=false) {
1021  fftw_execute_dft_c2r(plan,(fftw_complex *) in,(double *) out);
1022  }
1023 };
1024 
1025 // Compute the real Fourier transform of M real vectors, each of length n,
1026 // using phase sign -1. Before calling fft(), the array in must be
1027 // allocated as double[M*n] and the array out must be allocated as
1028 // Complex[M*(n/2+1)]. The arrays in and out may coincide,
1029 // allocated as Complex[M*(n/2+1)].
1030 //
1031 // Out-of-place usage:
1032 //
1033 // mrcfft1d Forward(n,M,istride,ostride,idist,odist,in,out);
1034 // Forward.fft(in,out);
1035 //
1036 // In-place usage:
1037 //
1038 // mrcfft1d Forward(n,M,istride,ostride,idist,odist);
1039 // Forward.fft(out);
1040 //
1041 // Notes:
1042 // istride is the spacing between the elements of each real vector;
1043 // ostride is the spacing between the elements of each Complex vector;
1044 // idist is the spacing between the first elements of the real vectors;
1045 // odist is the spacing between the first elements of the Complex vectors;
1046 // in contains the n real values stored as a Complex array;
1047 // out contains the first n/2+1 Complex Fourier values.
1048 //
1049 class mrcfft1d : public fftwblock<double,fftw_complex>,
1050  public Threadtable<keytype3,keyless3> {
1052 public:
1053  mrcfft1d(unsigned int nx, unsigned int M,
1054  size_t istride, size_t ostride,
1055  size_t idist, size_t odist,
1056  double *in=NULL, Complex *out=NULL,
1057  unsigned int threads=maxthreads)
1058  : fftw(std::max((realsize(nx,in,out)-2)*istride+(M-1)*idist+2,
1059  2*(nx/2*ostride+(M-1)*odist+1)),-1,threads,nx),
1060  fftwblock<double,fftw_complex>
1061  (nx,M,istride,ostride,idist,odist,(Complex *) in,out,threads) {}
1062 
1063  threaddata lookup(bool inplace, unsigned int threads) {
1064  return Lookup(threadtable,keytype3(nx,Q,R,threads,inplace));
1065  }
1066 
1067  void store(bool inplace, const threaddata& data) {
1068  Store(threadtable,keytype3(nx,Q,R,data.threads,inplace),data);
1069  }
1070 
1072  fftw::Normalize<Complex>(nx/2+1,M,ostride,odist,out);
1073  }
1074 
1075 #pragma GCC diagnostic push
1076 #pragma GCC diagnostic ignored "-Woverloaded-virtual"
1077  void fftNormalized(double *in, Complex *out=NULL) {
1078  fftw::fftNormalized<double,Complex>(nx/2+1,M,ostride,odist,in,out,false);
1079  }
1080 #pragma GCC diagnostic pop
1081 
1082  void fft0Normalized(double *in, Complex *out=NULL) {
1083  fftw::fftNormalized<double,Complex>(nx/2+1,M,ostride,odist,in,out,true);
1084  }
1085 };
1086 
1087 // Compute the real inverse Fourier transform of M complex vectors, each of
1088 // length n/2+1, corresponding to the non-negative parts of the frequency
1089 // spectra, using phase sign +1. Before calling fft(), the array in must be
1090 // allocated as Complex[M*(n/2+1)] and the array out must be allocated as
1091 // double[M*n]. The arrays in and out may coincide,
1092 // allocated as Complex[M*(n/2+1)].
1093 //
1094 // Out-of-place usage (input destroyed):
1095 //
1096 // mcrfft1d Backward(n,M,istride,ostride,idist,odist,in,out);
1097 // Backward.fft(in,out);
1098 //
1099 // In-place usage:
1100 //
1101 // mcrfft1d Backward(n,M,istride,ostride,idist,odist);
1102 // Backward.fft(out);
1103 //
1104 // Notes:
1105 // stride is the spacing between the elements of each Complex vector;
1106 // dist is the spacing between the first elements of the vectors;
1107 // in contains the first n/2+1 Complex Fourier values;
1108 // out contains the n real values stored as a Complex array.
1109 //
1110 class mcrfft1d : public fftwblock<fftw_complex,double>,
1111  public Threadtable<keytype3,keyless3> {
1113 public:
1114  mcrfft1d(unsigned int nx, unsigned int M, size_t istride, size_t ostride,
1115  size_t idist, size_t odist, Complex *in=NULL, double *out=NULL,
1116  unsigned int threads=maxthreads)
1117  : fftw(std::max(2*(nx/2*istride+(M-1)*idist+1),
1118  (realsize(nx,in,out)-2)*ostride+(M-1)*odist+2),1,threads,nx),
1119  fftwblock<fftw_complex,double>
1120  (nx,M,istride,ostride,idist,odist,in,(Complex *) out,threads) {}
1121 
1122  threaddata lookup(bool inplace, unsigned int threads) {
1123  return Lookup(threadtable,keytype3(nx,Q,R,threads,inplace));
1124  }
1125 
1126  void store(bool inplace, const threaddata& data) {
1127  Store(threadtable,keytype3(nx,Q,R,data.threads,inplace),data);
1128  }
1129 
1130  void Normalize(double *out) {
1131  fftw::Normalize<double>(nx,M,ostride,odist,out);
1132  }
1133 
1134 #pragma GCC diagnostic push
1135 #pragma GCC diagnostic ignored "-Woverloaded-virtual"
1136  void fftNormalized(Complex *in, double *out=NULL) {
1137  fftw::fftNormalized<Complex,double>(nx,M,ostride,odist,in,out,false);
1138  }
1139 #pragma GCC diagnostic pop
1140 
1141  void fft0Normalized(Complex *in, double *out=NULL) {
1142  fftw::fftNormalized<Complex,double>(nx,M,ostride,odist,in,out,true);
1143  }
1144 };
1145 
1146 // Compute the complex two-dimensional Fourier transform of nx times ny
1147 // complex values. Before calling fft(), the arrays in and out (which may
1148 // coincide) must be allocated as Complex[nx*ny].
1149 //
1150 // Out-of-place usage:
1151 //
1152 // fft2d Forward(nx,ny,-1,in,out);
1153 // Forward.fft(in,out);
1154 //
1155 // fft2d Backward(nx,ny,1,in,out);
1156 // Backward.fft(in,out);
1157 //
1158 // fft2d Backward(nx,ny,1,in,out);
1159 // Backward.fftNormalized(in,out); // True inverse of Forward.fft(out,in);
1160 //
1161 // In-place usage:
1162 //
1163 // fft2d Forward(nx,ny,-1);
1164 // Forward.fft(in);
1165 //
1166 // fft2d Backward(nx,ny,1);
1167 // Backward.fft(in);
1168 //
1169 // Note:
1170 // in[ny*i+j] contains the ny Complex values for each i=0,...,nx-1.
1171 //
1172 class fft2d : public fftw, public Threadtable<keytype2,keyless2> {
1173  unsigned int nx;
1174  unsigned int ny;
1176 public:
1177  fft2d(unsigned int nx, unsigned int ny, int sign, Complex *in=NULL,
1178  Complex *out=NULL, unsigned int threads=maxthreads)
1179  : fftw(2*nx*ny,sign,threads), nx(nx), ny(ny) {Setup(in,out);}
1180 
1181 #ifdef __Array_h__
1182  fft2d(int sign, const Array::array2<Complex>& in,
1183  const Array::array2<Complex>& out=Array::NULL2,
1184  unsigned int threads=maxthreads)
1185  : fftw(2*in.Size(),sign,threads), nx(in.Nx()), ny(in.Ny()) {
1186  Setup(in,out);
1187  }
1188 #endif
1189 
1190  threaddata lookup(bool inplace, unsigned int threads) {
1191  return this->Lookup(threadtable,keytype2(nx,ny,threads,inplace));
1192  }
1193  void store(bool inplace, const threaddata& data) {
1194  this->Store(threadtable,keytype2(nx,ny,data.threads,inplace),data);
1195  }
1196 
1197  fftw_plan Plan(Complex *in, Complex *out) {
1198  return fftw_plan_dft_2d(nx,ny,(fftw_complex *) in,(fftw_complex *) out,
1199  sign,effort);
1200  }
1201 
1202  void Execute(Complex *in, Complex *out, bool=false) {
1203  fftw_execute_dft(plan,(fftw_complex *) in,(fftw_complex *) out);
1204  }
1205 };
1206 
1207 // Compute the complex two-dimensional Fourier transform of nx times ny real
1208 // values, using phase sign -1.
1209 // Before calling fft(), the array in must be allocated as double[nx*ny] and
1210 // the array out must be allocated as Complex[nx*(ny/2+1)]. The arrays in
1211 // and out may coincide, allocated as Complex[nx*(ny/2+1)].
1212 //
1213 // Out-of-place usage:
1214 //
1215 // rcfft2d Forward(nx,ny,in,out);
1216 // Forward.fft(in,out); // Origin of Fourier domain at (0,0)
1217 // Forward.fft0(in,out); // Origin of Fourier domain at (nx/2,0);
1218 // input destroyed.
1219 //
1220 // In-place usage:
1221 //
1222 // rcfft2d Forward(nx,ny);
1223 // Forward.fft(in); // Origin of Fourier domain at (0,0)
1224 // Forward.fft0(in); // Origin of Fourier domain at (nx/2,0)
1225 //
1226 // Notes:
1227 // in contains the nx*ny real values stored as a Complex array;
1228 // out contains the upper-half portion (ky >= 0) of the Complex transform.
1229 //
1230 class rcfft2d : public fftw {
1231  unsigned int nx;
1232  unsigned int ny;
1233 public:
1234  rcfft2d(unsigned int nx, unsigned int ny, Complex *out=NULL,
1235  unsigned int threads=maxthreads)
1236  : fftw(2*nx*(ny/2+1),-1,threads,nx*ny), nx(nx), ny(ny) {Setup(out);}
1237 
1238  rcfft2d(unsigned int nx, unsigned int ny, double *in, Complex *out=NULL,
1239  unsigned int threads=maxthreads)
1240  : fftw(2*nx*(ny/2+1),-1,threads,nx*ny), nx(nx), ny(ny) {
1241  Setup(in,out);
1242  }
1243 
1244  fftw_plan Plan(Complex *in, Complex *out) {
1245  return fftw_plan_dft_r2c_2d(nx,ny,(double *) in,(fftw_complex *) out,
1246  effort);
1247  }
1248 
1249  void Execute(Complex *in, Complex *out, bool shift=false) {
1250  if(shift) {
1251  if(inplace) Shift(in,nx,ny,threads);
1252  else Shift((double *) in,nx,ny,threads);
1253  }
1254  fftw_execute_dft_r2c(plan,(double *) in,(fftw_complex *) out);
1255  }
1256 
1257  // Set Nyquist modes of even shifted transforms to zero.
1258  void deNyquist(Complex *f) {
1259  unsigned int nyp=ny/2+1;
1260  if(nx % 2 == 0)
1261 #ifndef FFTWPP_SINGLE_THREAD
1262 #pragma omp parallel for num_threads(threads)
1263 #endif
1264  for(unsigned int j=0; j < nyp; ++j)
1265  f[j]=0.0;
1266  if(ny % 2 == 0)
1267 #ifndef FFTWPP_SINGLE_THREAD
1268 #pragma omp parallel for num_threads(threads)
1269 #endif
1270  for(unsigned int i=0; i < nx; ++i)
1271  f[(i+1)*nyp-1]=0.0;
1272  }
1273 };
1274 
1275 // Compute the real two-dimensional inverse Fourier transform of the
1276 // nx*(ny/2+1) Complex values corresponding to the spectral values in the
1277 // half-plane ky >= 0, using phase sign +1.
1278 // Before calling fft(), the array in must be allocated as
1279 // Complex[nx*(ny/2+1)] and the array out must be allocated as
1280 // double[nx*ny]. The arrays in and out may coincide,
1281 // allocated as Complex[nx*(ny/2+1)].
1282 //
1283 // Out-of-place usage (input destroyed):
1284 //
1285 // crfft2d Backward(nx,ny,in,out);
1286 // Backward.fft(in,out); // Origin of Fourier domain at (0,0)
1287 // Backward.fft0(in,out); // Origin of Fourier domain at (nx/2,0)
1288 //
1289 // In-place usage:
1290 //
1291 // crfft2d Backward(nx,ny);
1292 // Backward.fft(in); // Origin of Fourier domain at (0,0)
1293 // Backward.fft0(in); // Origin of Fourier domain at (nx/2,0)
1294 //
1295 // Notes:
1296 // in contains the upper-half portion (ky >= 0) of the Complex transform;
1297 // out contains the nx*ny real values stored as a Complex array.
1298 //
1299 class crfft2d : public fftw {
1300  unsigned int nx;
1301  unsigned int ny;
1302 public:
1303  crfft2d(unsigned int nx, unsigned int ny, double *out=NULL,
1304  unsigned int threads=maxthreads) :
1305  fftw(2*nx*(ny/2+1),1,threads,nx*ny), nx(nx), ny(ny) {Setup(out);}
1306 
1307  crfft2d(unsigned int nx, unsigned int ny, Complex *in, double *out=NULL,
1308  unsigned int threads=maxthreads)
1309  : fftw(nx*realsize(ny,in,out),1,threads,nx*ny), nx(nx), ny(ny) {
1310  Setup(in,out);
1311  }
1312 
1313  fftw_plan Plan(Complex *in, Complex *out) {
1314  return fftw_plan_dft_c2r_2d(nx,ny,(fftw_complex *) in,(double *) out,
1315  effort);
1316  }
1317 
1318  void Execute(Complex *in, Complex *out, bool shift=false) {
1319  fftw_execute_dft_c2r(plan,(fftw_complex *) in,(double *) out);
1320  if(shift) {
1321  if(inplace) Shift(out,nx,ny,threads);
1322  else Shift((double *) out,nx,ny,threads);
1323  }
1324  }
1325 
1326  // Set Nyquist modes of even shifted transforms to zero.
1327  void deNyquist(Complex *f) {
1328  unsigned int nyp=ny/2+1;
1329  if(nx % 2 == 0)
1330 #ifndef FFTWPP_SINGLE_THREAD
1331 #pragma omp parallel for num_threads(threads)
1332 #endif
1333  for(unsigned int j=0; j < nyp; ++j)
1334  f[j]=0.0;
1335  if(ny % 2 == 0)
1336 #ifndef FFTWPP_SINGLE_THREAD
1337 #pragma omp parallel for num_threads(threads)
1338 #endif
1339  for(unsigned int i=0; i < nx; ++i)
1340  f[(i+1)*nyp-1]=0.0;
1341  }
1342 };
1343 
1344 // Compute the complex three-dimensional Fourier transform of
1345 // nx times ny times nz complex values. Before calling fft(), the arrays in
1346 // and out (which may coincide) must be allocated as Complex[nx*ny*nz].
1347 //
1348 // Out-of-place usage:
1349 //
1350 // fft3d Forward(nx,ny,nz,-1,in,out);
1351 // Forward.fft(in,out);
1352 //
1353 // fft3d Backward(nx,ny,nz,1,in,out);
1354 // Backward.fft(in,out);
1355 //
1356 // fft3d Backward(nx,ny,nz,1,in,out);
1357 // Backward.fftNormalized(in,out); // True inverse of Forward.fft(out,in);
1358 //
1359 // In-place usage:
1360 //
1361 // fft3d Forward(nx,ny,nz,-1);
1362 // Forward.fft(in);
1363 //
1364 // fft3d Backward(nx,ny,nz,1);
1365 // Backward.fft(in);
1366 //
1367 // Note:
1368 // in[nz*(ny*i+j)+k] contains the (i,j,k)th Complex value,
1369 // indexed by i=0,...,nx-1, j=0,...,ny-1, and k=0,...,nz-1.
1370 //
1371 class fft3d : public fftw {
1372  unsigned int nx;
1373  unsigned int ny;
1374  unsigned int nz;
1375 public:
1376  fft3d(unsigned int nx, unsigned int ny, unsigned int nz,
1377  int sign, Complex *in=NULL, Complex *out=NULL,
1378  unsigned int threads=maxthreads)
1379  : fftw(2*nx*ny*nz,sign,threads), nx(nx), ny(ny), nz(nz) {Setup(in,out);}
1380 
1381 #ifdef __Array_h__
1382  fft3d(int sign, const Array::array3<Complex>& in,
1383  const Array::array3<Complex>& out=Array::NULL3,
1384  unsigned int threads=maxthreads)
1385  : fftw(2*in.Size(),sign,threads), nx(in.Nx()), ny(in.Ny()), nz(in.Nz())
1386  {Setup(in,out);}
1387 #endif
1388 
1389  fftw_plan Plan(Complex *in, Complex *out) {
1390  return fftw_plan_dft_3d(nx,ny,nz,(fftw_complex *) in,
1391  (fftw_complex *) out, sign, effort);
1392  }
1393 };
1394 
1395 // Compute the complex two-dimensional Fourier transform of
1396 // nx times ny times nz real values, using phase sign -1.
1397 // Before calling fft(), the array in must be allocated as double[nx*ny*nz]
1398 // and the array out must be allocated as Complex[nx*ny*(nz/2+1)]. The
1399 // arrays in and out may coincide, allocated as Complex[nx*ny*(nz/2+1)].
1400 //
1401 // Out-of-place usage:
1402 //
1403 // rcfft3d Forward(nx,ny,nz,in,out);
1404 // Forward.fft(in,out); // Origin of Fourier domain at (0,0)
1405 // Forward.fft0(in,out); // Origin of Fourier domain at (nx/2,ny/2,0);
1406 // input destroyed
1407 // In-place usage:
1408 //
1409 // rcfft3d Forward(nx,ny,nz);
1410 // Forward.fft(in); // Origin of Fourier domain at (0,0)
1411 // Forward.fft0(in); // Origin of Fourier domain at (nx/2,ny/2,0)
1412 //
1413 // Notes:
1414 // in contains the nx*ny*nz real values stored as a Complex array;
1415 // out contains the upper-half portion (kz >= 0) of the Complex transform.
1416 //
1417 class rcfft3d : public fftw {
1418  unsigned int nx;
1419  unsigned int ny;
1420  unsigned int nz;
1421 public:
1422  rcfft3d(unsigned int nx, unsigned int ny, unsigned int nz, Complex *out=NULL,
1423  unsigned int threads=maxthreads)
1424  : fftw(2*nx*ny*(nz/2+1),-1,threads,nx*ny*nz), nx(nx), ny(ny), nz(nz) {
1425  Setup(out);
1426  }
1427 
1428  rcfft3d(unsigned int nx, unsigned int ny, unsigned int nz, double *in,
1429  Complex *out=NULL, unsigned int threads=maxthreads)
1430  : fftw(2*nx*ny*(nz/2+1),-1,threads,nx*ny*nz),
1431  nx(nx), ny(ny), nz(nz) {Setup(in,out);}
1432 
1433  fftw_plan Plan(Complex *in, Complex *out) {
1434  return fftw_plan_dft_r2c_3d(nx,ny,nz,(double *) in,(fftw_complex *) out,
1435  effort);
1436  }
1437 
1438  void Execute(Complex *in, Complex *out, bool shift=false) {
1439  if(shift) {
1440  if(inplace) Shift(in,nx,ny,nz,threads);
1441  else Shift((double *) in,nx,ny,nz,threads);
1442  }
1443  fftw_execute_dft_r2c(plan,(double *) in,(fftw_complex *) out);
1444  }
1445 
1446  // Set Nyquist modes of even shifted transforms to zero.
1447  void deNyquist(Complex *f) {
1448  unsigned int nzp=nz/2+1;
1449  unsigned int yz=ny*nzp;
1450  if(nx % 2 == 0) {
1451 #ifndef FFTWPP_SINGLE_THREAD
1452 #pragma omp parallel for num_threads(threads)
1453 #endif
1454  for(unsigned int k=0; k < yz; ++k)
1455  f[k]=0.0;
1456  }
1457 
1458  if(ny % 2 == 0) {
1459 #ifndef FFTWPP_SINGLE_THREAD
1460 #pragma omp parallel for num_threads(threads)
1461 #endif
1462  for(unsigned int i=0; i < nx; ++i) {
1463  unsigned int iyz=i*yz;
1464  for(unsigned int k=0; k < nzp; ++k)
1465  f[iyz+k]=0.0;
1466  }
1467  }
1468 
1469  if(nz % 2 == 0)
1470 #ifndef FFTWPP_SINGLE_THREAD
1471 #pragma omp parallel for num_threads(threads)
1472 #endif
1473  for(unsigned int i=0; i < nx; ++i)
1474  for(unsigned int j=0; j < ny; ++j)
1475  f[i*yz+(j+1)*nzp-1]=0.0;
1476  }
1477 };
1478 
1479 // Compute the real two-dimensional inverse Fourier transform of the
1480 // nx*ny*(nz/2+1) Complex values corresponding to the spectral values in the
1481 // half-plane kz >= 0, using phase sign +1.
1482 // Before calling fft(), the array in must be allocated as
1483 // Complex[nx*ny*(nz+1)/2] and the array out must be allocated as
1484 // double[nx*ny*nz]. The arrays in and out may coincide,
1485 // allocated as Complex[nx*ny*(nz/2+1)].
1486 //
1487 // Out-of-place usage (input destroyed):
1488 //
1489 // crfft3d Backward(nx,ny,nz,in,out);
1490 // Backward.fft(in,out); // Origin of Fourier domain at (0,0)
1491 // Backward.fft0(in,out); // Origin of Fourier domain at (nx/2,ny/2,0)
1492 //
1493 // In-place usage:
1494 //
1495 // crfft3d Backward(nx,ny,nz);
1496 // Backward.fft(in); // Origin of Fourier domain at (0,0)
1497 // Backward.fft0(in); // Origin of Fourier domain at (nx/2,ny/2,0)
1498 //
1499 // Notes:
1500 // in contains the upper-half portion (kz >= 0) of the Complex transform;
1501 // out contains the nx*ny*nz real values stored as a Complex array.
1502 //
1503 class crfft3d : public fftw {
1504  unsigned int nx;
1505  unsigned int ny;
1506  unsigned int nz;
1507 public:
1508  crfft3d(unsigned int nx, unsigned int ny, unsigned int nz, double *out=NULL,
1509  unsigned int threads=maxthreads)
1510  : fftw(2*nx*ny*(nz/2+1),1,threads,nx*ny*nz), nx(nx), ny(ny), nz(nz)
1511  {Setup(out);}
1512 
1513  crfft3d(unsigned int nx, unsigned int ny, unsigned int nz, Complex *in,
1514  double *out=NULL, unsigned int threads=maxthreads)
1515  : fftw(nx*ny*(realsize(nz,in,out)),1,threads,nx*ny*nz), nx(nx), ny(ny),
1516  nz(nz) {Setup(in,out);}
1517 
1518  fftw_plan Plan(Complex *in, Complex *out) {
1519  return fftw_plan_dft_c2r_3d(nx,ny,nz,(fftw_complex *) in,(double *) out,
1520  effort);
1521  }
1522 
1523  void Execute(Complex *in, Complex *out, bool shift=false) {
1524  fftw_execute_dft_c2r(plan,(fftw_complex *) in,(double *) out);
1525  if(shift) {
1526  if(inplace) Shift(out,nx,ny,nz,threads);
1527  else Shift((double *) out,nx,ny,nz,threads);
1528  }
1529  }
1530 
1531  // Set Nyquist modes of even shifted transforms to zero.
1532  void deNyquist(Complex *f) {
1533  unsigned int nzp=nz/2+1;
1534  unsigned int yz=ny*nzp;
1535  if(nx % 2 == 0) {
1536 #ifndef FFTWPP_SINGLE_THREAD
1537 #pragma omp parallel for num_threads(threads)
1538 #endif
1539  for(unsigned int k=0; k < yz; ++k)
1540  f[k]=0.0;
1541  }
1542 
1543  if(ny % 2 == 0) {
1544 #ifndef FFTWPP_SINGLE_THREAD
1545 #pragma omp parallel for num_threads(threads)
1546 #endif
1547  for(unsigned int i=0; i < nx; ++i) {
1548  unsigned int iyz=i*yz;
1549  for(unsigned int k=0; k < nzp; ++k)
1550  f[iyz+k]=0.0;
1551  }
1552  }
1553 
1554  if(nz % 2 == 0)
1555 #ifndef FFTWPP_SINGLE_THREAD
1556 #pragma omp parallel for num_threads(threads)
1557 #endif
1558  for(unsigned int i=0; i < nx; ++i)
1559  for(unsigned int j=0; j < ny; ++j)
1560  f[i*yz+(j+1)*nzp-1]=0.0;
1561  }
1562 };
1563 
1564 }
1565 
1566 #endif
crfft2d(unsigned int nx, unsigned int ny, Complex *in, double *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:1307
void Store(Table &threadtable, T key, const threaddata &data)
Definition: fftw++.h:649
unsigned int rows
Definition: fftw++.h:509
void Execute(fftw_plan plan, fftw_complex *in, double *out)
Definition: fftw++.h:852
keytype1(unsigned int nx, unsigned int threads, bool inplace)
Definition: fftw++.h:658
threaddata lookup(bool inplace, unsigned int threads)
Definition: fftw++.h:923
static unsigned int effort
Definition: fftw++.h:171
void store(bool inplace, const threaddata &data)
Definition: fftw++.h:964
void fftNormalized(double *in, Complex *out, bool shift=false)
Definition: fftw++.h:468
fftw_plan Plan(Complex *in, Complex *out)
Definition: fftw++.h:1389
unsigned int threads
Definition: fftw++.h:106
void store(bool inplace, const threaddata &data)
Definition: fftw++.h:754
void transpose(T *in, T *out=NULL)
Definition: fftw++.h:594
unsigned int mlength
Definition: fftw++.h:507
Complex * Setout(Complex *in, Complex *out)
Definition: fftw++.h:405
void fftNormalized(double *in, Complex *out=NULL)
Definition: fftw++.h:1077
rcfft1d(unsigned int nx, double *in, Complex *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:957
static void Shift(double *data, unsigned int nx, unsigned int ny, unsigned int nz, unsigned int)
Definition: fftw++.h:244
void multithread(unsigned int nx)
Definition: fftw++.h:127
unsigned int a
Definition: fftw++.h:506
fftw_plan Plan(int Q, fftw_complex *in, double *out)
Definition: fftw++.h:830
mfft1d(unsigned int nx, int sign, unsigned int M=1, size_t stride=1, size_t dist=0, Complex *in=NULL, Complex *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:907
void fftNormalized(unsigned int nx, unsigned int M, size_t ostride, size_t odist, I *in, O *out=NULL, bool shift=false)
Definition: fftw++.h:494
void store(bool inplace, const threaddata &data)
Definition: fftw++.h:926
crfft3d(unsigned int nx, unsigned int ny, unsigned int nz, double *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:1508
threaddata lookup(bool inplace, unsigned int threads)
Definition: fftw++.h:961
void Normalize(Complex *out)
Definition: fftw++.h:440
void Normalize(Complex *out)
Definition: fftw++.h:1071
fftw(unsigned int doubles, int sign, unsigned int threads, unsigned int n=0)
Definition: fftw++.h:266
void LoadWisdom()
Definition: fftw++.cc:31
unsigned int nx
Definition: fftw++.h:671
static const char * oddshift
Definition: fftw++.h:179
unsigned int nx
Definition: fftw++.h:999
fftw_plan Plan(Complex *in, Complex *out)
Definition: fftw++.h:968
void Execute(fftw_plan plan, double *in, fftw_complex *out)
Definition: fftw++.h:848
fftw_plan Plan(Complex *in, Complex *out)
Definition: fftw++.h:835
virtual void store(bool, const threaddata &)
Definition: fftw++.h:347
unsigned int nx
Definition: fftw++.h:1504
unsigned int nz
Definition: fftw++.h:1420
fftwblock(unsigned int nx, unsigned int M, size_t istride, size_t ostride, size_t idist, size_t odist, Complex *in, Complex *out, unsigned int Threads)
Definition: fftw++.h:773
void fftNormalized(Complex *in, double *out, bool shift=false)
Definition: fftw++.h:462
void store(bool inplace, const threaddata &data)
Definition: fftw++.h:1012
void Execute(fftw_plan plan, fftw_complex *in, fftw_complex *out)
Definition: fftw++.h:844
mrcfft1d(unsigned int nx, unsigned int M, size_t istride, size_t ostride, size_t idist, size_t odist, double *in=NULL, Complex *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:1053
unsigned int M
Definition: fftw++.h:768
unsigned int nx
Definition: fftw++.h:691
void Execute(Complex *in, Complex *out, bool=false)
Definition: fftw++.h:1202
threaddata(unsigned int threads, double mean, double stdev)
Definition: fftw++.h:110
keytype3(unsigned int nx, unsigned int ny, unsigned int nz, unsigned int threads, bool inplace)
Definition: fftw++.h:696
unsigned int cols
Definition: fftw++.h:509
size_t istride
Definition: fftw++.h:769
rcfft3d(unsigned int nx, unsigned int ny, unsigned int nz, Complex *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:1422
unsigned int ny
Definition: fftw++.h:1373
void Execute(Complex *in, Complex *out, bool shift=false)
Definition: fftw++.h:1318
threaddata lookup(bool inplace, unsigned int threads)
Definition: fftw++.h:1009
static const char * WisdomName
Definition: fftw++.h:174
unsigned int realsize(unsigned int n, Complex *in, Complex *out=NULL)
Definition: fftw++.h:137
unsigned int b
Definition: fftw++.h:506
unsigned int ny
Definition: fftw++.h:1505
crfft2d(unsigned int nx, unsigned int ny, double *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:1303
vector< t2list > out
output of the algorithm: a list of clusters
Definition: XbAlgo.cc:32
size_t idist
Definition: fftw++.h:770
void Normalize(double *out)
Definition: fftw++.h:1130
int exit
Definition: dump1090.h:237
void fft0(Complex *in, double *out)
Definition: fftw++.h:436
fftw_plan Plan(Complex *in, Complex *out)
Definition: fftw++.h:1197
ThreadBase(unsigned int threads)
Definition: fftw++.h:123
const char * inout
Definition: fftw++.cc:20
void SaveWisdom()
Definition: fftw++.cc:46
unsigned int threads
Definition: fftw++.h:694
unsigned int size
Definition: fftw++.h:515
void fft0(double *in, Complex *out=NULL)
Definition: fftw++.h:432
static void Shift(Complex *data, unsigned int nx, unsigned int ny, unsigned int nz, unsigned int)
Definition: fftw++.h:221
void fft(Complex *in, double *out)
Definition: fftw++.h:423
unsigned int ny
Definition: fftw++.h:692
unsigned int Q
Definition: fftw++.h:772
unsigned int nx
Definition: fftw++.h:951
bool operator()(const keytype3 &a, const keytype3 &b) const
Definition: fftw++.h:702
void deNyquist(Complex *f)
Definition: fftw++.h:1327
double stdev(double var, double f)
Definition: statistics.h:25
unsigned int nx
Definition: fftw++.h:1231
static double testseconds
Definition: fftw++.h:173
unsigned int ceilquotient(unsigned int a, unsigned int b)
Definition: align.h:92
fftw_plan plan
Definition: fftw++.h:504
void fft0Normalized(Complex *in, double *out=NULL)
Definition: fftw++.h:1141
#define I
virtual fftw_plan Plan(Complex *, Complex *)
Definition: fftw++.h:279
unsigned int ny
Definition: fftw++.h:1232
#define max(a, b)
std::complex< double > Complex
Definition: fftw++.h:83
bool operator()(const keytype2 &a, const keytype2 &b) const
Definition: fftw++.h:681
double totalseconds()
Definition: seconds.h:82
static Table threadtable
Definition: fftw++.h:1000
static unsigned int maxthreads
Definition: fftw++.h:172
static Table threadtable
Definition: fftw++.h:905
constexpr double s
Definition: AugerUnits.h:163
unsigned int nz
Definition: fftw++.h:1506
fft3d(unsigned int nx, unsigned int ny, unsigned int nz, int sign, Complex *in=NULL, Complex *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:1376
void deNyquist(Complex *f)
Definition: fftw++.h:1447
fftw_plan Planner(fftw *F, Complex *in, Complex *out)
Definition: fftw++.cc:56
void fft(Complex *in, Complex *out=NULL)
Definition: fftw++.h:414
void Execute(Complex *in, Complex *out, bool=false)
Definition: fftw++.h:1020
void Threads(unsigned int nthreads)
Definition: fftw++.h:124
void Execute(Complex *in, Complex *out, bool shift=false)
Definition: fftw++.h:1523
int get_thread_num()
Definition: fftw++.h:42
unsigned int nx
Definition: fftw++.h:655
unsigned int nlength
Definition: fftw++.h:507
#define S
threaddata Setup(Complex *in, double *out)
Definition: fftw++.h:393
fft1d(unsigned int nx, int sign, Complex *in=NULL, Complex *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:740
virtual void Execute(Complex *in, Complex *out, bool=false)
Definition: fftw++.h:401
#define FFTWPP_THREADS_PAR
Definition: fftw++.h:76
unsigned int Dist(unsigned int n, size_t stride, size_t dist)
Definition: fftw++.h:164
static Table threadtable
Definition: fftw++.h:1112
unsigned int Threads()
Definition: fftw++.h:876
void Execute(Complex *in, Complex *out, bool shift=false)
Definition: fftw++.h:1249
void Normalize(double *out)
Definition: fftw++.h:448
fftw_plan plan
Definition: fftw++.h:161
unsigned int nx
Definition: fftw++.h:1418
int get_max_threads()
Definition: fftw++.h:51
rcfft3d(unsigned int nx, unsigned int ny, unsigned int nz, double *in, Complex *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:1428
void Execute(Complex *in, Complex *out, bool=false)
Definition: fftw++.h:856
static Table threadtable
Definition: fftw++.h:952
unsigned int nz
Definition: fftw++.h:1374
fft2d(unsigned int nx, unsigned int ny, int sign, Complex *in=NULL, Complex *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:1177
unsigned int threads
Definition: fftw++.h:673
unsigned int doubles
Definition: fftw++.h:156
void deNyquist(Complex *f)
Definition: fftw++.h:1258
fftw_plan Plan(Complex *in, Complex *out)
Definition: fftw++.h:758
void Execute(Complex *in, Complex *out, bool=false)
Definition: fftw++.h:972
Transpose(unsigned int rows, unsigned int cols, unsigned int length, T *in, T *out=NULL, unsigned int threads=fftw::maxthreads)
Definition: fftw++.h:518
unsigned int nx
Definition: fftw++.h:737
void Normalize(unsigned int nx, unsigned int M, size_t ostride, size_t odist, O *out)
Definition: fftw++.h:478
virtual void fftNormalized(Complex *in, Complex *out=NULL, bool shift=false)
Definition: fftw++.h:455
Complex * CheckAlign(Complex *in, Complex *out, bool constructor=true)
Definition: fftw++.h:349
unsigned int threads
Definition: fftw++.h:512
mfft1d(unsigned int nx, int sign, unsigned int M, size_t istride, size_t ostride, size_t idist, size_t odist, Complex *in=NULL, Complex *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:914
fftw_plan plan1
Definition: fftw++.h:771
size_t odist
Definition: fftw++.h:770
unsigned int innerthreads
Definition: fftw++.h:120
void deNyquist(Complex *f)
Definition: fftw++.h:1532
rcfft1d(unsigned int nx, Complex *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:954
unsigned int nx
Definition: fftw++.h:1173
static Table threadtable
Definition: fftw++.h:738
fftw_plan Plan(Complex *in, Complex *out)
Definition: fftw++.h:1016
unsigned int R
Definition: fftw++.h:772
std::map< T, threaddata, L > Table
Definition: fftw++.h:642
fftw_plan Plan(int Q, fftw_complex *in, fftw_complex *out)
Definition: fftw++.h:820
static Table threadtable
Definition: fftw++.h:1175
virtual unsigned int Threads()
Definition: fftw++.h:177
void Execute(Complex *in, Complex *out, bool shift=false)
Definition: fftw++.h:1438
void store(bool inplace, const threaddata &data)
Definition: fftw++.h:1067
static const double twopi
Definition: fftw++.h:168
crfft1d(unsigned int nx, Complex *in, double *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:1005
threaddata Setup(Complex *in, Complex *out=NULL)
Definition: fftw++.h:361
threaddata Lookup(Table &table, T key)
Definition: fftw++.h:644
threaddata lookup(bool inplace, unsigned int threads)
Definition: fftw++.h:1122
threaddata lookup(bool inplace, unsigned int threads)
Definition: fftw++.h:1190
uint16_t * data
Definition: dump1090.h:228
unsigned int Threads()
Definition: fftw++.h:125
unsigned int ny
Definition: fftw++.h:1301
unsigned int threads
Definition: fftw++.h:119
void fft0Normalized(I in, O out)
Definition: fftw++.h:473
unsigned int nx
Definition: fftw++.h:1372
bool inplace
Definition: fftw++.h:162
void store(bool inplace, const threaddata &data)
Definition: fftw++.h:1193
mcrfft1d(unsigned int nx, unsigned int M, size_t istride, size_t ostride, size_t idist, size_t odist, Complex *in=NULL, double *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:1114
double count()
Definition: statistics.h:13
threaddata Setup(double *in, Complex *out=NULL)
Definition: fftw++.h:397
unsigned int threads
Definition: fftw++.h:158
double norm
Definition: fftw++.h:159
Complex * ComplexAlign(size_t size)
Definition: align.h:97
rcfft2d(unsigned int nx, unsigned int ny, double *in, Complex *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:1238
void add(double t)
Definition: statistics.h:15
static fftw_plan(* planner)(fftw *f, Complex *in, Complex *out)
Definition: fftw++.h:175
void fftNormalized(Complex *in, double *out=NULL)
Definition: fftw++.h:1136
unsigned int jlast
Definition: fftw++.h:508
void noplan()
Definition: fftw++.h:287
fftw_plan Plan(Complex *in, Complex *out)
Definition: fftw++.h:1313
unsigned int ny
Definition: fftw++.h:672
unsigned int nx
Definition: fftw++.h:1300
crfft3d(unsigned int nx, unsigned int ny, unsigned int nz, Complex *in, double *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:1513
void fft(double *in, Complex *out=NULL)
Definition: fftw++.h:419
void store(bool inplace, const threaddata &data)
Definition: fftw++.h:1126
unsigned int ny
Definition: fftw++.h:1174
virtual threaddata lookup(bool, unsigned int)
Definition: fftw++.h:344
fftw_plan Plan(Complex *in, Complex *out)
Definition: fftw++.h:1433
fftw_plan plan2
Definition: fftw++.h:771
void CheckAlign(Complex *p, const char *s)
Definition: fftw++.h:281
constexpr double m
Definition: AugerUnits.h:121
static void planThreads(unsigned int)
Definition: fftw++.h:292
unsigned int threads
Definition: fftw++.h:656
virtual ~fftw()
Definition: fftw++.h:275
int sign
Definition: fftw++.h:157
static Table threadtable
Definition: fftw++.h:1051
static void Shift(double *data, unsigned int nx, unsigned int ny, unsigned int)
Definition: fftw++.h:202
fftw_plan Plan(Complex *in, Complex *out)
Definition: fftw++.h:1518
threaddata lookup(bool inplace, unsigned int threads)
Definition: fftw++.h:751
unsigned int ny
Definition: fftw++.h:1419
fftw_plan Plan(Complex *in, Complex *out)
Definition: fftw++.h:1244
unsigned int nz
Definition: fftw++.h:693
void deleteAlign(T *v, size_t len)
Definition: align.h:77
rcfft2d(unsigned int nx, unsigned int ny, Complex *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:1234
unsigned int ilast
Definition: fftw++.h:508
unsigned int T
Definition: fftw++.h:772
fftw_plan Plan(int Q, double *in, fftw_complex *out)
Definition: fftw++.h:825
void fft0(Complex *in, Complex *out=NULL)
Definition: fftw++.h:427
size_t ostride
Definition: fftw++.h:769
threaddata lookup(bool inplace, unsigned int threads)
Definition: fftw++.h:1063
static void Shift(Complex *data, unsigned int nx, unsigned int ny, unsigned int)
Definition: fftw++.h:182
crfft1d(unsigned int nx, double *out=NULL, unsigned int threads=maxthreads)
Definition: fftw++.h:1002
bool operator()(const keytype1 &a, const keytype1 &b) const
Definition: fftw++.h:663
fftw_plan plan2
Definition: fftw++.h:505
keytype2(unsigned int nx, unsigned int ny, unsigned int threads, bool inplace)
Definition: fftw++.h:675
threaddata time(fftw_plan plan1, fftw_plan planT, Complex *in, Complex *out, unsigned int Threads)
Definition: fftw++.h:299
void fft0Normalized(double *in, Complex *out=NULL)
Definition: fftw++.h:1082

, generated on Tue Sep 26 2023.