-
Notifications
You must be signed in to change notification settings - Fork 116
/
Copy pathrandom.c
138 lines (106 loc) · 2.77 KB
/
random.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <stdio.h>
#include "random.h"
/* Simple Park-Miller for floating point; LCG as used in glibc and other places */
/********************************************************************************************/
#ifdef _WIN32
#include <windows.h>
/* Use TlsGetValue() / TlsSetValue() for thread-local storage,
* mingw-w64's __thread is painfully slow. */
static int tls_index = -1;
static void __attribute__((constructor))
init_fast_random()
{
tls_index = TlsAlloc();
fast_srandom(29264);
}
void
fast_srandom(unsigned long seed_)
{
TlsSetValue(tls_index, (void*)(intptr_t)seed_);
}
unsigned long
fast_getseed(void)
{
return (unsigned long)(intptr_t)TlsGetValue(tls_index);
}
uint16_t
fast_random(unsigned int max)
{
unsigned long pmseed = fast_getseed();
pmseed = ((pmseed * 1103515245) + 12345) & 0x7fffffff;
fast_srandom(pmseed);
return ((pmseed & 0xffff) * max) >> 16;
}
#else
/********************************************************************************************/
#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
#endif