Articulo de referencia

Generador de números pseudoaleatorios con multiplicación y acarreo

En informática , la multiplicación con acarreo (MWC) es un método inventado por George Marsaglia [ 1 ] para generar secuencias de enteros aleatorios a partir de un conjunto inic...

En informática , la multiplicación con acarreo (MWC) es un método inventado por George Marsaglia [ 1 ] para generar secuencias de enteros aleatorios a partir de un conjunto inicial de entre dos y miles de valores semilla elegidos aleatoriamente. Implica aritmética de enteros computacional simple y conduce a la generación de alta velocidad de secuencias de números aleatorios con períodos inmensos (que van desde aproximadamente260{\displaystyle 2^{60}}a22,000,000{\displaystyle 2^{2,000,000}}); esas son sus principales ventajas.

Al igual que ocurre con todos los generadores de números pseudoaleatorios , las secuencias resultantes son funciones de los valores semilla proporcionados.

Teoría general

Un generador MWC es una forma especial de generador de números aleatorios de Lehmer.incógnitanorte=bincógnitanorte1modpag{\displaystyle x_{n}=bx_{n-1}{\bmod {p}}}lo que permite una implementación eficiente de un módulo primopag{\displaystyle p}mucho mayor que el tamaño de palabra de la máquina.

Las implementaciones normales del generador Lehmer eligen un módulo cercano al tamaño de palabra de la máquina. Un generador MWC, en cambio, mantiene su estado en base.b{\displaystyle b}, por lo tanto, multiplicando porb{\displaystyle b}se hace implícitamente desplazando una palabra. La baseb{\displaystyle b}Por lo general, se elige para que sea igual al tamaño de palabra de la computadora, ya que esto hace que la aritmética módulob{\displaystyle b}trivial. Esto puede variar deb=28{\displaystyle b=2^{8}}para un microcontrolador ab=264{\displaystyle b=2^{64}}. (Este artículo utilizab=232{\displaystyle b=2^{32}}por ejemplo.)

Los valores del estado inicial ("semilla") son arbitrarios, excepto que no deben ser todos cero, ni todos en los valores máximos permitidos (incógnita0=b1{\displaystyle x_{0}=b-1}ydo0=a1{\displaystyle c_{0}=a-1}). (Esto se suele hacer eligiendo do0{\displaystyle c_{0}}entre 1 ya2{\displaystyle a-2}.). La secuencia MWC es entonces una secuencia de paresincógnitanorte,donorte{\displaystyle x_{n},c_{n}}determinado por

incógnitanorte=(aincógnitanorte1+donorte1)modb, donorte=aincógnitanorte1+donorte1b{\displaystyle x_{n}=(ax_{n-1}+c_{n-1})\,{\bmod {\,}}b,\ c_{n}=\left\lfloor {\frac {ax_{n-1}+c_{n-1}}{b}}\right\rfloor }

Esto se denomina secuencia MWC de retraso 1. A veces se prefiere una base impar, en cuyo casob=2k1{\displaystyle b=2^{k}-1}se puede utilizar, lo cual es casi tan simple de implementar. Un retraso-r{\displaystyle r}La secuencia es una generalización de la secuencia de retardo 1 que permite períodos más largos [ 2 ] . El retardo-r{\displaystyle r}La secuencia MWC es entonces una secuencia de pares incógnitanorte,donorte{\displaystyle x_{n},c_{n}}(paranorte>r{\displaystyle n>r}) determinado por

incógnitanorte=(aincógnitanorter+donorte1)modb, donorte=aincógnitanorter+donorte1b{\displaystyle x_{n}=(ax_{n-r}+c_{n-1})\,{\bmod {\,}}b,\ c_{n}=\left\lfloor {\frac {ax_{n-r}+c_{n-1}}{b}}\right\rfloor }

y la salida del generador MWC es la secuencia deincógnita{\displaystyle x}'s,

incógnitar,incógnitar+1,incógnitar+2,...{\displaystyle x_{r},x_{r+1},x_{r+2},...}

En este caso, los valores del estado inicial ("semilla") no deben ser todos cero niincógnita0=b1{\displaystyle x_{0}=b-1}ydor1=a1{\displaystyle c_{r-1}=a-1}.

El multiplicador MWCa{\displaystyle a}y retrasor{\displaystyle r}determinar el módulopag=abr1{\displaystyle p=ab^{r}-1}En la práctica,a{\displaystyle a}se elige de modo que el módulo sea primo y la secuencia tenga un período largo. Si el módulo es primo, el período de un retardo-r{\displaystyle r}El generador MWC es del orden deb{\displaystyle b}en el grupo multiplicativo de números módulopag{\displaystyle p}Aunque teóricamente es posible elegir un módulo no primo, un módulo primo elimina la posibilidad de que la semilla inicial comparta un divisor común con el módulo, lo que reduciría el período del generador.

Porque 2 es un residuo cuadrático de números de la forma8k±1{\displaystyle 8k\pm 1},b=2k{\displaystyle b=2^{k}}no puede ser una raíz primitiva depag=abr1{\displaystyle p=ab^{r}-1}Por lo tanto, los generadores MWC con base2k{\displaystyle 2^{k}}tienen sus parámetros elegidos de modo que su período sea ( ab r −1)/2. Esta es una de las dificultades que supera el uso de b = 2 k  − 1. 

La forma básica de un generador MWC tiene parámetros a , b y r , y r + 1 palabras de estado. El estado consta de r residuos módulo b.

0 ≤ x 0 , x 1 , x 2 ,..., x r −1 < b,

y un acarreo c r −1 < a .  

Aunque la teoría de los generadores MWC permite a > b , casi siempre se elige a menor por conveniencia de implementación .  

La función de transformación de estado de un generador MWC es un paso de reducción de Montgomery módulo p . El estado es un entero grande con la palabra más significativa c n −1 y la palabra menos significativa x nr . En cada paso, x nr ·( ab r −1) se suma a este entero. Esto se hace en dos partes: −1· x nr se suma a x nr , lo que resulta en una palabra menos significativa de cero. Y segundo, a · x nr se suma al acarreo. Esto hace que el entero sea una palabra más largo, produciendo dos nuevas palabras más significativas x n y c n .

Hasta ahora, esto simplemente ha añadido un múltiplo de p al estado, lo que da como resultado un representante diferente de la misma clase de residuo módulo p . Pero finalmente, el estado se desplaza una palabra hacia abajo, dividiéndolo por b . Esto descarta la palabra menos significativa de cero (que, en la práctica, nunca se calcula) y efectivamente multiplica el estado por b −1 (mod p ).

Así, un generador de multiplicación con acarreo es un generador de Lehmer con módulo p y multiplicador b −1 (mod p ). Esto es lo mismo que un generador con multiplicador b , pero produce la salida en orden inverso, lo que no afecta la calidad de los números pseudoaleatorios resultantes.

Couture y L'Ecuyer [ 3 ] demostraron el sorprendente resultado de que la red asociada a un generador de multiplicación con acarreo es muy similar a la red asociada al generador de Lehmer que simula. Por lo tanto, las técnicas matemáticas desarrolladas para los generadores de Lehmer (como la prueba espectral ) pueden aplicarse a los generadores de multiplicación con acarreo.

Eficiencia

Se implementa un generador congruencial lineal con base b = 2 32 como

incógnitanorte+1=(aincógnitanorte+do) mod232,{\displaystyle x_{n+1}=(ax_{n}+c)\ {\bmod {\,}}2^{32},}

donde c es una constante. Si a ≡ 1 (mod 4) y c es impar, la secuencia congruencial resultante en base 2 32 tendrá un período de 2 32 . [ 4 ]

Esto se puede calcular utilizando solo los 32 bits menos significativos del producto de a y el valor actual de x . Sin embargo, muchos microprocesadores pueden calcular un producto completo de 64 bits en casi el mismo tiempo que los 32 bits menos significativos. De hecho, muchos calculan el producto de 64 bits y luego ignoran la mitad superior.

Un generador de multiplicación con acarreo de retardo 1 nos permite hacer que el período sea casi 2 63 usando casi las mismas operaciones de computadora, excepto que la mitad superior del producto de 64 bits no se ignora después de que se calcula el producto. En cambio, se calcula una suma de 64 bits, y la mitad superior se usa como un nuevo valor de acarreo c en lugar de la constante aditiva fija de la secuencia congruencial estándar: Calcular ax + c en 64 bits, luego usar la mitad superior como el nuevo c , y la mitad inferior como el nuevo x .

Elección del multiplicador

Con el multiplicador a especificado, cada par de valores de entrada x , c se convierte en un nuevo par,

incógnita(aincógnita+do)mod232,  doaincógnita+do232.{\displaystyle x\leftarrow (ax+c)\,{\bmod {\,}}2^{32},\ \ c\leftarrow \left\lfloor {\frac {ax+c}{2^{32}}}\right\rfloor .}

Si x y c no son ambos cero, entonces el período de la secuencia de multiplicación con acarreo resultante será del orden de b = 2 32 en el grupo multiplicativo de residuos módulo ab r  1 , es decir, el n más pequeño tal que b n ≡ 1 (mod ab r  1).

Si p = ab r  1 es primo, entonces el pequeño teorema de Fermat garantiza que el orden de cualquier elemento debe dividir p  1 = ab r  2, por lo que una forma de asegurar un orden grande es elegir a tal que p sea un " primo seguro ", es decir, tanto p como ( p  1)/2 = ab r /2   1 son primos. En tal caso, para b = 2 32 y r = 1, el período será ab r /2   1, aproximándose a 2 63 , que en la práctica puede ser un subconjunto aceptablemente grande del número de pares posibles de 32 bits ( x , c ).

Más específicamente, en tal caso, el orden de cualquier elemento divide a p  1, y solo hay cuatro divisores posibles: 1, 2, ab r /2   1, o ab r  2. Los dos primeros se aplican solo a los elementos 1 y −1, y los argumentos de reciprocidad cuadrática muestran que la cuarta opción no se puede aplicar a b , por lo que solo queda la tercera opción.

A continuación se muestran algunos valores máximos de a para aplicaciones informáticas que satisfacen la condición de primo seguro anterior, para generadores de retardo 1:

Si bien un número primo seguro garantiza que casi cualquier elemento del grupo tenga un orden grande, el período del generador es específicamente del orden de b . Para módulos pequeños, se pueden usar métodos computacionalmente más costosos para encontrar multiplicadores a donde el período es ab /2   1. A continuación se muestran nuevamente los valores máximos de a de varios tamaños.

Generadores MWC como decimales periódicos

La salida de un generador de multiplicación con acarreo es equivalente a la expansión en base b de una fracción con denominador p = ab r  1. Aquí hay un ejemplo para el caso simple de b = 10 y r = 1, por lo que el resultado es un decimal periódico .

Comenzando condo0=1,incógnita0=0{\textstyle c_{0}=1,x_{0}=0}, la secuencia MWC

incógnitanorte=(7incógnitanorte1+donorte1)mod10, donorte=7incógnitanorte1+donorte110,{\displaystyle x_{n}=(7x_{n-1}+c_{n-1})\,{\bmod {\,}}10,\ c_{n}=\left\lfloor {\frac {7x_{n-1}+c_{n-1}}{10}}\right\rfloor ,}

produce esta secuencia de estados:

10,01,07,49,67,55,40,04,28,58,61,13,22,16,43,25,37,52,19,64,34,31, 10,01,07,...

con periodo 22. Consideremos solo la secuencia de x i :

0,1,7,9,7,5,0,4,8,8,1,3,2,6,3,5,7,2,9,4,4,1, 0,1,7,9,7,5,0,...

Observe que si esos segmentos repetidos de valores x se colocan en orden inverso :

1449275971014492759710144{\displaystyle 1449275\cdots 9710\,1449275\cdots 9710\,144\cdots }

obtenemos la expansión j /( ab −1) con a =7, b =10, j=10 :

1069=0,144927536231884057971014492753623{\displaystyle {\frac {10}{69}}=0.1449275362318840579710\,14492753623\ldots }

Esto es cierto en general: La secuencia de x producida por un generador MWC con retardo r :

incógnitanorte=(aincógnitanorter+donorte1)modb,  donorte=aincógnitanorter+donorte1b,{\displaystyle x_{n}=(ax_{n-r}+c_{n-1}){\bmod {\,}}b\,,\ \ c_{n}=\left\lfloor {\frac {ax_{n-r}+c_{n-1}}{b}}\right\rfloor ,}

cuando se coloca en orden inverso, será la expansión en base b de una fracción j /( ab r 1) para algún 0 < j < ab r .  

Equivalencia con el generador congruencial lineal

Continuando con el ejemplo anterior, si comenzamos conincógnita0=34{\textstyle x_{0}=34}y generar la secuencia congruencial ordinaria

incógnitanorte=7incógnitanorte1mod69{\displaystyle x_{n}=7x_{n-1}\,{\bmod {\,}}69},

obtenemos la secuencia del período 22

31,10,1,7,49,67,55,40,4,28,58,61,13,22,16,43,25,37,52,19,64,34, 31,10,1,7,...

y esa secuencia, reducida módulo 10, es

1,0,1,7,9,7,5,0,4,8,8,1,3,2,6,3,5,7,2,9,4,4, 1,0,1,7,9,7,5,0,...

la misma secuencia de x' resultante de la secuencia MWC.

Esto es cierto en general (pero aparentemente solo para secuencias MWC de retraso 1 ):

Dados los valores inicialesincógnita0,do0{\displaystyle x_{0},c_{0}}, la secuenciaincógnita1,incógnita2,{\displaystyle x_{1},x_{2},\ldots }como resultado de la secuencia MWC de retraso 1

incógnitanorte=(aincógnitanorte1+donorte1)modb,  donorte=aincógnitanorte1+donorte1b{\displaystyle x_{n}=(ax_{n-1}+c_{n-1})\,{\bmod {b}}\,,\ \ c_{n}=\left\lfloor {\frac {ax_{n-1}+c_{n-1}}{b}}\right\rfloor }

es exactamente la secuencia de salida del generador de números aleatorios de Lehmer y n = ay n 1   mod ( ab 1), reducida módulo b .  

Elegir un valor inicial diferente y 0 simplemente rota el ciclo de x' .

Generadores de multiplicación con acarreo complementarios

Para determinar el período de un generador MWC con retardo r , generalmente se elige un multiplicador a tal que p = ab r  1 sea primo. Luego, p  1 deberá factorizarse para hallar el orden de b mod p . Si p es un primo seguro , esto es sencillo, y el orden de b será p  1 o ( p  1)/2. En otros casos, p 1 puede ser difícil de factorizar.  

Sin embargo, el algoritmo también permite un multiplicador negativo . Esto conlleva una ligera modificación del procedimiento MWC y produce un módulo p = | ab r  1 | = ab r  +  1. Esto hace que p  1 = ab r sea fácil de factorizar, lo que permite determinar el período de generadores muy grandes.

El procedimiento modificado se llama multiplicación complementaria con acarreo (CMWC), y la configuración es la misma que para MWC con retardo r : multiplicador a , base b y semillas r  + 1, 

x 0 , x 1 , x 2 , ..., x r −1 , y c r −1 .

La modificación consiste en la generación de un nuevo par ( x , c ). Reorganizando el cálculo para evitar números negativos, el nuevo valor de x se complementa restándolo de b  1:

incógnitanorte=(b1)(aincógnitanorter+donorte1)modb, donorte=aincógnitanorter+donorte1b.{\displaystyle x_{n}=(b-1)-(ax_{n-r}+c_{n-1})\,{\bmod {\,}}b,\ c_{n}=\left\lfloor {\frac {ax_{n-r}+c_{n-1}}{b}}\right\rfloor .}

La secuencia resultante de x 's producida por el generador de números aleatorios CMWC tendrá un período del orden de b en el grupo multiplicativo de residuos módulo ab r +1, y la salida x 's , en orden inverso, formará la expansión en base b de j /( ab r +1) para algún 0  < j < ab r .   

El uso de lag -r CMWC facilita mucho la búsqueda de periodos para valores de r tan grandes como 512, 1024, 2048, etc. (Hacer que r sea una potencia de 2 simplifica ligeramente el acceso a los elementos del array que contienen los r valores de x más recientes ).

Otra ventaja de este procedimiento modificado es que el período es un múltiplo de b , por lo que la salida está exactamente equidistribuida módulo b . [ 3 ] (El MWC ordinario, durante todo su período, produce cada salida posible un número igual de veces, excepto que el cero se produce una vez menos, un sesgo que es despreciable si el período es lo suficientemente largo).

Una desventaja de la construcción CMWC es que, con una base que es potencia de dos, el período máximo alcanzable es menor que el de un generador MWC de tamaño similar; se pierden varios bits. Por lo tanto, un generador MWC suele ser preferible para pequeños retardos. Esto se puede solucionar utilizando b = 2k 1, o eligiendo un retardo una palabra mayor para compensar.

Algunos ejemplos: Con b = 2 32 y a = 109111 o 108798 o 108517, el período del CMWC de retardo 1024

incógnitanorte=(b1)(aincógnitanorte1024+donorte1)modb, donorte=aincógnitanorte1024+donorte1b.{\displaystyle x_{n}=(b-1)-(ax_{n-1024}+c_{n-1})\,{\bmod {\,}}b,\ c_{n}=\left\lfloor {\frac {ax_{n-1024}+c_{n-1}}{b}}\right\rfloor .}

será un ·2 32762 = ab 1024 /64, aproximadamente 10 9867 .

Con b = 2 32 y a = 3636507990, p = ab 1359  1 es un primo seguro, por lo que la secuencia MWC basada en que a tiene un período de 3636507990·2 43487 ≈ 10 13101 .

Con b = 2 32 , un CMWC RNG con un período cercano al récord puede basarse en el primo p = 15455296 b 42658  +  1. El orden de b para ese primo es 241489·2 1365056 ≈ 10 410928 .

módulos más generales

El módulo MWC de ab r −1 se elige para simplificar el cálculo, pero conlleva algunas desventajas, principalmente que el período es como máximo la mitad del módulo. Existen varias maneras de generalizar esto, a costa de realizar más multiplicaciones por iteración.

En primer lugar, es posible añadir términos adicionales al producto, obteniendo un módulo de la forma a r b r + a s b s −1. Esto requiere calcular c n b + x n = a r x nr + a s x ns . (El acarreo se limita a una palabra si a r + a sb .)

Sin embargo, esto no soluciona el problema del período, que depende de los bits bajos del módulo. Afortunadamente, el algoritmo de reducción de Montgomery permite otros módulos, siempre que sean relativamente primos con la base b , y esto se puede aplicar para permitir un módulo de la forma a r b ra 0 , para un amplio rango de valores a 0 . Goresky y Klapper [ 5 ] desarrollaron la teoría de estos generadores generalizados de multiplicación con acarreo, demostrando, en particular, que al elegir un a 0 negativo y a ra 0 < b el valor del acarreo siempre es menor que b , lo que hace que la implementación sea eficiente. La forma más general del módulo también mejora la calidad del generador, aunque no siempre se puede obtener el período completo.

Para implementar un generador de Goresky-Klapper se precalcula a −1 0  (mod b ), y se cambia la iteración de la siguiente manera: [ 6 ] 

t=donorte1+1raiincógnitanortei, incógnitanorte=a01tmodb, donorte=ta0incógnitanorteb.{\displaystyle t=c_{n-1}+\sum _{1}^{r}a_{i}x_{n-i},\ x_{n}=a_{0}^{-1}t{\bmod {b}},\ c_{n}=\left\lfloor {\frac {t-a_{0}x_{n}}{b}}\right\rfloor .}

En el caso común de que b = 2k , a0 debe ser impar para que exista el inverso.

Implementación

A continuación se presenta una implementación del algoritmo CMWC en el lenguaje de programación C. El programa también incluye una función de inicialización de ejemplo. En esta implementación, la base es 2³² 1 y el retardo r = 4096. El período del generador resultante es aproximadamente2131104{\displaystyle 2^{131104}}.

// Generador de multiplicación complementaria con acarreo C99 #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <time.h>// ¿Cuántos bits tiene rand()? // https://stackoverflow.com/a/27593398 #define LOG_1(n) (((n) >= 2) ? 1 : 0) #define LOG_2(n) (((n) >= 1<<2) ? (2 + LOG_1((n)>>2)) : LOG_1(n)) #define LOG_4(n) (((n) >= 1<<4) ? (4 + LOG_2((n)>>4)) : LOG_2(n)) #define LOG_8(n) (((n) >= 1<<8) ? (8 + LOG_4((n)>>8)) : LOG_4(n)) #define LOG(n) (((n) >= 1<<16) ? (16 + LOG_8((n)>>16)) : LOG_8(n)) #define BITS_TO_REPRESENT(n) (LOG(n) + !!((n) & ((n) - 1))) #if ((RAND_MAX | (RAND_MAX >> 1)) != RAND_MAX) #error "Se esperaba un RAND_MAX que es 2^n - 1!" #endif #define RAND_BITS BITS_TO_REPRESENT(RAND_MAX)// Partes de trabajo de CMWC #define CMWC_CYCLE 4096 // como recomienda Marsaglia #define CMWC_C_MAX 809430660 // como recomienda Marsaglia struct cmwc_state { uint32_t Q [ CMWC_CYCLE ]; uint32_t c ; // debe limitarse con CMWC_C_MAX unsigned i ; };// Recopila 32 bits de rand(). Se recomienda usar una fuente mejor. uint32_t rand32 ( void ) { uint32_t result = rand (); for ( int bits = RAND_BITS ; bits < 32 ; bits += RAND_BITS ) result = result << RAND_BITS | rand (); return result ; }// Inicializa el estado con la semilla void initCMWC ( struct cmwc_state * state , unsigned int seed ) { srand ( seed ); for ( int i = 0 ; i < CMWC_CYCLE ; i ++ ) state -> Q [ i ] = rand32 (); do state -> c = rand32 (); while ( state -> c >= CMWC_C_MAX ); state -> i = CMWC_CYCLE - 1 ; }// Motor CMWC uint32_t randCMWC ( struct cmwc_state * state ) // El parámetro *state estaba ausente { uint64_t const a = 18782 ; // como recomienda Marsaglia uint32_t const m = 0xfffffffe ; // como recomienda Marsaglia uint64_t t ; uint32_t x ;estado -> i = ( estado -> i + 1 ) & ( CMWC_CYCLE - 1 ); t = a * estado -> Q [ estado -> i ] + estado -> c ; /* Sea c = t / 0xffffffff, x = t mod 0xffffffff */ estado -> c = t >> 32 ; x = t + estado -> c ; si ( x < estado -> c ) { x ++ ; estado -> c ++ ; } return estado -> Q [ estado -> i ] = m - x ; }int main () { struct cmwc_state cmwc ; unsigned int seed = time ( NULL );initCMWC ( & cmwc , seed ); printf ( "CMWC aleatorio: %u \n " , randCMWC ( & cmwc )); }

A continuación se muestran implementaciones de generadores MWC de estado pequeño con salida de 64 bits mediante multiplicaciones de 128 bits.

// C99 + __uint128_t MWC, 128 bits de estado, período aprox. 2^127/* El estado no debe ser ni completamente cero, ni x = 2^64 - 1, c = MWC_A1 -  1. Por lo tanto, la condición 0 < c < MWC_A1 - 1 es suficiente. */uint64_t x , c = 1 ;#define MWC_A1 0xff3a275c007b8ee6uint64_t inline next () { const __uint128_t t = MWC_A1 * ( __uint128_t ) x + c ; c = t >> 64 ; return x = t ; }
// C99 + __uint128_t MWC, 256 bits de estado, período aprox. 2^255/* El estado no debe ser ni completamente cero, ni x = y = z = 2^64 - 1, c =  MWC_A3 - 1. Por lo tanto, la condición 0 < c < MWC_A3 - 1 es suficiente. */uint64_t x , y , z , c = 1 ;#definir MWC_A3 0xff377e26f82da74auint64_t inline next () { const __uint128_t t = MWC_A3 * ( __uint128_t ) x + c ; x = y ; y = z ; c = t >> 64 ; return z = t ; }

A continuación se presentan implementaciones de generadores MWC generalizados de Goresky-Klapper de estados pequeños con salida de 64 bits mediante multiplicaciones de 128 bits.

// C99 + __uint128_t Goresky-Klapper GMWC, 128 bits de estado, período aprox. 2^127/* El estado no debe ser ni completamente cero, ni x = 2^64 - 1, c = GMWC_A1 +  GMWC_MINUS_A0. Por lo tanto, la condición 0 < c < GMWC_A1 + GMWC_MINUS_A0 es  suficiente. */uint64_t x = 0 , c = 1 ;#define GMWC_MINUSA0 0x7d084a4d80885f #define GMWC_A0INV 0x9b1eea3792a42c61 #define GMWC_A1 0xff002aae7d81a646uint64_t inline next () { const __uint128_t t = GMWC_A1 * ( __uint128_t ) x + c ; x = GMWC_A0INV * ( uint64_t ) t ; c = ( t + GMWC_MINUSA0 * ( __uint128_t ) x ) >> 64 ; return x ; }
// C99 + __uint128_t Goresky-Klapper GMWC, 256 bits de estado, período aprox. 2^255/* El estado no debe ser ni completamente cero, ni x = y = z = 2^64 - 1, c =  GMWC_A3 + GMWC_MINUS_A0.  Por lo tanto, la condición 0 < c < GMWC_A3 + GMWC_MINUS_A0 es suficiente. */uint64_t x , y , z , c = 1 ; /* El estado puede inicializarse con cualquier conjunto de valores, no todos ceros. */#definir GMWC_MINUSA0 0x54c3da46afb70f #definir GMWC_A0INV 0xbbf397e9a69da811 #definir GMWC_A3 0xff963a86efd088a2uint64_t inline next () { const __uint128_t t = GMWC_A3 * ( __uint128_t ) x + c ; x = y ; y = z ; z = GMWC_A0INV * ( uint64_t ) t ; c = ( t + GMWC_MINUSA0 * ( __uint128_t ) z ) >> 64 ; return z ; }

Uso

Debido a su simplicidad y velocidad, CMWC es conocido por su uso en el desarrollo de videojuegos, particularmente en juegos roguelike modernos . Se le conoce informalmente como la Madre de todos los PRNG, un nombre acuñado originalmente por el propio Marsaglia. [ 7 ] En libtcod, CMWC4096 reemplazó a MT19937 como PRNG predeterminado. [ 8 ]

Véase también

Referencias

  1. Marsaglia, George ; Zaman, Arif (agosto de 1995). "El CD-ROM de números aleatorios de Marsaglia que incluye la batería Diehard de pruebas de aleatoriedad" .
  2. Marsaglia, George¨ (mayo de 2003). "Generadores de números aleatorios" . Journal of Modern Applied Statistical Methods . 2 (1): 2– 13. doi : 10.22237/jmasm/1051747320 .
  3. 1 2 Couture, Raymond; L'Ecuyer, Pierre (abril de 1997). "Propiedades de distribución de los generadores de números aleatorios de multiplicación con acarreo" (PDF) . Mathematics of Computation . 66 (218): 591– 607. Bibcode : 1997MaCom..66..591C . CiteSeerX 10.1.1.154.331 . doi : 10.1090/S0025-5718-97-00827-2 . Veremos que, para el MWC complementario, cada bit del valor de salida es justo, es decir, los dos dígitos binarios aparecerán con la misma frecuencia en un período completo, una propiedad que no comparten los generadores MWC. 
  4. Hull, TE; Dobell, AR (julio de 1962). "Generadores de números aleatorios" (PDF) . SIAM Review . 4 (3): 230– 254. Bibcode : 1962SIAMR...4..230H . doi : 10.1137/1004061 . hdl : 1828/3142 .
  5. 1 2 Goresky, Mark ; Klapper, Andrew (octubre de 2003). "Generadores de números aleatorios de multiplicación con acarreo eficientes con período máximo" (PDF) . ACM Transactions on Modeling and Computer Simulation . 13 (4): 310–321 . CiteSeerX 10.1.1.4.9190 . doi : 10.1145/945511.945514 . S2CID 13334372 .  
  6. Nótese que el artículo de Goresky y Klapper [ 5 ] contiene un error en la ecuación (4): la última igualdad no es verdadera; no se puede eliminar el segundo sumando del cálculo del acarreo.
  7. "La madre de todos los generadores de números aleatorios de Marsaglia" . home.sandiego.edu .
  8. "Generador de números aleatorios - RogueBasin" . www.roguebasin.com . Consultado el 30 de noviembre de 2016 .
  • Marsaglia, George (4 de julio de 2003). "Xorshift RNGs" . Journal of Statistical Software . 8 (14): 1– 6. doi : 10.18637/jss.v008.i14 .
  • Marsaglia, George (octubre de 2005). "Sobre la aleatoriedad de Pi y otras expansiones decimales" . Interstat . CiteSeerX 10.1.1.694.4783 . 
  • Press, William H.; Teukolsky , Saul A .; Vetterling, William T.; Flannery, Brian P. (2007). «Sección 7.1.2.B Multiplicación con acarreo (MWC)» . Numerical Recipes: The Art of Scientific Computing (3.ª  ed.). Nueva York: Cambridge University Press. ISBN 978-0-521-88068-8.

Obtenido de " https://en.wikipedia.org/w/index.php?title=Multiply-with-carry_pseudorandom_number_generator&oldid=1325240897 "