これなら分かる 応用数学教室4.7 「高速フーリエ変換」
1の原始N乗根による表現による離散フーリエ変換に引き続き。
$$ f(x) = a_0 + a_1 x + a_2 x^2 + … + a_{N-1} x^{N-1} = \sum_{l=0}^{N-1} a_l x^l $$
とすると、
$$ b_k = \sum_{l=0}^{N-1} a_l \omega_N^{kl} = f(\omega_N^k) $$
となる。
\(f(x)\)を書き直すと
$$ \begin{align*} f(x) &= (a_0 + a_2 x^2 + … + a_{N-2} x^{N-2}) + x (a_1 + a_3 x^2 + … + a_{N-1} x^{N-2}) \\ &= p(x^2) + xq(x^2) \\ \end{align*} $$
ただし、
$$ \begin{align*} p(x) &= (a_0 + a_2 x + … + a_{N-2} x^{N/2-1}) \\ q(x) &= (a_1 + a_3 x + … + a_{N-1} x^{N/2-1}) \\ \end{align*} $$
とする。
\(\omega_N = e^{i 2\pi/N}\) から \(\omega_N^{2k} = \omega_{N/2}^k\)、\(\omega_N^{N/2+k} = -\omega_N^k\) を使うと
$$ b_k = \Bigg\lbrace \begin{align*} f(\omega_N^j) &= p(\omega_{N/2}^j) + \omega_N^j q(\omega_{N/2}^j), & \\ f(\omega_N^{N/2+j}) &= p(\omega_{N/2}^j) - \omega_N^j q(\omega_{N/2}^j) & \\ & (j = 0, 1, …, N/2-1) \end{align*} $$
と計算することができる。\(p\)と\(q\)は\(f\)と同じ形なので、この分割を再帰的に行って計算量を減らすことができる。
プログラム化
require 'complex' |
テスト:
if $0 == __FILE__ |
- O(N logN)
- 数式からプログラムに起こすのかなりてこずった…
- 部分集合を処理するために配列を分けなおしたり再帰したりと無駄なことしてるけど、いちおう要素数を2倍にしても処理時間は4倍にはなってなくてFFTできてる模様
- 高速フーリエ変換 - [物理のかぎしっぽ]
- FFT (高速フーリエ・コサイン・サイン変換) の概略と設計法
- 要素の数が2のべき乗じゃなかったらどうするのか
うまく説明できないので理解したい方は本を参照してください(^^;;