LoginSignup
16
15

More than 1 year has passed since last update.

FFTの擬似コード

Last updated at Posted at 2016-06-02

DFTの回転因子をまとめただけのFFTの擬似コードです。擬似コードというかPythonなので一応実行は出来ますが、きちんとしたFFTの設計は大浦さんのページに詳しく載っています(文字化け注意)。

周波数間引き Radix-2 FFT

\begin{eqnarray}
A_{2k} &=& \sum_{j=0}^{N/2-1} (a_j + a_{N/2+j}) W_{N/2}^{jk} \\
A_{2k+1} &=& \sum_{j=0}^{N/2-1} ( a_j - a_{N/2+j}) W_N^j W_{N/2}^{jk} 
\end{eqnarray}
fft2f.py
import numpy as np
def fft(x):
    n = len(x)
    if n == 1:
        return x
    else:
        # Radix-2
        w  = np.exp(-2j*np.pi/n*np.arange(n//2))
        x0 = x[:n//2] + x[n//2:]
        x1 = x[:n//2] - x[n//2:]
        x0_ = fft( x0 )
        x1_ = fft( x1*w )
        return np.c_[x0_, x1_].ravel()

時間間引き Radix-2 FFT

\begin{eqnarray}
A_k &=& \sum_{j=0}^{N/2-1} a_{2j} W_{N/2}^{jk} + W^k_N\sum_{j=0}^{N/2-1} a_{2j+1} W_{N/2}^{jk} \\
A_{N/2+k} &=&  \sum_{j=0}^{N/2-1} a_{2j} W_{N/2}^{jk} - W^k_N\sum_{j=0}^{N/2-1} a_{2j+1} W_{N/2}^{jk} 
\end{eqnarray}
fft2t.py
import numpy as np
def fft(x):
    n = len(x)
    if n == 1:
        return x
    else:
        # Radix-2
        w  = np.exp(-2j*np.pi/n*np.arange(n//2))
        x0 = fft(x[0::2])
        x1 = fft(x[1::2])*w
        x0_ = x0 + x1
        x1_ = x0 - x1
        return np.r_[x0_, x1_]

周波数間引き Radix-4 FFT

\begin{eqnarray}
A_{4k} &=& \sum_{j=0}^{N/4-1} (a_j + a_{N/4+j} + a_{2N/4+j} + a_{3N/4+j}) W_{N/4}^{jk} \\
A_{4k+1} &=& \sum_{j=0}^{N/4-1} (a_j - a_{2N/4+j} - i(a_{N/4+j} - a_{3N/4+j}) ) W_N^j W_{N/4}^{jk} \\
A_{4k+2} &=& \sum_{j=0}^{N/4-1} (a_j - a_{N/4+j} + a_{2N/4+j} - a_{3N/4+j}) W_N^{2j} W_{N/4}^{jk} \\
A_{4k+3} &=& \sum_{j=0}^{N/4-1} (a_j - a_{2N/4+j} + i(a_{N/4+j} - a_{3N/4+j}) ) W_N^{3j} W_{N/4}^{jk}
\end{eqnarray}
fft4f.py
import numpy as np
def fft(x):
    n = len(x)
    if n == 1:
        return x
    elif n == 2:
        # Radix-2
        return np.r_[x[0]+x[1], x[0]-x[1]]
    else:
        # Radix-4
        w  = np.exp(-2j*np.pi/n*np.arange(n//4))
        w2 = np.exp(-2j*np.pi/n*2*np.arange(n//4))
        w3 = np.exp(-2j*np.pi/n*3*np.arange(n//4))
        x0 = x[:n//4] + x[n//4*2:n//4*3]
        x1 = x[:n//4] - x[n//4*2:n//4*3]
        x2 = x[n//4:n//4*2] + x[n//4*3:]
        x3 = x[n//4:n//4*2] - x[n//4*3:]
        x0_ = fft( x0 + x2 )
        x1_ = fft( (x1 - 1j*x3)*w )
        x2_ = fft( (x0 - x2)*w2 )
        x3_ = fft( (x1 + 1j*x3)*w3 )
        return np.c_[x0_,
                     x1_,
                     x2_,
                     x3_].ravel()

時間間引き Radix-4 FFT

\begin{eqnarray}
A_k &=& \sum_{j=0}^{N/4-1} a_{4j} W_{N/4}^{jk} + W^k_N\sum_{j=0}^{N/4-1} a_{4j+1} W_{N/4}^{jk} 
+ W^{2k}_N\sum_{j=0}^{N/4-1} a_{4j+2} W_{N/4}^{jk} + W^{3k}_N\sum_{j=0}^{N/4-1} a_{4j+3} W_{N/4}^{jk} \\
A_{N/4+k} &=& \sum_{j=0}^{N/4-1} a_{4j} W_{N/4}^{jk} - W^{2k}_N\sum_{j=0}^{N/4-1} a_{4j+2} W_{N/4}^{jk}
- i \bigg( W^k_N\sum_{j=0}^{N/4-1} a_{4j+1} W_{N/4}^{jk} - W^{3k}_N\sum_{j=0}^{N/4-1} a_{4j+3} W_{N/4}^{jk} \bigg) \\
A_{2N/4+k} &=& \sum_{j=0}^{N/4-1} a_{4j} W_{N/4}^{jk} - W^k_N\sum_{j=0}^{N/4-1} a_{4j+1} W_{N/4}^{jk} 
+ W^{2k}_N\sum_{j=0}^{N/4-1} a_{4j+2} W_{N/4}^{jk} - W^{3k}_N\sum_{j=0}^{N/4-1} a_{4j+3} W_{N/4}^{jk} \\
A_{3N/4+k} &=& \sum_{j=0}^{N/4-1} a_{4j} W_{N/4}^{jk} - W^{2k}_N\sum_{j=0}^{N/4-1} a_{4j+2} W_{N/4}^{jk}
+ i \bigg( W^k_N\sum_{j=0}^{N/4-1} a_{4j+1} W_{N/4}^{jk} - W^{3k}_N\sum_{j=0}^{N/4-1} a_{4j+3} W_{N/4}^{jk} \bigg)
\end{eqnarray}
fft4t.py
import numpy as np
def fft(x):
    n = len(x)
    if n == 1:
        return x
    elif n == 2:
        # Radix-2
        return np.r_[x[0]+x[1], x[0]-x[1]]
    else:
        # Radix-4
        w  = np.exp(-2j*np.pi/n*np.arange(n//4))
        w2 = np.exp(-2j*np.pi/n*2*np.arange(n//4))
        w3 = np.exp(-2j*np.pi/n*3*np.arange(n//4))
        x0 = fft(x[0::4])
        x1 = fft(x[1::4])*w
        x2 = fft(x[2::4])*w2
        x3 = fft(x[3::4])*w3
        x0_ = x0 + x2
        x1_ = x1 + x3
        x2_ = x0 - x2
        x3_ = x1 - x3
        return np.r_[x0_ + x1_,
                     x2_ - 1j*x3_,
                     x0_ - x1_,
                     x2_ + 1j*x3_]

周波数間引き Split-Radix FFT

\begin{eqnarray}
A_{2k} &=& \sum_{j=0}^{N/2-1} (a_j + a_{N/2+j}) W_{N/2}^{jk} \\
A_{4k+1} &=& \sum_{j=0}^{N/4-1} (a_j - a_{2N/4+j} - i(a_{N/4+j} - a_{3N/4+j}) ) W_N^j W_{N/4}^{jk} \\
A_{4k+3} &=& \sum_{j=0}^{N/4-1} (a_j - a_{2N/4+j} + i(a_{N/4+j} - a_{3N/4+j}) ) W_N^{3j} W_{N/4}^{jk}
\end{eqnarray}
fftsf.py
import numpy as np
def fft(x):
    n = len(x)
    if n == 1:
        return x
    elif n == 2:
        # Radix-2
        return np.r_[x[0]+x[1], x[0]-x[1]]
    else:
        # Split-Radix
        w  = np.exp(-2j*np.pi/n*np.arange(n//4))
        w3 = np.exp(-2j*np.pi/n*3*np.arange(n//4))
        x1 = x[:n//4] - x[n//4*2:n//4*3]
        x3 = x[n//4:n//4*2] - x[n//4*3:]
        x0 = fft(x[:n//2] + x[n//2:])
        x1_ = fft( (x1 - 1j*x3)*w )
        x3_ = fft( (x1 + 1j*x3)*w3 )
        return np.c_[x0[0::2],
                     x1_,
                     x0[1::2],
                     x3_].ravel()

時間間引き Split-Radix FFT

\begin{eqnarray}
A_k &=& \sum_{j=0}^{N/2-1} a_{2j} W_{N/2}^{jk}
+ W^k_N\sum_{j=0}^{N/4-1} a_{4j+1} W_{N/4}^{jk} + W^{3k}_N\sum_{j=0}^{N/4-1} a_{4j+3} W_{N/4}^{jk} \\
A_{N/4+k} &=& \sum_{j=0}^{N/2-1} a_{2j} W_{N/2}^{j(k+N/4)} 
- i \bigg( W^k_N\sum_{j=0}^{N/4-1} a_{4j+1} W_{N/4}^{jk} - W^{3k}_N\sum_{j=0}^{N/4-1} a_{4j+3} W_{N/4}^{jk} \bigg) \\
A_{2N/4+k} &=& \sum_{j=0}^{N/2-1} a_{2j} W_{N/2}^{jk}
- W^k_N\sum_{j=0}^{N/4-1} a_{4j+1} W_{N/4}^{jk} - W^{3k}_N\sum_{j=0}^{N/4-1} a_{4j+3} W_{N/4}^{jk} \\
A_{3N/4+k} &=& \sum_{j=0}^{N/2-1} a_{2j} W_{N/2}^{j(k+N/4)}
+ i \bigg( W^k_N\sum_{j=0}^{N/4-1} a_{4j+1} W_{N/4}^{jk} - W^{3k}_N\sum_{j=0}^{N/4-1} a_{4j+3} W_{N/4}^{jk} \bigg)
\end{eqnarray}
fftst.py
import numpy as np
def fft(x):
    n = len(x)
    if n == 1:
        return x
    elif n == 2:
        # Radix-2
        return np.r_[x[0]+x[1], x[0]-x[1]]
    else:
        # Split-Radix
        w  = np.exp(-2j*np.pi/n*np.arange(n//4))
        w3 = np.exp(-2j*np.pi/n*3*np.arange(n//4))
        x0 = fft(x[0::2])
        x1 = fft(x[1::4])*w
        x3 = fft(x[3::4])*w3
        x1_ = x1 + x3
        x3_ = x1 - x3
        return np.r_[x0[:n//4] + x1_,
                     x0[n//4:] - 1j*x3_,
                     x0[:n//4] - x1_,
                     x0[n//4:] + 1j*x3_]
16
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
15