00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <it/types.h>
00043 #include <it/fourier.h>
00044 #include <it/io.h>
00045 #include <it/math.h>
00046
00047
00048 #define CACHE_SIZE 128*1024
00049 #define DFT_LAST 16
00050
00051 static unsigned int cache_size = CACHE_SIZE;
00052
00053
00054 static int fft_init_done = 0;
00055 static int fft_log2size;
00056 static cvec dft_roots[DFT_LAST];
00057 static cvec fft_roots;
00058 static ivec fft_perm;
00059
00060
00061 static inline int intlog2 (int n)
00062 {
00063 int i;
00064
00065 for (i = 0; n; i++, n >>= 1);
00066
00067 return (i - 1);
00068 }
00069
00070
00071 void fft_init (void)
00072 {
00073 int size;
00074 int i, k, m;
00075
00076 if (fft_init_done)
00077 return;
00078
00079
00080 size = cache_size / sizeof (cplx) / 2;
00081 fft_log2size = intlog2 (size);
00082 fft_roots = cvec_new_unit_roots (size);
00083 cvec_push (fft_roots, cplx_1);
00084
00085
00086 fft_perm = ivec_new (size);
00087 fft_perm[0] = 0;
00088 fft_perm[size - 1] = size - 1;
00089 for (i = 1, k = 0; i < size - 1; i++) {
00090 m = size;
00091 do {
00092 m >>= 1;
00093 k ^= m;
00094 }
00095 while ((k & m) == 0);
00096 fft_perm[i] = k;
00097 }
00098
00099
00100 for (i = 2; i < DFT_LAST; i++)
00101 dft_roots[i] = cvec_new_unit_roots (i);
00102
00103 fft_init_done = 1;
00104 }
00105
00106
00107
00108 static inline void cplx_array_bitrev_permute (cplx * v, int n)
00109 {
00110 int i, m, r;
00111
00112 if (n <= 2)
00113 return;
00114
00115 r = 0;
00116 for (i = 1; i < n - 1; i++) {
00117 m = n;
00118 do {
00119 m >>= 1;
00120 r ^= m;
00121 }
00122 while ((r & m) == 0);
00123 if (r > i)
00124 cplx_swap (v[i], v[r]);
00125 }
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 static void __fft_dif (cplx * v, int log2n)
00138 {
00139 cvec roots = fft_roots;
00140 int log2f = fft_log2size;
00141 idx_t n, m, mh, s;
00142 idx_t k, l;
00143 idx_t log2m;
00144 cplx a, b;
00145 cplx *r;
00146
00147 n = 1 << log2n;
00148
00149 for (log2m = log2n; log2m > 0; log2m--) {
00150 m = 1 << log2m;
00151 mh = m >> 1;
00152 s = 1 << (log2f - log2m);
00153
00154 r = &roots[1 << log2f];
00155 for (k = 0; k < mh; k++) {
00156 for (l = 0; l < n; l += m) {
00157 a = v[l + k];
00158 b = v[l + k + mh];
00159 v[l + k] = cadd (a, b);
00160 v[l + k + mh] = cmul (csub (a, b), *r);
00161 }
00162 r -= s;
00163 }
00164 }
00165 }
00166
00167
00168 static void __ifft_dit (cplx * v, int log2n)
00169 {
00170 cvec roots = fft_roots;
00171 int log2f = fft_log2size;
00172 idx_t n, m, mh, s;
00173 idx_t k, l;
00174 idx_t log2m;
00175 cplx a, b;
00176 cplx *r;
00177
00178 n = 1 << log2n;
00179
00180 for (log2m = 1; log2m <= log2n; log2m++) {
00181 m = 1 << log2m;
00182 mh = m >> 1;
00183 s = 1 << (log2f - log2m);
00184
00185 r = &roots[0];
00186 for (k = 0; k < mh; k++) {
00187 for (l = 0; l < n; l += m) {
00188 a = v[l + k];
00189 b = cmul (v[l + k + mh], *r);
00190 v[l + k] = cadd (a, b);
00191 v[l + k + mh] = csub (a, b);
00192 }
00193 r += s;
00194 }
00195 }
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 static void _fft (cplx * v, int log2n)
00209 {
00210 int log2f = fft_log2size;
00211 int f = 1 << log2f;
00212 int n = 1 << log2n;
00213 cvec tmp;
00214 int i, j, k;
00215 int r, log2r;
00216 double c;
00217 cplx *p;
00218 cplx e;
00219
00220 if (log2n <= log2f) {
00221
00222 __fft_dif (v, log2n);
00223 return;
00224 }
00225
00226
00227 log2r = log2n - log2f;
00228 r = (1 << log2r);
00229
00230
00231 tmp = cvec_new (f);
00232
00233 for (j = 0; j < r; j++) {
00234
00235
00236 for (i = 0; i < f; i++)
00237 tmp[i] = v[j + r * i];
00238
00239
00240 __fft_dif (tmp, log2f);
00241
00242
00243 p = &v[j];
00244 *p = tmp[0];
00245 p += r;
00246
00247 c = -2 * M_PI * j / n;
00248 for (i = 1; i < f - 1; i++) {
00249
00250 k = fft_perm[i];
00251
00252 e.r = cos (c * i);
00253 e.i = sin (c * i);
00254
00255 *p = cmul (tmp[k], e);
00256 p += r;
00257 }
00258
00259 e.r = cos (c * (f - 1));
00260 e.i = sin (c * (f - 1));
00261 *p = cmul (tmp[f - 1], e);
00262 }
00263
00264 cvec_delete (tmp);
00265
00266
00267 p = v;
00268 for (j = 0; j < f; j++) {
00269 _fft (p, log2r);
00270 p += r;
00271 }
00272 }
00273
00274 static void _ifft (cplx * v, int log2n)
00275 {
00276 int log2f = fft_log2size;
00277 int f = 1 << log2f;
00278 int n = 1 << log2n;
00279 cvec tmp;
00280 int i, j, k;
00281 int r, log2r;
00282 double c;
00283 cplx *p;
00284 cplx e;
00285
00286 if (log2n <= log2f) {
00287
00288 __ifft_dit (v, log2n);
00289 return;
00290 }
00291
00292
00293 log2r = log2n - log2f;
00294 r = (1 << log2r);
00295
00296
00297 p = v;
00298 for (j = 0; j < f; j++) {
00299 _ifft (p, log2r);
00300 p += r;
00301 }
00302
00303
00304 tmp = cvec_new (f);
00305
00306 for (j = 0; j < r; j++) {
00307
00308
00309 p = &v[j];
00310 tmp[0] = *p;
00311 p += r;
00312
00313 c = 2 * M_PI * j / n;
00314 for (i = 1; i < f - 1; i++) {
00315
00316 k = fft_perm[i];
00317
00318 e.r = cos (c * i);
00319 e.i = sin (c * i);
00320
00321 tmp[k] = cmul (*p, e);
00322 p += r;
00323 }
00324
00325 e.r = cos (c * (f - 1));
00326 e.i = sin (c * (f - 1));
00327 tmp[f - 1] = cmul (*p, e);
00328
00329
00330 __ifft_dit (tmp, log2f);
00331
00332
00333 for (i = 0; i < f; i++)
00334 v[j + r * i] = tmp[i];
00335 }
00336
00337 cvec_delete (tmp);
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347 static void _fft_demangle (cplx * v, int log2n)
00348 {
00349 int log2f = fft_log2size;
00350 int f = 1 << log2f;
00351 int n = 1 << log2n;
00352 int i, j;
00353 int r, log2r;
00354 cplx *p;
00355
00356 if (log2n <= log2f) {
00357 cplx_array_bitrev_permute (v, n);
00358 return;
00359 }
00360
00361 log2r = log2n - log2f;
00362 r = (1 << log2r);
00363
00364
00365 if (log2r > log2f) {
00366 p = v;
00367 for (j = 0; j < f; j++) {
00368 _fft_demangle (p, log2r);
00369 cplx_array_bitrev_permute (p, r);
00370 p += r;
00371 }
00372 }
00373
00374 cplx_array_bitrev_permute (v, n);
00375
00376 p = v;
00377 for (i = 0; i < r; i++) {
00378 cplx_array_bitrev_permute (p, f);
00379 p += f;
00380 }
00381 }
00382
00383 static void _ifft_mangle (cplx * v, int log2n)
00384 {
00385 int log2f = fft_log2size;
00386 int f = 1 << log2f;
00387 int n = 1 << log2n;
00388 int i, j;
00389 int r, log2r;
00390 cplx *p;
00391
00392 if (log2n <= log2f) {
00393 cplx_array_bitrev_permute (v, n);
00394 return;
00395 }
00396
00397 log2r = log2n - log2f;
00398 r = (1 << log2r);
00399
00400
00401 p = v;
00402 for (i = 0; i < r; i++) {
00403 cplx_array_bitrev_permute (p, f);
00404 p += f;
00405 }
00406
00407 cplx_array_bitrev_permute (v, n);
00408
00409
00410 if (log2r > log2f) {
00411 p = v;
00412 for (j = 0; j < f; j++) {
00413 cplx_array_bitrev_permute (p, r);
00414 _ifft_mangle (p, log2r);
00415 p += r;
00416 }
00417 }
00418 }
00419
00420
00421 cvec it_fft (cvec v)
00422 {
00423 int n, log2n;
00424 cvec cv;
00425
00426 assert (cvec_length (v));
00427
00428 n = cvec_length (v);
00429 log2n = intlog2 (n);
00430 assert ((1 << log2n) == n);
00431 fft_init ();
00432 cv = cvec_clone (v);
00433 _fft (cv, log2n);
00434 _fft_demangle (cv, log2n);
00435 return (cv);
00436 }
00437
00438
00439 cvec it_ifft (cvec v)
00440 {
00441 int n, log2n;
00442 cvec cv;
00443
00444 assert (cvec_length (v));
00445
00446 n = cvec_length (v);
00447 log2n = intlog2 (n);
00448 assert ((1 << log2n) == n);
00449 fft_init ();
00450 cv = cvec_clone (v);
00451 _ifft_mangle (cv, log2n);
00452 _ifft (cv, log2n);
00453 cvec_div_by_real (cv, n);
00454 return (cv);
00455 }
00456
00457
00458 cvec cvec_fft_conv (cvec a, cvec b)
00459 {
00460 cvec ta, tb;
00461 int i, l, n;
00462 int log2n;
00463
00464
00465 ta = cvec_clone (a);
00466 tb = cvec_clone (b);
00467 l = cvec_length (a);
00468 if (cvec_length (b) > l)
00469 l = cvec_length (b);
00470 log2n = intlog2 (l);
00471 if ((1 << log2n) != l)
00472 log2n++;
00473 log2n++;
00474 n = 1 << log2n;
00475
00476 cvec_set_length (ta, n);
00477 cvec_set_length (tb, n);
00478
00479 for (i = cvec_length (a); i < n; i++)
00480 ta[i] = cplx_0;
00481 for (i = cvec_length (b); i < n; i++)
00482 tb[i] = cplx_0;
00483
00484
00485 fft_init ();
00486 _fft (ta, log2n);
00487 _fft (tb, log2n);
00488 cvec_mul (ta, tb);
00489 cvec_delete (tb);
00490 _ifft (ta, log2n);
00491 cvec_div_by_real (ta, n);
00492 cvec_set_length (ta, cvec_length (a) + cvec_length (b) - 1);
00493 return ta;
00494 }
00495
00496
00497 cvec cvec_fft_corr (cvec a, cvec b)
00498 {
00499 cvec ta, tb;
00500 int i, l, n;
00501 int log2n;
00502
00503
00504 ta = cvec_clone (a);
00505 tb = cvec_clone (b);
00506 l = cvec_length (a);
00507 if (cvec_length (b) > l)
00508 l = cvec_length (b);
00509 log2n = intlog2 (l);
00510 if ((1 << log2n) != l)
00511 log2n++;
00512 log2n++;
00513 n = 1 << log2n;
00514
00515 cvec_set_length (ta, n);
00516 cvec_set_length (tb, n);
00517
00518 for (i = cvec_length (a); i < n; i++)
00519 ta[i] = cplx_0;
00520 for (i = cvec_length (b); i < n; i++)
00521 tb[i] = cplx_0;
00522
00523
00524 fft_init ();
00525 _fft (ta, log2n);
00526 _fft (tb, log2n);
00527 cvec_conj_mul (ta, tb);
00528 cvec_delete (tb);
00529 _ifft (ta, log2n);
00530 cvec_div_by_real (ta, n);
00531 cvec_set_length (ta, l);
00532 return ta;
00533 }
00534
00535
00536 cvec cvec_fft_autocorr (cvec a)
00537 {
00538 cvec ta;
00539 int i, l, n;
00540 int log2n;
00541
00542
00543 ta = cvec_clone (a);
00544 l = cvec_length (a);
00545 log2n = intlog2 (l);
00546 if ((1 << log2n) != l)
00547 log2n++;
00548 log2n++;
00549 n = 1 << log2n;
00550
00551 cvec_set_length (ta, n);
00552
00553 for (i = cvec_length (a); i < n; i++)
00554 ta[i] = cplx_0;
00555
00556
00557 fft_init ();
00558 _fft (ta, log2n);
00559 cvec_abssqr (ta);
00560 _ifft (ta, log2n);
00561 cvec_div_by_real (ta, n);
00562 cvec_set_length (ta, l);
00563 return ta;
00564 }
00565
00566
00567 cvec it_fzt (cvec v, cplx z)
00568 {
00569 int i, l, n;
00570 int log2n;
00571 cplx c, d;
00572 cvec av, bv, cv;
00573 double p;
00574 double rho;
00575 double theta;
00576 double crho;
00577 double s;
00578
00579 assert (cvec_length (v));
00580 assert (cnorm (z) != 0);
00581
00582 l = cvec_length (v);
00583
00584 log2n = intlog2 (l);
00585 if ((1 << log2n) != l)
00586 log2n++;
00587 log2n++;
00588 n = 1 << log2n;
00589
00590 av = cvec_new (l);
00591 bv = cvec_new_zeros (n);
00592 cv = cvec_new (n);
00593
00594
00595 for (i = 0; i < cvec_length (v); i++)
00596 cv[i] = v[i];
00597
00598 for (i = cvec_length (v); i < n; i++)
00599 cv[i] = cplx_0;
00600
00601
00602 rho = cnorm (z);
00603 theta = cang (z);
00604
00605
00606 bv[0] = cplx_1;
00607 s = 1.0 / n;
00608
00609 for (i = 1; i < l; i++) {
00610 p = i * i / 2.0;
00611 crho = pow (rho, p);
00612 creal (c) = crho * cos (theta * p);
00613 cimag (c) = crho * sin (theta * p);
00614 d = cinv (c);
00615 bv[i] = d;
00616 bv[n - i] = d;
00617 av[i] = cscale (c, s);
00618 cv[i] = cmul (cv[i], c);
00619 }
00620
00621
00622 fft_init ();
00623 _fft (cv, log2n);
00624 _fft (bv, log2n);
00625 cvec_mul (cv, bv);
00626 _ifft (cv, log2n);
00627 cvec_delete (bv);
00628
00629
00630 cv[0].r *= s;
00631 cv[0].i *= s;
00632 for (i = 1; i < l; i++)
00633 cv[i] = cmul (cv[i], av[i]);
00634
00635 cvec_delete (av);
00636 cvec_set_length (cv, l);
00637
00638 return (cv);
00639 }
00640
00641
00642 #define FDFT_FORW 0
00643 #define FDFT_BACK 1
00644 static cvec it_fdft (cvec v, int inv)
00645 {
00646 int i, l, n;
00647 int log2n;
00648 cplx c, d;
00649 cvec av, bv, cv;
00650 double p;
00651 double s;
00652
00653 assert (cvec_length (v));
00654
00655 l = cvec_length (v);
00656
00657 log2n = intlog2 (l);
00658 if ((1 << log2n) != l)
00659 log2n++;
00660 log2n++;
00661 n = 1 << log2n;
00662
00663 av = cvec_new (l);
00664 bv = cvec_new_zeros (n);
00665 cv = cvec_new (n);
00666
00667
00668 for (i = 0; i < cvec_length (v); i++)
00669 cv[i] = v[i];
00670
00671 for (i = cvec_length (v); i < n; i++)
00672 cv[i] = cplx_0;
00673
00674
00675 bv[0] = cplx_1;
00676 if (inv)
00677 s = 1.0 / n / l;
00678 else
00679 s = 1.0 / n;
00680
00681 for (i = 1; i < l; i++) {
00682 p = i * i / 2.0;
00683 creal (c) = creal (d) = cos (M_PI * i * i / l);
00684 if (inv) {
00685 cimag (c) = sin (M_PI * i * i / l);
00686 cimag (d) = -cimag (c);
00687 }
00688 else {
00689 cimag (c) = sin (-M_PI * i * i / l);
00690 cimag (d) = -cimag (c);
00691 }
00692 bv[i] = d;
00693 bv[n - i] = d;
00694 av[i] = cscale (c, s);
00695 cv[i] = cmul (cv[i], c);
00696 }
00697
00698
00699 fft_init ();
00700 _fft (cv, log2n);
00701 _fft (bv, log2n);
00702 cvec_mul (cv, bv);
00703 _ifft (cv, log2n);
00704 cvec_delete (bv);
00705
00706
00707 cv[0].r *= s;
00708 cv[0].i *= s;
00709 for (i = 1; i < l; i++)
00710 cv[i] = cmul (cv[i], av[i]);
00711
00712 cvec_delete (av);
00713 cvec_set_length (cv, l);
00714
00715 return (cv);
00716 }
00717
00718
00719 static cvec it_sdft (cvec v)
00720 {
00721 idx_t n, k, m;
00722 idx_t N;
00723 cvec cv;
00724 cvec roots;
00725
00726 N = cvec_length (v);
00727 assert (N < DFT_LAST);
00728 cv = cvec_new (N);
00729
00730 fft_init ();
00731 roots = dft_roots[N];
00732 for (k = 0; k < N; k++) {
00733 cv[k] = cplx_0;
00734 m = 0;
00735 for (n = 0; n < N; n++) {
00736 cv[k] = cadd (cv[k], cmul (v[n], roots[m]));
00737 m += N - k;
00738 m %= N;
00739 }
00740 }
00741 return cv;
00742 }
00743
00744
00745 static cvec it_sidft (cvec v)
00746 {
00747 idx_t n, k, m;
00748 idx_t N;
00749 cvec cv;
00750 cvec roots;
00751
00752 N = cvec_length (v);
00753 assert (N < DFT_LAST);
00754 cv = cvec_new (N);
00755
00756 fft_init ();
00757 roots = dft_roots[N];
00758 for (n = 0; n < N; n++) {
00759 cv[n] = cplx_0;
00760 m = 0;
00761 for (k = 0; k < N; k++) {
00762 cv[n] = cadd (cv[n], cmul (v[k], roots[m]));
00763 m += n;
00764 m %= N;
00765 }
00766 }
00767 cvec_div_by_real (cv, N);
00768 return cv;
00769 }
00770
00771
00772 cvec it_dft (cvec v)
00773 {
00774 int l;
00775 int log2n;
00776
00777 l = cvec_length (v);
00778
00779 if (l == 0)
00780 return cvec_new (0);
00781
00782 if (l == 1)
00783 return cvec_clone (v);
00784
00785 log2n = intlog2 (l);
00786
00787 if (l == (1 << log2n))
00788 return it_fft (v);
00789
00790 if (l < DFT_LAST)
00791 return it_sdft (v);
00792
00793 return it_fdft (v, FDFT_FORW);
00794 }
00795
00796
00797 cvec it_idft (cvec v)
00798 {
00799 int l;
00800 int log2n;
00801
00802 l = cvec_length (v);
00803
00804 if (l == 0)
00805 return cvec_new (0);
00806
00807 if (l == 1)
00808 return cvec_clone (v);
00809
00810 log2n = intlog2 (l);
00811
00812 if (l == (1 << log2n))
00813 return it_ifft (v);
00814
00815 if (l < DFT_LAST)
00816 return it_sidft (v);
00817
00818 return it_fdft (v, FDFT_BACK);
00819 }
00820
00821
00822 cvec it_dft_real (vec v)
00823 {
00824
00825 cvec cv = vec_to_cvec (v);
00826 cvec r = it_dft (cv);
00827 cvec_delete (cv);
00828 return r;
00829 }
00830
00831
00832 vec it_idft_real (cvec cv)
00833 {
00834
00835 int i, l;
00836 cvec r = it_idft (cv);
00837 vec v;
00838
00839 l = cvec_length (cv);
00840 v = vec_new (l);
00841
00842 for (i = 0; i < l; i++)
00843 v[i] = creal (r[i]);
00844
00845 cvec_delete (r);
00846 return v;
00847 }
00848
00849
00850 #if 0
00851
00852
00853
00854
00855 cvec __it_dft_real_fast (vec v)
00856 {
00857 cvec cv, cvt;
00858 cvec roots;
00859 idx_t k, l;
00860
00861 l = vec_length (v);
00862 assert (l % 2 == 0);
00863
00864 cv = cvec_new (l / 2);
00865
00866
00867
00868
00869 for (k = 0; k < l / 2; k++) {
00870 creal (cv[k]) = v[2 * k];
00871 cimag (cv[k]) = v[2 * k + 1];
00872 }
00873
00874
00875 cvt = it_dft (cv);
00876 cvec_delete (cv);
00877
00878
00879 roots = cvec_new_unit_roots (l);
00880 for (k = 0; k < l; k++) {
00881 double r, i;
00882 r = creal (roots[k]);
00883 i = cimag (roots[k]);
00884 creal (roots[k]) = i;
00885 cimag (roots[k]) = r;
00886 }
00887
00888
00889
00890 cvec_set_length (cvt, l + 1);
00891 cvt[l / 2] = cvt[0];
00892 for (k = 0; k <= l / 2; k++) {
00893 cplx s = cconj (cvt[l / 2 - k]);
00894 cplx c = cvt[k];
00895
00896 c = csub (cadd (c, s), cmul (csub (c, s), roots[k]));
00897
00898
00899 cvt[l - k] = cconj (c);
00900 }
00901
00902 cvec_delete (roots);
00903
00904
00905 for (k = 0; k < l / 2; k++)
00906 cvt[k] = cconj (cvt[l - k]);
00907 cvec_set_length (cvt, l);
00908
00909
00910 cvec_div_by_real (cvt, 2);
00911
00912 return (cvt);
00913 }
00914 #endif