40 |
40 |
41 // The following are the transition matrices of the two MRG components |
41 // The following are the transition matrices of the two MRG components |
42 // (in matrix form), raised to the powers -1, 1, 2^76, and 2^127, resp. |
42 // (in matrix form), raised to the powers -1, 1, 2^76, and 2^127, resp. |
43 |
43 |
44 const double InvA1[3][3] = { // Inverse of A1p0 |
44 const double InvA1[3][3] = { // Inverse of A1p0 |
45 { 184888585.0, 0.0, 1945170933.0 }, |
45 { 184888585.0, 0.0, 1945170933.0 }, |
46 { 1.0, 0.0, 0.0 }, |
46 { 1.0, 0.0, 0.0 }, |
47 { 0.0, 1.0, 0.0 } |
47 { 0.0, 1.0, 0.0 } |
48 }; |
48 }; |
49 |
49 |
50 const double InvA2[3][3] = { // Inverse of A2p0 |
50 const double InvA2[3][3] = { // Inverse of A2p0 |
51 { 0.0, 360363334.0, 4225571728.0 }, |
51 { 0.0, 360363334.0, 4225571728.0 }, |
52 { 1.0, 0.0, 0.0 }, |
52 { 1.0, 0.0, 0.0 }, |
53 { 0.0, 1.0, 0.0 } |
53 { 0.0, 1.0, 0.0 } |
54 }; |
54 }; |
55 |
55 |
56 const double A1p0[3][3] = { |
56 const double A1p0[3][3] = { |
57 { 0.0, 1.0, 0.0 }, |
57 { 0.0, 1.0, 0.0 }, |
58 { 0.0, 0.0, 1.0 }, |
58 { 0.0, 0.0, 1.0 }, |
59 { -810728.0, 1403580.0, 0.0 } |
59 { -810728.0, 1403580.0, 0.0 } |
60 }; |
60 }; |
61 |
61 |
62 const double A2p0[3][3] = { |
62 const double A2p0[3][3] = { |
63 { 0.0, 1.0, 0.0 }, |
63 { 0.0, 1.0, 0.0 }, |
64 { 0.0, 0.0, 1.0 }, |
64 { 0.0, 0.0, 1.0 }, |
65 { -1370589.0, 0.0, 527612.0 } |
65 { -1370589.0, 0.0, 527612.0 } |
66 }; |
66 }; |
67 |
67 |
68 const double A1p76[3][3] = { |
68 const double A1p76[3][3] = { |
69 { 82758667.0, 1871391091.0, 4127413238.0 }, |
69 { 82758667.0, 1871391091.0, 4127413238.0 }, |
70 { 3672831523.0, 69195019.0, 1871391091.0 }, |
70 { 3672831523.0, 69195019.0, 1871391091.0 }, |
71 { 3672091415.0, 3528743235.0, 69195019.0 } |
71 { 3672091415.0, 3528743235.0, 69195019.0 } |
72 }; |
72 }; |
73 |
73 |
74 const double A2p76[3][3] = { |
74 const double A2p76[3][3] = { |
75 { 1511326704.0, 3759209742.0, 1610795712.0 }, |
75 { 1511326704.0, 3759209742.0, 1610795712.0 }, |
76 { 4292754251.0, 1511326704.0, 3889917532.0 }, |
76 { 4292754251.0, 1511326704.0, 3889917532.0 }, |
77 { 3859662829.0, 4292754251.0, 3708466080.0 } |
77 { 3859662829.0, 4292754251.0, 3708466080.0 } |
78 }; |
78 }; |
79 |
79 |
80 const double A1p127[3][3] = { |
80 const double A1p127[3][3] = { |
81 { 2427906178.0, 3580155704.0, 949770784.0 }, |
81 { 2427906178.0, 3580155704.0, 949770784.0 }, |
82 { 226153695.0, 1230515664.0, 3580155704.0 }, |
82 { 226153695.0, 1230515664.0, 3580155704.0 }, |
83 { 1988835001.0, 986791581.0, 1230515664.0 } |
83 { 1988835001.0, 986791581.0, 1230515664.0 } |
84 }; |
84 }; |
85 |
85 |
86 const double A2p127[3][3] = { |
86 const double A2p127[3][3] = { |
87 { 1464411153.0, 277697599.0, 1610723613.0 }, |
87 { 1464411153.0, 277697599.0, 1610723613.0 }, |
88 { 32183930.0, 1464411153.0, 1022607788.0 }, |
88 { 32183930.0, 1464411153.0, 1022607788.0 }, |
89 { 2824425944.0, 32183930.0, 2093834863.0 } |
89 { 2824425944.0, 32183930.0, 2093834863.0 } |
90 }; |
90 }; |
91 |
91 |
92 |
92 |
93 |
93 |
94 //------------------------------------------------------------------------- |
94 //------------------------------------------------------------------------- |
95 // Return (a*s + c) MOD m; a, s, c and m must be < 2^35 |
95 // Return (a*s + c) MOD m; a, s, c and m must be < 2^35 |
96 // |
96 // |
97 double MultModM (double a, double s, double c, double m) |
97 double MultModM (double a, double s, double c, double m) |
98 { |
98 { |
99 double v; |
99 double v; |
100 int32_t a1; |
100 int32_t a1; |
101 |
101 |
102 v = a * s + c; |
102 v = a * s + c; |
103 |
103 |
104 if (v >= two53 || v <= -two53) { |
104 if (v >= two53 || v <= -two53) { |
105 a1 = static_cast<int32_t> (a / two17); a -= a1 * two17; |
105 a1 = static_cast<int32_t> (a / two17); a -= a1 * two17; |
106 v = a1 * s; |
106 v = a1 * s; |
107 a1 = static_cast<int32_t> (v / m); v -= a1 * m; |
107 a1 = static_cast<int32_t> (v / m); v -= a1 * m; |
108 v = v * two17 + a * s + c; |
108 v = v * two17 + a * s + c; |
109 } |
109 } |
110 |
110 |
111 a1 = static_cast<int32_t> (v / m); |
111 a1 = static_cast<int32_t> (v / m); |
112 /* in case v < 0)*/ |
112 /* in case v < 0)*/ |
113 if ((v -= a1 * m) < 0.0) return v += m; else return v; |
113 if ((v -= a1 * m) < 0.0) return v += m;else return v; |
114 } |
114 } |
115 |
115 |
116 |
116 |
117 //------------------------------------------------------------------------- |
117 //------------------------------------------------------------------------- |
118 // Compute the vector v = A*s MOD m. Assume that -m < s[i] < m. |
118 // Compute the vector v = A*s MOD m. Assume that -m < s[i] < m. |
119 // Works also when v = s. |
119 // Works also when v = s. |
120 // |
120 // |
121 void MatVecModM (const double A[3][3], const double s[3], double v[3], |
121 void MatVecModM (const double A[3][3], const double s[3], double v[3], |
122 double m) |
122 double m) |
123 { |
123 { |
124 int i; |
124 int i; |
125 double x[3]; // Necessary if v = s |
125 double x[3]; // Necessary if v = s |
126 |
126 |
127 for (i = 0; i < 3; ++i) { |
127 for (i = 0; i < 3; ++i) { |
128 x[i] = MultModM (A[i][0], s[0], 0.0, m); |
128 x[i] = MultModM (A[i][0], s[0], 0.0, m); |
129 x[i] = MultModM (A[i][1], s[1], x[i], m); |
129 x[i] = MultModM (A[i][1], s[1], x[i], m); |
130 x[i] = MultModM (A[i][2], s[2], x[i], m); |
130 x[i] = MultModM (A[i][2], s[2], x[i], m); |
131 } |
131 } |
132 for (i = 0; i < 3; ++i) |
132 for (i = 0; i < 3; ++i) |
133 v[i] = x[i]; |
133 v[i] = x[i]; |
134 } |
134 } |
135 |
135 |
136 |
136 |
137 //------------------------------------------------------------------------- |
137 //------------------------------------------------------------------------- |
138 // Compute the matrix C = A*B MOD m. Assume that -m < s[i] < m. |
138 // Compute the matrix C = A*B MOD m. Assume that -m < s[i] < m. |
139 // Note: works also if A = C or B = C or A = B = C. |
139 // Note: works also if A = C or B = C or A = B = C. |
140 // |
140 // |
141 void MatMatModM (const double A[3][3], const double B[3][3], |
141 void MatMatModM (const double A[3][3], const double B[3][3], |
142 double C[3][3], double m) |
142 double C[3][3], double m) |
143 { |
143 { |
144 int i, j; |
144 int i, j; |
145 double V[3], W[3][3]; |
145 double V[3], W[3][3]; |
146 |
146 |
147 for (i = 0; i < 3; ++i) { |
147 for (i = 0; i < 3; ++i) { |
|
148 for (j = 0; j < 3; ++j) |
|
149 V[j] = B[j][i]; |
|
150 MatVecModM (A, V, V, m); |
|
151 for (j = 0; j < 3; ++j) |
|
152 W[j][i] = V[j]; |
|
153 } |
|
154 for (i = 0; i < 3; ++i) |
|
155 for (j = 0; j < 3; ++j) |
|
156 C[i][j] = W[i][j]; |
|
157 } |
|
158 |
|
159 |
|
160 //------------------------------------------------------------------------- |
|
161 // Compute the matrix B = (A^(2^e) Mod m); works also if A = B. |
|
162 // |
|
163 void MatTwoPowModM (const double A[3][3], double B[3][3], double m, int32_t e) |
|
164 { |
|
165 int i, j; |
|
166 |
|
167 /* initialize: B = A */ |
|
168 if (A != B) { |
|
169 for (i = 0; i < 3; ++i) |
148 for (j = 0; j < 3; ++j) |
170 for (j = 0; j < 3; ++j) |
149 V[j] = B[j][i]; |
171 B[i][j] = A[i][j]; |
150 MatVecModM (A, V, V, m); |
172 } |
151 for (j = 0; j < 3; ++j) |
173 /* Compute B = A^(2^e) mod m */ |
152 W[j][i] = V[j]; |
174 for (i = 0; i < e; i++) |
153 } |
175 MatMatModM (B, B, B, m); |
154 for (i = 0; i < 3; ++i) |
|
155 for (j = 0; j < 3; ++j) |
|
156 C[i][j] = W[i][j]; |
|
157 } |
|
158 |
|
159 |
|
160 //------------------------------------------------------------------------- |
|
161 // Compute the matrix B = (A^(2^e) Mod m); works also if A = B. |
|
162 // |
|
163 void MatTwoPowModM (const double A[3][3], double B[3][3], double m, int32_t e) |
|
164 { |
|
165 int i, j; |
|
166 |
|
167 /* initialize: B = A */ |
|
168 if (A != B) { |
|
169 for (i = 0; i < 3; ++i) |
|
170 for (j = 0; j < 3; ++j) |
|
171 B[i][j] = A[i][j]; |
|
172 } |
|
173 /* Compute B = A^(2^e) mod m */ |
|
174 for (i = 0; i < e; i++) |
|
175 MatMatModM (B, B, B, m); |
|
176 } |
176 } |
177 |
177 |
178 |
178 |
179 //------------------------------------------------------------------------- |
179 //------------------------------------------------------------------------- |
180 // Compute the matrix B = (A^n Mod m); works even if A = B. |
180 // Compute the matrix B = (A^n Mod m); works even if A = B. |
181 // |
181 // |
182 void MatPowModM (const double A[3][3], double B[3][3], double m, int32_t n) |
182 void MatPowModM (const double A[3][3], double B[3][3], double m, int32_t n) |
183 { |
183 { |
184 int i, j; |
184 int i, j; |
185 double W[3][3]; |
185 double W[3][3]; |
186 |
186 |
187 /* initialize: W = A; B = I */ |
187 /* initialize: W = A; B = I */ |
188 for (i = 0; i < 3; ++i) |
188 for (i = 0; i < 3; ++i) |
189 for (j = 0; j < 3; ++j) { |
189 for (j = 0; j < 3; ++j) { |
190 W[i][j] = A[i][j]; |
190 W[i][j] = A[i][j]; |
191 B[i][j] = 0.0; |
191 B[i][j] = 0.0; |
192 } |
192 } |
193 for (j = 0; j < 3; ++j) |
193 for (j = 0; j < 3; ++j) |
194 B[j][j] = 1.0; |
194 B[j][j] = 1.0; |
195 |
195 |
196 /* Compute B = A^n mod m using the binary decomposition of n */ |
196 /* Compute B = A^n mod m using the binary decomposition of n */ |
197 while (n > 0) { |
197 while (n > 0) { |
198 if (n % 2) MatMatModM (W, B, B, m); |
198 if (n % 2) MatMatModM (W, B, B, m); |
199 MatMatModM (W, W, W, m); |
199 MatMatModM (W, W, W, m); |
200 n /= 2; |
200 n /= 2; |
201 } |
201 } |
202 } |
202 } |
203 |
203 |
204 |
204 |
205 static ns3::GlobalValue g_rngSeed ("RngSeed", |
205 static ns3::GlobalValue g_rngSeed ("RngSeed", |
212 ns3::MakeIntegerChecker<uint32_t> ()); |
212 ns3::MakeIntegerChecker<uint32_t> ()); |
213 |
213 |
214 } // end of anonymous namespace |
214 } // end of anonymous namespace |
215 |
215 |
216 |
216 |
217 namespace ns3{ |
217 namespace ns3 { |
218 //------------------------------------------------------------------------- |
218 //------------------------------------------------------------------------- |
219 // Generate the next random number. |
219 // Generate the next random number. |
220 // |
220 // |
221 double RngStream::U01 () |
221 double RngStream::U01 () |
222 { |
222 { |
223 int32_t k; |
223 int32_t k; |
224 double p1, p2, u; |
224 double p1, p2, u; |
225 |
225 |
226 /* Component 1 */ |
226 /* Component 1 */ |
227 p1 = a12 * Cg[1] - a13n * Cg[0]; |
227 p1 = a12 * Cg[1] - a13n * Cg[0]; |
228 k = static_cast<int32_t> (p1 / m1); |
228 k = static_cast<int32_t> (p1 / m1); |
229 p1 -= k * m1; |
229 p1 -= k * m1; |
230 if (p1 < 0.0) p1 += m1; |
230 if (p1 < 0.0) p1 += m1; |
231 Cg[0] = Cg[1]; Cg[1] = Cg[2]; Cg[2] = p1; |
231 Cg[0] = Cg[1]; Cg[1] = Cg[2]; Cg[2] = p1; |
232 |
232 |
233 /* Component 2 */ |
233 /* Component 2 */ |
234 p2 = a21 * Cg[5] - a23n * Cg[3]; |
234 p2 = a21 * Cg[5] - a23n * Cg[3]; |
235 k = static_cast<int32_t> (p2 / m2); |
235 k = static_cast<int32_t> (p2 / m2); |
236 p2 -= k * m2; |
236 p2 -= k * m2; |
237 if (p2 < 0.0) p2 += m2; |
237 if (p2 < 0.0) p2 += m2; |
238 Cg[3] = Cg[4]; Cg[4] = Cg[5]; Cg[5] = p2; |
238 Cg[3] = Cg[4]; Cg[4] = Cg[5]; Cg[5] = p2; |
239 |
239 |
240 /* Combination */ |
240 /* Combination */ |
241 u = ((p1 > p2) ? (p1 - p2) * norm : (p1 - p2 + m1) * norm); |
241 u = ((p1 > p2) ? (p1 - p2) * norm : (p1 - p2 + m1) * norm); |
242 |
242 |
243 return (anti == false) ? u : (1 - u); |
243 return (anti == false) ? u : (1 - u); |
244 } |
244 } |
245 |
245 |
246 |
246 |
247 //------------------------------------------------------------------------- |
247 //------------------------------------------------------------------------- |
248 // Generate the next random number with extended (53 bits) precision. |
248 // Generate the next random number with extended (53 bits) precision. |
249 // |
249 // |
250 double RngStream::U01d () |
250 double RngStream::U01d () |
251 { |
251 { |
252 double u; |
252 double u; |
253 u = U01(); |
253 u = U01(); |
254 if (anti) { |
254 if (anti) { |
255 // Don't forget that U01() returns 1 - u in the antithetic case |
255 // Don't forget that U01() returns 1 - u in the antithetic case |
256 u += (U01() - 1.0) * fact; |
256 u += (U01() - 1.0) * fact; |
257 return (u < 0.0) ? u + 1.0 : u; |
257 return (u < 0.0) ? u + 1.0 : u; |
258 } else { |
258 } else { |
259 u += U01() * fact; |
259 u += U01() * fact; |
260 return (u < 1.0) ? u : (u - 1.0); |
260 return (u < 1.0) ? u : (u - 1.0); |
261 } |
261 } |
262 } |
262 } |
263 |
263 |
264 //------------------------------------------------------------------------- |
264 //------------------------------------------------------------------------- |
265 // Check that the seeds are legitimate values. Returns true if legal seeds, |
265 // Check that the seeds are legitimate values. Returns true if legal seeds, |
266 // false otherwise. |
266 // false otherwise. |
267 // |
267 // |
268 bool RngStream::CheckSeed (const uint32_t seed[6]) |
268 bool RngStream::CheckSeed (const uint32_t seed[6]) |
269 { |
269 { |
270 int i; |
270 int i; |
271 |
271 |
272 for (i = 0; i < 3; ++i) { |
272 for (i = 0; i < 3; ++i) { |
273 if (seed[i] >= m1) { |
273 if (seed[i] >= m1) { |
274 cerr << "****************************************\n\n" |
274 cerr << "****************************************\n\n" |
275 << "ERROR: Seed[" << i << "] >= 4294967087, Seed is not set." |
275 << "ERROR: Seed[" << i << "] >= 4294967087, Seed is not set." |
276 << "\n\n****************************************\n\n"; |
276 << "\n\n****************************************\n\n"; |
277 return (false); |
277 return (false); |
278 } |
278 } |
279 } |
279 } |
280 for (i = 3; i < 6; ++i) { |
280 for (i = 3; i < 6; ++i) { |
281 if (seed[i] >= m2) { |
281 if (seed[i] >= m2) { |
282 cerr << "Seed[" << i << "] = " << seed[i] << endl; |
282 cerr << "Seed[" << i << "] = " << seed[i] << endl; |
283 cerr << "*****************************************\n\n" |
283 cerr << "*****************************************\n\n" |
284 << "ERROR: Seed[" << i << "] >= 4294944443, Seed is not set." |
284 << "ERROR: Seed[" << i << "] >= 4294944443, Seed is not set." |
285 << "\n\n*****************************************\n\n"; |
285 << "\n\n*****************************************\n\n"; |
286 return (false); |
286 return (false); |
287 } |
287 } |
288 } |
288 } |
289 if (seed[0] == 0 && seed[1] == 0 && seed[2] == 0) { |
289 if (seed[0] == 0 && seed[1] == 0 && seed[2] == 0) { |
290 cerr << "****************************\n\n" |
290 cerr << "****************************\n\n" |
291 << "ERROR: First 3 seeds = 0.\n\n" |
291 << "ERROR: First 3 seeds = 0.\n\n" |
292 << "****************************\n\n"; |
292 << "****************************\n\n"; |
293 return (false); |
293 return (false); |
294 } |
294 } |
295 if (seed[3] == 0 && seed[4] == 0 && seed[5] == 0) { |
295 if (seed[3] == 0 && seed[4] == 0 && seed[5] == 0) { |
296 cerr << "****************************\n\n" |
296 cerr << "****************************\n\n" |
297 << "ERROR: Last 3 seeds = 0.\n\n" |
297 << "ERROR: Last 3 seeds = 0.\n\n" |
298 << "****************************\n\n"; |
298 << "****************************\n\n"; |
299 return (false); |
299 return (false); |
300 } |
300 } |
301 return true; |
301 return true; |
302 } |
302 } |
303 |
303 |
304 uint32_t |
304 uint32_t |
305 RngStream::EnsureGlobalInitialized (void) |
305 RngStream::EnsureGlobalInitialized (void) |
306 { |
306 { |
490 // if e = 0, let n = c. |
490 // if e = 0, let n = c. |
491 // Jump n steps forward if n > 0, backwards if n < 0. |
491 // Jump n steps forward if n > 0, backwards if n < 0. |
492 // |
492 // |
493 void RngStream::AdvanceState (int32_t e, int32_t c) |
493 void RngStream::AdvanceState (int32_t e, int32_t c) |
494 { |
494 { |
495 double B1[3][3], C1[3][3], B2[3][3], C2[3][3]; |
495 double B1[3][3], C1[3][3], B2[3][3], C2[3][3]; |
496 |
496 |
497 if (e > 0) { |
497 if (e > 0) { |
498 MatTwoPowModM (A1p0, B1, m1, e); |
498 MatTwoPowModM (A1p0, B1, m1, e); |
499 MatTwoPowModM (A2p0, B2, m2, e); |
499 MatTwoPowModM (A2p0, B2, m2, e); |
500 } else if (e < 0) { |
500 } else if (e < 0) { |
501 MatTwoPowModM (InvA1, B1, m1, -e); |
501 MatTwoPowModM (InvA1, B1, m1, -e); |
502 MatTwoPowModM (InvA2, B2, m2, -e); |
502 MatTwoPowModM (InvA2, B2, m2, -e); |
503 } |
503 } |
504 |
504 |
505 if (c >= 0) { |
505 if (c >= 0) { |
506 MatPowModM (A1p0, C1, m1, c); |
506 MatPowModM (A1p0, C1, m1, c); |
507 MatPowModM (A2p0, C2, m2, c); |
507 MatPowModM (A2p0, C2, m2, c); |
508 } else { |
508 } else { |
509 MatPowModM (InvA1, C1, m1, -c); |
509 MatPowModM (InvA1, C1, m1, -c); |
510 MatPowModM (InvA2, C2, m2, -c); |
510 MatPowModM (InvA2, C2, m2, -c); |
511 } |
511 } |
512 |
512 |
513 if (e) { |
513 if (e) { |
514 MatMatModM (B1, C1, C1, m1); |
514 MatMatModM (B1, C1, C1, m1); |
515 MatMatModM (B2, C2, C2, m2); |
515 MatMatModM (B2, C2, C2, m2); |
516 } |
516 } |
517 |
517 |
518 MatVecModM (C1, Cg, Cg, m1); |
518 MatVecModM (C1, Cg, Cg, m1); |
519 MatVecModM (C2, &Cg[3], &Cg[3], m2); |
519 MatVecModM (C2, &Cg[3], &Cg[3], m2); |
520 } |
520 } |
521 |
521 |
522 |
522 |
523 //------------------------------------------------------------------------- |
523 //------------------------------------------------------------------------- |
524 void RngStream::GetState (uint32_t seed[6]) const |
524 void RngStream::GetState (uint32_t seed[6]) const |
525 { |
525 { |
526 for (int i = 0; i < 6; ++i) |
526 for (int i = 0; i < 6; ++i) |
527 seed[i] = static_cast<uint32_t> (Cg[i]); |
527 seed[i] = static_cast<uint32_t> (Cg[i]); |
528 } |
528 } |
529 |
529 |
530 |
530 |
531 //------------------------------------------------------------------------- |
531 //------------------------------------------------------------------------- |
532 void RngStream::IncreasedPrecis (bool incp) |
532 void RngStream::IncreasedPrecis (bool incp) |
533 { |
533 { |
534 incPrec = incp; |
534 incPrec = incp; |
535 } |
535 } |
536 |
536 |
537 |
537 |
538 //------------------------------------------------------------------------- |
538 //------------------------------------------------------------------------- |
539 void RngStream::SetAntithetic (bool a) |
539 void RngStream::SetAntithetic (bool a) |
540 { |
540 { |
541 anti = a; |
541 anti = a; |
542 } |
542 } |
543 |
543 |
544 |
544 |
545 //------------------------------------------------------------------------- |
545 //------------------------------------------------------------------------- |
546 // Generate the next random number. |
546 // Generate the next random number. |
547 // |
547 // |
548 double RngStream::RandU01 () |
548 double RngStream::RandU01 () |
549 { |
549 { |
550 if (incPrec) |
550 if (incPrec) |
551 return U01d(); |
551 return U01d(); |
552 else |
552 else |
553 return U01(); |
553 return U01(); |
554 } |
554 } |
555 |
555 |
556 |
556 |
557 //------------------------------------------------------------------------- |
557 //------------------------------------------------------------------------- |
558 // Generate the next random integer. |
558 // Generate the next random integer. |
559 // |
559 // |
560 int32_t RngStream::RandInt (int32_t low, int32_t high) |
560 int32_t RngStream::RandInt (int32_t low, int32_t high) |
561 { |
561 { |
562 return low + static_cast<int32_t> ((high - low + 1) * RandU01 ()); |
562 return low + static_cast<int32_t> ((high - low + 1) * RandU01 ()); |
563 }; |
563 }; |
564 |
564 |
565 } //namespace ns3 |
565 } //namespace ns3 |