Merge branch 'master' into ltreeowner
[pachi.git] / random.c
blob20457ea5d756b681abf2678c1483aded5c3f2a1a
1 #include <stdio.h>
3 #include "random.h"
6 /* Simple Park-Miller */
8 #ifndef NO_THREAD_LOCAL
10 static __thread unsigned long pmseed = 29264;
12 void
13 fast_srandom(unsigned long seed_)
15 pmseed = seed_;
18 unsigned long
19 fast_getseed(void)
21 return pmseed;
24 uint16_t
25 fast_random(unsigned int max)
27 unsigned long hi, lo;
28 lo = 16807 * (pmseed & 0xffff);
29 hi = 16807 * (pmseed >> 16);
30 lo += (hi & 0x7fff) << 16;
31 lo += hi >> 15;
32 pmseed = (lo & 0x7fffffff) + (lo >> 31);
33 return ((pmseed & 0xffff) * max) >> 16;
36 floating_t
37 fast_frandom(void)
39 /* Construct (1,2) IEEE floating_t from our random integer */
40 /* http://rgba.org/articles/sfrand/sfrand.htm */
41 union { unsigned long ul; floating_t f; } p;
42 p.ul = (((pmseed *= 16807) & 0x007fffff) - 1) | 0x3f800000;
43 return p.f - 1.0f;
46 #else
48 /* Thread local storage not supported through __thread,
49 * use pthread_getspecific() instead. */
51 #include <pthread.h>
53 static pthread_key_t seed_key;
55 static void __attribute__((constructor))
56 random_init(void)
58 pthread_key_create(&seed_key, NULL);
59 fast_srandom(29264UL);
62 void
63 fast_srandom(unsigned long seed_)
65 pthread_setspecific(seed_key, (void *)seed_);
68 unsigned long
69 fast_getseed(void)
71 return (unsigned long)pthread_getspecific(seed_key);
74 uint16_t
75 fast_random(unsigned int max)
77 unsigned long pmseed = (unsigned long)pthread_getspecific(seed_key);
78 unsigned long hi, lo;
79 lo = 16807 * (pmseed & 0xffff);
80 hi = 16807 * (pmseed >> 16);
81 lo += (hi & 0x7fff) << 16;
82 lo += hi >> 15;
83 pmseed = (lo & 0x7fffffff) + (lo >> 31);
84 pthread_setspecific(seed_key, (void *)pmseed);
85 return ((pmseed & 0xffff) * max) >> 16;
88 floating_t
89 fast_frandom(void)
91 /* Construct (1,2) IEEE floating_t from our random integer */
92 /* http://rgba.org/articles/sfrand/sfrand.htm */
93 unsigned long pmseed = (unsigned long)pthread_getspecific(seed_key);
94 pmseed *= 16807;
95 union { unsigned long ul; floating_t f; } p;
96 p.ul = ((pmseed & 0x007fffff) - 1) | 0x3f800000;
97 pthread_setspecific(seed_key, (void *)pmseed);
98 return p.f - 1.0f;
101 #endif