-----------------------
#define UL
unsigned long
#define znew
((z=36969*(z&65535)+(z>>16))<<16)
#define wnew
((w=18000*(w&65535)+(w>>16))&65535)
#define MWC
(znew+wnew)
#define SHR3
(jsr=(jsr=(jsr=jsr^(jsr<<17))^(jsr>>13))^(jsr<<5))
#define CONG
(jcong=69069*jcong+1234567)
#define KISS
((MWC^CONG)+SHR3)
#define LFIB4
(t[c]=t[c]+t[c+58]+t[c+119]+t[++c+178])
#define SWB
(t[c+237]=(x=t[c+15])-(y=t[++c]+(xbr>
#define UNI (KISS*2.328306e-10)
#define VNI
((long) KISS)*4.656613e-10
/* Variables
estáticas globales */
static UL
z=362436069, w=521288629, jsr=123456789, jcong=380116160;
static UL
t[256];
static UL
x=0,y=0; static unsigned char c=0;
/* Deben usarse
semillas aleatorias para iniciar z,w,jsr,jcong y
la tabla t[256].
Por ejemplo usando KISS: */
void settable(UL
i1,UL i2,UL i3,UL i4)
{ int i; z=i1;w=i2,jsr=i3;
jcong=i4;
for(i=0;i<256;i++)
t[i]=KISS; }
------------------------------
Fin del código C.
Basta colocar las 17 líneas de
código al comienzo de tu programa, inicializar la tabla
y tener varios RNG muy prometedores.
Posiblemente quieras cambiar los nombres
de las variables z, w, x, y, t, c por algunos más largos
para evitar el conflicto con otras con el mismo nombre en tu código.
Los generadores KISS,
MWC, LFIB4, SWB,
SHR3 y CONG proporcionan un
entero aleatorio de 32 bits. UNI produce una
distribución uniforme en (0,1), VNI hace
lo mismo en (-1,1).
Si quieres un generador de periodo astronómicamente
grande KISS+SWB tiene un periodo
mayor de 27700!!
El generador KISS (keep
it simple stupid) combina los dos generadores de multiplicacion
con acarreo en MWC con los tres registros de desplazamiento en
SHR3 y el generador congruencial CONG usando la suma y XOR. Período
aproximado 2123.
El generador MWC concatena
dos generadores de 16 bits del tipo multiplicacion con acarreo,
x(n)=36969x(n-1)+carry, y(n)=18000y(n-1)+carry mod 216.
Tiene un periodo de 260 aproximadamente y al parecer
pasa todos los tests de aleatoriedad. Interesante por sí
solo aunque sea parte de KISS.
SHR3 es un generador
con tres registros de desplazamiento con periodo 232-1 . Usa
y(n)=y(n-1)(I+L17)(I+R13)(I+L5) con las y's vistas como vectores
binarios, L la matriz binaria de orden 32x32 que desplaza un vector
a la izquierda 1 y R su transpuesta.
SHR3 pasa todos los tests excepto el de rango
binario pues 32 valores sucesivos vistos como vectores binarios
deben ser linealmente independientes, mientras 32 enteros aleatorios
de 32 bits , serán independientes solo el 29% de las veces.
CONG es un generador
congruencial con el muy popular multiplicador 69069: x(n)=69069x(n-1)+1234567.
Tiene periodo 232. La mitad superior de sus 32 bits pasan bien
los test de aleatoriedad pero los 32 inferiores parecen ser demasiado
regulares.
LFIB4 es una extension
de la clase anteriormente definida como generadores retrasados
(lagged) de Fibonacci: x(n)=x(n-r) op x(n-s) donde las x's pertenecen
a un conjunto finito donde hay definida una operación binaria
como + o - en los enteros módulo 232, o como
* en los enteros impares citados o la operacion XOR en los vectores
binarios. Excepto los que usan multiplicaciones este tipo de generadores
fallan varios tests de aleatoriedad excepto si los retrasos (lags)
son muy largos. Marsaglia ha desarrollado el generador con 4 retrasos
LFIB4, x(n)=x(n-256)+x(n-179)+x(n-119)+x(n-55) mod232.
Tiene de periodo 231*(2256-1) o aproximadamente 2287 y parece
pasar todos los tests. Combinado con KISS produce un periodo de
2410, basta usar KISS+LFIB4 en cualquier expresión C.
SWB es un generador
de resta con acarreo desarrollado para mostrar que un método
simple puede producir periodos muy largos. x(n)=x(n-222)-x(n-237)-acarreo
mod 232. El acarreo es 0 excepto cuando calcular x(n-1) produjo
un overflow en cuyo caso estará a 1. Este generador tiene
un periodo MUY largo 27098(2480-1), aproximadamente 27578 Parece
pasar todos los test de aleatoriedad pero Marsaglia recomienda
combinarlo con KISS, MWC, SHR3 o CONG.
Finalmente, UNI
y VNI se emplean cuando se necesitan números
reales en el intervalo (0,1) o el (-1,1) respectivamente.
Los procedimientos MWC,
SHR3, CONG, KISS, LFIB4, SWB, UNI y VNI permiten insertarse directamente
en cualquier expresión C evitando la carga de tiempo y
espacio que lleva una función ordinaria. Las variables
globales z, w, jsr y jcong deben tener valores asignados previamente.
Si se usan LFIB4 o SWB
debe haberse inicializado anteriormente la tabla t[256].