-
Notifications
You must be signed in to change notification settings - Fork 30
Expand file tree
/
Copy pathrandom_num.cpp
More file actions
84 lines (64 loc) · 2.2 KB
/
Copy pathrandom_num.cpp
File metadata and controls
84 lines (64 loc) · 2.2 KB
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
#include "compiler.h"
static unsigned int rnd_idnum[2] = {1, 1};
#define ROL32(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
/*
* Generates a random 32-bit integer using two cross-coupled LCGs.
*
* Uses different LCG constants for each state half so the sequences
* are fundamentally independent:
* state[0]: Numerical Recipes (Knuth) — mult 1664525, inc 1013904223
* state[1]: Borland Delphi — mult 22695477, inc 1
*
* Cross-coupling via rotate-and-XOR mixes bits between the two halves.
* Rotation amounts (16, 5) and LCG pairing were selected by brute-force
* optimization over all combinations, scored on chi-squared uniformity,
* bit balance, serial correlation, avalanche effect, and gap tests.
*/
static unsigned int fast_generate_random(void)
{
rnd_idnum[0] ^= ROL32(rnd_idnum[1], 16);
rnd_idnum[0] *= 1664525L;
rnd_idnum[0] += 1013904223L;
rnd_idnum[1] *= 22695477L;
rnd_idnum[1] += 1L;
rnd_idnum[1] ^= ROL32(rnd_idnum[0], 5);
return rnd_idnum[0];
}
void fast_random_seed(unsigned int seed)
{
int i;
rnd_idnum[0] = seed;
rnd_idnum[1] = ~(seed + 6);
// warmup: run several rounds to diffuse seed across both state halves
for (i = 0; i < 4; i++)
fast_generate_random();
}
/* returns random integer in range [lLow, lHigh] inclusive */
int RANDOM_LONG2(int lLow, int lHigh)
{
const double c_divider = ((unsigned long long)1) << 32; // div by (1<<32)
double rnd;
int result;
if (unlikely(lLow >= lHigh))
return(lLow);
rnd = fast_generate_random();
rnd *= (double)lHigh - (double)lLow + 1.0;
rnd /= c_divider; // div by (1<<32)
result = (int)(rnd + (double)lLow);
// clamp: floating point rounding can produce lHigh+1 at the edge
if (unlikely(result > lHigh))
result = lHigh;
return result;
}
/* returns random float in range [flLow, flHigh] inclusive */
float RANDOM_FLOAT2(float flLow, float flHigh)
{
const double c_divider = (((unsigned long long)1) << 32) - 1; // div by (1<<32)-1
double rnd;
if (unlikely(flLow >= flHigh))
return(flLow);
rnd = fast_generate_random();
rnd *= (double)flHigh - (double)flLow;
rnd /= c_divider; // div by (1<<32)-1
return (float)(rnd + (double)flLow);
}