MRPT  1.9.9
fourier.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "math-precomp.h" // Precompiled headers
11 
12 #include <mrpt/math/fourier.h>
13 #include <algorithm>
14 #include <mrpt/core/bits_math.h>
15 #include <cmath>
16 
17 using namespace mrpt;
18 using namespace std;
19 using namespace mrpt::math;
20 
21 // Next we declare some auxiliary functions:
22 namespace mrpt::math
23 {
24 // Replaces data[1..2*nn] by its discrete Fourier transform, if isign is input
25 // as 1; or replaces
26 // data[1..2*nn] by nn times its inverse discrete Fourier transform, if isign is
27 // input as -1.
28 // data is a complex array of length nn or, equivalently, a real array of length
29 // 2*nn. nn MUST
30 // be an integer power of 2 (this is not checked for!).
31 static void four1(float data[], unsigned long nn, int isign)
32 {
33  unsigned long n, mmax, m, j, i;
34  double wtemp, wr, wpr, wpi, wi,
35  theta; // Double precision for the trigonometric recurrences.
36  float tempr, tempi;
37 
38  n = nn << 1;
39  j = 1;
40 
41  for (i = 1; i < n;
42  i += 2) // This is the bit-reversal section of the routine.
43  {
44  if (j > i)
45  {
46  std::swap(data[j], data[i]); // Exchange the two complex numbers.
47  std::swap(data[j + 1], data[i + 1]);
48  }
49  m = nn;
50  while (m >= 2 && j > m)
51  {
52  j -= m;
53  m >>= 1;
54  }
55  j += m;
56  }
57  // Here begins the Danielson-Lanczos section of the routine.
58  mmax = 2;
59  while (n > mmax) // Outer loop executed log2 nn times.
60  {
61  unsigned long istep = mmax << 1;
62  theta = isign * (6.28318530717959 /
63  mmax); // Initialize the trigonometric recurrence.
64  wtemp = sin(0.5 * theta);
65  wpr = -2.0 * wtemp * wtemp;
66  wpi = sin(theta);
67  wr = 1.0;
68  wi = 0.0;
69  for (m = 1; m < mmax; m += 2) // Here are the two nested inner loops.
70  {
71  for (i = m; i <= n; i += istep)
72  {
73  j = i + mmax; // This is the Danielson-Lanczos formula:
74  tempr = (float)(wr * data[j] - wi * data[j + 1]);
75  tempi = (float)(wr * data[j + 1] + wi * data[j]);
76  data[j] = data[i] - tempr;
77  data[j + 1] = data[i + 1] - tempi;
78  data[i] += tempr;
79  data[i + 1] += tempi;
80  }
81  wr = (wtemp = wr) * wpr - wi * wpi +
82  wr; // Trigonometric recurrence.
83  wi = wi * wpr + wtemp * wpi + wi;
84  }
85  mmax = istep;
86  }
87 }
88 
89 // Calculates the Fourier transform of a set of n real-valued data points.
90 // Replaces this data (which
91 // is stored in array data[1..n]) by the positive frequency half of its complex
92 // Fourier transform.
93 // The real-valued first and last components of the complex transform are
94 // returned as elements
95 // data[1] and data[2], respectively. n must be a power of 2. This routine also
96 // calculates the
97 // inverse transform of a complex data array if it is the transform of real
98 // data. (Result in this case
99 // must be multiplied by 2/n.)
100 static void realft(float data[], unsigned long n)
101 {
102  unsigned long i, i1, i2, i3, i4, np3;
103  float c1 = 0.5, c2, h1r, h1i, h2r, h2i;
104  double wr, wi, wpr, wpi, wtemp,
105  theta; // Double precision for the trigonometric recurrences.
106  theta = 3.141592653589793 / (double)(n >> 1); // Initialize the recurrence.
107 
108  c2 = -0.5;
109  four1(data, n >> 1, 1); // The forward transform is here.
110 
111  wtemp = sin(0.5 * theta);
112  wpr = -2.0 * wtemp * wtemp;
113  wpi = sin(theta);
114  wr = 1.0 + wpr;
115  wi = wpi;
116  np3 = n + 3;
117  for (i = 2; i <= (n >> 2); i++) // Case i=1 done separately below.
118  {
119  i4 = 1 + (i3 = np3 - (i2 = 1 + (i1 = i + i - 1)));
120  h1r = c1 * (data[i1] + data[i3]); // The two separate transforms are
121  // separated out of data.
122  h1i = c1 * (data[i2] - data[i4]);
123  h2r = -c2 * (data[i2] + data[i4]);
124  h2i = c2 * (data[i1] - data[i3]);
125  data[i1] =
126  (float)(h1r + wr * h2r - wi * h2i); // Here they are recombined to
127  // form the true transform of
128  // the original real data.
129  data[i2] = (float)(h1i + wr * h2i + wi * h2r);
130  data[i3] = (float)(h1r - wr * h2r + wi * h2i);
131  data[i4] = (float)(-h1i + wr * h2i + wi * h2r);
132  wr = (wtemp = wr) * wpr - wi * wpi + wr; // The recurrence.
133  wi = wi * wpr + wtemp * wpi + wi;
134  }
135 
136  data[1] = (h1r = data[1]) + data[2];
137  // Squeeze the first and last data together to get them all within the
138  // original array.
139  data[2] = h1r - data[2];
140 }
141 
142 /**
143  Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
144  You may use, copy, modify this code for any purpose and
145  without fee. You may distribute this ORIGINAL package.
146  */
147 using FFT_TYPE = float;
148 
149 static void makewt(int nw, int* ip, FFT_TYPE* w);
150 static void bitrv2(int n, int* ip, FFT_TYPE* a);
151 static void cftbsub(int n, FFT_TYPE* a, FFT_TYPE* w);
152 static void cftfsub(int n, FFT_TYPE* a, FFT_TYPE* w);
153 static void rftfsub(int n, FFT_TYPE* a, int nc, FFT_TYPE* c);
154 static void rftbsub(int n, FFT_TYPE* a, int nc, FFT_TYPE* c);
155 
156 static void cftbsub(int n, FFT_TYPE* a, FFT_TYPE* w)
157 {
158  int j, j1, j2, j3, k, k1, ks, l, m;
159  FFT_TYPE wk1r, wk1i, wk2r, wk2i, wk3r, wk3i;
160  FFT_TYPE x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
161 
162  l = 2;
163  while ((l << 1) < n)
164  {
165  m = l << 2;
166  for (j = 0; j <= l - 2; j += 2)
167  {
168  j1 = j + l;
169  j2 = j1 + l;
170  j3 = j2 + l;
171  x0r = a[j] + a[j1];
172  x0i = a[j + 1] + a[j1 + 1];
173  x1r = a[j] - a[j1];
174  x1i = a[j + 1] - a[j1 + 1];
175  x2r = a[j2] + a[j3];
176  x2i = a[j2 + 1] + a[j3 + 1];
177  x3r = a[j2] - a[j3];
178  x3i = a[j2 + 1] - a[j3 + 1];
179  a[j] = x0r + x2r;
180  a[j + 1] = x0i + x2i;
181  a[j2] = x0r - x2r;
182  a[j2 + 1] = x0i - x2i;
183  a[j1] = x1r - x3i;
184  a[j1 + 1] = x1i + x3r;
185  a[j3] = x1r + x3i;
186  a[j3 + 1] = x1i - x3r;
187  }
188  if (m < n)
189  {
190  wk1r = w[2];
191  for (j = m; j <= l + m - 2; j += 2)
192  {
193  j1 = j + l;
194  j2 = j1 + l;
195  j3 = j2 + l;
196  x0r = a[j] + a[j1];
197  x0i = a[j + 1] + a[j1 + 1];
198  x1r = a[j] - a[j1];
199  x1i = a[j + 1] - a[j1 + 1];
200  x2r = a[j2] + a[j3];
201  x2i = a[j2 + 1] + a[j3 + 1];
202  x3r = a[j2] - a[j3];
203  x3i = a[j2 + 1] - a[j3 + 1];
204  a[j] = x0r + x2r;
205  a[j + 1] = x0i + x2i;
206  a[j2] = x2i - x0i;
207  a[j2 + 1] = x0r - x2r;
208  x0r = x1r - x3i;
209  x0i = x1i + x3r;
210  a[j1] = wk1r * (x0r - x0i);
211  a[j1 + 1] = wk1r * (x0r + x0i);
212  x0r = x3i + x1r;
213  x0i = x3r - x1i;
214  a[j3] = wk1r * (x0i - x0r);
215  a[j3 + 1] = wk1r * (x0i + x0r);
216  }
217  k1 = 1;
218  ks = -1;
219  for (k = (m << 1); k <= n - m; k += m)
220  {
221  k1++;
222  ks = -ks;
223  wk1r = w[k1 << 1];
224  wk1i = w[(k1 << 1) + 1];
225  wk2r = ks * w[k1];
226  wk2i = w[k1 + ks];
227  wk3r = wk1r - 2 * wk2i * wk1i;
228  wk3i = 2 * wk2i * wk1r - wk1i;
229  for (j = k; j <= l + k - 2; j += 2)
230  {
231  j1 = j + l;
232  j2 = j1 + l;
233  j3 = j2 + l;
234  x0r = a[j] + a[j1];
235  x0i = a[j + 1] + a[j1 + 1];
236  x1r = a[j] - a[j1];
237  x1i = a[j + 1] - a[j1 + 1];
238  x2r = a[j2] + a[j3];
239  x2i = a[j2 + 1] + a[j3 + 1];
240  x3r = a[j2] - a[j3];
241  x3i = a[j2 + 1] - a[j3 + 1];
242  a[j] = x0r + x2r;
243  a[j + 1] = x0i + x2i;
244  x0r -= x2r;
245  x0i -= x2i;
246  a[j2] = wk2r * x0r - wk2i * x0i;
247  a[j2 + 1] = wk2r * x0i + wk2i * x0r;
248  x0r = x1r - x3i;
249  x0i = x1i + x3r;
250  a[j1] = wk1r * x0r - wk1i * x0i;
251  a[j1 + 1] = wk1r * x0i + wk1i * x0r;
252  x0r = x1r + x3i;
253  x0i = x1i - x3r;
254  a[j3] = wk3r * x0r - wk3i * x0i;
255  a[j3 + 1] = wk3r * x0i + wk3i * x0r;
256  }
257  }
258  }
259  l = m;
260  }
261  if (l < n)
262  {
263  for (j = 0; j <= l - 2; j += 2)
264  {
265  j1 = j + l;
266  x0r = a[j] - a[j1];
267  x0i = a[j + 1] - a[j1 + 1];
268  a[j] += a[j1];
269  a[j + 1] += a[j1 + 1];
270  a[j1] = x0r;
271  a[j1 + 1] = x0i;
272  }
273  }
274 }
275 
276 static void cftfsub(int n, FFT_TYPE* a, FFT_TYPE* w)
277 {
278  int j, j1, j2, j3, k, k1, ks, l, m;
279  FFT_TYPE wk1r, wk1i, wk2r, wk2i, wk3r, wk3i;
280  FFT_TYPE x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
281 
282  l = 2;
283  while ((l << 1) < n)
284  {
285  m = l << 2;
286  for (j = 0; j <= l - 2; j += 2)
287  {
288  j1 = j + l;
289  j2 = j1 + l;
290  j3 = j2 + l;
291  x0r = a[j] + a[j1];
292  x0i = a[j + 1] + a[j1 + 1];
293  x1r = a[j] - a[j1];
294  x1i = a[j + 1] - a[j1 + 1];
295  x2r = a[j2] + a[j3];
296  x2i = a[j2 + 1] + a[j3 + 1];
297  x3r = a[j2] - a[j3];
298  x3i = a[j2 + 1] - a[j3 + 1];
299  a[j] = x0r + x2r;
300  a[j + 1] = x0i + x2i;
301  a[j2] = x0r - x2r;
302  a[j2 + 1] = x0i - x2i;
303  a[j1] = x1r + x3i;
304  a[j1 + 1] = x1i - x3r;
305  a[j3] = x1r - x3i;
306  a[j3 + 1] = x1i + x3r;
307  }
308  if (m < n)
309  {
310  wk1r = w[2];
311  for (j = m; j <= l + m - 2; j += 2)
312  {
313  j1 = j + l;
314  j2 = j1 + l;
315  j3 = j2 + l;
316  x0r = a[j] + a[j1];
317  x0i = a[j + 1] + a[j1 + 1];
318  x1r = a[j] - a[j1];
319  x1i = a[j + 1] - a[j1 + 1];
320  x2r = a[j2] + a[j3];
321  x2i = a[j2 + 1] + a[j3 + 1];
322  x3r = a[j2] - a[j3];
323  x3i = a[j2 + 1] - a[j3 + 1];
324  a[j] = x0r + x2r;
325  a[j + 1] = x0i + x2i;
326  a[j2] = x0i - x2i;
327  a[j2 + 1] = x2r - x0r;
328  x0r = x1r + x3i;
329  x0i = x1i - x3r;
330  a[j1] = wk1r * (x0i + x0r);
331  a[j1 + 1] = wk1r * (x0i - x0r);
332  x0r = x3i - x1r;
333  x0i = x3r + x1i;
334  a[j3] = wk1r * (x0r + x0i);
335  a[j3 + 1] = wk1r * (x0r - x0i);
336  }
337  k1 = 1;
338  ks = -1;
339  for (k = (m << 1); k <= n - m; k += m)
340  {
341  k1++;
342  ks = -ks;
343  wk1r = w[k1 << 1];
344  wk1i = w[(k1 << 1) + 1];
345  wk2r = ks * w[k1];
346  wk2i = w[k1 + ks];
347  wk3r = wk1r - 2 * wk2i * wk1i;
348  wk3i = 2 * wk2i * wk1r - wk1i;
349  for (j = k; j <= l + k - 2; j += 2)
350  {
351  j1 = j + l;
352  j2 = j1 + l;
353  j3 = j2 + l;
354  x0r = a[j] + a[j1];
355  x0i = a[j + 1] + a[j1 + 1];
356  x1r = a[j] - a[j1];
357  x1i = a[j + 1] - a[j1 + 1];
358  x2r = a[j2] + a[j3];
359  x2i = a[j2 + 1] + a[j3 + 1];
360  x3r = a[j2] - a[j3];
361  x3i = a[j2 + 1] - a[j3 + 1];
362  a[j] = x0r + x2r;
363  a[j + 1] = x0i + x2i;
364  x0r -= x2r;
365  x0i -= x2i;
366  a[j2] = wk2r * x0r + wk2i * x0i;
367  a[j2 + 1] = wk2r * x0i - wk2i * x0r;
368  x0r = x1r + x3i;
369  x0i = x1i - x3r;
370  a[j1] = wk1r * x0r + wk1i * x0i;
371  a[j1 + 1] = wk1r * x0i - wk1i * x0r;
372  x0r = x1r - x3i;
373  x0i = x1i + x3r;
374  a[j3] = wk3r * x0r + wk3i * x0i;
375  a[j3 + 1] = wk3r * x0i - wk3i * x0r;
376  }
377  }
378  }
379  l = m;
380  }
381  if (l < n)
382  {
383  for (j = 0; j <= l - 2; j += 2)
384  {
385  j1 = j + l;
386  x0r = a[j] - a[j1];
387  x0i = a[j + 1] - a[j1 + 1];
388  a[j] += a[j1];
389  a[j + 1] += a[j1 + 1];
390  a[j1] = x0r;
391  a[j1 + 1] = x0i;
392  }
393  }
394 }
395 
396 static void makewt(int nw, int* ip, FFT_TYPE* w)
397 {
398  void bitrv2(int n, int* ip, FFT_TYPE* a);
399  int nwh, j;
400  FFT_TYPE delta, x, y;
401 
402  ip[0] = nw;
403  ip[1] = 1;
404  if (nw > 2)
405  {
406  nwh = nw >> 1;
407  delta = atan(1.0f) / nwh;
408  w[0] = 1;
409  w[1] = 0;
410  w[nwh] = cos(delta * nwh);
411  w[nwh + 1] = w[nwh];
412  for (j = 2; j <= nwh - 2; j += 2)
413  {
414  x = cos(delta * j);
415  y = sin(delta * j);
416  w[j] = x;
417  w[j + 1] = y;
418  w[nw - j] = y;
419  w[nw - j + 1] = x;
420  }
421  bitrv2(nw, ip + 2, w);
422  }
423 }
424 
425 /**
426  Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
427  You may use, copy, modify this code for any purpose and
428  without fee. You may distribute this ORIGINAL package.
429  */
430 static void makect(int nc, int* ip, FFT_TYPE* c)
431 {
432  int nch, j;
433  FFT_TYPE delta;
434 
435  ip[1] = nc;
436  if (nc > 1)
437  {
438  nch = nc >> 1;
439  delta = atan(1.0f) / nch;
440  c[0] = 0.5f;
441  c[nch] = 0.5f * cos(delta * nch);
442  for (j = 1; j <= nch - 1; j++)
443  {
444  c[j] = 0.5f * cos(delta * j);
445  c[nc - j] = 0.5f * sin(delta * j);
446  }
447  }
448 }
449 
450 /**
451  Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
452  You may use, copy, modify this code for any purpose and
453  without fee. You may distribute this ORIGINAL package.
454  */
455 static void bitrv2(int n, int* ip, FFT_TYPE* a)
456 {
457  int j, j1, k, k1, l, m, m2;
458  FFT_TYPE xr, xi;
459 
460  ip[0] = 0;
461  l = n;
462  m = 1;
463  while ((m << 2) < l)
464  {
465  l >>= 1;
466  for (j = 0; j <= m - 1; j++)
467  {
468  ip[m + j] = ip[j] + l;
469  }
470  m <<= 1;
471  }
472  if ((m << 2) > l)
473  {
474  for (k = 1; k <= m - 1; k++)
475  {
476  for (j = 0; j <= k - 1; j++)
477  {
478  j1 = (j << 1) + ip[k];
479  k1 = (k << 1) + ip[j];
480  xr = a[j1];
481  xi = a[j1 + 1];
482  a[j1] = a[k1];
483  a[j1 + 1] = a[k1 + 1];
484  a[k1] = xr;
485  a[k1 + 1] = xi;
486  }
487  }
488  }
489  else
490  {
491  m2 = m << 1;
492  for (k = 1; k <= m - 1; k++)
493  {
494  for (j = 0; j <= k - 1; j++)
495  {
496  j1 = (j << 1) + ip[k];
497  k1 = (k << 1) + ip[j];
498  xr = a[j1];
499  xi = a[j1 + 1];
500  a[j1] = a[k1];
501  a[j1 + 1] = a[k1 + 1];
502  a[k1] = xr;
503  a[k1 + 1] = xi;
504  j1 += m2;
505  k1 += m2;
506  xr = a[j1];
507  xi = a[j1 + 1];
508  a[j1] = a[k1];
509  a[j1 + 1] = a[k1 + 1];
510  a[k1] = xr;
511  a[k1 + 1] = xi;
512  }
513  }
514  }
515 }
516 
517 /**
518  Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
519  You may use, copy, modify this code for any purpose and
520  without fee. You may distribute this ORIGINAL package.
521  */
522 static void cdft(int n, int isgn, FFT_TYPE* a, int* ip, FFT_TYPE* w)
523 {
524  if (n > (ip[0] << 2))
525  {
526  makewt(n >> 2, ip, w);
527  }
528  if (n > 4)
529  {
530  bitrv2(n, ip + 2, a);
531  }
532  if (isgn < 0)
533  {
534  cftfsub(n, a, w);
535  }
536  else
537  {
538  cftbsub(n, a, w);
539  }
540 }
541 
542 static void rftfsub(int n, FFT_TYPE* a, int nc, FFT_TYPE* c)
543 {
544  int j, k, kk, ks;
545  FFT_TYPE wkr, wki, xr, xi, yr, yi;
546 
547  ks = (nc << 2) / n;
548  kk = 0;
549  for (k = (n >> 1) - 2; k >= 2; k -= 2)
550  {
551  j = n - k;
552  kk += ks;
553  wkr = 0.5f - c[kk];
554  wki = c[nc - kk];
555  xr = a[k] - a[j];
556  xi = a[k + 1] + a[j + 1];
557  yr = wkr * xr + wki * xi;
558  yi = wkr * xi - wki * xr;
559  a[k] -= yr;
560  a[k + 1] -= yi;
561  a[j] += yr;
562  a[j + 1] -= yi;
563  }
564 }
565 
566 static void rdft(int n, int isgn, FFT_TYPE* a, int* ip, FFT_TYPE* w)
567 {
568  int nw, nc;
569  FFT_TYPE xi;
570 
571  nw = ip[0];
572  if (n > (nw << 2))
573  {
574  nw = n >> 2;
575  makewt(nw, ip, w);
576  }
577  nc = ip[1];
578  if (n > (nc << 2))
579  {
580  nc = n >> 2;
581  makect(nc, ip, w + nw);
582  }
583  if (isgn < 0)
584  {
585  a[1] = 0.5f * (a[0] - a[1]);
586  a[0] -= a[1];
587  if (n > 4)
588  {
589  rftfsub(n, a, nc, w + nw);
590  bitrv2(n, ip + 2, a);
591  }
592  cftfsub(n, a, w);
593  }
594  else
595  {
596  if (n > 4)
597  {
598  bitrv2(n, ip + 2, a);
599  }
600  cftbsub(n, a, w);
601  if (n > 4)
602  {
603  rftbsub(n, a, nc, w + nw);
604  }
605  xi = a[0] - a[1];
606  a[0] += a[1];
607  a[1] = xi;
608  }
609 }
610 
611 static void rftbsub(int n, FFT_TYPE* a, int nc, FFT_TYPE* c)
612 {
613  int j, k, kk, ks;
614  FFT_TYPE wkr, wki, xr, xi, yr, yi;
615 
616  ks = (nc << 2) / n;
617  kk = 0;
618  for (k = (n >> 1) - 2; k >= 2; k -= 2)
619  {
620  j = n - k;
621  kk += ks;
622  wkr = 0.5f - c[kk];
623  wki = c[nc - kk];
624  xr = a[k] - a[j];
625  xi = a[k + 1] + a[j + 1];
626  yr = wkr * xr - wki * xi;
627  yi = wkr * xi + wki * xr;
628  a[k] -= yr;
629  a[k + 1] -= yi;
630  a[j] += yr;
631  a[j + 1] -= yi;
632  }
633 }
634 
635 /**
636  Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
637  You may use, copy, modify this code for any purpose and
638  without fee. You may distribute this ORIGINAL package.
639 
640 -------- Real DFT / Inverse of Real DFT --------
641  [definition]
642  <case1> RDFT
643  R[k1][k2] = sum_j1=0^n1-1 sum_j2=0^n2-1 a[j1][j2] *
644  cos(2*pi*j1*k1/n1 + 2*pi*j2*k2/n2),
645  0<=k1<n1, 0<=k2<n2
646  I[k1][k2] = sum_j1=0^n1-1 sum_j2=0^n2-1 a[j1][j2] *
647  sin(2*pi*j1*k1/n1 + 2*pi*j2*k2/n2),
648  0<=k1<n1, 0<=k2<n2
649  <case2> IRDFT (excluding scale)
650  a[k1][k2] = (1/2) * sum_j1=0^n1-1 sum_j2=0^n2-1
651  (R[j1][j2] *
652  cos(2*pi*j1*k1/n1 + 2*pi*j2*k2/n2) +
653  I[j1][j2] *
654  sin(2*pi*j1*k1/n1 + 2*pi*j2*k2/n2)),
655  0<=k1<n1, 0<=k2<n2
656  (notes: R[n1-k1][n2-k2] = R[k1][k2],
657  I[n1-k1][n2-k2] = -I[k1][k2],
658  R[n1-k1][0] = R[k1][0],
659  I[n1-k1][0] = -I[k1][0],
660  R[0][n2-k2] = R[0][k2],
661  I[0][n2-k2] = -I[0][k2],
662  0<k1<n1, 0<k2<n2)
663  [usage]
664  <case1>
665  ip[0] = 0; // first time only
666  rdft2d(n1, n2, 1, a, t, ip, w);
667  <case2>
668  ip[0] = 0; // first time only
669  rdft2d(n1, n2, -1, a, t, ip, w);
670  [parameters]
671  n1 :data length (int)
672  n1 >= 2, n1 = power of 2
673  n2 :data length (int)
674  n2 >= 2, n2 = power of 2
675  a[0...n1-1][0...n2-1]
676  :input/output data (FFT_TYPE **)
677  <case1>
678  output data
679  a[k1][2*k2] = R[k1][k2] = R[n1-k1][n2-k2],
680  a[k1][2*k2+1] = I[k1][k2] = -I[n1-k1][n2-k2],
681  0<k1<n1, 0<k2<n2/2,
682  a[0][2*k2] = R[0][k2] = R[0][n2-k2],
683  a[0][2*k2+1] = I[0][k2] = -I[0][n2-k2],
684  0<k2<n2/2,
685  a[k1][0] = R[k1][0] = R[n1-k1][0],
686  a[k1][1] = I[k1][0] = -I[n1-k1][0],
687  a[n1-k1][1] = R[k1][n2/2] = R[n1-k1][n2/2],
688  a[n1-k1][0] = -I[k1][n2/2] = I[n1-k1][n2/2],
689  0<k1<n1/2,
690  a[0][0] = R[0][0],
691  a[0][1] = R[0][n2/2],
692  a[n1/2][0] = R[n1/2][0],
693  a[n1/2][1] = R[n1/2][n2/2]
694  <case2>
695  input data
696  a[j1][2*j2] = R[j1][j2] = R[n1-j1][n2-j2],
697  a[j1][2*j2+1] = I[j1][j2] = -I[n1-j1][n2-j2],
698  0<j1<n1, 0<j2<n2/2,
699  a[0][2*j2] = R[0][j2] = R[0][n2-j2],
700  a[0][2*j2+1] = I[0][j2] = -I[0][n2-j2],
701  0<j2<n2/2,
702  a[j1][0] = R[j1][0] = R[n1-j1][0],
703  a[j1][1] = I[j1][0] = -I[n1-j1][0],
704  a[n1-j1][1] = R[j1][n2/2] = R[n1-j1][n2/2],
705  a[n1-j1][0] = -I[j1][n2/2] = I[n1-j1][n2/2],
706  0<j1<n1/2,
707  a[0][0] = R[0][0],
708  a[0][1] = R[0][n2/2],
709  a[n1/2][0] = R[n1/2][0],
710  a[n1/2][1] = R[n1/2][n2/2]
711  t[0...2*n1-1]
712  :work area (FFT_TYPE *)
713  ip[0...*]
714  :work area for bit reversal (int *)
715  length of ip >= 2+sqrt(n) ; if n % 4 == 0
716  2+sqrt(n/2); otherwise
717  (n = max(n1, n2/2))
718  ip[0],ip[1] are pointers of the cos/sin table.
719  w[0...*]
720  :cos/sin table (FFT_TYPE *)
721  length of w >= max(n1/2, n2/4) + n2/4
722  w[],ip[] are initialized if ip[0] == 0.
723  [remark]
724  Inverse of
725  rdft2d(n1, n2, 1, a, t, ip, w);
726  is
727  rdft2d(n1, n2, -1, a, t, ip, w);
728  for (j1 = 0; j1 <= n1 - 1; j1++) {
729  for (j2 = 0; j2 <= n2 - 1; j2++) {
730  a[j1][j2] *= 2.0 / (n1 * n2);
731  }
732  }
733  */
734 static void rdft2d(
735  int n1, int n2, int isgn, FFT_TYPE** a, FFT_TYPE* t, int* ip, FFT_TYPE* w)
736 {
737  int n, nw, nc, n1h, i, j, i2;
738  FFT_TYPE xi;
739 
740  n = n1 << 1;
741  if (n < n2)
742  {
743  n = n2;
744  }
745  nw = ip[0];
746  if (n > (nw << 2))
747  {
748  nw = n >> 2;
749  makewt(nw, ip, w);
750  }
751  nc = ip[1];
752  if (n2 > (nc << 2))
753  {
754  nc = n2 >> 2;
755  makect(nc, ip, w + nw);
756  }
757  n1h = n1 >> 1;
758  if (isgn < 0)
759  {
760  for (i = 1; i <= n1h - 1; i++)
761  {
762  j = n1 - i;
763  xi = a[i][0] - a[j][0];
764  a[i][0] += a[j][0];
765  a[j][0] = xi;
766  xi = a[j][1] - a[i][1];
767  a[i][1] += a[j][1];
768  a[j][1] = xi;
769  }
770  for (j = 0; j <= n2 - 2; j += 2)
771  {
772  for (i = 0; i <= n1 - 1; i++)
773  {
774  i2 = i << 1;
775  t[i2] = a[i][j];
776  t[i2 + 1] = a[i][j + 1];
777  }
778  cdft(n1 << 1, isgn, t, ip, w);
779  for (i = 0; i <= n1 - 1; i++)
780  {
781  i2 = i << 1;
782  a[i][j] = t[i2];
783  a[i][j + 1] = t[i2 + 1];
784  }
785  }
786  for (i = 0; i <= n1 - 1; i++)
787  {
788  rdft(n2, isgn, a[i], ip, w);
789  }
790  }
791  else
792  {
793  for (i = 0; i <= n1 - 1; i++)
794  {
795  rdft(n2, isgn, a[i], ip, w);
796  }
797  for (j = 0; j <= n2 - 2; j += 2)
798  {
799  for (i = 0; i <= n1 - 1; i++)
800  {
801  i2 = i << 1;
802  t[i2] = a[i][j];
803  t[i2 + 1] = a[i][j + 1];
804  }
805  cdft(n1 << 1, isgn, t, ip, w);
806  for (i = 0; i <= n1 - 1; i++)
807  {
808  i2 = i << 1;
809  a[i][j] = t[i2];
810  a[i][j + 1] = t[i2 + 1];
811  }
812  }
813  for (i = 1; i <= n1h - 1; i++)
814  {
815  j = n1 - i;
816  a[j][0] = 0.5f * (a[i][0] - a[j][0]);
817  a[i][0] -= a[j][0];
818  a[j][1] = 0.5f * (a[i][1] + a[j][1]);
819  a[i][1] -= a[j][1];
820  }
821  }
822 }
823 
824 /**
825  Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
826  You may use, copy, modify this code for any purpose and
827  without fee. You may distribute this ORIGINAL package.
828 
829 -------- Complex DFT (Discrete Fourier Transform) --------
830  [definition]
831  <case1>
832  X[k1][k2] = sum_j1=0^n1-1 sum_j2=0^n2-1 x[j1][j2] *
833  exp(2*pi*i*j1*k1/n1) *
834  exp(2*pi*i*j2*k2/n2), 0<=k1<n1, 0<=k2<n2
835  <case2>
836  X[k1][k2] = sum_j1=0^n1-1 sum_j2=0^n2-1 x[j1][j2] *
837  exp(-2*pi*i*j1*k1/n1) *
838  exp(-2*pi*i*j2*k2/n2), 0<=k1<n1, 0<=k2<n2
839  (notes: sum_j=0^n-1 is a summation from j=0 to n-1)
840  [usage]
841  <case1>
842  ip[0] = 0; // first time only
843  cdft2d(n1, 2*n2, 1, a, t, ip, w);
844  <case2>
845  ip[0] = 0; // first time only
846  cdft2d(n1, 2*n2, -1, a, t, ip, w);
847  [parameters]
848  n1 :data length (int)
849  n1 >= 1, n1 = power of 2
850  2*n2 :data length (int)
851  n2 >= 1, n2 = power of 2
852  a[0...n1-1][0...2*n2-1]
853  :input/output data (double **)
854  input data
855  a[j1][2*j2] = Re(x[j1][j2]),
856  a[j1][2*j2+1] = Im(x[j1][j2]),
857  0<=j1<n1, 0<=j2<n2
858  output data
859  a[k1][2*k2] = Re(X[k1][k2]),
860  a[k1][2*k2+1] = Im(X[k1][k2]),
861  0<=k1<n1, 0<=k2<n2
862  t[0...2*n1-1]
863  :work area (double *)
864  ip[0...*]
865  :work area for bit reversal (int *)
866  length of ip >= 2+sqrt(n) ; if n % 4 == 0
867  2+sqrt(n/2); otherwise
868  (n = max(n1, n2))
869  ip[0],ip[1] are pointers of the cos/sin table.
870  w[0...*]
871  :cos/sin table (double *)
872  length of w >= max(n1/2, n2/2)
873  w[],ip[] are initialized if ip[0] == 0.
874  [remark]
875  Inverse of
876  cdft2d(n1, 2*n2, -1, a, t, ip, w);
877  is
878  cdft2d(n1, 2*n2, 1, a, t, ip, w);
879  for (j1 = 0; j1 <= n1 - 1; j1++) {
880  for (j2 = 0; j2 <= 2 * n2 - 1; j2++) {
881  a[j1][j2] *= 1.0 / (n1 * n2);
882  }
883  }
884 
885 */
886 static void cdft2d(
887  int n1, int n2, int isgn, FFT_TYPE** a, FFT_TYPE* t, int* ip, FFT_TYPE* w)
888 {
889  void makewt(int nw, int* ip, FFT_TYPE* w);
890  void cdft(int n, int isgn, FFT_TYPE* a, int* ip, FFT_TYPE* w);
891  int n, i, j, i2;
892 
893  n = n1 << 1;
894  if (n < n2)
895  {
896  n = n2;
897  }
898  if (n > (ip[0] << 2))
899  {
900  makewt(n >> 2, ip, w);
901  }
902  for (i = 0; i <= n1 - 1; i++)
903  {
904  cdft(n2, isgn, a[i], ip, w);
905  }
906  for (j = 0; j <= n2 - 2; j += 2)
907  {
908  for (i = 0; i <= n1 - 1; i++)
909  {
910  i2 = i << 1;
911  t[i2] = a[i][j];
912  t[i2 + 1] = a[i][j + 1];
913  }
914  cdft(n1 << 1, isgn, t, ip, w);
915  for (i = 0; i <= n1 - 1; i++)
916  {
917  i2 = i << 1;
918  a[i][j] = t[i2];
919  a[i][j + 1] = t[i2 + 1];
920  }
921  }
922 }
923 
924 } // namespace mrpt::math
925 
927  CVectorFloat& in_realData, CVectorFloat& out_FFT_Re,
928  CVectorFloat& out_FFT_Im, CVectorFloat& out_FFT_Mag)
929 {
930  MRPT_START
931 
932  unsigned long n = (unsigned long)in_realData.size();
933 
934  // TODO: Test data lenght is 2^N...
935 
936  CVectorFloat auxVect(n + 1);
937 
938  memcpy(&auxVect[1], &in_realData[0], n * sizeof(auxVect[0]));
939 
940  realft(&auxVect[0], n);
941 
942  unsigned int n_2 = 1 + (n / 2);
943 
944  out_FFT_Re.resize(n_2);
945  out_FFT_Im.resize(n_2);
946  out_FFT_Mag.resize(n_2);
947 
948  for (unsigned int i = 0; i < n_2; i++)
949  {
950  if (i == (n_2 - 1))
951  out_FFT_Re[i] = auxVect[2];
952  else
953  out_FFT_Re[i] = auxVect[1 + i * 2];
954 
955  if (i == 0 || i == (n_2 - 1))
956  out_FFT_Im[i] = 0;
957  else
958  out_FFT_Im[i] = auxVect[1 + i * 2 + 1];
959 
960  out_FFT_Mag[i] =
961  std::sqrt(square(out_FFT_Re[i]) + square(out_FFT_Im[i]));
962  }
963 
964  MRPT_END
965 }
966 
968  const CMatrixFloat& in_data, CMatrixFloat& out_real, CMatrixFloat& out_imag)
969 {
970  MRPT_START
971 
972  size_t i, j;
973  using float_ptr = FFT_TYPE*;
974 
975  // The dimensions:
976  size_t dim1 = in_data.rows();
977  size_t dim2 = in_data.cols();
978 
979  // Transform to format compatible with C routines:
980  // ------------------------------------------------------------
981  FFT_TYPE** a;
982  FFT_TYPE* t;
983  int* ip;
984  FFT_TYPE* w;
985 
986  // Reserve memory and copy data:
987  // --------------------------------------
988  a = new float_ptr[dim1];
989  for (i = 0; i < dim1; i++)
990  {
991  a[i] = new FFT_TYPE[dim2];
992  for (j = 0; j < dim2; j++) a[i][j] = in_data.get_unsafe(i, j);
993  }
994 
995  t = new FFT_TYPE[2 * dim1 + 20];
996  ip = new int[(int)ceil(20 + 2 + sqrt((FFT_TYPE)max(dim1, dim2 / 2)))];
997  ip[0] = 0;
998  w = new FFT_TYPE[max(dim1 / 2, dim2 / 4) + dim2 / 4 + 20];
999 
1000  // Do the job!
1001  // --------------------------------------
1002  rdft2d((int)dim1, (int)dim2, 1, a, t, ip, w);
1003 
1004  // Transform back to MRPT matrix format:
1005  // --------------------------------------
1006  out_real.setSize(dim1, dim2);
1007  out_imag.setSize(dim1, dim2);
1008 
1009  // a[k1][2*k2] = R[k1][k2] = R[n1-k1][n2-k2],
1010  // a[k1][2*k2+1] = I[k1][k2] = -I[n1-k1][n2-k2],
1011  // 0<k1<n1, 0<k2<n2/2,
1012  for (i = 1; i < dim1; i++)
1013  for (j = 1; j < dim2 / 2; j++)
1014  {
1015  out_real.set_unsafe(i, j, (float)a[i][j * 2]);
1016  out_real.set_unsafe(dim1 - i, dim2 - j, (float)a[i][j * 2]);
1017  out_imag.set_unsafe(i, j, (float)-a[i][j * 2 + 1]);
1018  out_imag.set_unsafe(dim1 - i, dim2 - j, (float)a[i][j * 2 + 1]);
1019  }
1020  // a[0][2*k2] = R[0][k2] = R[0][n2-k2],
1021  // a[0][2*k2+1] = I[0][k2] = -I[0][n2-k2],
1022  // 0<k2<n2/2,
1023  for (j = 1; j < dim2 / 2; j++)
1024  {
1025  out_real.set_unsafe(0, j, (float)a[0][j * 2]);
1026  out_real.set_unsafe(0, dim2 - j, (float)a[0][j * 2]);
1027  out_imag.set_unsafe(0, j, (float)-a[0][j * 2 + 1]);
1028  out_imag.set_unsafe(0, dim2 - j, (float)a[0][j * 2 + 1]);
1029  }
1030 
1031  // a[k1][0] = R[k1][0] = R[n1-k1][0],
1032  // a[k1][1] = I[k1][0] = -I[n1-k1][0],
1033  // a[n1-k1][1] = R[k1][n2/2] = R[n1-k1][n2/2],
1034  // a[n1-k1][0] = -I[k1][n2/2] = I[n1-k1][n2/2],
1035  // 0<k1<n1/2,
1036  for (i = 1; i < dim1 / 2; i++)
1037  {
1038  out_real.set_unsafe(i, 0, (float)a[i][0]);
1039  out_real.set_unsafe(dim1 - i, 0, (float)a[i][0]);
1040  out_imag.set_unsafe(i, 0, (float)-a[i][1]);
1041  out_imag.set_unsafe(dim1 - i, 0, (float)a[i][1]);
1042  out_real.set_unsafe(i, dim2 / 2, (float)a[dim1 - i][1]);
1043  out_real.set_unsafe(dim1 - i, dim2 / 2, (float)a[dim1 - i][1]);
1044  out_imag.set_unsafe(i, dim2 / 2, (float)a[dim1 - i][0]);
1045  out_imag.set_unsafe(dim1 - i, dim2 / 2, (float)-a[dim1 - i][0]);
1046  }
1047 
1048  // a[0][0] = R[0][0],
1049  // a[0][1] = R[0][n2/2],
1050  // a[n1/2][0] = R[n1/2][0],
1051  // a[n1/2][1] = R[n1/2][n2/2]
1052  out_real.set_unsafe(0, 0, (float)a[0][0]);
1053  out_real.set_unsafe(0, dim2 / 2, (float)a[0][1]);
1054  out_real.set_unsafe(dim1 / 2, 0, (float)a[dim1 / 2][0]);
1055  out_real.set_unsafe(dim1 / 2, dim2 / 2, (float)a[dim1 / 2][1]);
1056 
1057  // Free temporary memory:
1058  for (i = 0; i < dim1; i++) delete[] a[i];
1059  delete[] a;
1060  delete[] t;
1061  delete[] ip;
1062  delete[] w;
1063 
1064  MRPT_END
1065 }
1066 
1068  const CMatrixFloat& in_real, const CMatrixFloat& in_imag,
1069  CMatrixFloat& out_data)
1070 {
1071  MRPT_START
1072 
1073  size_t i, j;
1074  using float_ptr = FFT_TYPE*;
1075 
1076  ASSERT_(in_real.rows() == in_imag.rows());
1077  ASSERT_(in_real.cols() == in_imag.cols());
1078 
1079  // The dimensions:
1080  size_t dim1 = in_real.rows();
1081  size_t dim2 = in_real.cols();
1082 
1083  if (mrpt::round2up(dim1) != dim1 || mrpt::round2up(dim2) != dim2)
1084  THROW_EXCEPTION("Matrix sizes are not a power of two!");
1085 
1086  // Transform to format compatible with C routines:
1087  // ------------------------------------------------------------
1088  FFT_TYPE** a;
1089  FFT_TYPE* t;
1090  int* ip;
1091  FFT_TYPE* w;
1092 
1093  // Reserve memory and copy data:
1094  // --------------------------------------
1095  a = new float_ptr[dim1];
1096  for (i = 0; i < dim1; i++) a[i] = new FFT_TYPE[dim2];
1097 
1098  // a[j1][2*j2] = R[j1][j2] = R[n1-j1][n2-j2],
1099  // a[j1][2*j2+1] = I[j1][j2] = -I[n1-j1][n2-j2],
1100  // 0<j1<n1, 0<j2<n2/2,
1101  for (i = 1; i < dim1; i++)
1102  for (j = 1; j < dim2 / 2; j++)
1103  {
1104  a[i][2 * j] = in_real.get_unsafe(i, j);
1105  a[i][2 * j + 1] = -in_imag.get_unsafe(i, j);
1106  }
1107 
1108  // a[0][2*j2] = R[0][j2] = R[0][n2-j2],
1109  // a[0][2*j2+1] = I[0][j2] = -I[0][n2-j2],
1110  // 0<j2<n2/2,
1111  for (j = 1; j < dim2 / 2; j++)
1112  {
1113  a[0][2 * j] = in_real.get_unsafe(0, j);
1114  a[0][2 * j + 1] = -in_imag.get_unsafe(0, j);
1115  }
1116 
1117  // a[j1][0] = R[j1][0] = R[n1-j1][0],
1118  // a[j1][1] = I[j1][0] = -I[n1-j1][0],
1119  // a[n1-j1][1] = R[j1][n2/2] = R[n1-j1][n2/2],
1120  // a[n1-j1][0] = -I[j1][n2/2] = I[n1-j1][n2/2],
1121  // 0<j1<n1/2,
1122  for (i = 1; i < dim1 / 2; i++)
1123  {
1124  a[i][0] = in_real.get_unsafe(i, 0);
1125  a[i][1] = -in_imag.get_unsafe(i, 0);
1126  a[dim1 - i][1] = in_real.get_unsafe(i, dim2 / 2);
1127  a[dim1 - i][0] = in_imag.get_unsafe(i, dim2 / 2);
1128  }
1129 
1130  // a[0][0] = R[0][0],
1131  // a[0][1] = R[0][n2/2],
1132  // a[n1/2][0] = R[n1/2][0],
1133  // a[n1/2][1] = R[n1/2][n2/2]
1134  a[0][0] = in_real.get_unsafe(0, 0);
1135  a[0][1] = in_real.get_unsafe(0, dim2 / 2);
1136  a[dim1 / 2][0] = in_real.get_unsafe(dim1 / 2, 0);
1137  a[dim1 / 2][1] = in_real.get_unsafe(dim1 / 2, dim2 / 2);
1138 
1139  t = new FFT_TYPE[2 * dim1 + 20];
1140  ip = new int[(int)ceil(20 + 2 + sqrt((FFT_TYPE)max(dim1, dim2 / 2)))];
1141  ip[0] = 0;
1142  w = new FFT_TYPE[max(dim1 / 2, dim2 / 4) + dim2 / 4 + 20];
1143 
1144  // Do the job!
1145  // --------------------------------------
1146  rdft2d((int)dim1, (int)dim2, -1, a, t, ip, w);
1147 
1148  // Transform back to MRPT matrix format:
1149  // --------------------------------------
1150  out_data.setSize(dim1, dim2);
1151 
1152  FFT_TYPE scale = 2.0f / (dim1 * dim2);
1153 
1154  for (i = 0; i < dim1; i++)
1155  for (j = 0; j < dim2; j++)
1156  out_data.set_unsafe(i, j, (float)(a[i][j] * scale));
1157 
1158  // Free temporary memory:
1159  for (i = 0; i < dim1; i++) delete[] a[i];
1160  delete[] a;
1161  delete[] t;
1162  delete[] ip;
1163  delete[] w;
1164 
1165  MRPT_END
1166 }
1167 
1168 /*---------------------------------------------------------------
1169  myGeneralDFT
1170 
1171  sign -> -1: DFT, 1:IDFT
1172  ---------------------------------------------------------------*/
1173 static void myGeneralDFT(
1174  int sign, const CMatrixFloat& in_real, const CMatrixFloat& in_imag,
1175  CMatrixFloat& out_real, CMatrixFloat& out_imag)
1176 {
1177  ASSERT_(in_real.rows() == in_imag.rows());
1178  ASSERT_(in_real.cols() == in_imag.cols());
1179 
1180  // The dimensions:
1181  size_t dim1 = in_real.rows();
1182  size_t dim2 = in_real.cols();
1183 
1184  size_t k1, k2, n1, n2;
1185  float w_r, w_i;
1186  float ang1 = (float)(sign * M_2PI / dim1);
1187  float ang2 = (float)(sign * M_2PI / dim2);
1188  float phase;
1189  float R, I;
1190  float scale = sign == 1 ? (1.0f / (dim1 * dim2)) : 1;
1191 
1192  out_real.setSize(dim1, dim2);
1193  out_imag.setSize(dim1, dim2);
1194 
1195  for (k1 = 0; k1 < dim1; k1++)
1196  {
1197  for (k2 = 0; k2 < dim2; k2++)
1198  {
1199  R = I = 0; // Accum:
1200 
1201  for (n1 = 0; n1 < dim1; n1++)
1202  {
1203  phase = ang1 * n1 * k1;
1204  for (n2 = 0; n2 < dim2; n2++)
1205  {
1206  w_r = cos(phase);
1207  w_i = sin(phase);
1208 
1209  R += w_r * in_real.get_unsafe(n1, n2) -
1210  w_i * in_imag.get_unsafe(n1, n2);
1211  I += w_i * in_real.get_unsafe(n1, n2) +
1212  w_r * in_imag.get_unsafe(n1, n2);
1213 
1214  phase += ang2 * k2;
1215  } // end for k2
1216  } // end for k1
1217 
1218  // Save result:
1219  out_real.set_unsafe(k1, k2, R * scale);
1220  out_imag.set_unsafe(k1, k2, I * scale);
1221 
1222  } // end for k2
1223  } // end for k1
1224 }
1225 
1226 /*---------------------------------------------------------------
1227  dft2_complex
1228  ---------------------------------------------------------------*/
1230  const CMatrixFloat& in_real, const CMatrixFloat& in_imag,
1231  CMatrixFloat& out_real, CMatrixFloat& out_imag)
1232 {
1233  MRPT_START
1234 
1235  ASSERT_(in_real.rows() == in_imag.rows());
1236  ASSERT_(in_real.cols() == in_imag.cols());
1237 
1238  // The dimensions:
1239  size_t dim1 = in_real.rows();
1240  size_t dim2 = in_real.cols();
1241  size_t i, j;
1242 
1243  bool dim1IsPower2 = (mrpt::round2up(dim1) == dim1);
1244  bool dim2IsPower2 = (mrpt::round2up(dim2) == dim2);
1245 
1246  // FFT or DFT??
1247  if (dim1IsPower2 && dim2IsPower2)
1248  {
1249  // ----------------------------------------
1250  // Optimized FFT:
1251  // ----------------------------------------
1252  using float_ptr = FFT_TYPE*;
1253 
1254  // Transform to format compatible with C routines:
1255  // ------------------------------------------------------------
1256  static FFT_TYPE** a = nullptr;
1257  static FFT_TYPE* t = nullptr;
1258  static int* ip = nullptr;
1259  static FFT_TYPE* w = nullptr;
1260 
1261  // Reserve memory
1262  // --------------------------------------
1263  static int alreadyInitSize1 = -1, alreadyInitSize2 = -1;
1264 
1265  if (alreadyInitSize1 != (int)dim1 || alreadyInitSize2 != (int)dim2)
1266  {
1267  // Create/realloc buffers:
1268  if (a)
1269  {
1270  for (i = 0; i < dim1; i++) delete[] a[i];
1271  delete[] a;
1272  }
1273  if (ip) delete[] ip;
1274  if (t) delete[] t;
1275  if (w) delete[] w;
1276 
1277  alreadyInitSize1 = (int)dim1;
1278  alreadyInitSize2 = (int)dim2;
1279 
1280  a = new float_ptr[dim1];
1281  for (i = 0; i < dim1; i++) a[i] = new FFT_TYPE[2 * dim2];
1282 
1283  t = new FFT_TYPE[2 * dim1 + 20];
1284  ip = new int[(int)ceil(
1285  20 + 2 + sqrt((FFT_TYPE)max(dim1, dim2 / 2)))];
1286  ip[0] = 0;
1287  w = new FFT_TYPE[max(dim1 / 2, dim2 / 4) + dim2 / 4 + 20];
1288  }
1289 
1290  // and copy data:
1291  // --------------------------------------
1292  for (i = 0; i < dim1; i++)
1293  for (j = 0; j < dim2; j++)
1294  {
1295  a[i][2 * j + 0] = in_real.get_unsafe(i, j);
1296  a[i][2 * j + 1] = in_imag.get_unsafe(i, j);
1297  }
1298 
1299  // Do the job!
1300  // --------------------------------------
1301  cdft2d((int)dim1, (int)(2 * dim2), 1, a, t, ip, w);
1302 
1303  // Transform back to MRPT matrix format:
1304  // --------------------------------------
1305  out_real.setSize(dim1, dim2);
1306  out_imag.setSize(dim1, dim2);
1307 
1308  // a[k1][2*k2] = Re(X[k1][k2]),
1309  // a[k1][2*k2+1] = Im(X[k1][k2]),
1310  // 0<=k1<n1, 0<=k2<n2
1311  for (i = 0; i < dim1; i++)
1312  for (j = 0; j < dim2; j++)
1313  {
1314  out_real.set_unsafe(i, j, (float)a[i][j * 2 + 0]);
1315  out_imag.set_unsafe(i, j, (float)a[i][j * 2 + 1]);
1316  }
1317 
1318  } // end FFT
1319  else
1320  {
1321  // ----------------------------------------
1322  // General DFT:
1323  // ----------------------------------------
1324  printf("Using general DFT...\n");
1325  myGeneralDFT(-1, in_real, in_imag, out_real, out_imag);
1326  }
1327 
1328  MRPT_END
1329 }
1330 
1331 /*---------------------------------------------------------------
1332  idft2_complex
1333  ---------------------------------------------------------------*/
1335  const CMatrixFloat& in_real, const CMatrixFloat& in_imag,
1336  CMatrixFloat& out_real, CMatrixFloat& out_imag)
1337 {
1338  MRPT_START
1339 
1340  ASSERT_(in_real.rows() == in_imag.rows());
1341  ASSERT_(in_real.cols() == in_imag.cols());
1342 
1343  // The dimensions:
1344  size_t dim1 = in_real.rows();
1345  size_t dim2 = in_real.cols();
1346  size_t i, j;
1347 
1348  bool dim1IsPower2 = (mrpt::round2up(dim1) == dim1);
1349  bool dim2IsPower2 = (mrpt::round2up(dim2) == dim2);
1350 
1351  // FFT or DFT??
1352  if (dim1IsPower2 && dim2IsPower2)
1353  {
1354  using float_ptr = FFT_TYPE*;
1355  // ----------------------------------------
1356  // Optimized FFT:
1357  // ----------------------------------------
1358 
1359  // Transform to format compatible with C routines:
1360  // ------------------------------------------------------------
1361  static FFT_TYPE** a = nullptr;
1362  static FFT_TYPE* t = nullptr;
1363  static int* ip = nullptr;
1364  static FFT_TYPE* w = nullptr;
1365 
1366  // Reserve memory
1367  // --------------------------------------
1368 
1369  // and copy data:
1370  // --------------------------------------
1371  static int alreadyInitSize1 = -1, alreadyInitSize2 = -1;
1372 
1373  if (alreadyInitSize1 != (int)dim1 || alreadyInitSize2 != (int)dim2)
1374  {
1375  // Create/realloc buffers:
1376  if (a)
1377  {
1378  for (i = 0; i < dim1; i++) delete[] a[i];
1379  delete[] a;
1380  }
1381  if (ip) delete[] ip;
1382  if (t) delete[] t;
1383  if (w) delete[] w;
1384 
1385  alreadyInitSize1 = (int)dim1;
1386  alreadyInitSize2 = (int)dim2;
1387 
1388  a = new float_ptr[dim1];
1389  for (i = 0; i < dim1; i++) a[i] = new FFT_TYPE[2 * dim2];
1390  t = new FFT_TYPE[2 * dim1 + 20];
1391  ip = new int[(int)ceil(
1392  20 + 2 + sqrt((FFT_TYPE)max(dim1, dim2 / 2)))];
1393  ip[0] = 0;
1394  w = new FFT_TYPE[max(dim1 / 2, dim2 / 4) + dim2 / 4 + 20];
1395  }
1396 
1397  // and copy data:
1398  // --------------------------------------
1399  for (i = 0; i < dim1; i++)
1400  for (j = 0; j < dim2; j++)
1401  {
1402  a[i][2 * j + 0] = in_real.get_unsafe(i, j);
1403  a[i][2 * j + 1] = in_imag.get_unsafe(i, j);
1404  }
1405 
1406  // Do the job!
1407  // --------------------------------------
1408  cdft2d((int)dim1, (int)(2 * dim2), -1, a, t, ip, w);
1409 
1410  // Transform back to MRPT matrix format:
1411  // --------------------------------------
1412  out_real.setSize(dim1, dim2);
1413  out_imag.setSize(dim1, dim2);
1414 
1415  FFT_TYPE scale = 1.0f / (dim1 * dim2);
1416 
1417  // a[k1][2*k2] = Re(X[k1][k2]),
1418  // a[k1][2*k2+1] = Im(X[k1][k2]),
1419  // 0<=k1<n1, 0<=k2<n2
1420  for (i = 0; i < dim1; i++)
1421  for (j = 0; j < dim2; j++)
1422  {
1423  // out_real.set_unsafe(i,j,(float)(a[i][j*2+0]*scale));
1424  // out_imag.set_unsafe(i,j,(float)(a[i][j*2+1]*scale));
1425  out_real.set_unsafe(i, j, (float)(a[i][j * 2 + 0]));
1426  out_imag.set_unsafe(i, j, (float)(a[i][j * 2 + 1]));
1427  }
1428 
1429  out_real *= scale;
1430  out_imag *= scale;
1431 
1432  // The element (0,0) is purely real!
1433  out_imag.set_unsafe(0, 0, 0);
1434 
1435  } // end FFT
1436  else
1437  {
1438  // ----------------------------------------
1439  // General DFT:
1440  // ----------------------------------------
1441  printf("Using general DFT...\n");
1442  myGeneralDFT(1, in_real, in_imag, out_real, out_imag);
1443  }
1444 
1445  MRPT_END
1446 }
1447 
1449  const CMatrixFloat& A, const CMatrixFloat& B, CMatrixFloat& out_corr)
1450 {
1451  MRPT_START
1452 
1453  ASSERT_(A.cols() == B.cols() && A.rows() == B.rows());
1454  if (mrpt::round2up(A.rows()) != A.rows() ||
1455  mrpt::round2up(A.cols()) != A.cols())
1456  THROW_EXCEPTION("Size of input matrices must be powers of two.");
1457 
1458  // Find smallest valid size:
1459  size_t x, y;
1460  const size_t lx = A.cols();
1461  const size_t ly = A.rows();
1462 
1463  const CMatrixFloat& i1 = A;
1464  const CMatrixFloat& i2 = B;
1465 
1466  // FFT:
1467  CMatrixFloat I1_R, I1_I, I2_R, I2_I, ZEROS(ly, lx);
1468  math::dft2_complex(i1, ZEROS, I1_R, I1_I);
1469  math::dft2_complex(i2, ZEROS, I2_R, I2_I);
1470 
1471  // Compute the COMPLEX division of I2 by I1:
1472  for (y = 0; y < ly; y++)
1473  for (x = 0; x < lx; x++)
1474  {
1475  float r1 = I1_R.get_unsafe(y, x);
1476  float r2 = I2_R.get_unsafe(y, x);
1477 
1478  float ii1 = I1_I.get_unsafe(y, x);
1479  float ii2 = I2_I.get_unsafe(y, x);
1480 
1481  float den = square(r1) + square(ii1);
1482  I2_R.set_unsafe(y, x, (r1 * r2 + ii1 * ii2) / den);
1483  I2_I.set_unsafe(y, x, (ii2 * r1 - r2 * ii1) / den);
1484  }
1485 
1486  // IFFT:
1487  CMatrixFloat res_R, res_I;
1488  math::idft2_complex(I2_R, I2_I, res_R, res_I);
1489 
1490  out_corr.setSize(ly, lx);
1491  for (y = 0; y < ly; y++)
1492  for (x = 0; x < lx; x++)
1493  out_corr(y, x) = sqrt(square(res_R(y, x)) + square(res_I(y, x)));
1494 
1495  MRPT_END
1496 }
static void four1(float data[], unsigned long nn, int isign)
Definition: fourier.cpp:31
#define MRPT_START
Definition: exceptions.h:262
GLdouble GLdouble t
Definition: glext.h:3689
#define M_2PI
Definition: common.h:58
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:41
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:6502
void dft2_real(const CMatrixFloat &in_data, CMatrixFloat &out_real, CMatrixFloat &out_imag)
Compute the 2D Discrete Fourier Transform (DFT) of a real matrix, returning the real and imaginary pa...
Definition: fourier.cpp:967
GLenum GLsizei n
Definition: glext.h:5074
void fft_real(CVectorFloat &in_realData, CVectorFloat &out_FFT_Re, CVectorFloat &out_FFT_Im, CVectorFloat &out_FFT_Mag)
Computes the FFT of a 2^N-size vector of real numbers, and returns the Re+Im+Magnitude parts...
Definition: fourier.cpp:926
static void rftfsub(int n, FFT_TYPE *a, int nc, FFT_TYPE *c)
Definition: fourier.cpp:542
Column vector, like Eigen::MatrixX*, but automatically initialized to zeros since construction...
Definition: eigen_frwds.h:44
STL namespace.
static void myGeneralDFT(int sign, const CMatrixFloat &in_real, const CMatrixFloat &in_imag, CMatrixFloat &out_real, CMatrixFloat &out_imag)
Definition: fourier.cpp:1173
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:4178
T square(const T x)
Inline function for the square of a number.
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:113
static void cdft2d(int n1, int n2, int isgn, FFT_TYPE **a, FFT_TYPE *t, int *ip, FFT_TYPE *w)
Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
Definition: fourier.cpp:886
static void rftbsub(int n, FFT_TYPE *a, int nc, FFT_TYPE *c)
Definition: fourier.cpp:611
This base provides a set of functions for maths stuff.
static void cftbsub(int n, FFT_TYPE *a, FFT_TYPE *w)
Definition: fourier.cpp:156
void cross_correlation_FFT(const CMatrixFloat &A, const CMatrixFloat &B, CMatrixFloat &out_corr)
Correlation of two matrixes using 2D FFT.
Definition: fourier.cpp:1448
const GLubyte * c
Definition: glext.h:6313
T round2up(T val)
Round up to the nearest power of two of a given number.
static void cftfsub(int n, FFT_TYPE *a, FFT_TYPE *w)
Definition: fourier.cpp:276
static void bitrv2(int n, int *ip, FFT_TYPE *a)
Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
Definition: fourier.cpp:455
float FFT_TYPE
Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
Definition: fourier.cpp:147
void idft2_complex(const CMatrixFloat &in_real, const CMatrixFloat &in_imag, CMatrixFloat &out_real, CMatrixFloat &out_imag)
Compute the 2D inverse Discrete Fourier Transform (DFT).
Definition: fourier.cpp:1334
static void rdft(int n, int isgn, FFT_TYPE *a, int *ip, FFT_TYPE *w)
Definition: fourier.cpp:566
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void idft2_real(const CMatrixFloat &in_real, const CMatrixFloat &in_imag, CMatrixFloat &out_data)
Compute the 2D inverse Discrete Fourier Transform (DFT)
Definition: fourier.cpp:1067
const float R
static void makewt(int nw, int *ip, FFT_TYPE *w)
Definition: fourier.cpp:396
static void rdft2d(int n1, int n2, int isgn, FFT_TYPE **a, FFT_TYPE *t, int *ip, FFT_TYPE *w)
Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
Definition: fourier.cpp:734
#define MRPT_END
Definition: exceptions.h:266
static void realft(float data[], unsigned long n)
Definition: fourier.cpp:100
GLenum GLint GLint y
Definition: glext.h:3538
int sign(T x)
Returns the sign of X as "1" or "-1".
static void makect(int nc, int *ip, FFT_TYPE *c)
Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
Definition: fourier.cpp:430
GLenum GLint x
Definition: glext.h:3538
void dft2_complex(const CMatrixFloat &in_real, const CMatrixFloat &in_imag, CMatrixFloat &out_real, CMatrixFloat &out_imag)
Compute the 2D Discrete Fourier Transform (DFT) of a complex matrix, returning the real and imaginary...
Definition: fourier.cpp:1229
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3546
GLubyte GLubyte GLubyte a
Definition: glext.h:6279
static void cdft(int n, int isgn, FFT_TYPE *a, int *ip, FFT_TYPE *w)
Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
Definition: fourier.cpp:522
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".
Definition: os.cpp:356



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 7d5e6d718 Fri Aug 24 01:51:28 2018 +0200 at lun nov 2 08:35:50 CET 2020