c@343
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
c@335
|
2
|
c@335
|
3 #include "dsp/transforms/FFT.h"
|
c@335
|
4
|
c@335
|
5 #define BOOST_TEST_DYN_LINK
|
c@335
|
6 #define BOOST_TEST_MAIN
|
c@335
|
7
|
c@335
|
8 #include <boost/test/unit_test.hpp>
|
c@335
|
9
|
c@355
|
10 #include <stdexcept>
|
c@355
|
11
|
c@335
|
12 BOOST_AUTO_TEST_SUITE(TestFFT)
|
c@335
|
13
|
c@335
|
14 #define COMPARE_CONST(a, n) \
|
c@335
|
15 for (int cmp_i = 0; cmp_i < (int)(sizeof(a)/sizeof(a[0])); ++cmp_i) { \
|
c@335
|
16 BOOST_CHECK_SMALL(a[cmp_i] - n, 1e-14); \
|
c@335
|
17 }
|
c@335
|
18
|
c@335
|
19 #define COMPARE_ARRAY(a, b) \
|
c@335
|
20 for (int cmp_i = 0; cmp_i < (int)(sizeof(a)/sizeof(a[0])); ++cmp_i) { \
|
c@335
|
21 BOOST_CHECK_SMALL(a[cmp_i] - b[cmp_i], 1e-14); \
|
c@335
|
22 }
|
c@335
|
23
|
c@339
|
24 //!!! need at least one test with complex time-domain signal
|
c@335
|
25
|
c@335
|
26 BOOST_AUTO_TEST_CASE(forwardArrayBounds)
|
c@335
|
27 {
|
c@395
|
28 // initialise bins to something recognisable, so we can tell if
|
c@395
|
29 // they haven't been written; and allocate the inputs on the heap
|
c@395
|
30 // so that, if running under valgrind, we get warnings about
|
c@395
|
31 // overruns
|
c@395
|
32 double *in = new double[4];
|
c@395
|
33 in[0] = 1;
|
c@395
|
34 in[1] = 1;
|
c@395
|
35 in[2] = -1;
|
c@395
|
36 in[3] = -1;
|
c@335
|
37 double re[] = { 999, 999, 999, 999, 999, 999 };
|
c@335
|
38 double im[] = { 999, 999, 999, 999, 999, 999 };
|
c@335
|
39 FFT(4).process(false, in, 0, re+1, im+1);
|
c@335
|
40 // And check we haven't overrun the arrays
|
c@335
|
41 BOOST_CHECK_EQUAL(re[0], 999.0);
|
c@335
|
42 BOOST_CHECK_EQUAL(im[0], 999.0);
|
c@335
|
43 BOOST_CHECK_EQUAL(re[5], 999.0);
|
c@335
|
44 BOOST_CHECK_EQUAL(im[5], 999.0);
|
c@395
|
45 delete[] in;
|
c@335
|
46 }
|
c@335
|
47
|
c@339
|
48 BOOST_AUTO_TEST_CASE(r_forwardArrayBounds)
|
c@339
|
49 {
|
c@395
|
50 // initialise bins to something recognisable, so we can tell if
|
c@395
|
51 // they haven't been written; and allocate the inputs on the heap
|
c@395
|
52 // so that, if running under valgrind, we get warnings about
|
c@395
|
53 // overruns
|
c@395
|
54 double *in = new double[4];
|
c@395
|
55 in[0] = 1;
|
c@395
|
56 in[1] = 1;
|
c@395
|
57 in[2] = -1;
|
c@395
|
58 in[3] = -1;
|
c@339
|
59 double re[] = { 999, 999, 999, 999, 999, 999 };
|
c@339
|
60 double im[] = { 999, 999, 999, 999, 999, 999 };
|
c@339
|
61 FFTReal(4).forward(in, re+1, im+1);
|
c@339
|
62 // And check we haven't overrun the arrays
|
c@339
|
63 BOOST_CHECK_EQUAL(re[0], 999.0);
|
c@339
|
64 BOOST_CHECK_EQUAL(im[0], 999.0);
|
c@339
|
65 BOOST_CHECK_EQUAL(re[5], 999.0);
|
c@339
|
66 BOOST_CHECK_EQUAL(im[5], 999.0);
|
c@395
|
67 delete[] in;
|
c@339
|
68 }
|
c@339
|
69
|
c@335
|
70 BOOST_AUTO_TEST_CASE(inverseArrayBounds)
|
c@335
|
71 {
|
c@395
|
72 // initialise bins to something recognisable, so we can tell if
|
c@395
|
73 // they haven't been written; and allocate the inputs on the heap
|
c@395
|
74 // so that, if running under valgrind, we get warnings about
|
c@395
|
75 // overruns
|
c@395
|
76 double *re = new double[4];
|
c@395
|
77 double *im = new double[4];
|
c@395
|
78 re[0] = 0;
|
c@395
|
79 re[1] = 1;
|
c@395
|
80 re[2] = 0;
|
c@395
|
81 re[3] = 1;
|
c@395
|
82 im[0] = 0;
|
c@395
|
83 im[1] = -2;
|
c@395
|
84 im[2] = 0;
|
c@395
|
85 im[3] = 2;
|
c@335
|
86 double outre[] = { 999, 999, 999, 999, 999, 999 };
|
c@335
|
87 double outim[] = { 999, 999, 999, 999, 999, 999 };
|
c@339
|
88 FFT(4).process(true, re, im, outre+1, outim+1);
|
c@335
|
89 // And check we haven't overrun the arrays
|
c@335
|
90 BOOST_CHECK_EQUAL(outre[0], 999.0);
|
c@335
|
91 BOOST_CHECK_EQUAL(outim[0], 999.0);
|
c@335
|
92 BOOST_CHECK_EQUAL(outre[5], 999.0);
|
c@335
|
93 BOOST_CHECK_EQUAL(outim[5], 999.0);
|
c@395
|
94 delete[] re;
|
c@395
|
95 delete[] im;
|
c@335
|
96 }
|
c@335
|
97
|
c@339
|
98 BOOST_AUTO_TEST_CASE(r_inverseArrayBounds)
|
c@339
|
99 {
|
c@395
|
100 // initialise bins to something recognisable, so we can tell if
|
c@395
|
101 // they haven't been written; and allocate the inputs on the heap
|
c@395
|
102 // so that, if running under valgrind, we get warnings about
|
c@395
|
103 // overruns
|
c@395
|
104 double *re = new double[3];
|
c@395
|
105 double *im = new double[3];
|
c@395
|
106 re[0] = 0;
|
c@395
|
107 re[1] = 1;
|
c@395
|
108 re[2] = 0;
|
c@395
|
109 im[0] = 0;
|
c@395
|
110 im[1] = -2;
|
c@395
|
111 im[2] = 0;
|
c@339
|
112 double outre[] = { 999, 999, 999, 999, 999, 999 };
|
c@339
|
113 FFTReal(4).inverse(re, im, outre+1);
|
c@339
|
114 // And check we haven't overrun the arrays
|
c@339
|
115 BOOST_CHECK_EQUAL(outre[0], 999.0);
|
c@339
|
116 BOOST_CHECK_EQUAL(outre[5], 999.0);
|
c@395
|
117 delete[] re;
|
c@395
|
118 delete[] im;
|
c@339
|
119 }
|
c@339
|
120
|
c@339
|
121 BOOST_AUTO_TEST_CASE(dc)
|
c@339
|
122 {
|
c@339
|
123 // DC-only signal. The DC bin is purely real
|
c@339
|
124 double in[] = { 1, 1, 1, 1 };
|
c@339
|
125 double re[] = { 999, 999, 999, 999 };
|
c@339
|
126 double im[] = { 999, 999, 999, 999 };
|
c@339
|
127 FFT(4).process(false, in, 0, re, im);
|
c@339
|
128 BOOST_CHECK_EQUAL(re[0], 4.0);
|
c@339
|
129 BOOST_CHECK_EQUAL(re[1], 0.0);
|
c@339
|
130 BOOST_CHECK_EQUAL(re[2], 0.0);
|
c@339
|
131 BOOST_CHECK_EQUAL(re[3], 0.0);
|
c@339
|
132 COMPARE_CONST(im, 0.0);
|
c@339
|
133 double back[4];
|
c@339
|
134 double backim[4];
|
c@339
|
135 FFT(4).process(true, re, im, back, backim);
|
c@339
|
136 COMPARE_ARRAY(back, in);
|
c@339
|
137 COMPARE_CONST(backim, 0.0);
|
c@339
|
138 }
|
c@339
|
139
|
c@339
|
140 BOOST_AUTO_TEST_CASE(r_dc)
|
c@339
|
141 {
|
c@339
|
142 // DC-only signal. The DC bin is purely real
|
c@339
|
143 double in[] = { 1, 1, 1, 1 };
|
c@339
|
144 double re[] = { 999, 999, 999, 999 };
|
c@339
|
145 double im[] = { 999, 999, 999, 999 };
|
c@339
|
146 FFTReal(4).forward(in, re, im);
|
c@339
|
147 BOOST_CHECK_EQUAL(re[0], 4.0);
|
c@339
|
148 BOOST_CHECK_EQUAL(re[1], 0.0);
|
c@339
|
149 BOOST_CHECK_EQUAL(re[2], 0.0);
|
c@339
|
150 BOOST_CHECK_EQUAL(re[3], 0.0);
|
c@339
|
151 COMPARE_CONST(im, 0.0);
|
c@339
|
152 double back[4];
|
c@339
|
153 // check conjugates are reconstructed
|
c@339
|
154 re[3] = 999;
|
c@339
|
155 im[3] = 999;
|
c@339
|
156 FFTReal(4).inverse(re, im, back);
|
c@339
|
157 COMPARE_ARRAY(back, in);
|
c@339
|
158 }
|
c@339
|
159
|
c@384
|
160 BOOST_AUTO_TEST_CASE(c_dc)
|
c@384
|
161 {
|
c@384
|
162 // DC-only signal. The DC bin is purely real
|
c@384
|
163 double rin[] = { 1, 1, 1, 1 };
|
c@384
|
164 double iin[] = { 1, 1, 1, 1 };
|
c@384
|
165 double re[] = { 999, 999, 999, 999 };
|
c@384
|
166 double im[] = { 999, 999, 999, 999 };
|
c@384
|
167 FFT(4).process(false, rin, iin, re, im);
|
c@384
|
168 BOOST_CHECK_EQUAL(re[0], 4.0);
|
c@384
|
169 BOOST_CHECK_EQUAL(re[1], 0.0);
|
c@384
|
170 BOOST_CHECK_EQUAL(re[2], 0.0);
|
c@384
|
171 BOOST_CHECK_EQUAL(re[3], 0.0);
|
c@384
|
172 BOOST_CHECK_EQUAL(im[0], 4.0);
|
c@384
|
173 BOOST_CHECK_EQUAL(im[1], 0.0);
|
c@384
|
174 BOOST_CHECK_EQUAL(im[2], 0.0);
|
c@384
|
175 BOOST_CHECK_EQUAL(im[3], 0.0);
|
c@384
|
176 double back[4];
|
c@384
|
177 double backim[4];
|
c@384
|
178 FFT(4).process(true, re, im, back, backim);
|
c@384
|
179 COMPARE_ARRAY(back, rin);
|
c@384
|
180 COMPARE_ARRAY(backim, iin);
|
c@384
|
181 }
|
c@384
|
182
|
c@339
|
183 BOOST_AUTO_TEST_CASE(sine)
|
c@339
|
184 {
|
c@339
|
185 // Sine. Output is purely imaginary
|
c@339
|
186 double in[] = { 0, 1, 0, -1 };
|
c@339
|
187 double re[] = { 999, 999, 999, 999 };
|
c@339
|
188 double im[] = { 999, 999, 999, 999 };
|
c@339
|
189 FFT(4).process(false, in, 0, re, im);
|
c@339
|
190 COMPARE_CONST(re, 0.0);
|
c@339
|
191 BOOST_CHECK_EQUAL(im[0], 0.0);
|
c@339
|
192 BOOST_CHECK_EQUAL(im[1], -2.0);
|
c@339
|
193 BOOST_CHECK_EQUAL(im[2], 0.0);
|
c@339
|
194 BOOST_CHECK_EQUAL(im[3], 2.0);
|
c@339
|
195 double back[4];
|
c@339
|
196 double backim[4];
|
c@339
|
197 FFT(4).process(true, re, im, back, backim);
|
c@339
|
198 COMPARE_ARRAY(back, in);
|
c@339
|
199 COMPARE_CONST(backim, 0.0);
|
c@339
|
200 }
|
c@339
|
201
|
c@339
|
202 BOOST_AUTO_TEST_CASE(r_sine)
|
c@339
|
203 {
|
c@339
|
204 // Sine. Output is purely imaginary
|
c@339
|
205 double in[] = { 0, 1, 0, -1 };
|
c@339
|
206 double re[] = { 999, 999, 999, 999 };
|
c@339
|
207 double im[] = { 999, 999, 999, 999 };
|
c@339
|
208 FFTReal(4).forward(in, re, im);
|
c@339
|
209 COMPARE_CONST(re, 0.0);
|
c@339
|
210 BOOST_CHECK_EQUAL(im[0], 0.0);
|
c@339
|
211 BOOST_CHECK_EQUAL(im[1], -2.0);
|
c@339
|
212 BOOST_CHECK_EQUAL(im[2], 0.0);
|
c@339
|
213 BOOST_CHECK_EQUAL(im[3], 2.0);
|
c@339
|
214 double back[4];
|
c@339
|
215 // check conjugates are reconstructed
|
c@339
|
216 re[3] = 999;
|
c@339
|
217 im[3] = 999;
|
c@339
|
218 FFTReal(4).inverse(re, im, back);
|
c@339
|
219 COMPARE_ARRAY(back, in);
|
c@339
|
220 }
|
c@339
|
221
|
c@339
|
222 BOOST_AUTO_TEST_CASE(cosine)
|
c@339
|
223 {
|
c@339
|
224 // Cosine. Output is purely real
|
c@339
|
225 double in[] = { 1, 0, -1, 0 };
|
c@339
|
226 double re[] = { 999, 999, 999, 999 };
|
c@339
|
227 double im[] = { 999, 999, 999, 999 };
|
c@339
|
228 FFT(4).process(false, in, 0, re, im);
|
c@339
|
229 BOOST_CHECK_EQUAL(re[0], 0.0);
|
c@339
|
230 BOOST_CHECK_EQUAL(re[1], 2.0);
|
c@339
|
231 BOOST_CHECK_EQUAL(re[2], 0.0);
|
c@339
|
232 BOOST_CHECK_EQUAL(re[3], 2.0);
|
c@339
|
233 COMPARE_CONST(im, 0.0);
|
c@339
|
234 double back[4];
|
c@339
|
235 double backim[4];
|
c@339
|
236 FFT(4).process(true, re, im, back, backim);
|
c@339
|
237 COMPARE_ARRAY(back, in);
|
c@339
|
238 COMPARE_CONST(backim, 0.0);
|
c@339
|
239 }
|
c@339
|
240
|
c@339
|
241 BOOST_AUTO_TEST_CASE(r_cosine)
|
c@339
|
242 {
|
c@339
|
243 // Cosine. Output is purely real
|
c@339
|
244 double in[] = { 1, 0, -1, 0 };
|
c@339
|
245 double re[] = { 999, 999, 999, 999 };
|
c@339
|
246 double im[] = { 999, 999, 999, 999 };
|
c@339
|
247 FFTReal(4).forward(in, re, im);
|
c@339
|
248 BOOST_CHECK_EQUAL(re[0], 0.0);
|
c@339
|
249 BOOST_CHECK_EQUAL(re[1], 2.0);
|
c@339
|
250 BOOST_CHECK_EQUAL(re[2], 0.0);
|
c@339
|
251 BOOST_CHECK_EQUAL(re[3], 2.0);
|
c@339
|
252 COMPARE_CONST(im, 0.0);
|
c@339
|
253 double back[4];
|
c@339
|
254 // check conjugates are reconstructed
|
c@339
|
255 re[3] = 999;
|
c@339
|
256 im[3] = 999;
|
c@339
|
257 FFTReal(4).inverse(re, im, back);
|
c@339
|
258 COMPARE_ARRAY(back, in);
|
c@339
|
259 }
|
c@384
|
260
|
c@384
|
261 BOOST_AUTO_TEST_CASE(c_cosine)
|
c@384
|
262 {
|
c@384
|
263 // Cosine. Output is purely real
|
c@384
|
264 double rin[] = { 1, 0, -1, 0 };
|
c@384
|
265 double iin[] = { 1, 0, -1, 0 };
|
c@384
|
266 double re[] = { 999, 999, 999, 999 };
|
c@384
|
267 double im[] = { 999, 999, 999, 999 };
|
c@384
|
268 FFT(4).process(false, rin, iin, re, im);
|
c@384
|
269 BOOST_CHECK_EQUAL(re[0], 0.0);
|
c@384
|
270 BOOST_CHECK_EQUAL(re[1], 2.0);
|
c@384
|
271 BOOST_CHECK_EQUAL(re[2], 0.0);
|
c@384
|
272 BOOST_CHECK_EQUAL(re[3], 2.0);
|
c@384
|
273 BOOST_CHECK_EQUAL(im[0], 0.0);
|
c@384
|
274 BOOST_CHECK_EQUAL(im[1], 2.0);
|
c@384
|
275 BOOST_CHECK_EQUAL(im[2], 0.0);
|
c@384
|
276 BOOST_CHECK_EQUAL(im[3], 2.0);
|
c@384
|
277 double back[4];
|
c@384
|
278 double backim[4];
|
c@384
|
279 FFT(4).process(true, re, im, back, backim);
|
c@384
|
280 COMPARE_ARRAY(back, rin);
|
c@384
|
281 COMPARE_ARRAY(backim, iin);
|
c@384
|
282 }
|
c@339
|
283
|
c@339
|
284 BOOST_AUTO_TEST_CASE(sineCosine)
|
c@339
|
285 {
|
c@339
|
286 // Sine and cosine mixed
|
c@339
|
287 double in[] = { 0.5, 1, -0.5, -1 };
|
c@339
|
288 double re[] = { 999, 999, 999, 999 };
|
c@339
|
289 double im[] = { 999, 999, 999, 999 };
|
c@339
|
290 FFT(4).process(false, in, 0, re, im);
|
c@339
|
291 BOOST_CHECK_EQUAL(re[0], 0.0);
|
c@339
|
292 BOOST_CHECK_CLOSE(re[1], 1.0, 1e-12);
|
c@339
|
293 BOOST_CHECK_EQUAL(re[2], 0.0);
|
c@339
|
294 BOOST_CHECK_CLOSE(re[3], 1.0, 1e-12);
|
c@339
|
295 BOOST_CHECK_EQUAL(im[0], 0.0);
|
c@339
|
296 BOOST_CHECK_CLOSE(im[1], -2.0, 1e-12);
|
c@339
|
297 BOOST_CHECK_EQUAL(im[2], 0.0);
|
c@339
|
298 BOOST_CHECK_CLOSE(im[3], 2.0, 1e-12);
|
c@339
|
299 double back[4];
|
c@339
|
300 double backim[4];
|
c@339
|
301 FFT(4).process(true, re, im, back, backim);
|
c@339
|
302 COMPARE_ARRAY(back, in);
|
c@339
|
303 COMPARE_CONST(backim, 0.0);
|
c@339
|
304 }
|
c@339
|
305
|
c@339
|
306 BOOST_AUTO_TEST_CASE(r_sineCosine)
|
c@339
|
307 {
|
c@339
|
308 // Sine and cosine mixed
|
c@339
|
309 double in[] = { 0.5, 1, -0.5, -1 };
|
c@339
|
310 double re[] = { 999, 999, 999, 999 };
|
c@339
|
311 double im[] = { 999, 999, 999, 999 };
|
c@339
|
312 FFTReal(4).forward(in, re, im);
|
c@339
|
313 BOOST_CHECK_EQUAL(re[0], 0.0);
|
c@339
|
314 BOOST_CHECK_CLOSE(re[1], 1.0, 1e-12);
|
c@339
|
315 BOOST_CHECK_EQUAL(re[2], 0.0);
|
c@339
|
316 BOOST_CHECK_CLOSE(re[3], 1.0, 1e-12);
|
c@339
|
317 BOOST_CHECK_EQUAL(im[0], 0.0);
|
c@339
|
318 BOOST_CHECK_CLOSE(im[1], -2.0, 1e-12);
|
c@339
|
319 BOOST_CHECK_EQUAL(im[2], 0.0);
|
c@339
|
320 BOOST_CHECK_CLOSE(im[3], 2.0, 1e-12);
|
c@339
|
321 double back[4];
|
c@339
|
322 // check conjugates are reconstructed
|
c@339
|
323 re[3] = 999;
|
c@339
|
324 im[3] = 999;
|
c@339
|
325 FFTReal(4).inverse(re, im, back);
|
c@339
|
326 COMPARE_ARRAY(back, in);
|
c@339
|
327 }
|
c@384
|
328
|
c@384
|
329 BOOST_AUTO_TEST_CASE(c_sineCosine)
|
c@384
|
330 {
|
c@384
|
331 double rin[] = { 1, 0, -1, 0 };
|
c@384
|
332 double iin[] = { 0, 1, 0, -1 };
|
c@384
|
333 double re[] = { 999, 999, 999, 999 };
|
c@384
|
334 double im[] = { 999, 999, 999, 999 };
|
c@384
|
335 FFT(4).process(false, rin, iin, re, im);
|
c@384
|
336 BOOST_CHECK_EQUAL(re[0], 0.0);
|
c@384
|
337 BOOST_CHECK_EQUAL(re[1], 4.0);
|
c@384
|
338 BOOST_CHECK_EQUAL(re[2], 0.0);
|
c@384
|
339 BOOST_CHECK_EQUAL(re[3], 0.0);
|
c@384
|
340 COMPARE_CONST(im, 0.0);
|
c@384
|
341 double back[4];
|
c@384
|
342 double backim[4];
|
c@384
|
343 FFT(4).process(true, re, im, back, backim);
|
c@384
|
344 COMPARE_ARRAY(back, rin);
|
c@384
|
345 COMPARE_ARRAY(backim, iin);
|
c@384
|
346 }
|
c@339
|
347
|
c@339
|
348 BOOST_AUTO_TEST_CASE(nyquist)
|
c@339
|
349 {
|
c@339
|
350 double in[] = { 1, -1, 1, -1 };
|
c@339
|
351 double re[] = { 999, 999, 999, 999 };
|
c@339
|
352 double im[] = { 999, 999, 999, 999 };
|
c@339
|
353 FFT(4).process(false, in, 0, re, im);
|
c@339
|
354 BOOST_CHECK_EQUAL(re[0], 0.0);
|
c@339
|
355 BOOST_CHECK_EQUAL(re[1], 0.0);
|
c@339
|
356 BOOST_CHECK_EQUAL(re[2], 4.0);
|
c@339
|
357 BOOST_CHECK_EQUAL(re[3], 0.0);
|
c@339
|
358 COMPARE_CONST(im, 0.0);
|
c@339
|
359 double back[4];
|
c@339
|
360 double backim[4];
|
c@339
|
361 FFT(4).process(true, re, im, back, backim);
|
c@339
|
362 COMPARE_ARRAY(back, in);
|
c@339
|
363 COMPARE_CONST(backim, 0.0);
|
c@339
|
364 }
|
c@339
|
365
|
c@339
|
366 BOOST_AUTO_TEST_CASE(r_nyquist)
|
c@339
|
367 {
|
c@339
|
368 double in[] = { 1, -1, 1, -1 };
|
c@339
|
369 double re[] = { 999, 999, 999, 999 };
|
c@339
|
370 double im[] = { 999, 999, 999, 999 };
|
c@339
|
371 FFTReal(4).forward(in, re, im);
|
c@339
|
372 BOOST_CHECK_EQUAL(re[0], 0.0);
|
c@339
|
373 BOOST_CHECK_EQUAL(re[1], 0.0);
|
c@339
|
374 BOOST_CHECK_EQUAL(re[2], 4.0);
|
c@339
|
375 BOOST_CHECK_EQUAL(re[3], 0.0);
|
c@339
|
376 COMPARE_CONST(im, 0.0);
|
c@339
|
377 double back[4];
|
c@339
|
378 // check conjugates are reconstructed
|
c@339
|
379 re[3] = 999;
|
c@339
|
380 im[3] = 999;
|
c@339
|
381 FFTReal(4).inverse(re, im, back);
|
c@339
|
382 COMPARE_ARRAY(back, in);
|
c@339
|
383 }
|
c@339
|
384
|
c@339
|
385 BOOST_AUTO_TEST_CASE(dirac)
|
c@339
|
386 {
|
c@339
|
387 double in[] = { 1, 0, 0, 0 };
|
c@339
|
388 double re[] = { 999, 999, 999, 999 };
|
c@339
|
389 double im[] = { 999, 999, 999, 999 };
|
c@339
|
390 FFT(4).process(false, in, 0, re, im);
|
c@339
|
391 BOOST_CHECK_EQUAL(re[0], 1.0);
|
c@339
|
392 BOOST_CHECK_EQUAL(re[1], 1.0);
|
c@339
|
393 BOOST_CHECK_EQUAL(re[2], 1.0);
|
c@339
|
394 BOOST_CHECK_EQUAL(re[3], 1.0);
|
c@339
|
395 COMPARE_CONST(im, 0.0);
|
c@339
|
396 double back[4];
|
c@339
|
397 double backim[4];
|
c@339
|
398 FFT(4).process(true, re, im, back, backim);
|
c@339
|
399 COMPARE_ARRAY(back, in);
|
c@339
|
400 COMPARE_CONST(backim, 0.0);
|
c@339
|
401 }
|
c@339
|
402
|
c@339
|
403 BOOST_AUTO_TEST_CASE(r_dirac)
|
c@339
|
404 {
|
c@339
|
405 double in[] = { 1, 0, 0, 0 };
|
c@339
|
406 double re[] = { 999, 999, 999, 999 };
|
c@339
|
407 double im[] = { 999, 999, 999, 999 };
|
c@339
|
408 FFTReal(4).forward(in, re, im);
|
c@339
|
409 BOOST_CHECK_EQUAL(re[0], 1.0);
|
c@339
|
410 BOOST_CHECK_EQUAL(re[1], 1.0);
|
c@339
|
411 BOOST_CHECK_EQUAL(re[2], 1.0);
|
c@339
|
412 BOOST_CHECK_EQUAL(re[3], 1.0);
|
c@339
|
413 COMPARE_CONST(im, 0.0);
|
c@339
|
414 double back[4];
|
c@339
|
415 // check conjugates are reconstructed
|
c@339
|
416 re[3] = 999;
|
c@339
|
417 im[3] = 999;
|
c@339
|
418 FFTReal(4).inverse(re, im, back);
|
c@339
|
419 COMPARE_ARRAY(back, in);
|
c@339
|
420 }
|
c@339
|
421
|
c@355
|
422 BOOST_AUTO_TEST_CASE(sizes)
|
c@355
|
423 {
|
c@355
|
424 // Complex supports any size. A single test with an odd size
|
c@355
|
425 // will do here, without getting too much into our expectations
|
c@355
|
426 // about supported butterflies etc
|
c@355
|
427
|
c@355
|
428 double in[] = { 1, 1, 1 };
|
c@355
|
429 double re[] = { 999, 999, 999 };
|
c@355
|
430 double im[] = { 999, 999, 999 };
|
c@355
|
431 FFT(3).process(false, in, 0, re, im);
|
c@355
|
432 BOOST_CHECK_EQUAL(re[0], 3.0);
|
c@355
|
433 BOOST_CHECK_EQUAL(re[1], 0.0);
|
c@355
|
434 BOOST_CHECK_EQUAL(re[2], 0.0);
|
c@355
|
435 COMPARE_CONST(im, 0.0);
|
c@355
|
436 double back[3];
|
c@355
|
437 double backim[3];
|
c@355
|
438 FFT(3).process(true, re, im, back, backim);
|
c@355
|
439 COMPARE_ARRAY(back, in);
|
c@355
|
440 COMPARE_CONST(backim, 0.0);
|
c@355
|
441 }
|
c@355
|
442
|
c@355
|
443 BOOST_AUTO_TEST_CASE(r_sizes)
|
c@355
|
444 {
|
c@355
|
445 // Real supports any even size, but not odd ones
|
c@355
|
446
|
c@355
|
447 BOOST_CHECK_THROW(FFTReal r(3), std::invalid_argument);
|
c@355
|
448
|
c@355
|
449 double in[] = { 1, 1, 1, 1, 1, 1 };
|
c@355
|
450 double re[] = { 999, 999, 999, 999, 999, 999 };
|
c@355
|
451 double im[] = { 999, 999, 999, 999, 999, 999 };
|
c@355
|
452 FFTReal(6).forward(in, re, im);
|
c@355
|
453 BOOST_CHECK_EQUAL(re[0], 6.0);
|
c@355
|
454 BOOST_CHECK_EQUAL(re[1], 0.0);
|
c@355
|
455 BOOST_CHECK_EQUAL(re[2], 0.0);
|
c@355
|
456 BOOST_CHECK_EQUAL(re[3], 0.0);
|
c@355
|
457 BOOST_CHECK_EQUAL(re[4], 0.0);
|
c@355
|
458 BOOST_CHECK_EQUAL(re[5], 0.0);
|
c@355
|
459 COMPARE_CONST(im, 0.0);
|
c@355
|
460 double back[6];
|
c@355
|
461 FFTReal(6).inverse(re, im, back);
|
c@355
|
462 COMPARE_ARRAY(back, in);
|
c@355
|
463 }
|
c@355
|
464
|
c@335
|
465 BOOST_AUTO_TEST_SUITE_END()
|
c@335
|
466
|