良い xorshift、悪い xorshift

| ← back |
| home |

長周期の擬似乱数生成手法とメルセンヌ・ツイスタの無駄知識(?)の紹介は別のページにあります. 簡易な長周期擬似乱数の合成手法 知らなくても不都合は無いメルセンヌ・ツイスタの知識


オマケとしてページ末尾で32bit/64bit xorshift向けのレジスタ初期値(seed)生成プログラムをご紹介しています.
(2023.1.8 初期値生成に使っているM系列信号を性質の良いものに変えました)


特性の良い xorshift のパラメータ (a, b, c)

視覚的に xorshift の特性の違いが分かるサンプル・プログラム
/' (c) 2021 cepstrum.co.jp '/
' FreeBASIC GUI program
' >fbc -s gui
'--------------------------------------------------------------------------
' xorshift random number generator

function uint_xorshift(a as uinteger, b as uinteger, c as uinteger) as uinteger<32>
  static r as uinteger<32> = &Hffffffff

  r=r xor (r shl a)
  r=r xor (r shr b)
  r=r xor (r shl c)
  return r
end function

'--------------------------------------------------------------------------

dim x    as uinteger
dim y    as uinteger
dim dotc as uinteger
dim a    as uinteger = 5
dim b    as uinteger = 17
dim c    as uinteger = 13
dim shft as uinteger = 1

screenres 1024, 1024

sleep 300
while inkey$<>""
wend

while inkey$=""
  x   =(uint_xorshift(a, b, c) shr shft) mod 1024
  y   =(uint_xorshift(a, b, c) shr shft) mod 1024
  dotc=(uint_xorshift(a, b, c) shr shft) mod 64
  line (x, y)-(x, y), dotc
wend



メルセンヌ・ツイスタ(MT19937)が大きすぎて使えないというのなら、TinyMTを使えば良いのに

40年前の論文の指摘

『良いパラメータ』の意味

M系列信号の常識・M系列信号を使っている人の常識

32bit/64bit xorshift向けのレジスタ初期値(seed)生成プログラム
/* (c) 2023 cepstrum.co.jp */

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

//-----------------------------------------------------------------
// M-sequence generater, return value = 0/1

unsigned mseq16bit(unsigned seed) {
  static uint16_t reg16bit=0x5a5a;
  uint16_t        msb;
  unsigned char   b0, b2, b3, b5;

  if (seed!=0) reg16bit=seed&0xffff;     // change seed value

  b0=reg16bit&0x1;
  b2=(reg16bit>>2)&0x1;
  b3=(reg16bit>>3)&0x1;
  b5=(reg16bit>>5)&0x1;
  msb=(b0^b2^b3^b5)&0x1;
  reg16bit=(reg16bit>>1)&0x7fff;
  reg16bit=reg16bit|(msb<<15);
  return msb;
}

//-----------------------------------------------------------------
// generate 32bit seed (register initial value) for 32bit xorshift

uint32_t gen32bit_seed(unsigned mseq_seed) {
  uint32_t seed;
  unsigned i;

  mseq16bit(mseq_seed);    // set M-sequence seed
  seed=0;
  for (i=0; i<16; i=i+1) mseq16bit(0);
  for (i=0; i<16; i=i+1) seed=(seed<<1)|mseq16bit(0);
  for (i=0; i<16; i=i+1) mseq16bit(0);
  for (i=0; i<16; i=i+1) seed=(seed<<1)|mseq16bit(0);
  return seed;
}

//-----------------------------------------------------------------
// generate 64bit seed (register initial value) for 64bit xorshift

uint64_t gen64bit_seed(unsigned mseq_seed) {
  uint64_t seed;
  unsigned i;

  mseq16bit(mseq_seed);    // set M-sequence seed
  seed=0;
  for (i=0; i<16; i=i+1) mseq16bit(0);
  for (i=0; i<16; i=i+1) seed=(seed<<1)|mseq16bit(0);
  for (i=0; i<16; i=i+1) mseq16bit(0);
  for (i=0; i<16; i=i+1) seed=(seed<<1)|mseq16bit(0);
  for (i=0; i<16; i=i+1) mseq16bit(0);
  for (i=0; i<16; i=i+1) seed=(seed<<1)|mseq16bit(0);
  for (i=0; i<16; i=i+1) mseq16bit(0);
  for (i=0; i<16; i=i+1) seed=(seed<<1)|mseq16bit(0);
  return seed;
}

//-----------------------------------------------------------------
// test gen32bit_seed() function

int main() {
  int i;
  int iteration=20;

  for (i=0; i<iteration; i=i+1) printf("A %3i %#010x\n", i, gen32bit_seed(0));

  for (i=0; i<iteration; i=i+1) printf("B %3i %#010x\n", i, gen32bit_seed(i+1));

  gen32bit_seed(123456);  // set new M-sequence seed
  for (i=0; i<iteration; i=i+1) printf("C %3i %#010x\n", i, gen32bit_seed(0));

  gen32bit_seed(time(NULL)&0xffff);  // set new M-sequence seed
  for (i=0; i<iteration; i=i+1) printf("D %3i %#010x\n", i, gen32bit_seed(0));

  /*
  for (i=0; i<iteration; i=i+1) printf("a %3i %10u\n", i, gen32bit_seed(0));

  for (i=0; i<iteration; i=i+1) printf("b %3i %10u\n", i, gen32bit_seed(i+1));

  gen32bit_seed(123456);  // set new M-sequence seed
  for (i=0; i<iteration; i=i+1) printf("c %3i %10u\n", i, gen32bit_seed(0));

  gen32bit_seed(time(NULL)&0xffff);  // set new M-sequence seed
  for (i=0; i<iteration; i=i+1) printf("d %3i %10u\n", i, gen32bit_seed(0));
  */
}
A   0 0x07e002b6
A   1 0xbad8c213
A   2 0x535dc645
A   3 0x4f9219fe
A   4 0x071adb05
A   5 0x7c50eef1
A   6 0xf4c69145
A   7 0x8329dc05
A   8 0x14309aa3
A   9 0x2b1a36ed
A  10 0xaa94f6ce
A  11 0x2167f0f3
A  12 0x1b112949
A  13 0x90211f37
A  14 0xf8da28df
A  15 0xdb1bc05b
A  16 0x786e5c43
A  17 0x0b74b17f
A  18 0x0c6977ce
A  19 0x864d4450
B   0 0x045113d3
B   1 0x822889e9
B   2 0x86799a3a
B   3 0x45455727
B   4 0x411444f4
B   5 0xc76ddece
B   6 0xc33ccd1d
B   7 0x26f33840
B   8 0x22a22b93
B   9 0xa4dbb1a9
B  10 0xa08aa27a
B  11 0x63b66f67
B  12 0x67e77cb4
B  13 0xe19ee68e
B  14 0xe5cff55d
B  15 0x13791c20
B  16 0x17280ff3
B  17 0x915195c9
B  18 0x9500861a
B  19 0x563c4b07
C   0 0x62c6e599
C   1 0x7b9844fd
C   2 0x87cb24d6
C   3 0x08375b24
C   4 0x64cd2e6b
C   5 0xfd68d0c5
C   6 0xf3c72124
C   7 0xd0dc9a24
C   8 0x41cf1321
C   9 0xdfb20298
C  10 0xd867da15
C  11 0x551c33f6
C  12 0x52cbe3d8
C  13 0x90fe59a4
C  14 0x7386b332
C  15 0x0d7454f2
C  16 0xdf4bd7d9
C  17 0x76068ca7
C  18 0xe47f4312
C  19 0xfcd45541
D   0 0x0de90ead
D   1 0xf2856c55
D   2 0xd13e75bc
D   3 0x677b22ba
D   4 0x980b3692
D   5 0x62615ac4
D   6 0xaaba4791
D   7 0x396173d3
D   8 0xeea227e5
D   9 0x6a0754c5
D  10 0x7a7baf34
D  11 0x86d83c82
D  12 0xbdd97272
D  13 0x00a88064
D  14 0x1a6d907c
D  15 0xf3b2ef70
D  16 0x0ea3c22a
D  17 0x80bd5240
D  18 0xcaf31694
D  19 0x14efdc30
mseq_seed  gen32bit_seed(mseq_seed)
-----------------------------------
0x0001     0x045113d3
0x0002     0x822889e9
0x0004     0x45455727
0x0008     0x26f33840
0x0010     0x13791c20
0x0020     0x8ded9dc3
0x0040     0x46f64ee1
0x0080     0xa37ba770
0x0100     0x51bdd3b8
0x0200     0x28dee9dc
0x0400     0x146ff4ee
0x0800     0x8a377a77
0x1000     0x451b3d3b
0x2000     0x228d9e9d
0x4000     0x11464f4e
0x8000     0x08a327a7

English page is here

| ← back | ↑top |

| home |