1 // random number generation (out of line) -*- C++ -*-
3 // Copyright (C) 2006 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 2, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING. If not, write to the Free
18 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction. Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License. This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
34 _GLIBCXX_BEGIN_NAMESPACE(tr1)
37 * Implementation-space details.
41 // General case for x = (ax + c) mod m -- use Schrage's algorithm to avoid
44 // Because a and c are compile-time integral constants the compiler kindly
45 // elides any unreachable paths.
47 // Preconditions: a > 0, m > 0.
49 template<typename _Tp, _Tp __a, _Tp __c, _Tp __m, bool>
59 static const _Tp __q = __m / __a;
60 static const _Tp __r = __m % __a;
62 _Tp __t1 = __a * (__x % __q);
63 _Tp __t2 = __r * (__x / __q);
67 __x = __m - __t2 + __t1;
72 const _Tp __d = __m - __x;
82 // Special case for m == 0 -- use unsigned integer overflow as modulo
84 template<typename _Tp, _Tp __a, _Tp __c, _Tp __m>
85 struct _Mod<_Tp, __a, __c, __m, true>
89 { return __a * __x + __c; }
92 // Dispatch based on modulus value to prevent divide-by-zero compile-time
93 // errors when m == 0.
94 template<typename _Tp, _Tp __a, _Tp __c, _Tp __m>
97 { return _Mod<_Tp, __a, __c, __m, __m == 0>::__calc(__x); }
99 // Like the above, for a == 1, c == 0, in terms of w.
100 template<typename _Tp, _Tp __w, bool>
105 { return __x % (_Tp(1) << __w); }
108 template<typename _Tp, _Tp __w>
109 struct _Mod_w<_Tp, __w, true>
116 template<typename _Tp, _Tp __w>
119 { return _Mod_w<_Tp, __w,
120 __w == std::numeric_limits<_Tp>::digits>::__calc(__x); }
122 // Selector to return the maximum value possible that will fit in
123 // @p __w bits of @p _Tp.
124 template<typename _Tp, _Tp __w, bool>
129 { return (_Tp(1) << __w) - 1; }
132 template<typename _Tp, _Tp __w>
133 struct _Max_w<_Tp, __w, true>
137 { return std::numeric_limits<_Tp>::max(); }
140 } // namespace _Private
144 * Constructs the LCR engine with integral seed @p __x0.
146 template<class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
147 linear_congruential<_UIntType, __a, __c, __m>::
148 linear_congruential(unsigned long __x0)
149 { this->seed(__x0); }
152 * Constructs the LCR engine with seed generated from @p __g.
154 template<class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
156 linear_congruential<_UIntType, __a, __c, __m>::
157 linear_congruential(_Gen& __g)
161 * Seeds the LCR with integral value @p __x0, adjusted so that the
162 * ring identity is never a member of the convergence set.
164 template<class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
166 linear_congruential<_UIntType, __a, __c, __m>::
167 seed(unsigned long __x0)
169 if ((_Private::__mod<_UIntType, 1, 0, __m>(__c) == 0)
170 && (_Private::__mod<_UIntType, 1, 0, __m>(__x0) == 0))
171 _M_x = _Private::__mod<_UIntType, 1, 0, __m>(1);
173 _M_x = _Private::__mod<_UIntType, 1, 0, __m>(__x0);
177 * Seeds the LCR engine with a value generated by @p __g.
179 template<class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
182 linear_congruential<_UIntType, __a, __c, __m>::
183 seed(_Gen& __g, false_type)
185 _UIntType __x0 = __g();
186 if ((_Private::__mod<_UIntType, 1, 0, __m>(__c) == 0)
187 && (_Private::__mod<_UIntType, 1, 0, __m>(__x0) == 0))
188 _M_x = _Private::__mod<_UIntType, 1, 0, __m>(1);
190 _M_x = _Private::__mod<_UIntType, 1, 0, __m>(__x0);
194 * Returns a value that is less than or equal to all values potentially
195 * returned by operator(). The return value of this function does not
196 * change during the lifetime of the object..
198 * The minumum depends on the @p __c parameter: if it is zero, the
199 * minimum generated must be > 0, otherwise 0 is allowed.
201 template<class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
202 typename linear_congruential<_UIntType, __a, __c, __m>::result_type
203 linear_congruential<_UIntType, __a, __c, __m>::
205 { return (_Private::__mod<_UIntType, 1, 0, __m>(__c) == 0) ? 1 : 0; }
208 * Gets the maximum possible value of the generated range.
210 * For a linear congruential generator, the maximum is always @p __m - 1.
212 template<class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
213 typename linear_congruential<_UIntType, __a, __c, __m>::result_type
214 linear_congruential<_UIntType, __a, __c, __m>::
216 { return (__m == 0) ? std::numeric_limits<_UIntType>::max() : (__m - 1); }
219 * Gets the next generated value in sequence.
221 template<class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
222 typename linear_congruential<_UIntType, __a, __c, __m>::result_type
223 linear_congruential<_UIntType, __a, __c, __m>::
226 _M_x = _Private::__mod<_UIntType, __a, __c, __m>(_M_x);
231 template<class _UIntType, int __w, int __n, int __m, int __r,
232 _UIntType __a, int __u, int __s,
233 _UIntType __b, int __t, _UIntType __c, int __l>
235 mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s,
236 __b, __t, __c, __l>::
237 seed(unsigned long __value)
239 _M_x[0] = _Private::__mod_w<_UIntType, __w>(__value);
241 for (int __i = 1; __i < state_size; ++__i)
243 _UIntType __x = _M_x[__i - 1];
244 __x ^= __x >> (__w - 2);
247 _M_x[__i] = _Private::__mod_w<_UIntType, __w>(__x);
252 template<class _UIntType, int __w, int __n, int __m, int __r,
253 _UIntType __a, int __u, int __s,
254 _UIntType __b, int __t, _UIntType __c, int __l>
257 mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s,
258 __b, __t, __c, __l>::
259 seed(_Gen& __gen, false_type)
261 for (int __i = 0; __i < state_size; ++__i)
262 _M_x[__i] = _Private::__mod_w<_UIntType, __w>(__gen());
266 template<class _UIntType, int __w, int __n, int __m, int __r,
267 _UIntType __a, int __u, int __s,
268 _UIntType __b, int __t, _UIntType __c, int __l>
270 mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s,
271 __b, __t, __c, __l>::result_type
272 mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s,
273 __b, __t, __c, __l>::
276 using _Private::_Max_w;
277 using std::numeric_limits;
278 return _Max_w<_UIntType, __w,
279 __w == numeric_limits<_UIntType>::digits>::__value();
282 template<class _UIntType, int __w, int __n, int __m, int __r,
283 _UIntType __a, int __u, int __s,
284 _UIntType __b, int __t, _UIntType __c, int __l>
286 mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s,
287 __b, __t, __c, __l>::result_type
288 mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s,
289 __b, __t, __c, __l>::
292 // Reload the vector - cost is O(n) amortized over n calls.
293 if (_M_p >= state_size)
295 const _UIntType __upper_mask = (~_UIntType()) << __r;
296 const _UIntType __lower_mask = ~__upper_mask;
298 for (int __k = 0; __k < (__n - __m); ++__k)
300 _UIntType __y = ((_M_x[__k] & __upper_mask)
301 |(_M_x[__k + 1] & __lower_mask));
302 _M_x[__k] = (_M_x[__k + __m] ^ (__y >> 1)
303 ^ ((__y & 0x01) ? __a : 0));
306 for (int __k = (__n - __m); __k < (__n - 1); ++__k)
308 _UIntType __y = ((_M_x[__k] & __upper_mask)
309 | (_M_x[__k + 1] & __lower_mask));
310 _M_x[__k] = (_M_x[__k + (__m - __n)] ^ (__y >> 1)
311 ^ ((__y & 0x01) ? __a : 0));
317 // Calculate o(x(i)).
318 result_type __z = _M_x[_M_p++];
320 __z ^= (__z << __s) & __b;
321 __z ^= (__z << __t) & __c;
328 template<typename _IntType, _IntType __m, int __s, int __r>
330 subtract_with_carry<_IntType, __m, __s, __r>::
331 seed(unsigned long __value)
333 std::tr1::linear_congruential<unsigned long, 40014, 0, 2147483563>
336 for (int __i = 0; __i < long_lag; ++__i)
337 _M_x[__i] = _Private::__mod<_IntType, 1, 0, modulus>(__lcg());
339 _M_carry = (_M_x[long_lag - 1] == 0) ? 1 : 0;
344 // This implementation differs from the tr1 spec because the tr1 spec refused
345 // to make any sense to me: the exponent of the factor in the spec goes from
346 // 1 to (n-1), but it would only make sense to me if it went from 0 to (n-1).
348 // This algorithm is still problematic because it can overflow left right and
351 template<typename _IntType, _IntType __m, int __s, int __r>
354 subtract_with_carry<_IntType, __m, __s, __r>::
355 seed(_Gen& __gen, false_type)
357 const int __n = (std::numeric_limits<_IntType>::digits + 31) / 32;
358 for (int __i = 0; __i < long_lag; ++__i)
361 unsigned long __factor = 1;
362 for (int __j = 0; __j < __n; ++__j)
364 _M_x[__i] += __gen() * __factor;
365 __factor *= 0x80000000;
367 _M_x[__i] = _Private::__mod<_IntType, 1, 0, modulus>(_M_x[__i]);
369 _M_carry = (_M_x[long_lag - 1] == 0) ? 1 : 0;
373 template<typename _IntType, _IntType __m, int __s, int __r>
374 typename subtract_with_carry<_IntType, __m, __s, __r>::result_type
375 subtract_with_carry<_IntType, __m, __s, __r>::
378 // Derive short lag index from current index.
379 int __ps = _M_p - short_lag;
383 // Calculate new x(i) without overflow or division.
385 if (_M_x[__ps] >= _M_x[_M_p] + _M_carry)
387 __xi = _M_x[__ps] - _M_x[_M_p] - _M_carry;
392 __xi = modulus - _M_x[_M_p] - _M_carry + _M_x[__ps];
397 // Adjust current index to loop around in ring buffer.
398 if (_M_p >= long_lag)
405 template<class _UniformRandomNumberGenerator, int __p, int __r>
406 typename discard_block<_UniformRandomNumberGenerator,
407 __p, __r>::result_type
408 discard_block<_UniformRandomNumberGenerator, __p, __r>::
411 if (_M_n >= used_block)
413 while (_M_n < block_size)
424 _GLIBCXX_END_NAMESPACE