더북(TheBook)

소스 10-7은 고속 이산 푸리에 변환 알고리즘을 C/C++로 구현한 FFT1d 함수이다. 이 함수의 인자는 DFT1d 함수와 동일하다. 즉, 입력 데이터의 실수부와 허수부가 각각 reim으로 전달되고, 데이터의 개수는 N에 저장된다. 네 번째 인자 dir의 값이 +1이면 순방향 FFT를 수행하고, -1이면 역방향 FFT를 수행한다. 이산 푸리에 변환된 결과는 다시 reim에 저장된다. FFT1d 함수의 선언은 앞서 10.2절에서 소스 10-3에 나타내었다. 참고로 입력 데이터 순서 바꾸기 코드는 전통적인 비트 반전 방법 대신 좀 더 효율적이고 널리 사용되고 있는 코드를 사용하였다.

소스 10-7 1차원 데이터에 대한 FFT 구현 함수(IppFourier.cpp)
#include <algorithm>
void FFT1d(double* re, double* im, int N, int dir)
{
    register int i, j, k;

    //-------------------------------------------------------------------------
    // 입력 데이터 순서 바꾸기
    //-------------------------------------------------------------------------

    int n2 = N >> 1;
    int nb = 0;

    while (N != (1 << nb))
        nb++;

    for (i = 0, j = 0; i < N - 1; i++)
    {
        if (i < j)
        {
            std::swap(re[i], re[j]);
            std::swap(im[i], im[j]);
        }

        k = n2;
        while (k <= j)
        {
            j -= k;
            k >>= 1;
        }

        j += k;
    }

    //-------------------------------------------------------------------------
    // 버터플라이(Butterfly) 알고리즘
    //-------------------------------------------------------------------------

    int i1, l, l1, l2;
    double c1, c2, t1, t2, u1, u2, z;

    c1 = -1.0;
    c2 = 0.0;
    l2 = 1;

    for (l = 0; l < nb; l++)
    {
        l1 = l2;
        l2 <<= 1;
        u1 = 1.0;
        u2 = 0.0;

        for (j = 0; j < l1; j++)
        {
            for (i = j; i < N; i += l2)
            {
                i1 = i + l1;
                t1 = u1 * re[i1] - u2 * im[i1];
                t2 = u1 * im[i1] + u2 * re[i1];
                re[i1] = re[i] - t1;
                im[i1] = im[i] - t2;
                re[i] += t1;
                im[i] += t2;
            }

            z = u1 * c1 - u2 * c2;
            u2 = u1 * c2 + u2 * c1;
            u1 = z;
        }

        c2 = sqrt((1.0 - c1) / 2.0);

        if (dir == 1) // Forward
            c2 = -c2;

        c1 = sqrt((1.0 + c1) / 2.0);
    }

    if (dir == -1) // IDFT
    {
        for (i = 0; i < N; i++)
        {
            re[i] /= static_cast<double>(N);
            im[i] /= static_cast<double>(N);
        }
    }
}
신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.