Try   HackMD

最下位bit列から状態を復元するアルゴリズムの実装

逆関数の考察

復元が可能であることの数学的な保証

具体的にはどうすればいいの? って話です。
つい最近、実用方面でも重要になりましたね。

数年前に書いた記事では計算をこねくり回していましたが、要するに『最下位bitの生成に使われる係数列は行列の最下段』であることと、『それを並べた行列が「128回分の最下位bit列をベクトルとして生成する」行列になること』、そしてその行列が可逆であることが重要なので、各基底

ω0, ω1, , ω127について
Ti
を作用させたベクトルを並べて行列を作り、その逆行列を求めればよいことになる。

[y0y1y127]=[a0 0a0 1a0 127a1 0a1 1a1 127a127 0a127 1a127 127][x0x1x127]

のとき、

y0=[a0 0a0 1a0 127][x0x1x127](=a0 0x0+a0 1x1++a0 127x127)

で、この

(a0 0, a0 1, , a0 127)が、元の行列のうち、『次の内部状態の最下位bitの生成に関わる部分』のすべてになります。この
(ai 0, ai 1, , ai 127)
を128個集めて並べ、行列を作るのが目標です。

しかし、今行列として表現されている

Tは、処理上はビット整数に対するビットローテートやxorとして表現されており、行列として表しなおすのは得策ではありません。

そこで、遷移関数を作用させて得られる値(=更新後の内部状態)を使って

(ai 0, ai 1, , ai 127)を得ることを考えます。

ここでベクトル空間の性質が活きます。

[x0x1x127]=[x000]+[0x10]++[00x127]
と分解することができます(以下、
xi
以外の要素が
0
になっているベクトルを
xi
と表します)。さらに、これら個々に遷移関数を作用させた結果を足し合わせれば、
x
に遷移関数を作用させたのと同じく
y
になるのです。
ベクトルの和は各成分ごとの和になるので、各
f(xi)
の第0成分を足し合わせれば
y0
が得られることになります。これは
f2, f3
についても同様です。

以上を実装したものがこちら。

最初に実装したやつ(gist)

SwShRNGLibraryに組み込んだやつ、前処理が不要なので実行速度的にはたぶんこっちのほうが有利(github)