|
[ 簡単な説明 ] 高速フーリエ変換のライブラリです。 入力データを実数部、虚数部別の 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;
}
|