zoukankan      html  css  js  c++  java
  • 非递归的快速傅立叶变换

    快速傅里叶变换没什么好说的, 只是需要注意避免递归.

    避免递归

    上面那个递归版本的FFT实际上常数很大,因为要复制数组。我们观察一下递归树,假设这是一个长度为8的多项式。

    +===============================================+
    | 000   001   010   011   100   101   110   111 |
    +-----------------------------------------------+
    | 000   010   100   110 | 001   011   101   111 |
    +-----------------------------------------------+
    | 000   100 | 010   110 | 001   101 | 011   111 |
    +-----------------------------------------------+
    | 000 | 100 | 010 | 110 | 001 | 101 | 011 | 111 |
    +===============================================+

    实际上,从叶子往上做的话就是把每个数的二进制位颠倒过来。

     1 struct Complex
     2 {
     3   double real, imag;
     4   Complex(const double r = .0, const double i = .0): real(r), imag(i) { }
     5 };
     6 const Complex ZERO(.0, .0);
     7 inline Complex operator+(const Complex& lhs, const Complex& rhs) { return Complex(lhs.real+rhs.real, lhs.imag+rhs.imag); }
     8 inline Complex operator-(const Complex& lhs, const Complex& rhs) { return Complex(lhs.real-rhs.real, lhs.imag-rhs.imag); }
     9 inline Complex operator*(const Complex& lhs, const Complex& rhs) { return Complex(lhs.real*rhs.real-lhs.imag*rhs.imag, lhs.real*rhs.imag+lhs.imag*rhs.real); }
    10 inline int bit_reverse(const int x, const int n)
    11 {
    12   int res = 0;
    13   for (int i = 0; i < n; ++i)
    14     res |= (x>>i&1)<<(n-i-1);
    15   return res;
    16 }
    17 void fft(Complex y[], const Complex a[], const int n, const int rev)
    18 {
    19   const int len = 1<<n;
    20   for (int i = 0; i < len; ++i) y[i] = a[bit_reverse(i, n)];
    21   for (int d = 1; d <= n; ++d)
    22   {
    23     const int m = 1<<d;
    24     const Complex wn(std::cos(2*PI/m*rev), std::sin(2*PI/m*rev));
    25     for (int k = 0; k < len; k += m)
    26     {
    27       Complex w(1., .0);
    28       for (int j = 0; j < m/2; ++j)
    29       {
    30         const Complex u = y[k+j], t = w*y[k+j+m/2];
    31         y[k+j] = u+t, y[k+j+m/2] = u-t;
    32         w = w*wn;
    33       }
    34     }
    35   }
    36   if (rev == -1)
    37     for (int i = 0; i < len; ++i) y[i].real /= len, y[i].imag = .0;
    38 }
    39 void convolution(Complex c[], Complex a[], Complex b[], const int la, const int lb)
    40 {
    41   static Complex tmp1[MAXN], tmp2[MAXN];
    42   int n = 0, len = 1<<n;
    43   for (; len < 2*la || len < 2*lb; ++n) len <<= 1;
    44   std::fill(a+la, a+len, ZERO);
    45   std::fill(b+lb, b+len, ZERO);
    46   fft(tmp1, a, n, 1);
    47   fft(tmp2, b, n, 1);
    48   for (int i = 0; i < len; ++i) tmp1[i] = tmp1[i]*tmp2[i];
    49   fft(c, tmp1, n, -1);
    50 }
  • 相关阅读:
    java generic type
    android avoiding-memory-leaks
    a various of context
    LruCache
    Java Reference
    SQL join
    Eclipse java中一个工程引用另一个工程的类
    java 匿名内部类的方法参数需要final吗?
    java的final
    如何将每一条记录放入到对应的范围中
  • 原文地址:https://www.cnblogs.com/hatsuakiratenan/p/3132444.html
Copyright © 2011-2022 走看看