pachi_py/pachi/random.c (65 lines of code) (raw):

#include <stdio.h> #include "random.h" /* Simple Park-Miller for floating point; LCG as used in glibc and other places */ #ifndef NO_THREAD_LOCAL static __thread unsigned long pmseed = 29264; void fast_srandom(unsigned long seed_) { pmseed = seed_; } unsigned long fast_getseed(void) { return pmseed; } uint16_t fast_random(unsigned int max) { pmseed = ((pmseed * 1103515245) + 12345) & 0x7fffffff; return ((pmseed & 0xffff) * max) >> 16; } float fast_frandom(void) { /* Construct (1,2) IEEE floating_t from our random integer */ /* http://rgba.org/articles/sfrand/sfrand.htm */ union { unsigned long ul; floating_t f; } p; p.ul = (((pmseed *= 16807) & 0x007fffff) - 1) | 0x3f800000; return p.f - 1.0f; } #else /* Thread local storage not supported through __thread, * use pthread_getspecific() instead. */ #include <pthread.h> static pthread_key_t seed_key; static void __attribute__((constructor)) random_init(void) { pthread_key_create(&seed_key, NULL); fast_srandom(29264UL); } void fast_srandom(unsigned long seed_) { pthread_setspecific(seed_key, (void *)seed_); } unsigned long fast_getseed(void) { return (unsigned long)pthread_getspecific(seed_key); } uint16_t fast_random(unsigned int max) { unsigned long pmseed = (unsigned long)pthread_getspecific(seed_key); pmseed = ((pmseed * 1103515245) + 12345) & 0x7fffffff; pthread_setspecific(seed_key, (void *)pmseed); return ((pmseed & 0xffff) * max) >> 16; } float fast_frandom(void) { /* Construct (1,2) IEEE floating_t from our random integer */ /* http://rgba.org/articles/sfrand/sfrand.htm */ unsigned long pmseed = (unsigned long)pthread_getspecific(seed_key); pmseed *= 16807; union { unsigned long ul; floating_t f; } p; p.ul = ((pmseed & 0x007fffff) - 1) | 0x3f800000; pthread_setspecific(seed_key, (void *)pmseed); return p.f - 1.0f; } #endif