forked from uva-reiss-cs4414/xv6
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lcg_parkmiller.c
41 lines (30 loc) · 1.06 KB
/
lcg_parkmiller.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
#include "lcg_parkmiller.h"
static unsigned random_seed = 1;
#define RANDOM_MAX ((1u << 31u) - 1u)
unsigned lcg_parkmiller(unsigned *state)
{
const unsigned N = 0x7fffffff;
const unsigned G = 48271u;
/*
Indirectly compute state*G%N.
Let:
div = state/(N/G)
rem = state%(N/G)
Then:
rem + div*(N/G) == state
rem*G + div*(N/G)*G == state*G
Now:
div*(N/G)*G == div*(N - N%G) === -div*(N%G) (mod N)
Therefore:
rem*G - div*(N%G) === state*G (mod N)
Add N if necessary so that the result is between 1 and N-1.
*/
unsigned div = *state / (N / G); /* max : 2,147,483,646 / 44,488 = 48,271 */
unsigned rem = *state % (N / G); /* max : 2,147,483,646 % 44,488 = 44,487 */
unsigned a = rem * G; /* max : 44,487 * 48,271 = 2,147,431,977 */
unsigned b = div * (N % G); /* max : 48,271 * 3,399 = 164,073,129 */
return *state = (a > b) ? (a - b) : (a + (N - b));
}
unsigned next_random() {
return lcg_parkmiller(&random_seed);
}