![]() |
![]() |
|
長周期の擬似乱数生成手法とメルセンヌ・ツイスタの無駄知識(?)の紹介は別のページにあります. 簡易な長周期擬似乱数の合成手法 知らなくても不都合は無いメルセンヌ・ツイスタの知識
オマケとしてページ末尾で32bit/64bit xorshift向けのレジスタ初期値(seed)生成プログラムをご紹介しています.
オマケのオマケとして擬似乱数の初期値としてtime()関数で得られる値(カウントアップするUTCの経過秒数)を用いる場合に、値を置換・攪拌・ランダム化する処理もご紹介しています. . . . .
2025.3.6 time() 関数と RDTSC (ReaD Time Stamp Counter) 命令を併用した初期値生成プログラム rdtsc.c を少し手直ししました.
特性の良い xorshift のパラメータ (a, b, c) |
視覚的に xorshift の特性の違いが分かるサンプル・プログラム |
/' (c) 2021, 2005 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 a as uinteger = 3 dim b as uinteger = 13 dim c as uinteger = 7 dim sft as uinteger = 9 screenres 1024, 1024 while inkey$<>""; wend sleep 300 while inkey$=""; x=(uint_xorshift(a, b, c) shr sft) mod 1024 y=(uint_xorshift(a, b, c) shr sft) mod 1024 line (x, y)-(x, y), (uint_xorshift(a, b, c) shr sft) mod 64 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 B 0 0x045113d3 C 0 0x62c6e599 D 0 0x0de90ead A 1 0xbad8c213 B 1 0x822889e9 C 1 0x7b9844fd D 1 0xf2856c55 A 2 0x535dc645 B 2 0x86799a3a C 2 0x87cb24d6 D 2 0xd13e75bc A 3 0x4f9219fe B 3 0x45455727 C 3 0x08375b24 D 3 0x677b22ba A 4 0x071adb05 B 4 0x411444f4 C 4 0x64cd2e6b D 4 0x980b3692 A 5 0x7c50eef1 B 5 0xc76ddece C 5 0xfd68d0c5 D 5 0x62615ac4 A 6 0xf4c69145 B 6 0xc33ccd1d C 6 0xf3c72124 D 6 0xaaba4791 A 7 0x8329dc05 B 7 0x26f33840 C 7 0xd0dc9a24 D 7 0x396173d3 A 8 0x14309aa3 B 8 0x22a22b93 C 8 0x41cf1321 D 8 0xeea227e5 A 9 0x2b1a36ed B 9 0xa4dbb1a9 C 9 0xdfb20298 D 9 0x6a0754c5 A 10 0xaa94f6ce B 10 0xa08aa27a C 10 0xd867da15 D 10 0x7a7baf34 A 11 0x2167f0f3 B 11 0x63b66f67 C 11 0x551c33f6 D 11 0x86d83c82 A 12 0x1b112949 B 12 0x67e77cb4 C 12 0x52cbe3d8 D 12 0xbdd97272 A 13 0x90211f37 B 13 0xe19ee68e C 13 0x90fe59a4 D 13 0x00a88064 A 14 0xf8da28df B 14 0xe5cff55d C 14 0x7386b332 D 14 0x1a6d907c A 15 0xdb1bc05b B 15 0x13791c20 C 15 0x0d7454f2 D 15 0xf3b2ef70 A 16 0x786e5c43 B 16 0x17280ff3 C 16 0xdf4bd7d9 D 16 0x0ea3c22a A 17 0x0b74b17f B 17 0x915195c9 C 17 0x76068ca7 D 17 0x80bd5240 A 18 0x0c6977ce B 18 0x9500861a C 18 0xe47f4312 D 18 0xcaf31694 A 19 0x864d4450 B 19 0x563c4b07 C 19 0xfcd45541 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
time()関数で得た値のランダム化(その1) : S-boxを用いた攪拌 |
/* generate 32bit seed value of random number generator */ /* from time() and AES S-box conversion */ /* (c) 2025 cepstrum.co.jp */ #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <time.h> //------------------------------------------------------------------- unsigned aes_sbox[256]={ // AES S-box table 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0e32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; //------------------------------------------------------------------- // apply S-box conversion to 32bit data unsigned sbox_conv(unsigned x) { unsigned y=0; y=y|(aes_sbox[(x>> 0)&0xff]<< 0); y=y|(aes_sbox[(x>> 8)&0xff]<< 8); y=y|(aes_sbox[(x>>16)&0xff]<<16); y=y|(aes_sbox[(x>>24)&0xff]<<24); return y; } //------------------------------------------------------------------- // apply double S-box conversion to 32bit data unsigned sbox_double_conv(unsigned x) { unsigned y; unsigned p, q; // 1st S-box conversion p=sbox_conv(x); // shuffle (bit reverse like block shuffle) q=0; q=q|( p &0x0000000f); q=q|((p>>12)&0x000000f0); q=q|( p &0x00000f00); q=q|((p>>12)&0x0000f000); q=q|((p<<12)&0x000f0000); q=q|( p &0x00f00000); q=q|((p<<12)&0x0f000000); q=q|( p &0xf0000000); // 2nd S-box conversion y=sbox_conv(q); return y; } //------------------------------------------------------------------- int main() { unsigned seed1, seed2; unsigned long long lu=0; // unsigned 64bit unsigned long long zlu; // unsigned 64bit while(1) { // forever loop (don't stop) do { zlu=lu; // save last time value lu=time(NULL); // read UTC time value } while (zlu==lu); // wait untile time change seed1=sbox_conv(lu&0xffffffff); // S-box conversion seed2=sbox_double_conv(lu&0xffffffff); // double S-box conversion printf("time=%10u seed1=%10u(0x%08X) seed2=%10u(0x%08X)\n", lu&0xffffffff, seed1, seed1, seed2, seed2); } }
..... time=1740788990 seed1=2233802939(0x852520BB) seed2= 334582585(0x13F15339) time=1740788991 seed1=2233802774(0x85252016) seed2= 335369137(0x13FD53B1) time=1740788992 seed1=2233859171(0x8525FC63) seed2=1945586413(0x73F74AED) time=1740788993 seed1=2233859196(0x8525FC7C) seed2=1942768202(0x73CC4A4A) time=1740788994 seed1=2233859191(0x8525FC77) seed2=1942768219(0x73CC4A5B) time=1740788995 seed1=2233859195(0x8525FC7B) seed2=1942768185(0x73CC4A39) time=1740788996 seed1=2233859314(0x8525FCF2) seed2=1930775040(0x73154A00) time=1740788997 seed1=2233859179(0x8525FC6B) seed2=1945586233(0x73F74A39) time=1740788998 seed1=2233859183(0x8525FC6F) seed2=1945586383(0x73F74ACF) time=1740788999 seed1=2233859269(0x8525FCC5) seed2=1936804604(0x73714AFC) .....
/* generate 32bit seed value of random number generator */ /* (c) 2025 cepstrum.co.jp */ #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <time.h> //------------------------------------------------------------------- unsigned simple_mod(unsigned x) { return x=x+((x%3)<<2)-((x%5)<<4)+((x%7)<<6)+((x%11)<<8)-((x%13)<<10)+((x%17)<<12)-((x%19)<<14)+((x%23)<<16); } //------------------------------------------------------------------- int main() { unsigned seed; unsigned long long lu=0; // unsigned 64bit unsigned long long zlu; // unsigned 64bit while(1) { // forever loop (don't stop) do { zlu=lu; // save last time value lu=time(NULL); // read UTC time value } while (zlu==lu); // wait untile time change seed=simple_mod(lu); // simple conversion printf("time=%10u seed1=%10u(0x%08X)\n", lu&0xffffffff, seed, seed); } }
..... time=1741016530 seed1=1742030358(0x67D54616) time=1741016531 seed1=1742394187(0x67DAD34B) time=1741016532 seed1=1742446708(0x67DBA074) time=1741016533 seed1=1740991913(0x67C56DA9) time=1741016534 seed1=1741044446(0x67C63ADE) time=1741016535 seed1=1741097047(0x67C70857) time=1741016536 seed1=1741149132(0x67C7D3CC) time=1741016537 seed1=1741214977(0x67C8D501) time=1741016538 seed1=1741267498(0x67C9A22A) time=1741016539 seed1=1741320031(0x67CA6F5F) .....
time()関数で得た値のランダム化(その2) : timp stamp counterの値の併用 |
/* generate 32bit seed value of random number generator */ /* from time() and time stamp counter value */ /* for x64 processor and gcc */ /* use __rdtsc intrinsic for Microsoft compiler <intrin.h> */ /* (c) 2025 cepstrum.co.jp */ #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <time.h> //----------------------------------------------------- // execute RDTSC instruction and return time stamp counter value unsigned long long rdtsc(void) { unsigned long long lo, hi; __asm__ volatile ("rdtsc" : "=a" (lo), "=d" (hi)); return lo|(hi<<32); } //----------------------------------------------------- int main() { unsigned seed; // seed value for random number generator unsigned counter=0; // overflow counter unsigned long long lu1, lu2; // unsigned 64bit while(1) { // forever loop (don't stop) do { // time consuming loop counter=counter+8; // count up } while(counter!=0); // wait until counter overflow lu1=time(NULL); // read UTC time value lu2=rdtsc(); // read time stamp counter seed=(lu1^(lu2>>1))&0xffffffff; // generate 32bit seed value printf("time=%10u tsc=%10u seed=%10u(0x%08X)\n", lu1&0xffffffff, lu2&0xffffffff, seed, seed); } }
..... time=1741217650 tsc=3758225877 seed=2546475928(0x97C82398) time=1741217650 tsc= 3720435 seed=1741995275(0x67D4BD0B) time=1741217650 tsc= 546690075 seed=2005022079(0x7782357F) time=1741217650 tsc=1088356141 seed=1202168036(0x47A7A0E4) time=1741217650 tsc=1630275875 seed=1465834467(0x575EDBE3) time=1741217651 tsc=2171753907 seed= 661779882(0x2771F5AA) time=1741217651 tsc=2713111927 seed= 924039624(0x3713B9C8) time=1741217651 tsc=3261178399 seed= 116919932(0x06F80E7C) time=1741217651 tsc=3801389195 seed= 377656118(0x16829336) time=1741217652 tsc= 48018715 seed=3869672953(0xE6A685F9) time=1741217652 tsc= 609693231 seed=4125313123(0xF5E34863) time=1741217652 tsc=1150902331 seed=3313790825(0xC5846F69) time=1741217652 tsc=1694594115 seed=3578291541(0xD5486555) time=1741217652 tsc=2235925379 seed=2775195317(0xA56A1EB5) time=1741217653 tsc=2778729023 seed=3038304874(0xB518DA6A) time=1741217653 tsc=3319660111 seed=2233868370(0x85262052) time=1741217653 tsc=3866970143 seed=2499181434(0x94F67B7A) time=1741217653 tsc= 116817159 seed=1689510390(0x64B3E1F6) .....
内輪のジョークをネットで拡散するのは止めよう |
|
|
|