123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
|
/*******************************************************************************
copyright: Copyright (c) 2008. Fawzi Mohamed
license: BSD style: $(LICENSE)
version: Initial release: July 2008
author: Fawzi Mohamed
*******************************************************************************/
module tango.math.random.engines.KISS;
private import Integer = tango.text.convert.Integer;
/+ Kiss99 random number generator, by Marisaglia
+ a simple RNG that passes all statistical tests
+ This is the engine, *never* use it directly, always use it though a RandomG class
+/
struct Kiss99{
private uint kiss_x = 123456789;
private uint kiss_y = 362436000;
private uint kiss_z = 521288629;
private uint kiss_c = 7654321;
private uint nBytes = 0;
private uint restB = 0;
enum int canCheckpoint=true;
enum int canSeed=true;
void skip(uint n){
for (int i=n;i!=n;--i){
next();
}
}
ubyte nextB(){
if (nBytes>0) {
ubyte res=cast(ubyte)(restB & 0xFF);
restB >>= 8;
--nBytes;
return res;
} else {
restB=next();
ubyte res=cast(ubyte)(restB & 0xFF);
restB >>= 8;
nBytes=3;
return res;
}
}
uint next(){
enum ulong a = 698769069UL;
ulong t;
kiss_x = 69069*kiss_x+12345;
kiss_y ^= (kiss_y<<13); kiss_y ^= (kiss_y>>17); kiss_y ^= (kiss_y<<5);
t = a*kiss_z+kiss_c; kiss_c = cast(uint)(t>>32);
kiss_z=cast(uint)t;
return kiss_x+kiss_y+kiss_z;
}
ulong nextL(){
return ((cast(ulong)next())<<32)+cast(ulong)next();
}
void seed(scope uint delegate() r){
kiss_x = r();
for (int i=0;i<100;++i){
kiss_y=r();
if (kiss_y!=0) break;
}
if (kiss_y==0) kiss_y=362436000;
kiss_z=r();
/* Don’t really need to seed c as well (is reset after a next),
but doing it allows to completely restore a given internal state */
kiss_c = r() % 698769069; /* Should be less than 698769069 */
nBytes = 0;
restB=0;
}
/// writes the current status in a string
immutable(char)[] toString(){
char[] res=new char[6+6*9];
int i=0;
res[i..i+6]="KISS99";
i+=6;
foreach (val;[kiss_x,kiss_y,kiss_z,kiss_c,nBytes,restB]){
res[i]='_';
++i;
Integer.format(res[i..i+8],val,cast(char[])"x8");
i+=8;
}
assert(i==res.length,"unexpected size");
return cast(immutable(char)[])res;
}
/// reads the current status from a string (that should have been trimmed)
/// returns the number of chars read
size_t fromString(const(char[]) s){
size_t i=0;
assert(s[i..i+4]=="KISS","unexpected kind, expected KISS");
assert(s[i+4..i+7]=="99_","unexpected version, expected 99");
i+=6;
foreach (val;[&kiss_x,&kiss_y,&kiss_z,&kiss_c,&nBytes,&restB]){
assert(s[i]=='_',"no separator _ found");
++i;
size_t ate;
*val=cast(uint)Integer.convert(s[i..i+8],16,&ate);
assert(ate==8,"unexpected read size");
i+=8;
}
return i;
}
}
|