// (C) Copyright John Maddock 2005. // (C) Copyright Henry S. Warren 2005. // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_TR1_RANDOM_HPP_INCLUDED # define BOOST_TR1_RANDOM_HPP_INCLUDED # include #ifdef BOOST_HAS_TR1_RANDOM # include BOOST_TR1_HEADER(random) #else // Boost.Random: #include #ifndef __SUNPRO_CC // Sunpros linker complains if we so much as include this... # include #endif #include #include #include namespace std { namespace tr1{ using ::boost::variate_generator; template class linear_congruential { private: typedef ::boost::random::linear_congruential impl_type; public: // types typedef UIntType result_type; // parameter values BOOST_STATIC_CONSTANT(UIntType, multiplier = a); BOOST_STATIC_CONSTANT(UIntType, increment = c); BOOST_STATIC_CONSTANT(UIntType, modulus = m); // constructors and member function explicit linear_congruential(unsigned long x0 = 1) : m_gen(x0){} linear_congruential(const linear_congruential& that) : m_gen(that.m_gen){} template linear_congruential(Gen& g) { init1(g, ::boost::is_same()); } void seed(unsigned long x0 = 1) { m_gen.seed(x0); } template void seed(Gen& g) { init2(g, ::boost::is_fundamental()); } result_type min BOOST_PREVENT_MACRO_SUBSTITUTION() const { return (m_gen.min)(); } result_type max BOOST_PREVENT_MACRO_SUBSTITUTION() const { return (m_gen.max)(); } result_type operator()() { return m_gen(); } bool operator==(const linear_congruential& that)const { return m_gen == that.m_gen; } bool operator!=(const linear_congruential& that)const { return m_gen != that.m_gen; } #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) template friend std::basic_ostream& operator<<(std::basic_ostream& os, const linear_congruential& lcg) { return os << lcg.m_gen; } template friend std::basic_istream& operator>>(std::basic_istream& is, linear_congruential& lcg) { return is >> lcg.m_gen; } #endif private: template void init1(Gen& g, const ::boost::true_type&) { m_gen = g.m_gen; } template void init1(Gen& g, const ::boost::false_type&) { init2(g, ::boost::is_fundamental()); } template void init2(Gen& g, const ::boost::true_type&) { m_gen.seed(static_cast(g)); } template void init2(Gen& g, const ::boost::false_type&) { //typedef typename Gen::result_type gen_rt; boost::tr1_details::functor2iterator f1(g), f2; m_gen.seed(f1, f2); } impl_type m_gen; }; template class mersenne_twister { typedef ::boost::random::mersenne_twister imp_type; public: // types typedef UIntType result_type; // parameter values BOOST_STATIC_CONSTANT(int, word_size = w); BOOST_STATIC_CONSTANT(int, state_size = n); BOOST_STATIC_CONSTANT(int, shift_size = m); BOOST_STATIC_CONSTANT(int, mask_bits = r); BOOST_STATIC_CONSTANT(UIntType, parameter_a = a); BOOST_STATIC_CONSTANT(int, output_u = u); BOOST_STATIC_CONSTANT(int, output_s = s); BOOST_STATIC_CONSTANT(UIntType, output_b = b); BOOST_STATIC_CONSTANT(int, output_t = t); BOOST_STATIC_CONSTANT(UIntType, output_c = c); BOOST_STATIC_CONSTANT(int, output_l = l); // constructors and member function mersenne_twister(){} explicit mersenne_twister(unsigned long value) : m_gen(value == 0 ? 4357UL : value){} template mersenne_twister(Gen& g) { init1(g, ::boost::is_same()); } void seed() { m_gen.seed(); } void seed(unsigned long value) { m_gen.seed(value == 0 ? 5489UL : value); } template void seed(Gen& g) { init2(g, ::boost::is_fundamental()); } result_type min BOOST_PREVENT_MACRO_SUBSTITUTION() const { return (m_gen.min)(); } result_type max BOOST_PREVENT_MACRO_SUBSTITUTION() const { return (m_gen.max)(); } result_type operator()() { return m_gen(); } bool operator==(const mersenne_twister& that)const { return m_gen == that.m_gen; } bool operator!=(const mersenne_twister& that)const { return m_gen != that.m_gen; } #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) template friend std::basic_ostream& operator<<(std::basic_ostream& os, const mersenne_twister& lcg) { return os << lcg.m_gen; } template friend std::basic_istream& operator>>(std::basic_istream& is, mersenne_twister& lcg) { return is >> lcg.m_gen; } #endif private: template void init1(Gen& g, const ::boost::true_type&) { m_gen = g.m_gen; } template void init1(Gen& g, const ::boost::false_type&) { init2(g, ::boost::is_fundamental()); } template void init2(Gen& g, const ::boost::true_type&) { m_gen.seed(static_cast(g == 0 ? 4357UL : g)); } template void init2(Gen& g, const ::boost::false_type&) { m_gen.seed(g); } imp_type m_gen; }; template class subtract_with_carry { public: // types typedef IntType result_type; // parameter values BOOST_STATIC_CONSTANT(IntType, modulus = m); BOOST_STATIC_CONSTANT(int, long_lag = r); BOOST_STATIC_CONSTANT(int, short_lag = s); // constructors and member function subtract_with_carry(){} explicit subtract_with_carry(unsigned long value) : m_gen(value == 0 ? 19780503UL : value){} template subtract_with_carry(Gen& g) { init1(g, ::boost::is_same >()); } void seed(unsigned long value = 19780503ul) { m_gen.seed(value == 0 ? 19780503UL : value); } template void seed(Gen& g) { init2(g, ::boost::is_fundamental()); } result_type min BOOST_PREVENT_MACRO_SUBSTITUTION() const { return (m_gen.min)(); } result_type max BOOST_PREVENT_MACRO_SUBSTITUTION() const { return (m_gen.max)(); } result_type operator()() { return m_gen(); } bool operator==(const subtract_with_carry& that)const { return m_gen == that.m_gen; } bool operator!=(const subtract_with_carry& that)const { return m_gen != that.m_gen; } #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) template friend std::basic_ostream& operator<<(std::basic_ostream& os, const subtract_with_carry& lcg) { return os << lcg.m_gen; } template friend std::basic_istream& operator>>(std::basic_istream& is, subtract_with_carry& lcg) { return is >> lcg.m_gen; } #endif private: template void init1(Gen& g, const ::boost::true_type&) { m_gen = g.m_gen; } template void init1(Gen& g, const ::boost::false_type&) { init2(g, ::boost::is_fundamental()); } template void init2(Gen& g, const ::boost::true_type&) { m_gen.seed(static_cast(g == 0 ? 19780503UL : g)); } template void init2(Gen& g, const ::boost::false_type&) { m_gen.seed(g); } ::boost::random::subtract_with_carry m_gen; }; template class subtract_with_carry_01 { public: // types typedef RealType result_type; // parameter values BOOST_STATIC_CONSTANT(int, word_size = w); BOOST_STATIC_CONSTANT(int, long_lag = r); BOOST_STATIC_CONSTANT(int, short_lag = s); // constructors and member function subtract_with_carry_01(){} explicit subtract_with_carry_01(unsigned long value) : m_gen(value == 0 ? 19780503UL : value){} template subtract_with_carry_01(Gen& g) { init1(g, ::boost::is_same >()); } void seed(unsigned long value = 19780503UL) { m_gen.seed(value == 0 ? 19780503UL : value); } template void seed(Gen& g) { init2(g, ::boost::is_fundamental()); } result_type min BOOST_PREVENT_MACRO_SUBSTITUTION() const { return (m_gen.min)(); } result_type max BOOST_PREVENT_MACRO_SUBSTITUTION() const { return (m_gen.max)(); } result_type operator()() { return m_gen(); } bool operator==(const subtract_with_carry_01& that)const { return m_gen == that.m_gen; } bool operator!=(const subtract_with_carry_01& that)const { return m_gen != that.m_gen; } #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) template friend std::basic_ostream& operator<<(std::basic_ostream& os, const subtract_with_carry_01& lcg) { return os << lcg.m_gen; } template friend std::basic_istream& operator>>(std::basic_istream& is, subtract_with_carry_01& lcg) { return is >> lcg.m_gen; } #endif private: template void init1(Gen& g, const ::boost::true_type&) { m_gen = g.m_gen; } template void init1(Gen& g, const ::boost::false_type&) { init2(g, ::boost::is_fundamental()); } template void init2(Gen& g, const ::boost::true_type&) { m_gen.seed(static_cast(g == 0 ? 19780503UL : g)); } template void init2(Gen& g, const ::boost::false_type&) { //typedef typename Gen::result_type gen_rt; boost::tr1_details::functor2iterator f1(g), f2; m_gen.seed(f1, f2); } ::boost::random::subtract_with_carry_01 m_gen; }; using ::boost::random::discard_block; template class xor_combine { public: // types typedef UniformRandomNumberGenerator1 base1_type; typedef UniformRandomNumberGenerator2 base2_type; typedef unsigned long result_type; // parameter values BOOST_STATIC_CONSTANT(int, shift1 = s1); BOOST_STATIC_CONSTANT(int, shift2 = s2); // constructors and member function xor_combine(){ init_minmax(); } xor_combine(const base1_type & rng1, const base2_type & rng2) : m_b1(rng1), m_b2(rng2) { init_minmax(); } xor_combine(unsigned long s) : m_b1(s), m_b2(s+1) { init_minmax(); } template xor_combine(Gen& g) { init_minmax(); init1(g, ::boost::is_same >()); } void seed() { m_b1.seed(); m_b2.seed(); } void seed(unsigned long s) { m_b1.seed(s); m_b2.seed(s+1); } template void seed(Gen& g) { init2(g, ::boost::is_fundamental()); } const base1_type& base1() const { return m_b1; } const base2_type& base2() const { return m_b2; } result_type min BOOST_PREVENT_MACRO_SUBSTITUTION() const { return m_min; } result_type max BOOST_PREVENT_MACRO_SUBSTITUTION() const { return m_max; } result_type operator()() { return (m_b1() << s1) ^ (m_b2() << s2); } bool operator == (const xor_combine& that)const { return (m_b1 == that.m_b1) && (m_b2 == that.m_b2); } bool operator != (const xor_combine& that)const { return !(*this == that); } #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) template friend std::basic_ostream& operator<<(std::basic_ostream& os, const xor_combine& lcg) { return os << lcg.m_b1 << " " << lcg.m_b2; } template friend std::basic_istream& operator>>(std::basic_istream& is, xor_combine& lcg) { return is >> lcg.m_b1 >> lcg.m_b2; } #endif private: void init_minmax(); base1_type m_b1; base2_type m_b2; result_type m_min; result_type m_max; template void init1(Gen& g, const ::boost::true_type&) { m_b1 = g.m_b1; m_b2 = g.m_b2; } template void init1(Gen& g, const ::boost::false_type&) { init2(g, ::boost::is_fundamental()); } template void init2(Gen& g, const ::boost::true_type&) { m_b1.seed(static_cast(g)); m_b2.seed(static_cast(g)); } template void init2(Gen& g, const ::boost::false_type&) { m_b1.seed(g); m_b2.seed(g); } }; template void xor_combine::init_minmax() { // // The following code is based on that given in "Hacker's Delight" // by Henry S. Warren, (Addison-Wesley, 2003), and at // http://www.hackersdelight.org/index.htm. // Used here by permission. // // calculation of minimum value: // result_type a = (m_b1.min)() << s1; result_type b = (m_b1.max)() << s1; result_type c = (m_b2.min)() << s2; result_type d = (m_b2.max)() << s2; result_type m, temp; m = 0x1uL << ((sizeof(result_type) * CHAR_BIT) - 1); while (m != 0) { if (~a & c & m) { temp = (a | m) & (static_cast(0u) - m); if (temp <= b) a = temp; } else if (a & ~c & m) { temp = (c | m) & (static_cast(0u) - m); if (temp <= d) c = temp; } m >>= 1; } m_min = a ^ c; // // calculation of maximum value: // if((((std::numeric_limits::max)() >> s1) < (m_b1.max)()) || ((((std::numeric_limits::max)()) >> s2) < (m_b2.max)())) { m_max = (std::numeric_limits::max)(); return; } a = (m_b1.min)() << s1; b = (m_b1.max)() << s1; c = (m_b2.min)() << s2; d = (m_b2.max)() << s2; m = 0x1uL << ((sizeof(result_type) * CHAR_BIT) - 1); while (m != 0) { if (b & d & m) { temp = (b - m) | (m - 1); if (temp >= a) b = temp; else { temp = (d - m) | (m - 1); if (temp >= c) d = temp; } } m = m >> 1; } m_max = b ^ d; } typedef linear_congruential< ::boost::int32_t, 16807, 0, 2147483647> minstd_rand0; typedef linear_congruential< ::boost::int32_t, 48271, 0, 2147483647> minstd_rand; typedef mersenne_twister< ::boost::uint32_t, 32,624,397,31,0x9908b0df,11,7,0x9d2c5680,15,0xefc60000,18> mt19937; typedef subtract_with_carry_01 ranlux_base_01; typedef subtract_with_carry_01 ranlux64_base_01; typedef discard_block, 223, 24> ranlux3; typedef discard_block, 389, 24> ranlux4; typedef discard_block, 223, 24> ranlux3_01; typedef discard_block, 389, 24> ranlux4_01; #ifndef __SUNPRO_CC using ::boost::random_device; #endif using ::boost::uniform_int; class bernoulli_distribution { public: // types typedef int input_type; typedef bool result_type; // constructors and member function explicit bernoulli_distribution(double p = 0.5) : m_dist(p){} double p() const { return m_dist.p(); } void reset() { m_dist.reset(); } template result_type operator()(UniformRandomNumberGenerator& urng) { return m_dist(urng); } #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) template friend std::basic_ostream& operator<<(std::basic_ostream& os, const bernoulli_distribution& lcg) { return os << lcg.m_dist; } template friend std::basic_istream& operator>>(std::basic_istream& is, bernoulli_distribution& lcg) { return is >> lcg.m_dist; } #endif private: ::boost::bernoulli_distribution m_dist; }; //using ::boost::bernoulli_distribution; using ::boost::geometric_distribution; using ::boost::poisson_distribution; using ::boost::binomial_distribution; using ::boost::uniform_real; using ::boost::exponential_distribution; using ::boost::normal_distribution; using ::boost::gamma_distribution; } } #endif #endif