1 // (C) Copyright John Maddock 2005.
2 // (C) Copyright Henry S. Warren 2005.
3 // Use, modification and distribution are subject to the
4 // Boost Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 #ifndef BOOST_TR1_RANDOM_HPP_INCLUDED
8 # define BOOST_TR1_RANDOM_HPP_INCLUDED
9 # include <boost/tr1/detail/config.hpp>
11 #ifdef BOOST_HAS_TR1_RANDOM
12 # include BOOST_TR1_HEADER(random)
15 #include <boost/random.hpp>
17 // Sunpros linker complains if we so much as include this...
18 # include <boost/nondet_random.hpp>
20 #include <boost/tr1/detail/functor2iterator.hpp>
21 #include <boost/type_traits/is_fundamental.hpp>
22 #include <boost/type_traits/is_same.hpp>
24 namespace std
{ namespace tr1
{
26 using ::boost::variate_generator
;
28 template<class UIntType
, UIntType a
, UIntType c
, UIntType m
>
29 class linear_congruential
32 typedef ::boost::random::linear_congruential
<UIntType
, a
, c
, m
, 0> impl_type
;
35 typedef UIntType result_type
;
37 BOOST_STATIC_CONSTANT(UIntType
, multiplier
= a
);
38 BOOST_STATIC_CONSTANT(UIntType
, increment
= c
);
39 BOOST_STATIC_CONSTANT(UIntType
, modulus
= m
);
40 // constructors and member function
41 explicit linear_congruential(unsigned long x0
= 1)
43 linear_congruential(const linear_congruential
& that
)
45 template<class Gen
> linear_congruential(Gen
& g
)
47 init1(g
, ::boost::is_same
<Gen
,linear_congruential
>());
49 void seed(unsigned long x0
= 1)
51 template<class Gen
> void seed(Gen
& g
)
53 init2(g
, ::boost::is_fundamental
<Gen
>());
55 result_type min
BOOST_PREVENT_MACRO_SUBSTITUTION() const
56 { return (m_gen
.min
)(); }
57 result_type max
BOOST_PREVENT_MACRO_SUBSTITUTION() const
58 { return (m_gen
.max
)(); }
59 result_type
operator()()
63 bool operator==(const linear_congruential
& that
)const
64 { return m_gen
== that
.m_gen
; }
65 bool operator!=(const linear_congruential
& that
)const
66 { return m_gen
!= that
.m_gen
; }
68 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
69 template<class CharT
, class Traits
>
70 friend std::basic_ostream
<CharT
,Traits
>&
71 operator<<(std::basic_ostream
<CharT
,Traits
>& os
,
72 const linear_congruential
& lcg
)
74 return os
<< lcg
.m_gen
;
77 template<class CharT
, class Traits
>
78 friend std::basic_istream
<CharT
,Traits
>&
79 operator>>(std::basic_istream
<CharT
,Traits
>& is
,
80 linear_congruential
& lcg
)
82 return is
>> lcg
.m_gen
;
88 void init1(Gen
& g
, const ::boost::true_type
&)
93 void init1(Gen
& g
, const ::boost::false_type
&)
95 init2(g
, ::boost::is_fundamental
<Gen
>());
98 void init2(Gen
& g
, const ::boost::true_type
&)
100 m_gen
.seed(static_cast<unsigned long>(g
));
103 void init2(Gen
& g
, const ::boost::false_type
&)
105 //typedef typename Gen::result_type gen_rt;
106 boost::tr1_details::functor2iterator
<Gen
, unsigned long> f1(g
), f2
;
112 template<class UIntType
, int w
, int n
, int m
, int r
,
113 UIntType a
, int u
, int s
, UIntType b
, int t
, UIntType c
, int l
>
114 class mersenne_twister
116 typedef ::boost::random::mersenne_twister
117 <UIntType
, w
, n
, m
, r
, a
, u
, s
, b
, t
, c
, l
, 0> imp_type
;
120 typedef UIntType result_type
;
122 BOOST_STATIC_CONSTANT(int, word_size
= w
);
123 BOOST_STATIC_CONSTANT(int, state_size
= n
);
124 BOOST_STATIC_CONSTANT(int, shift_size
= m
);
125 BOOST_STATIC_CONSTANT(int, mask_bits
= r
);
126 BOOST_STATIC_CONSTANT(UIntType
, parameter_a
= a
);
127 BOOST_STATIC_CONSTANT(int, output_u
= u
);
128 BOOST_STATIC_CONSTANT(int, output_s
= s
);
129 BOOST_STATIC_CONSTANT(UIntType
, output_b
= b
);
130 BOOST_STATIC_CONSTANT(int, output_t
= t
);
131 BOOST_STATIC_CONSTANT(UIntType
, output_c
= c
);
132 BOOST_STATIC_CONSTANT(int, output_l
= l
);
133 // constructors and member function
135 explicit mersenne_twister(unsigned long value
)
136 : m_gen(value
== 0 ? 4357UL : value
){}
137 template<class Gen
> mersenne_twister(Gen
& g
)
139 init1(g
, ::boost::is_same
<mersenne_twister
,Gen
>());
143 void seed(unsigned long value
)
144 { m_gen
.seed(value
== 0 ? 5489UL : value
); }
145 template<class Gen
> void seed(Gen
& g
)
146 { init2(g
, ::boost::is_fundamental
<Gen
>()); }
147 result_type min
BOOST_PREVENT_MACRO_SUBSTITUTION() const
148 { return (m_gen
.min
)(); }
149 result_type max
BOOST_PREVENT_MACRO_SUBSTITUTION() const
150 { return (m_gen
.max
)(); }
151 result_type
operator()()
153 bool operator==(const mersenne_twister
& that
)const
154 { return m_gen
== that
.m_gen
; }
155 bool operator!=(const mersenne_twister
& that
)const
156 { return m_gen
!= that
.m_gen
; }
158 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
159 template<class CharT
, class Traits
>
160 friend std::basic_ostream
<CharT
,Traits
>&
161 operator<<(std::basic_ostream
<CharT
,Traits
>& os
,
162 const mersenne_twister
& lcg
)
164 return os
<< lcg
.m_gen
;
167 template<class CharT
, class Traits
>
168 friend std::basic_istream
<CharT
,Traits
>&
169 operator>>(std::basic_istream
<CharT
,Traits
>& is
,
170 mersenne_twister
& lcg
)
172 return is
>> lcg
.m_gen
;
177 void init1(Gen
& g
, const ::boost::true_type
&)
182 void init1(Gen
& g
, const ::boost::false_type
&)
184 init2(g
, ::boost::is_fundamental
<Gen
>());
187 void init2(Gen
& g
, const ::boost::true_type
&)
189 m_gen
.seed(static_cast<unsigned long>(g
== 0 ? 4357UL : g
));
192 void init2(Gen
& g
, const ::boost::false_type
&)
199 template<class IntType
, IntType m
, int s
, int r
>
200 class subtract_with_carry
204 typedef IntType result_type
;
206 BOOST_STATIC_CONSTANT(IntType
, modulus
= m
);
207 BOOST_STATIC_CONSTANT(int, long_lag
= r
);
208 BOOST_STATIC_CONSTANT(int, short_lag
= s
);
210 // constructors and member function
211 subtract_with_carry(){}
212 explicit subtract_with_carry(unsigned long value
)
213 : m_gen(value
== 0 ? 19780503UL : value
){}
214 template<class Gen
> subtract_with_carry(Gen
& g
)
215 { init1(g
, ::boost::is_same
<Gen
, subtract_with_carry
<IntType
, m
, s
, r
> >()); }
216 void seed(unsigned long value
= 19780503ul)
217 { m_gen
.seed(value
== 0 ? 19780503UL : value
); }
218 template<class Gen
> void seed(Gen
& g
)
219 { init2(g
, ::boost::is_fundamental
<Gen
>()); }
220 result_type min
BOOST_PREVENT_MACRO_SUBSTITUTION() const
221 { return (m_gen
.min
)(); }
222 result_type max
BOOST_PREVENT_MACRO_SUBSTITUTION() const
223 { return (m_gen
.max
)(); }
224 result_type
operator()()
226 bool operator==(const subtract_with_carry
& that
)const
227 { return m_gen
== that
.m_gen
; }
228 bool operator!=(const subtract_with_carry
& that
)const
229 { return m_gen
!= that
.m_gen
; }
231 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
232 template<class CharT
, class Traits
>
233 friend std::basic_ostream
<CharT
,Traits
>&
234 operator<<(std::basic_ostream
<CharT
,Traits
>& os
,
235 const subtract_with_carry
& lcg
)
237 return os
<< lcg
.m_gen
;
240 template<class CharT
, class Traits
>
241 friend std::basic_istream
<CharT
,Traits
>&
242 operator>>(std::basic_istream
<CharT
,Traits
>& is
,
243 subtract_with_carry
& lcg
)
245 return is
>> lcg
.m_gen
;
250 void init1(Gen
& g
, const ::boost::true_type
&)
255 void init1(Gen
& g
, const ::boost::false_type
&)
257 init2(g
, ::boost::is_fundamental
<Gen
>());
260 void init2(Gen
& g
, const ::boost::true_type
&)
262 m_gen
.seed(static_cast<unsigned long>(g
== 0 ? 19780503UL : g
));
265 void init2(Gen
& g
, const ::boost::false_type
&)
269 ::boost::random::subtract_with_carry
<IntType
, m
, s
, r
, 0> m_gen
;
272 template<class RealType
, int w
, int s
, int r
>
273 class subtract_with_carry_01
277 typedef RealType result_type
;
279 BOOST_STATIC_CONSTANT(int, word_size
= w
);
280 BOOST_STATIC_CONSTANT(int, long_lag
= r
);
281 BOOST_STATIC_CONSTANT(int, short_lag
= s
);
283 // constructors and member function
284 subtract_with_carry_01(){}
285 explicit subtract_with_carry_01(unsigned long value
)
286 : m_gen(value
== 0 ? 19780503UL : value
){}
287 template<class Gen
> subtract_with_carry_01(Gen
& g
)
288 { init1(g
, ::boost::is_same
<Gen
, subtract_with_carry_01
<RealType
, w
, s
, r
> >()); }
289 void seed(unsigned long value
= 19780503UL)
290 { m_gen
.seed(value
== 0 ? 19780503UL : value
); }
291 template<class Gen
> void seed(Gen
& g
)
292 { init2(g
, ::boost::is_fundamental
<Gen
>()); }
293 result_type min
BOOST_PREVENT_MACRO_SUBSTITUTION() const
294 { return (m_gen
.min
)(); }
295 result_type max
BOOST_PREVENT_MACRO_SUBSTITUTION() const
296 { return (m_gen
.max
)(); }
297 result_type
operator()()
299 bool operator==(const subtract_with_carry_01
& that
)const
300 { return m_gen
== that
.m_gen
; }
301 bool operator!=(const subtract_with_carry_01
& that
)const
302 { return m_gen
!= that
.m_gen
; }
304 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
305 template<class CharT
, class Traits
>
306 friend std::basic_ostream
<CharT
,Traits
>&
307 operator<<(std::basic_ostream
<CharT
,Traits
>& os
,
308 const subtract_with_carry_01
& lcg
)
310 return os
<< lcg
.m_gen
;
313 template<class CharT
, class Traits
>
314 friend std::basic_istream
<CharT
,Traits
>&
315 operator>>(std::basic_istream
<CharT
,Traits
>& is
,
316 subtract_with_carry_01
& lcg
)
318 return is
>> lcg
.m_gen
;
323 void init1(Gen
& g
, const ::boost::true_type
&)
328 void init1(Gen
& g
, const ::boost::false_type
&)
330 init2(g
, ::boost::is_fundamental
<Gen
>());
333 void init2(Gen
& g
, const ::boost::true_type
&)
335 m_gen
.seed(static_cast<unsigned long>(g
== 0 ? 19780503UL : g
));
338 void init2(Gen
& g
, const ::boost::false_type
&)
340 //typedef typename Gen::result_type gen_rt;
341 boost::tr1_details::functor2iterator
<Gen
, unsigned long> f1(g
), f2
;
344 ::boost::random::subtract_with_carry_01
<RealType
, w
, s
, r
, 0> m_gen
;
347 using ::boost::random::discard_block
;
349 template<class UniformRandomNumberGenerator1
, int s1
, class UniformRandomNumberGenerator2
, int s2
>
354 typedef UniformRandomNumberGenerator1 base1_type
;
355 typedef UniformRandomNumberGenerator2 base2_type
;
356 typedef unsigned long result_type
;
358 BOOST_STATIC_CONSTANT(int, shift1
= s1
);
359 BOOST_STATIC_CONSTANT(int, shift2
= s2
);
360 // constructors and member function
361 xor_combine(){ init_minmax(); }
362 xor_combine(const base1_type
& rng1
, const base2_type
& rng2
)
363 : m_b1(rng1
), m_b2(rng2
) { init_minmax(); }
364 xor_combine(unsigned long s
)
365 : m_b1(s
), m_b2(s
+1) { init_minmax(); }
366 template<class Gen
> xor_combine(Gen
& g
)
369 init1(g
, ::boost::is_same
<Gen
, xor_combine
<UniformRandomNumberGenerator1
, s1
, UniformRandomNumberGenerator2
, s2
> >());
376 void seed(unsigned long s
)
381 template<class Gen
> void seed(Gen
& g
)
383 init2(g
, ::boost::is_fundamental
<Gen
>());
386 const base1_type
& base1() const
388 const base2_type
& base2() const
390 result_type min
BOOST_PREVENT_MACRO_SUBSTITUTION() const
392 result_type max
BOOST_PREVENT_MACRO_SUBSTITUTION() const
394 result_type
operator()()
395 { return (m_b1() << s1
) ^ (m_b2() << s2
); }
397 bool operator == (const xor_combine
& that
)const
398 { return (m_b1
== that
.m_b1
) && (m_b2
== that
.m_b2
); }
399 bool operator != (const xor_combine
& that
)const
400 { return !(*this == that
); }
402 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
403 template<class CharT
, class Traits
>
404 friend std::basic_ostream
<CharT
,Traits
>&
405 operator<<(std::basic_ostream
<CharT
,Traits
>& os
,
406 const xor_combine
& lcg
)
408 return os
<< lcg
.m_b1
<< " " << lcg
.m_b2
;
411 template<class CharT
, class Traits
>
412 friend std::basic_istream
<CharT
,Traits
>&
413 operator>>(std::basic_istream
<CharT
,Traits
>& is
,
416 return is
>> lcg
.m_b1
>> lcg
.m_b2
;
428 void init1(Gen
& g
, const ::boost::true_type
&)
434 void init1(Gen
& g
, const ::boost::false_type
&)
436 init2(g
, ::boost::is_fundamental
<Gen
>());
439 void init2(Gen
& g
, const ::boost::true_type
&)
441 m_b1
.seed(static_cast<unsigned long>(g
));
442 m_b2
.seed(static_cast<unsigned long>(g
));
445 void init2(Gen
& g
, const ::boost::false_type
&)
452 template<class UniformRandomNumberGenerator1
, int s1
, class UniformRandomNumberGenerator2
, int s2
>
453 void xor_combine
<UniformRandomNumberGenerator1
, s1
, UniformRandomNumberGenerator2
, s2
>::init_minmax()
456 // The following code is based on that given in "Hacker's Delight"
457 // by Henry S. Warren, (Addison-Wesley, 2003), and at
458 // http://www.hackersdelight.org/index.htm.
459 // Used here by permission.
461 // calculation of minimum value:
463 result_type a
= (m_b1
.min
)() << s1
;
464 result_type b
= (m_b1
.max
)() << s1
;
465 result_type c
= (m_b2
.min
)() << s2
;
466 result_type d
= (m_b2
.max
)() << s2
;
469 m
= 0x1uL
<< ((sizeof(result_type
) * CHAR_BIT
) - 1);
472 temp
= (a
| m
) & (static_cast<result_type
>(0u) - m
);
473 if (temp
<= b
) a
= temp
;
475 else if (a
& ~c
& m
) {
476 temp
= (c
| m
) & (static_cast<result_type
>(0u) - m
);
477 if (temp
<= d
) c
= temp
;
484 // calculation of maximum value:
486 if((((std::numeric_limits
<result_type
>::max
)() >> s1
) < (m_b1
.max
)())
487 || ((((std::numeric_limits
<result_type
>::max
)()) >> s2
) < (m_b2
.max
)()))
489 m_max
= (std::numeric_limits
<result_type
>::max
)();
492 a
= (m_b1
.min
)() << s1
;
493 b
= (m_b1
.max
)() << s1
;
494 c
= (m_b2
.min
)() << s2
;
495 d
= (m_b2
.max
)() << s2
;
497 m
= 0x1uL
<< ((sizeof(result_type
) * CHAR_BIT
) - 1);
501 temp
= (b
- m
) | (m
- 1);
502 if (temp
>= a
) b
= temp
;
504 temp
= (d
- m
) | (m
- 1);
505 if (temp
>= c
) d
= temp
;
513 typedef linear_congruential
< ::boost::int32_t, 16807, 0, 2147483647> minstd_rand0
;
514 typedef linear_congruential
< ::boost::int32_t, 48271, 0, 2147483647> minstd_rand
;
515 typedef mersenne_twister
< ::boost::uint32_t, 32,624,397,31,0x9908b0df,11,7,0x9d2c5680,15,0xefc60000,18> mt19937
;
516 typedef subtract_with_carry_01
<float, 24, 10, 24> ranlux_base_01
;
517 typedef subtract_with_carry_01
<double, 48, 10, 24> ranlux64_base_01
;
518 typedef discard_block
<subtract_with_carry
< ::boost::int32_t, (1<<24), 10, 24>, 223, 24> ranlux3
;
519 typedef discard_block
<subtract_with_carry
< ::boost::int32_t, (1<<24), 10, 24>, 389, 24> ranlux4
;
520 typedef discard_block
<subtract_with_carry_01
<float, 24, 10, 24>, 223, 24> ranlux3_01
;
521 typedef discard_block
<subtract_with_carry_01
<float, 24, 10, 24>, 389, 24> ranlux4_01
;
524 using ::boost::random_device
;
526 using ::boost::uniform_int
;
528 class bernoulli_distribution
532 typedef int input_type
;
533 typedef bool result_type
;
534 // constructors and member function
535 explicit bernoulli_distribution(double p
= 0.5)
538 { return m_dist
.p(); }
541 template<class UniformRandomNumberGenerator
>
542 result_type
operator()(UniformRandomNumberGenerator
& urng
)
546 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
547 template<class CharT
, class Traits
>
548 friend std::basic_ostream
<CharT
,Traits
>&
549 operator<<(std::basic_ostream
<CharT
,Traits
>& os
,
550 const bernoulli_distribution
& lcg
)
552 return os
<< lcg
.m_dist
;
555 template<class CharT
, class Traits
>
556 friend std::basic_istream
<CharT
,Traits
>&
557 operator>>(std::basic_istream
<CharT
,Traits
>& is
,
558 bernoulli_distribution
& lcg
)
560 return is
>> lcg
.m_dist
;
565 ::boost::bernoulli_distribution
<double> m_dist
;
567 //using ::boost::bernoulli_distribution;
568 using ::boost::geometric_distribution
;
569 using ::boost::poisson_distribution
;
570 using ::boost::binomial_distribution
;
571 using ::boost::uniform_real
;
572 using ::boost::exponential_distribution
;
573 using ::boost::normal_distribution
;
574 using ::boost::gamma_distribution
;