forked from gabbage/fanmod-cmd
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrandom.hpp
164 lines (148 loc) · 5.28 KB
/
random.hpp
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
// random.cpp. R. Loos, 16. 11. 2000
#ifndef INFO_UT_HPP
#define INFO_UT_HPP
#define random_double() ( (double)(++rand % 100000001) * 1e-8) /*[0,1]*/
namespace randlib {
// Revision History
// 2005 Random double and random subarray generation (Sebastian Wernicke)
// 2000 Revision by Rüdiger Loos, C++ with
// 1999 boost interface (Beman Dawes).
// 1996 Revision by Roland Weiss, C++ version
// 1982 Initial C version for Aldes
// (C) Copyright Rüdiger Loos 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// (C) Copyright Beman Dawes 1994-99. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// rand -----------------------------------------------------------------------//
// a rand object initializes a pseudo random number generator
class rand {
public:
explicit rand(long seed = 310952)
: ran_arr_sentinel(-1), ran_arr_ptr(&ran_arr_sentinel) {
//assert( 0 <= seed && seed < MM );
ran_start(seed);
}
rand& operator=( long new_value ) {
//assert( 0 <= new_value && new_value < MM );
ran_start(new_value);
return *this;
}
operator long() const { return *ran_arr_ptr; }
double fvalue() const { return double(*ran_arr_ptr) / MM; }
long operator++() {
return *ran_arr_ptr>=0? *ran_arr_ptr++: ran_arr_cycle();
}
long operator++(int) {
long temp = *ran_arr_ptr;
operator++();
return temp;
}
long dice(long n) { return operator++() % n + 1; }
bool trueWithProb(double d) { return ((operator++() & 0x0FFFFFFFL) <= (d*0x0FFFFFFFL)); }
// satisfy std::RandomNumberGenerator and std::Generator requirements:
typedef long argument_type;
typedef long result_type;
long operator()( long n ) { return operator++() % n; }
long operator()() { return operator++(); }
private:
enum constants {
KK = 100, // the long lag
LL = 37, // the short lag
MM = (1L<<30), // the modulus
TT = 70, // guaranteed separation between streams
QUALITY = 1009}; // recommended quality level for high-res use
long ran_x[KK]; // the generator state
long ran_arr_buf[QUALITY];
long ran_arr_sentinel;
long *ran_arr_ptr; // the next random number, or -1
bool is_odd(const int x) { return x & 1; }
int evenize(const int x) { return x & (MM-2); }
int mod_diff(const int x, const int y) { // subtraction mod MM
return (x - y) & (MM - 1);
}
void ran_start(long seed); // ctor. seed selects different streams
void ran_array(long aa[], int n); // put n new random numbers in ran_arr_buf
// array length (must be at least KK)
long ran_arr_cycle();
}; // class rand
} // namespace random
// This program by D E Knuth is in the public domain and freely copyable
// AS LONG AS YOU MAKE ABSOLUTELY NO CHANGES!
// It is explained in Seminumerical Algorithms, 3rd edition, Section 3.6
// (or in the errata to the 2nd edition --- see
// http://www-cs-faculty.stanford.edu/~knuth/taocp.html
// in the changes to pages 171 and following of Volume 2). */
// If you find any bugs, please report them immediately to
// (and you will be rewarded if the bug is genuine). Thanks! */
/************ see the book for explanations and caveats! *******************/
// moved to C++ by R. Loos, 12. 11. 2000, with ideas from Beman Dawes.
inline void gen_selection (long start, long end,
double prob, unsigned long *array,
randlib::rand& rand) {
long len = end-start;
if (len == 0)
{
array[0] = end;
return;
}
bool *sel = new bool[len];
long point = 0;
double rem = double(len) * prob;
long num = (long)rem;
rem -= num;
if ( random_double() <= rem )
{++num;}
for (int i = 0; i!= len; ++i)
{sel[i] = true;}
if (prob < 0.6) { // CASE OF SMALL PROBABILITIES
//Use Floyds random selection algorithm
for (long J = len-num; J != len; ++J) {
long pos = ++rand % (J+1);
if (sel[pos]) {
sel[pos] = false;
array[point] = start + pos;
} else {
sel[J] = false;
array[point] = start + J;
}
++point;
}
//while (num != 0) {
// long pos = ++rand % len;
// if (sel[pos]) {
// sel[pos] = false;
// array[point] = start + pos;
// //--num;
// //++point;
// }
//}
} else { // CASE OF LARGE PROBABILITIES
num = len-num;
for (long J = len-num; J != len; ++J) {
long pos = ++rand % (J+1);
if (sel[pos]) {
sel[pos] = false;
array[point] = start + pos;
} else {
sel[J] = false;
array[point] = start + J;
}
++point;
}
for (int i = 0; i != len; ++i) {
if (sel[i]) {
array[point] = start + i;
++point;
}
}
}
array[point] = end;
delete[] sel;
return;
}
#endif // INFO_UT_HPP