[ 簡単な説明 ] 高速フーリエ変換のライブラリです。 入力データを実数部、虚数部別の double 型配列で与えるルーチンと Complex 型配列で与えるルーチンを、それぞれ1次元と2次元のフーリエ変換ルーチンで準備しました。 ただし、2次元ルーチンの入力データは、nmax × n サイズの1次元配列で与えます。 各ルーチンは、flag でFFT、逆FFTモードを指定できます。(0:FFT、非0:逆FFT) FFTのルーチンは、Cooley−Tukeyのアルゴリズムを使用しています。2次元FFTのルーチンは内部で1次元FFTのルーチンをコールしています。 |
関数名 | 関数の機能 | 呼び出し例 (flag : 0 fft, 1 : inverse-fft) |
|
fft1( ) | 1次元高速フーリエ変換 | 実数部、虚数部別 配列 | fft1(ar, ai, n, iter, flag); |
fft1x( ) | Complex 型配列 | fft1x(a, n, iter, flag); | |
fft2( ) | 2次元高速フーリエ変換 | 実数部、虚数部別 配列 | fft2(ar, ai, n, nmax, flag); |
fft2x( ) | Complex 型配列 | fft2x(a, n, nmax, flag); |
/* fft.c */ #include <stdio.h> #include <stdlib.h> #include "sslib.h" void fft1(double ar[], double ai[], int n, int iter, int flag) { int i, it, j, j1, j2, k, xp, xp2; double arg, dr1, dr2, di1, di2, tr, ti, w, wr, wi; if(n < 2) { fprintf(stderr, "Error : n < 2 in fft1()\n"); return; } if(iter <= 0) { iter = 0; i = n; while((i /= 2) != 0) iter++; } j = 1; for(i = 0; i < iter; i++) j *= 2; if(n != j) { fprintf(stderr, "Error : n != 2 ^ k in fft1()\n"); return; } w = (flag? M_PI: -M_PI) / (double)n; xp2 = n; for(it = 0; it < iter; it++) { xp = xp2; xp2 /= 2; w *= 2; for(k = 0, i = - xp; k < xp2; i++) { wr = cos(arg = w * k++); wi = sin(arg); for(j = xp; j <= n; j += xp) { j2 = (j1 = j + i) + xp2; tr = (dr1 = ar[j1]) - (dr2 = ar[j2]); ti = (di1 = ai[j1]) - (di2 = ai[j2]); ar[j1] = dr1 + dr2; ai[j1] = di1 + di2; ar[j2] = tr * wr - ti * wi; ai[j2] = ti * wr + tr * wi; } } } j = j1 = n / 2; j2 = n - 1; for(i = 1; i < j2; i++) { if(i < j) { w = ar[i]; ar[i] = ar[j]; ar[j] = w; w = ai[i]; ai[i] = ai[j]; ai[j] = w; } k = j1; while(k <= j) { j -= k; k /= 2; } j += k; } if(flag == 0) return; w = 1. / (double)n; for(i = 0; i < n; i++) { ar[i] *= w; ai[i] *= w; } return; } void fft1x(Complex a[], int n, int iter, int flag) { int i, it, j, j1, j2, k, xp, xp2; double arg, sign, w; Complex d1, d2, *p, *q, t, ww; if(n < 2) { fprintf(stderr, "Error : n < 2 in fft1()\n"); return; } if(iter <= 0) { iter = 0; i = n; while((i /= 2) != 0) iter++; } j = 1; for(i = 0; i < iter; i++) j *= 2; if(n != j) { fprintf(stderr, "Error : n != 2 ^ k in fft1()\n"); return; } sign = (flag == 1)? 1.: -1.; xp2 = n; for(it = 0; it < iter; it++) { xp = xp2; xp2 = xp / 2; w = M_PI / xp2; for(k = 0; k < xp2; k++) { arg = k * w; ww = tocomplex(cos(arg), sign * sin(arg)); i = k - xp; for(j = xp, p = a + i + xp, q = a + i + xp + xp2; j <= n; j += xp, p += xp, q += xp) { t = csub(*p, *q); *p = cadd(*p, *q); *q = cmul(t, ww); } } } j1 = n / 2; j2 = n - 1; j = 1; for(i = 1, p = a; i <= j2; i++, p++) { if(i < j) swapx(p, a + j - 1); k = j1; while(k < j) { j -= k; k /= 2; } j += k; } if(flag == 0) return; w = n; for(i = 0, p = a; i < n; i++, p++) *p = cdiv1(*p, w); return; } void fft2(double ar[], double ai[], int n, int nmax, int flag) { int i, iter, j, k; double *p, *q, *wr, *wi; if(n < 2) { fprintf(stderr, "Error : Illegal parameter in fft2()\n"); return; } iter = 0; i = n; while((i /= 2) != 0) iter++; j = 1; for(i = 1; i <= iter; i++) j *= 2; if(n != j) { fprintf(stderr, "Error : n != 2 ^ k in fft2()\n"); return; } wr = (double *)malloc(n * sizeof(double)); if(wr == NULL) { fprintf(stderr, "Error : Out of memory in fft2()\n"); return; } wi = (double *)malloc(n * sizeof(double)); if(wi == NULL) { fprintf(stderr, "Error : Out of memory in fft2()\n"); free((char *)wr); return; } for(j = 0; j < n; j++, k += nmax) { for(i = 0, p = ar + j, q = ai + j; i < n; i++, p += nmax, q += nmax) { *(wr + i) = *p; *(wi + i) = *q; } fft1(wr, wi, n, iter, flag); for(i = 0, p = ar + j, q = ai + j; i < n; i++, p += nmax, q += nmax) { *p = *(wr + i); *q = *(wi + i); } } for(i = k = 0; i < n; i++, k += nmax) { for(j = 0, p = ar + k, q = ai + k; j < n; j++) { *(wr + j) = *p++; *(wi + j) = *q++; } fft1(wr, wi, n, iter, flag); for(j = 0, p = ar + k, q = ai + k; j < n; j++) { *p++ = *(wr + j); *q++ = *(wi + j); } } free((char *)wr); free((char *)wi); return; } void fft2x(Complex a[], int n, int nmax, int flag) { int i, iter, j, k; Complex *p, *w; if(n < 2) { fprintf(stderr, "Error : Illegal parameter in fft2()\n"); return; } iter = 0; i = n; while((i /= 2) != 0) iter++; j = 1; for(i = 1; i <= iter; i++) j *= 2; if(n != j) { fprintf(stderr, "Error : n != 2 ^ k in fft2x()\n"); return; } w = (Complex *)malloc(n * sizeof(Complex)); if(w == NULL) { fprintf(stderr, "Error : Out of memory in fft2x()\n"); return; } for(j = 0; j < n; j++, k += nmax) { for(i = 0, p = a + j; i < n; i++, p += nmax) *(w + i) = *p; fft1x(w, n, iter, flag); for(i = 0, p = a + j; i < n; i++, p += nmax) *p = *(w + i); } for(i = k = 0; i < n; i++, k += nmax) { for(j = 0, p = a + k; j < n; j++) *(w + j) = *p++; fft1x(w, n, iter, flag); for(j = 0, p = a + k; j < n; j++) *p++ = *(w + j); } free((char *)w); return; } |