Fft算法.

对于变换长度为N的序列x(n)其傅立叶变换可以表示如下:

 

N

nk

X(k)=DFT[x(n)] =         Σx(n)W

 

n="0"

 

                     式(1)


其中,W="exp"(-2π/N)

在下面的源码里,对应函数为 DFT

 

算法导论 里介绍了一种递归计算fft地方法, 函数为FFT_recursive

主要利用了 DFT(x) = DFT[0](x) + w*DFT[1](x)

继而导出迭代的fft计算方法,就是现在最常用的,函数为FFT_Iter

步骤为:

将输入数组元素反置变换

for 树的每一层:

    for 这一层上需要计算的每一对数据:

        根据这一对数据,及蝶形公式,计算上一层的数据

 另外,代码里写了一个简单的复数类和向量计算函数

 

  1#include <vector>
  2#include <math.h>
  3#include <assert.h>
  4//#include <windows.h>
  5
  6using namespace std;
  7
  8//************************************/
  9// Fushu
 10/**************************************/
 11class FuShu
 12{
 13    public:
 14        FuShu(double r=0double i=0): x(r), y(i)
 15        {
 16        }

 17        
 18        FuShu & operator+= (FuShu const &rhs)
 19        {
 20            x += rhs.x;
 21            y += rhs.y;
 22            return *this;
 23        }

 24        
 25        FuShu & operator-= (FuShu const &rhs)
 26        {
 27            x -= rhs.x;
 28            y -= rhs.y;
 29            return *this;
 30        }

 31        
 32        FuShu & operator*= (FuShu const &rhs)
 33        {
 34            double x2 = x * rhs.x - y * rhs.y;
 35            double y2 =    x * rhs.y + y * rhs.x;
 36            x=x2;
 37            y=y2;
 38            return *this;
 39        }

 40        
 41    //private:
 42        double x,y;
 43}
;
 44
 45FuShu operator+ (FuShu const & lhs, FuShu const & rhs)
 46{
 47    FuShu res = lhs;
 48    return res+=rhs;
 49}
    
 50
 51FuShu operator- (FuShu const & lhs, FuShu const & rhs)
 52{
 53    FuShu res = lhs;
 54    return res-=rhs;
 55}
        
 56
 57FuShu operator* (FuShu const & lhs, FuShu const & rhs)
 58{
 59    FuShu res = lhs;
 60    return res*=rhs;
 61}
    
 62
 63double fabs(FuShu const & lhs)
 64{
 65    return fabs(lhs.x) + fabs(lhs.y);
 66}

 67// bool operator== (FuShu const & lhs, FuShu const & rhs)
 68// {
 69    // return lhs.x == rhs.x && lhs.y == rhs.y;
 70// }    
 71
 72void Print(FuShu const & lhs)
 73{
 74    if(lhs.y>=0)
 75    printf("%g+%gj ", lhs.x, lhs.y);
 76    else
 77    printf("%g%gj ", lhs.x, lhs.y);
 78}

 79
 80void Print(vector <FuShu> const & lhs)
 81{
 82    size_t n=lhs.size();
 83    for(size_t i=0; i<n; i++)
 84        Print(lhs[i]);
 85    printf("\n");
 86}

 87
 88
 89//************************************/
 90// vector
 91/**************************************/
 92
 93template <typename T>
 94vector <T> operator+ (vector <T> const & lhs, vector <T> const & rhs)
 95{
 96    assert(lhs.size() == rhs.size());
 97    vector <T> res;
 98    size_t n = lhs.size();
 99    res.resize(n);
100    for(size_t i=0; i<n; i++)
101        res[i] = lhs[i] + rhs[i];
102    return res;
103}

104
105template <typename T>
106vector <T> operator- (vector <T> const & lhs, vector <T> const & rhs)
107{
108    assert(lhs.size() == rhs.size());
109    vector <T> res;
110    size_t n = lhs.size();
111    res.resize(n);
112    for(size_t i=0; i<n; i++)
113        res[i] = lhs[i] - rhs[i];
114    return res;
115}

116
117
118template <typename T>
119vector <T> operator* (FuShu const & lhs, vector <T> const & rhs)
120{
121    vector <T> res;
122    size_t n = rhs.size();
123    res.resize(n);
124    for(size_t i=0; i<n; i++)
125        res[i] = lhs[i] * rhs[i];
126    return res;
127}

128
129template <typename T>
130double fabs(vector <T> const & lhs)
131{
132    double res(0);
133    size_t n=lhs.size();
134    
135    for(size_t i=0; i<n; i++)
136        res += fabs(lhs[i]);
137    return res;
138}

139// template <typename T>
140// bool operator== (FuShu const & lhs, vector <T> const & rhs)
141// {
142    // size_t n = lhs.size();
143    // if(n != rhs.size())
144        // return false;
145        
146    // for(size_t i=0; i<n; i++)
147        // if(lhs[i] != rhs[i])
148            // return false;
149            
150    // return true;
151// }
152
153template <typename T>
154vector <T> & operator<<(vector <T> & lhs, T const &rhs)
155{
156    lhs.push_back(rhs);
157    return lhs;
158}

159
160/***************************************************/
161// FFT
162/***************************************************/
163vector<FuShu> DFT(vector<FuShu> const &a)
164{
165    size_t n=a.size();
166    if(n==1return a;
167    
168    vector<FuShu> res(n);
169    for(size_t k=0; k<n; k++)
170    {
171        FuShu wnk(cos(6.28*k/n), sin(6.28*k/n));
172        FuShu w = 1;
173        for(size_t j=0; j<n; ++j, w*=wnk)
174            res[k] += a[j] * w;
175    }

176    
177    return res;
178}

179
180vector<FuShu> FFT_recursive(vector<FuShu> const &a)
181{
182    size_t n=a.size();
183    if(n==1return a;
184    
185    FuShu wn(cos(6.28/n), sin(6.28/n));
186    FuShu w(1);
187    vector<FuShu> a0, a1;
188    a0.reserve(n/2);
189    a1.reserve(n/2);
190    for(size_t i=0; i<n/2; i++)
191    {
192        a0.push_back(a[i*2]);
193        a1.push_back(a[i*2+1]);
194    }

195    
196    vector<FuShu> y0 = FFT_recursive(a0);
197    vector<FuShu> y1 = FFT_recursive(a1);
198    
199    vector<FuShu> vy;
200    vy.resize(n);
201    for(size_t k=0; k<n/2; k++)
202    {
203        vy[k] = y0[k] + w * y1[k];
204        vy[k + n/2= y0[k] - w * y1[k];
205        w = w*wn;
206    }

207    
208    return vy;
209}

210
211unsigned int rev(unsigned int num, unsigned int nBits)
212{
213    unsigned int r = 0;
214    for(unsigned int i=0; i<nBits; i++)
215    {
216        if(num&(1<<i))
217            r |= 1<<(nBits-i-1);
218    }

219    
220    return r;
221}

222
223vector<FuShu> FFT_Iter(vector<FuShu> const &a, unsigned int nBits)
224{
225    size_t n=a.size();
226    if(n==1return a;
227    
228    vector<FuShu>  A;
229    A.reserve(n);
230    for(size_t i=0; i<n; i++)
231        A<<a[rev(i,nBits)];
232    
233    size_t m=2;
234    for(size_t s=0; s<nBits; s++, m*=2)
235    {
236        FuShu wm(cos(6.28/m), sin(6.28/m));
237        for(size_t k=0; k<n; k+=m)
238        {
239            FuShu w=1;
240            for(size_t j=0; j<m/2; j++, w*=wm)
241            {
242                FuShu t = w * A[k+j+m/2];
243                FuShu u = A[k+j];
244                A[k+j] = u+t;
245                A[k+j+m/2= u-t;
246            }

247        }

248    }

249    
250    return A;
251}

252
253/***************************************************/
254// Main
255/***************************************************/
256
257void main()
258{
259
260    srand(clock());
261    for(int i=0; i<10; i++)
262    {
263        FuShu a(rand(),rand()), b(rand(),rand());
264
265        vector<FuShu> vA;
266        vA<<<<b<<<<b;
267        
268        printf("input:\n");
269        Print(vA);
270        printf("FFT_recursive result:\n");
271        vector<FuShu> vB = FFT_recursive(vA);
272        Print(vB);
273        printf("DFT result:\n");
274        vector<FuShu> vBDft = DFT(vA);
275        Print(vBDft);
276        
277        printf("FFT_Iter result:\n");
278        vector<FuShu> vBItr = FFT_Iter(vA,2);
279        Print(vBItr);
280        
281        printf("diff: %g\n", fabs(vB - vBItr));
282        assert( fabs(vB - vBItr)<1e-1);
283    }

284#if 0        
285    for(unsigned int i=0; i<8; i++)
286        printf("%d ", rev(i,3));
287#endif        
288}

Powered by Jekyll and Theme by solid

本站总访问量