1 /******************************************************************************* 2 copyright: Copyright (c) 2008. Fawzi Mohamed 3 license: BSD style: $(LICENSE) 4 version: Initial release: July 2008 5 author: Fawzi Mohamed 6 *******************************************************************************/ 7 module tango.math.random.engines.KISS; 8 private import Integer = tango.text.convert.Integer; 9 10 /+ Kiss99 random number generator, by Marisaglia 11 + a simple RNG that passes all statistical tests 12 + This is the engine, *never* use it directly, always use it though a RandomG class 13 +/ 14 struct Kiss99{ 15 private uint kiss_x = 123456789; 16 private uint kiss_y = 362436000; 17 private uint kiss_z = 521288629; 18 private uint kiss_c = 7654321; 19 private uint nBytes = 0; 20 private uint restB = 0; 21 22 enum int canCheckpoint=true; 23 enum int canSeed=true; 24 25 void skip(uint n){ 26 for (int i=n;i!=n;--i){ 27 next(); 28 } 29 } 30 ubyte nextB(){ 31 if (nBytes>0) { 32 ubyte res=cast(ubyte)(restB & 0xFF); 33 restB >>= 8; 34 --nBytes; 35 return res; 36 } else { 37 restB=next(); 38 ubyte res=cast(ubyte)(restB & 0xFF); 39 restB >>= 8; 40 nBytes=3; 41 return res; 42 } 43 } 44 uint next(){ 45 enum ulong a = 698769069UL; 46 ulong t; 47 kiss_x = 69069*kiss_x+12345; 48 kiss_y ^= (kiss_y<<13); kiss_y ^= (kiss_y>>17); kiss_y ^= (kiss_y<<5); 49 t = a*kiss_z+kiss_c; kiss_c = cast(uint)(t>>32); 50 kiss_z=cast(uint)t; 51 return kiss_x+kiss_y+kiss_z; 52 } 53 ulong nextL(){ 54 return ((cast(ulong)next())<<32)+cast(ulong)next(); 55 } 56 57 void seed(scope uint delegate() r){ 58 kiss_x = r(); 59 for (int i=0;i<100;++i){ 60 kiss_y=r(); 61 if (kiss_y!=0) break; 62 } 63 if (kiss_y==0) kiss_y=362436000; 64 kiss_z=r(); 65 /* Don’t really need to seed c as well (is reset after a next), 66 but doing it allows to completely restore a given internal state */ 67 kiss_c = r() % 698769069; /* Should be less than 698769069 */ 68 nBytes = 0; 69 restB=0; 70 } 71 /// writes the current status in a string 72 immutable(char)[] toString(){ 73 char[] res=new char[6+6*9]; 74 int i=0; 75 res[i..i+6]="KISS99"; 76 i+=6; 77 foreach (val;[kiss_x,kiss_y,kiss_z,kiss_c,nBytes,restB]){ 78 res[i]='_'; 79 ++i; 80 Integer.format(res[i..i+8],val,cast(char[])"x8"); 81 i+=8; 82 } 83 assert(i==res.length,"unexpected size"); 84 return cast(immutable(char)[])res; 85 } 86 /// reads the current status from a string (that should have been trimmed) 87 /// returns the number of chars read 88 size_t fromString(const(char[]) s){ 89 size_t i=0; 90 assert(s[i..i+4]=="KISS","unexpected kind, expected KISS"); 91 assert(s[i+4..i+7]=="99_","unexpected version, expected 99"); 92 i+=6; 93 foreach (val;[&kiss_x,&kiss_y,&kiss_z,&kiss_c,&nBytes,&restB]){ 94 assert(s[i]=='_',"no separator _ found"); 95 ++i; 96 size_t ate; 97 *val=cast(uint)Integer.convert(s[i..i+8],16,&ate); 98 assert(ate==8,"unexpected read size"); 99 i+=8; 100 } 101 return i; 102 } 103 }