Xorshift

提供: testwiki
ナビゲーションに移動 検索に移動

Xorshift疑似乱数列生成法の1つである。George Marsaglia(w:George Marsaglia)が2003年に提案した。演算が排他的論理和ビットシフトのみであるため高速である[1] などの特徴がある。

実装例

Xorshiftアルゴリズム[2]Cによる実装例[3]:

#include <stdint.h>

struct xorshift32_state {
  uint32_t a;
};

/* The state word must be initialized to non-zero */
uint32_t xorshift32(struct xorshift32_state *state)
{
	/* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */
	uint32_t x = state->a;
	x ^= x << 13;
	x ^= x >> 17;
	x ^= x << 5;
	return state->a = x;
}

struct xorshift64_state {
  uint64_t a;
};

uint64_t xorshift64(struct xorshift64_state *state)
{
	uint64_t x = state->a;
	x ^= x << 13;
	x ^= x >> 7;
	x ^= x << 17;
	return state->a = x;
}

struct xorshift128_state {
  uint32_t x[4];
};

/* The state array must be initialized to not be all zero */
uint32_t xorshift128(struct xorshift128_state *state)
{
	/* Algorithm "xor128" from p. 5 of Marsaglia, "Xorshift RNGs" */
	uint32_t t  = state->x[3];
    
    uint32_t s  = state->x[0];  /* Perform a contrived 32-bit shift. */
	state->x[3] = state->x[2];
	state->x[2] = state->x[1];
	state->x[1] = s;

	t ^= t << 11;
	t ^= t >> 8;
	return state->x[0] = t ^ s ^ (s >> 19);
}

/* The Xorshift128 algorithm can be reworded to use a pair of uint64_t state,
   or for systems with such support, a uint128_t state. */

このアルゴリズムの周期はそれぞれ2321,2641,2961,21281 で、テンプレート:仮リンクをパスしている。

64ビット整数を効率よく扱える計算機では、xor,shift操作の組を3つから2つにして計算負荷を減らしても、周期は2641に保たれる。[4]

struct xorshift64_state {
  uint64_t a;
};

uint64_t xorshift64(struct xorshift64_state *state)
{
	uint64_t x = state->a;
	x ^= x << 7;
	x ^= x >> 9;
	return state->a = x;
}

周期の特定

シード値を128bitの二元横ベクトルβ、現在の状態から次状態への二元遷移行列をTと置くと、Xorshiftアルゴリズムにより生成される乱数列はβ,βT,βT2,と表される。詳しい証明は省略するが[2]、行列TのOrderがk=2n1で表される時、かつその時に限り、任意の0でないβに対しβ,βT,βT2,,βTk1は全て異なる値となる。

予備的なテストとしては、今周期kについてk=2n1となることを期待しているため、期待するnT2n=Tを満たす最小のnであるかを調べる、というものがある。これはTn回二乗すれば良いため、乱数列を調べるのと比較すると十分に速く調べられる。

完全なテストとしては、期待する周期

k

の約数

d

について

TdIkd

を示せば良い。例えば、

n

bitのビット列

x

に対する操作が

x ^= x << a;
x ^= x >> b;
x ^= x << c;
return x;

である場合、

T=(I+La)(I+Rb)(I+Lc)

である。但し、

Li,ja={1i=j+a0otherwise

及び

Ri,ja={1i=ja0otherwise

である。

n=32の場合、TdId={65535167119352526451358589934591431655765及びT232=Tを調べれば十分である。

n=64の場合、2641641の倍数であるということに注意すると、TdId={27530740360952814706818088952877807187786201571777214294589695108510259257115009536893488147419103236148914691236517205及びT264=Tを調べれば十分である。

別の例としては

t = x ^ (x << 11);
x = y; y = z; z = w;
return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));

に対しては

(xn+1yn+1zn+1wn+1)=(xnynznwn)T

のように立式し、

T=(OOO(I+L11)(I+R8)IOOOOIOOOOI(I+R19))

について同様に解く。各変数が32 bitだとすれば

n=128

, 64 bitだとすれば

n=256

であり、対応する

d

は以下の表のようになる。

n 32 64 128 256
d 0x0000ffff 0x00000280fffffd7f 0x0000000000042f00fffffffffffbd0ff 0x000000000000000000d3eafc3af14600ffffffffffffffffff2c1503c50eb9ff
0x00ff00ff 0x0000ffff0000ffff 0x00000280fffffd7f00000280fffffd7f 0x000000000000013540775b48cc32ba00fffffffffffffecabf88a4b733cd45ff
0x0f0f0f0f 0x00663d80ff99c27f 0x00003d30f19cd100ffffc2cf0e632eff 0x0000000000042f00fffffffffffbd0ff0000000000042f00fffffffffffbd0ff
0x33333333 0x00ff00ff00ff00ff 0x0000ffff0000ffff0000ffff0000ffff 0x00000280fffffd7f00000280fffffd7f00000280fffffd7f00000280fffffd7f
0x55555555 0x0f0f0f0f0f0f0f0f 0x00663d80ff99c27f00663d80ff99c27f 0x00003d30f19cd100ffffc2cf0e632eff00003d30f19cd100ffffc2cf0e632eff
0x3333333333333333 0x00ff00ff00ff00ff00ff00ff00ff00ff 0x0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff
0x5555555555555555 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 0x00663d80ff99c27f00663d80ff99c27f00663d80ff99c27f00663d80ff99c27f
0x33333333333333333333333333333333 0x00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff
0x55555555555555555555555555555555 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f
0x3333333333333333333333333333333333333333333333333333333333333333
0x5555555555555555555555555555555555555555555555555555555555555555

脚注

テンプレート:Reflist

参考文献

テンプレート:Applied-math-stub

  1. 2003年の論文執筆時点で、1800MHzのPCで毎秒2.2億個の擬似乱数を生成できた。
  2. 2.0 2.1 Marsaglia, 2003
  3. Cでは "^" は排他的論理和を、"<<" と ">>" はビットシフトを表す。
  4. テンプレート:Cite web 但し、周期が保たれる組み合わせは(7,9)と(9,7)のみである。