今回は高速アダマール変換を見ていきます。 アダマール変換 (Hadamard Transform) は、昔 CPU パワーが充分でなかったときにフーリエ変換がコストのかかる計算だったので、その代替としてよく使われていたそうですが、最近はあまり使われてないみたいですね*1。
この記事では、変換データ数が少ない場合にどのように変換されているかを簡単に見るだけにします。 高速アダマール変換を表すクラス FastHadamardTransformer は前回みた RealTransformer インターフェースを実装しています。 また、変換データ数(transform() メソッドに渡す double の配列の要素数)は、FastFourierTransformer や FastSineTransformer と同じく、2 の累乗 (2, 4, 8, ・・・)でなければなりません。
N=2
データ数が2の場合は手で計算できるレベルのものです。 変換を表にするとx | y |
---|---|
x0 | y0 = x0 + x1 |
x1 | y1 = x0 - x1 |
この変換は1次変換なので、行列を使って表すことができます(便利かどうかは別にして:-P):
と定義して、変換行列を とすると
と表すことができます。 2×2行列なら簡単に逆行列が求まって、
となります。
N=4
次はデータ数が4の場合。 x から y への変換ですが、間に a という変数を挟むとどんな変換が行われているか分かりやすいですね。 N が増えたときにどのように拡張されているかも分かると思います:x | a | y |
---|---|---|
x0 | a0 = x0 + x1 | y0 = a0 + a1 |
x1 | a1 = x2 + x3 | y1 = a2 + a3 |
x2 | a2 = x0 - x1 | y2 = a0 - a1 |
x3 | a3 = x2 - x3 | y3 = a2 - a3 |
変換を行列で表すとこうなります:
ただ、要素を書き下すだけでももう限界。
N=8
データ数が 8 の場合。 書くのは面倒だけど、やってることはそんなに難しくないかと。x | a | b | y |
---|---|---|---|
x0 | a0 = x0 + x1 | b0 = a0 + a1 | y0 = b0 + b1 |
x1 | a1 = x2 + x3 | b1 = a2 + a3 | y1 = b2 + b3 |
x2 | a2 = x4 + x5 | b2 = a4 + a5 | y2 = b4 + b5 |
x3 | a3 = x6 + x7 | b3 = a6 + a7 | y3 = b6 + b7 |
x4 | a4 = x0 - x1 | b4 = a0 - a1 | y4 = b0 - b1 |
x5 | a5 = x2 - x3 | b5 = a2 - a3 | y5 = b2 - b3 |
x6 | a6 = x4 - x5 | b6 = a4 - a5 | y6 = b4 - b5 |
x7 | a7 = x6 - x7 | b7 = a6 - a7 | y7 = b6 - b7 |
行列表現は面倒なので書きません。
*1:もっと一般化して使われてるのかな?