test_Fw2dFFT.cxx
Go to the documentation of this file.
1 // test_Fw2dFFT.cxx
2 //
3 // David Adams
4 // April 2019
5 //
6 // Test Fw2dFFT.
7 
9 #include <string>
10 #include <iostream>
11 #include <fstream>
12 #include <sstream>
13 #include <vector>
14 #include <iomanip>
15 #include <cmath>
16 
17 #undef NDEBUG
18 #include <cassert>
19 
20 using std::string;
21 using std::cout;
22 using std::endl;
23 using std::ostringstream;
24 using std::ofstream;
25 using std::vector;
26 using std::setw;
27 using std::fixed;
28 using std::setprecision;
29 
30 using Index = unsigned int;
32 using DataVector = std::vector<DataFloat>;
37 
38 template<typename T>
39 void printValue(T val) {
40  Index prec = 3;
41  Index wid = 10;
42  cout << setw(wid) << fixed << setprecision(prec) << val;
43 }
44 
45 template<>
47  printValue(std::real(val));
48  cout << ", ";
49  printValue(std::imag(val));
50 }
51 
52 template<class Data>
53 void printData(const Data& dat) {
54  string myname = "printData: ";
55  Index nrow = dat.nSamples()[0];
56  Index ncol = dat.nSamples()[1];
57  IndexArray ifrqs;
58  Index& irow = ifrqs[0];
59  Index& icol = ifrqs[1];
60  for ( irow=0; irow<nrow; ++irow ) {
61  for ( icol=0; icol<ncol; ++icol ) {
62  cout << myname;
63  cout << setw(4) << irow;
64  cout << setw(4) << icol;
65  cout << ": ";
66  printValue(dat.value(ifrqs));
67  cout << endl;
68  }
69  }
70 }
71 
72 template<class Data>
73 bool printData(const Data& dat1, const Data& dat2) {
74  string myname = "printData: ";
75  assert( dat1.nSamples() == dat2.nSamples() );
76  Index nrow = dat1.nSamples()[0];
77  Index ncol = dat1.nSamples()[1];
78  IndexArray ifrqs;
79  Index& irow = ifrqs[0];
80  Index& icol = ifrqs[1];
81  int nbad = 0;
82  for ( irow=0; irow<nrow; ++irow ) {
83  for ( icol=0; icol<ncol; ++icol ) {
84  cout << myname;
85  cout << setw(4) << irow;
86  cout << setw(4) << icol;
87  float val1 = dat1.value(ifrqs);
88  float val2 = dat2.value(ifrqs);
89  cout << ": ";
90  printValue(val1);
91  cout << " ?= ";
92  printValue(val2);
93  if ( fabs(val2 - val1) > 0.001 ) {
94  cout << " !";
95  ++nbad;
96  }
97  cout << endl;
98  }
99  }
100  return nbad == 0;
101 }
102 
103 //**********************************************************************
104 
105 int test_Fw2dFFT(Index ignorm, Index itnorm, int loglev) {
106  const string myname = "test_Fw2dFFT: ";
107 #ifdef NDEBUG
108  cout << myname << "NDEBUG must be off." << endl;
109  abort();
110 #endif
111  string line = "-----------------------------";
112 
113  RealDftNormalization norm(ignorm, itnorm);
114  cout << line << endl;
115  cout << myname << " Global norm: " << ignorm << " " << norm.globalName() << endl;
116  cout << myname << " Term norm: " << itnorm << " " << norm.termName() << endl;
117 
118  cout << myname << line << endl;
119  cout << myname << "Create data." << endl;
120  Index n0 = 3;
121  Index n1 = 20;
122  Index nsam = n0*n1;
123  Index ndft = 2*n0*(n1/2 + 1);
124  DataVector sams = {
125  2.0, 3.0, 2.0, 1.0, 0.0, -1.0, -2.0, -3.0, -2.0, -1.0,
126  0.0, 1.0, 2.0, 3.0, 2.0, 1.0, 0.0, -1.0, -2.0, -3.0,
127  3.0, 6.0, 16.1, 28.6, 30.2, 27.7, 16.3, 9.6, 4.2, -1.0,
128  -2.3, -4.2, -9.2, -18.6, -21.9, -29.0, -24.3, -14.2, -5.0, -3.0,
129  -2.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 2.0, 1.0,
130  0.0, -1.0, -2.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0
131  };
132  assert( sams.size() == nsam );
133  cout << myname << "Sample length: " << nsam << endl;
134  float samsum = 0.0;
135  for ( float sam : sams ) samsum += sam;
136  cout << myname << "Sample mean: " << samsum/nsam << endl;
137  cout << myname << " n0: " << n0 << endl;
138  cout << myname << " n1: " << n1 << endl;
139  cout << myname << " # samples: " << nsam << endl;
140  cout << myname << " # DFT: " << ndft << endl;
141 
142  cout << myname << line << endl;
143  cout << myname << "Create the sample counts." << endl;
144  IndexArray nsams;
145  nsams[0] = n0;
146  nsams[1] = n1;
147 
148  cout << myname << line << endl;
149  cout << myname << "Create data." << endl;
150  Data dat(nsams, sams);
151  cout << myname << " Rank: " << dat.rank() << endl;
152  cout << myname << " Size: " << dat.size() << endl;
153  assert( dat.isValid() );
154  printData(dat);
155  assert( dat.size() == nsam );
156 
157  cout << myname << line << endl;
158  cout << myname << "Create an empty DFT." << endl;
159  DftData dft(norm, nsams);
160  assert( dft.dataSize(nsams) == nsam );
161  assert( dft.dftFloatDataSize(nsams) == ndft );
162  printData(dft);
163 
164  cout << myname << line << endl;
165  cout << myname << "Build transform." << endl;
166  Fw2dFFT xf(ndft, 0);
167 
168  cout << myname << line << endl;
169  cout << myname << "Build plans." << endl;
170  assert( ! xf.haveForwardPlan(nsams) );
171  assert( ! xf.haveBackwardPlan(nsams) );
172  xf.forwardPlan(nsams);
173  xf.backwardPlan(nsams);
174  assert( xf.haveForwardPlan(nsams) );
175  assert( xf.haveBackwardPlan(nsams) );
176 
177  cout << myname << line << endl;
178  cout << myname << "Transform forward." << endl;
179  int fstat = xf.fftForward(dat, dft, loglev);
180  assert( fstat == 0 );
181  printData(dft);
182 
183  cout << myname << line << endl;
184  cout << myname << "Transform backward." << endl;
185  Data dat2;
186  int bstat = xf.fftBackward(dft, dat2, loglev);
187  assert( bstat == 0 );
188  assert( printData(dat, dat2) );
189 
190 /*
191  cout << myname << line << endl;
192  cout << myname << "Check power." << endl;
193  float pwr1 = 0.0;
194  for ( float sam : sams ) pwr1 += sam*sam;
195  float pwr2 = dft.power();
196  float pwr3 = 0.0;
197  float pwr4 = 0.0;
198  for ( Index ifrq=0; ifrq<nsam; ++ifrq ) {
199  float amp = dft.amplitude(ifrq);
200  float xre = dft.real(ifrq);
201  float xim = dft.imag(ifrq);
202  if ( !dft.normalization().isPower() || ifrq < dft.nCompact() ) {
203  pwr3 += amp*amp;
204  pwr4 += xre*xre + xim*xim;
205  }
206  }
207  double pfac = 1.0;
208  if ( dft.normalization().isStandard() ) pfac = 1.0/nsam;
209  if ( dft.normalization().isBin() ) pfac = nsam;
210  pwr3 *= pfac;
211  pwr4 *= pfac;
212  cout << myname << "Tick power: " << pwr1 << endl;
213  cout << myname << " DFT power: " << pwr2 << endl;
214  cout << myname << " Amp power: " << pwr3 << endl;
215  cout << myname << " ReI power: " << pwr4 << endl;
216  assert( fabs(pwr2 - pwr1) < 1.e-5*pwr1 );
217 
218  cout << myname << line << endl;
219  cout << myname << "Call inverse." << endl;
220  FloatVector sams2, xres2, xims2;
221  int rstat = xf.fftInverse(dft, sams2, loglev);
222  if ( rstat != 0 ) {
223  cout << myname << "FFT invert returned " << rstat << endl;
224  assert( false );
225  }
226 
227  assert( sams2.size() == nsam );
228  for ( Index isam=0; isam<nsam; ++isam ) {
229  cout << setw(4) << isam << ":" << setw(10) << fixed << sams[isam]
230  << " ?= " << setw(10) << fixed << sams2[isam] << endl;
231  assert( fabs(sams2[isam] - sams[isam]) < 1.e-4 );
232  }
233 
234 */
235  cout << myname << line << endl;
236  cout << myname << "Done." << endl;
237  return 0;
238 }
239 
240 //**********************************************************************
241 
242 int main(int argc, char* argv[]) {
243  Index ignorm = 1;
244  Index itnorm = 1;
245  int loglev = 0;
246  if ( argc > 1 ) {
247  string sarg(argv[1]);
248  if ( sarg == "-h" ) {
249  cout << "Usage: " << argv[0] << " [ignorm [itnorm [loglev]]]" << endl;
250  return 0;
251  }
252  ignorm = std::stoi(sarg);
253  }
254  if ( argc > 2 ) {
255  string sarg(argv[2]);
256  itnorm = std::stoi(sarg);
257  }
258  if ( argc > 3 ) {
259  string sarg(argv[3]);
260  loglev = std::stoi(sarg);
261  }
262  return test_Fw2dFFT(ignorm, itnorm, loglev);
263 }
264 
265 //**********************************************************************
std::vector< DataFloat > DataVector
auto size() const
std::array< Index, 2 > IndexArray
Definition: Real2dDftData.h:27
Real2dData< DataFloat > Data
Definition: Fw2dFFT.h:36
int fftForward(const Data &dat, DFT &dft, Index logLevel=0)
Definition: Fw2dFFT.cxx:93
int main(int argc, char *argv[])
Fw2dFFT::Complex Complex
std::string string
Definition: nybbler.cc:12
void printData(const Data &dat)
Fw2dFFT::DataFloat DataFloat
std::string termName() const
struct vector vector
Plan & backwardPlan(const IndexArray &nsams)
Definition: Fw2dFFT.cxx:77
DftData::IndexArray IndexArray
unsigned int Index
Q_EXPORT QTSManip setprecision(int p)
Definition: qtextstream.h:343
FftwReal2dDftData< DftFloat > DFT
Definition: Fw2dFFT.h:37
int fftBackward(const DFT &dft, Data &dat, Index logLevel=0)
Definition: Fw2dFFT.cxx:123
void printValue(T val)
static Index dataSize(const std::array< Index, N > &nsams)
Definition: Real2dDftData.h:34
Plan & forwardPlan(const IndexArray &nsams)
Definition: Fw2dFFT.cxx:62
auto norm(Vector const &v)
Return norm of the specified vector.
Q_EXPORT QTSManip setw(int w)
Definition: qtextstream.h:331
bool haveForwardPlan(const IndexArray &nsams) const
Definition: Fw2dFFT.cxx:50
static Index dftFloatDataSize(const std::array< Index, N > &nsams)
void line(double t, double *p, double &x, double &y, double &z)
int test_Fw2dFFT(Index ignorm, Index itnorm, int loglev)
float DataFloat
Definition: Fw2dFFT.h:34
bool haveBackwardPlan(const IndexArray &nsams) const
Definition: Fw2dFFT.cxx:56
std::string globalName() const
DFT::Complex Complex
Definition: Fw2dFFT.h:40
QTextStream & endl(QTextStream &s)