-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrandom.c
195 lines (175 loc) · 4.42 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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#include <stdint.h>
uint8_t randomUint8();
uint16_t randomUint16();
uint32_t randomUint32();
uint64_t randomUint64();
uint8_t randomUint8 (uint8_t max);
uint16_t randomUint16(uint16_t max);
uint32_t randomUint32(uint32_t max);
uint64_t randomUint64(uint64_t max);
/**
* Shit random source.
*
* @returns A "random" uint8_t (0 to 2**8-1)
*/
uint8_t randomUint8()
{
#error "TODO implement good random"
return (uint8_t) 4; // Chosen by fair dice roll.
// Guaranteed to be random.
}
/**
* Generates a random uint16_t uses randomUint8().
*
* @returns A random uint16_t (0 to 2**16-1)
*/
uint16_t randomUint16()
{
uint16_t ret;
ret = (uint16_t) randomUint8();
ret |= ((uint16_t) randomUint8()) << 8;
return ret;
}
/**
* Generates a random uint32_t uses randomUint8().
*
* @returns A random uint32_t (0 to 2**32-1)
*/
uint32_t randomUint32()
{
uint32_t ret;
ret = (uint32_t) randomUint8();
ret |= ((uint32_t) randomUint8()) << 8;
ret |= ((uint32_t) randomUint8()) << 16;
ret |= ((uint32_t) randomUint8()) << 24;
return ret;
}
/**
* Generates a random uint64_t uses randomUint8().
*
* @returns A random uint64_t (0 to 2**64-1)
*/
uint64_t randomUint64()
{
return randomUint32() | (((uint64_t) randomUint32()) << 32);
}
/**
* Random uint8_t with no modulo bias.
*
* @param uint8_t max: The maximum random value to output.
* @returns A random value 0 to max
*/
uint8_t randomUint8(uint8_t max)
{
uint8_t ret;
// If nice base 2 modulo (ie 2**n)
if (((max + 1) & max) == 0)
{
ret = randomUint8() & max;
}
else
{
// skip is "n*(max+1)" for the largest n such that "n*(max+1) < 2**8"
uint8_t skip = UINT8_MAX - UINT8_MAX % (max + 1);
// Loop until random number is less than skip then modulo.
// Note worst case is max is 2**7+1 and chances of looping are just less
// than 50%. The chances of looping 128 times is so low (<1 in 2**128)
// that the heat death of the universe would happen before this.
do
{
ret = randomUint8();
} while (ret >= skip);
ret %= max + 1;
}
return ret;
}
/**
* Random uint16_t with no modulo bias.
*
* @param uint16_t max: The maximum random value to output.
* @returns A random value 0 to max
*/
uint16_t randomUint16(uint16_t max)
{
uint16_t ret;
// If nice base 2 modulo (ie 2**n)
if (((max + 1) & max) == 0)
{
ret = randomUint16() & max;
}
else
{
// skip is "n*(max+1)" for the largest n such that "n*(max+1) < 2**16"
uint16_t skip = UINT16_MAX - UINT16_MAX % (max + 1);
// Loop until random number is less than skip then modulo.
// Note worst case is max is 2**15+1 and chances of looping are just less
// than 50%. The chances of looping 128 times is so low (<1 in 2**128)
// that the heat death of the universe would happen before this.
do
{
ret = randomUint16();
} while (ret >= skip);
ret %= max + 1;
}
return ret;
}
/**
* Random uint32_t with no modulo bias.
*
* @param uint32_t max: The maximum random value to output.
* @returns A random value 0 to max
*/
uint32_t randomUint32(uint32_t max)
{
uint32_t ret;
// If nice base 2 modulo (ie 2**n)
if (((max + 1) & max) == 0)
{
ret = randomUint32() & max;
}
else
{
// skip is "n*(max+1)" for the largest n such that "n*(max+1) < 2**32"
uint32_t skip = UINT32_MAX - UINT32_MAX % (max + 1);
// Loop until random number is less than skip then modulo.
// Note worst case is max is 2**31+1 and chances of looping are just less
// than 50%. The chances of looping 128 times is so low (<1 in 2**128)
// that the heat death of the universe would happen before this.
do
{
ret = randomUint32();
} while (ret >= skip);
ret %= max + 1;
}
return ret;
}
/**
* Random uint64_t with no modulo bias.
*
* @param uint64_t max: The maximum random value to output.
* @returns A random value 0 to max
*/
uint64_t randomUint64(uint64_t max)
{
uint64_t ret;
// If nice base 2 modulo (ie 2**n)
if (((max + 1) & max) == 0)
{
ret = randomUint64() & max;
}
else
{
// skip is "n*(max+1)" for the largest n such that "n*(max+1) < 2**64"
uint64_t skip = UINT64_MAX - UINT64_MAX % (max + UINT64_C(1));
// Loop until random number is less than skip then modulo.
// Note worst case is max is 2**63+1 and chances of looping are just less
// than 50%. The chances of looping 128 times is so low (<1 in 2**128)
// that the heat death of the universe would happen before this.
do
{
ret = randomUint64();
} while (ret >= skip);
ret %= max + 1;
}
return ret;
}