1 //  (C) Copyright John Maddock 2005.
2 //  Use, modification and distribution are subject to the
3 //  Boost Software License, Version 1.0. (See accompanying file
4 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #ifdef TEST_STD_HEADERS
7 #include <random>
8 #else
9 #include <boost/tr1/random.hpp>
10 #endif
11 
12 #include <boost/type_traits/is_arithmetic.hpp>
13 #include <boost/cstdint.hpp>
14 #include <boost/static_assert.hpp>
15 #include "verify_return.hpp"
16 #include <iostream>
17 
18 template <class T>
check_uniform(T *)19 void check_uniform(T*)
20 {
21    typedef typename T::result_type result_type;
22    BOOST_STATIC_ASSERT(::boost::is_arithmetic<result_type>::value);
23 
24    T t;
25    result_type r = 0;
26    verify_return_type((t.min)(), r);
27    verify_return_type((t.max)(), r);
28    verify_return_type(t(), r);
29 }
30 
31 struct seed_architype
32 {
33    typedef unsigned result_type;
operator ()seed_architype34    unsigned operator()()const
35    {
36       return 0;
37    }
38 };
39 
40 unsigned seed_proc();
41 
42 class uniform_random_generator_architype
43 {
44 public:
45    typedef unsigned long result_type;
operator ()()46    result_type operator()()
47    { return 0; }
BOOST_PREVENT_MACRO_SUBSTITUTION() const48    result_type min BOOST_PREVENT_MACRO_SUBSTITUTION()const
49    { return 0; }
BOOST_PREVENT_MACRO_SUBSTITUTION() const50    result_type max BOOST_PREVENT_MACRO_SUBSTITUTION()const
51    { return 0; }
52 
get()53    static uniform_random_generator_architype& get()
54    {
55       static uniform_random_generator_architype r;
56       return r;
57    }
58 private:
59    uniform_random_generator_architype();
60    uniform_random_generator_architype(const uniform_random_generator_architype&);
61    uniform_random_generator_architype& operator=(const uniform_random_generator_architype&);
62 };
63 
64 class pseudo_random_generator_architype
65 {
66 public:
pseudo_random_generator_architype()67    pseudo_random_generator_architype(){}
pseudo_random_generator_architype(const pseudo_random_generator_architype &)68    pseudo_random_generator_architype(const pseudo_random_generator_architype&){}
operator =(const pseudo_random_generator_architype &)69    pseudo_random_generator_architype& operator=(const pseudo_random_generator_architype&)
70    { return *this; }
71 
72    typedef unsigned long result_type;
operator ()()73    result_type operator()()
74    { return 0; }
BOOST_PREVENT_MACRO_SUBSTITUTION() const75    result_type min BOOST_PREVENT_MACRO_SUBSTITUTION()const
76    { return 0; }
BOOST_PREVENT_MACRO_SUBSTITUTION() const77    result_type max BOOST_PREVENT_MACRO_SUBSTITUTION()const
78    { return 0; }
79 
pseudo_random_generator_architype(unsigned long)80    pseudo_random_generator_architype(unsigned long){}
pseudo_random_generator_architype(Gen &)81    template <class Gen> pseudo_random_generator_architype(Gen&){}
seed()82    void seed(){}
seed(unsigned long)83    void seed(unsigned long){}
seed(Gen &)84    template <class Gen> void seed(Gen&){}
85 
operator ==(const pseudo_random_generator_architype &) const86    bool operator == (const pseudo_random_generator_architype&)const
87    { return false; }
operator !=(const pseudo_random_generator_architype &) const88    bool operator != (const pseudo_random_generator_architype&)const
89    { return false; }
90 
91 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
92    template<class CharT, class Traits>
93    friend std::basic_ostream<CharT,Traits>&
operator <<(std::basic_ostream<CharT,Traits> & os,const pseudo_random_generator_architype & lcg)94    operator<<(std::basic_ostream<CharT,Traits>& os,
95             const pseudo_random_generator_architype& lcg)
96    {
97       return os;
98    }
99 
100    template<class CharT, class Traits>
101    friend std::basic_istream<CharT,Traits>&
operator >>(std::basic_istream<CharT,Traits> & is,pseudo_random_generator_architype & lcg)102    operator>>(std::basic_istream<CharT,Traits>& is,
103             pseudo_random_generator_architype& lcg)
104    {
105       return is;
106    }
107 #endif
108 };
109 
110 class random_distribution_architype
111 {
112 public:
random_distribution_architype()113    random_distribution_architype(){}
random_distribution_architype(const random_distribution_architype &)114    random_distribution_architype(const random_distribution_architype&){}
operator =(const random_distribution_architype &)115    random_distribution_architype& operator=(const random_distribution_architype&)
116    { return *this; }
117 
118    typedef unsigned input_type;
119    typedef double result_type;
120 
reset()121    void reset(){}
122 
123    template <class U>
operator ()(U & u)124    result_type operator()(U& u)
125    {
126       return u();
127    }
128 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
129    template<class CharT, class Traits>
130    friend std::basic_ostream<CharT,Traits>&
operator <<(std::basic_ostream<CharT,Traits> & os,const random_distribution_architype & lcg)131    operator<<(std::basic_ostream<CharT,Traits>& os,
132             const random_distribution_architype& lcg)
133    {
134       return os;
135    }
136 
137    template<class CharT, class Traits>
138    friend std::basic_istream<CharT,Traits>&
operator >>(std::basic_istream<CharT,Traits> & is,random_distribution_architype & lcg)139    operator>>(std::basic_istream<CharT,Traits>& is,
140             random_distribution_architype& lcg)
141    {
142       return is;
143    }
144 #endif
145 };
146 
147 
148 template <class T>
check_pseudo_random(T * p)149 void check_pseudo_random(T* p)
150 {
151    typedef typename T::result_type result_type;
152    check_uniform(p);
153    T t1;
154    T t2(t1);
155    t1 = t2;
156    unsigned long s = 0;
157    T t3(s);
158    seed_architype seed;
159    T t4(seed);
160    t1.seed();
161    t1.seed(s);
162    t1.seed(seed);
163    T t5(seed_proc);
164    t1.seed(seed_proc);
165    const T& x = t1;
166    const T& y = t2;
167    verify_return_type(x == y, true);
168    verify_return_type(x == y, false);
169 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
170    std::cout << t1;
171    std::cin >> t1;
172 #endif
173 }
174 
175 template <class T>
check_random_distribution(T * pd)176 void check_random_distribution(T* pd)
177 {
178    T t1(*pd);
179    t1 = *pd;
180    uniform_random_generator_architype& gen = uniform_random_generator_architype::get();
181    typedef typename T::input_type input_type;
182    typedef typename T::result_type result_type;
183    t1.reset();
184    verify_return_type(t1(gen), result_type());
185    const T& ct = t1;
186 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
187    std::cout << ct << std::endl;
188    std::cin >> t1 >> std::ws;
189 #endif
190 }
191 
192 template <class VG>
check_generator(VG * g)193 void check_generator(VG* g)
194 {
195    typedef typename VG::engine_type engine_type;
196    typedef typename VG::engine_value_type engine_value_type;
197    typedef typename VG::distribution_type distribution_type;
198    typedef typename distribution_type::input_type input_type;
199    typedef typename VG::result_type result_type;
200    verify_return_type((*g)(), result_type(0));
201    const VG* cg = g;
202    verify_return_type(&g->engine(), static_cast<engine_value_type*>(0));
203    verify_return_type(&cg->engine(), static_cast<const engine_value_type*>(0));
204    verify_return_type(&g->distribution(), static_cast<distribution_type*>(0));
205    verify_return_type(&cg->distribution(), static_cast<const distribution_type*>(0));
206 }
207 
208 template <class VG>
check_generator_extended(VG * g)209 void check_generator_extended(VG* g)
210 {
211    typedef typename VG::engine_type engine_type;
212    typedef typename VG::engine_value_type engine_value_type;
213    typedef typename VG::distribution_type distribution_type;
214    typedef typename distribution_type::input_type input_type;
215    typedef typename VG::result_type result_type;
216    //verify_return_type((*g)(input_type(0)), result_type(0));
217    const VG* cg = g;
218    verify_return_type((cg->min)(), result_type(0));
219    verify_return_type((cg->max)(), result_type(0));
220 }
221 
main()222 int main()
223 {
224    typedef std::tr1::linear_congruential< ::boost::int32_t, 16807, 0, 2147483647> lc_t;
225    lc_t lc;
226    BOOST_STATIC_ASSERT(lc_t::multiplier == 16807);
227    BOOST_STATIC_ASSERT(lc_t::increment == 0);
228    BOOST_STATIC_ASSERT(lc_t::modulus == 2147483647);
229    check_pseudo_random(&lc);
230 
231    typedef std::tr1::mersenne_twister< ::boost::uint32_t,32,351,175,19,0xccab8ee7,11,7,0x31b6ab00,15,0xffe50000,17> mt11213b;
232    mt11213b mt;
233    check_pseudo_random(&mt);
234 
235    typedef std::tr1::subtract_with_carry< ::boost::int32_t, 24, 10, 24> sub_t;
236    sub_t sub;
237    check_pseudo_random(&sub);
238 
239    typedef std::tr1::subtract_with_carry_01<float, 24, 10, 24> ranlux_base_01;
240    ranlux_base_01 rl1;
241    check_pseudo_random(&rl1);
242    typedef std::tr1::subtract_with_carry_01<double, 48, 10, 24> ranlux64_base_01;
243    ranlux64_base_01 rl2;
244    check_pseudo_random(&rl2);
245 
246    typedef std::tr1::discard_block< std::tr1::subtract_with_carry< ::boost::int32_t , (1<<24), 10, 24>, 223, 24> ranlux3;
247    ranlux3 rl3;
248    check_pseudo_random(&rl3);
249 
250    std::tr1::xor_combine<pseudo_random_generator_architype, 0, pseudo_random_generator_architype, 1> xorc;
251    check_pseudo_random(&xorc);
252    verify_return_type(xorc.base1(), pseudo_random_generator_architype());
253    verify_return_type(xorc.base2(), pseudo_random_generator_architype());
254 
255 #ifndef __SUNPRO_CC
256    // we don't normally allow workarounds in here, but this
257    // class is unsupported on this platform.
258    std::tr1::random_device d;
259    check_uniform(&d);
260    verify_return_type(d.entropy(), double(0));
261 #endif
262 
263    uniform_random_generator_architype& gen = uniform_random_generator_architype::get();
264    std::tr1::uniform_int<unsigned long> ui;
265    check_random_distribution(&ui);
266    typedef std::tr1::uniform_int<unsigned long>::result_type ui_r_t;
267    verify_return_type((ui.min)(), ui_r_t());
268    verify_return_type((ui.max)(), ui_r_t());
269    //verify_return_type(ui(gen, ui_r_t()), ui_r_t());
270 
271    std::tr1::bernoulli_distribution bd;
272    verify_return_type(bd.p(), double(0));
273    check_random_distribution(&bd);
274 
275    std::tr1::geometric_distribution<> gd;
276    verify_return_type(gd.p(), double(0));
277    check_random_distribution(&gd);
278    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::geometric_distribution<>::result_type, int>::value));
279    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::geometric_distribution<>::input_type, double>::value));
280    std::tr1::geometric_distribution<long, double> gd2(0.5);
281    verify_return_type(gd2.p(), double(0));
282    check_random_distribution(&gd2);
283    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::geometric_distribution<long, double>::result_type, long>::value));
284    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::geometric_distribution<long, double>::input_type, double>::value));
285 
286    std::tr1::poisson_distribution<> pd;
287    verify_return_type(pd.mean(), double(0));
288    check_random_distribution(&pd);
289    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::poisson_distribution<>::result_type, int>::value));
290    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::poisson_distribution<>::input_type, double>::value));
291    std::tr1::poisson_distribution<long, double> pd2(0.5);
292    verify_return_type(pd2.mean(), double(0));
293    check_random_distribution(&pd2);
294    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::poisson_distribution<long, double>::result_type, long>::value));
295    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::poisson_distribution<long, double>::input_type, double>::value));
296 
297    std::tr1::binomial_distribution<> bind;
298    verify_return_type(bind.p(), double(0));
299    verify_return_type(bind.t(), int(0));
300    check_random_distribution(&bind);
301    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::binomial_distribution<>::result_type, int>::value));
302    //BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::binomial_distribution<>::input_type, double>::value));
303    std::tr1::binomial_distribution<long, double> bind2(1, 0.5);
304    verify_return_type(bind2.t(), long(0));
305    check_random_distribution(&bind2);
306    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::binomial_distribution<long, double>::result_type, long>::value));
307    //BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::binomial_distribution<long, double>::input_type, double>::value));
308 
309    std::tr1::uniform_real<> urd;
310    check_random_distribution(&urd);
311    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::uniform_real<>::result_type, double>::value));
312    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::uniform_real<>::input_type, double>::value));
313    std::tr1::uniform_real<long double> urd2(0.5L, 1.5L);
314    verify_return_type((urd2.min)(), (long double)(0));
315    verify_return_type((urd2.max)(), (long double)(0));
316    check_random_distribution(&urd2);
317    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::uniform_real<long double>::result_type, long double>::value));
318    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::uniform_real<long double>::input_type, long double>::value));
319 
320    std::tr1::exponential_distribution<> exd;
321    check_random_distribution(&exd);
322    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::exponential_distribution<>::result_type, double>::value));
323    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::exponential_distribution<>::input_type, double>::value));
324    std::tr1::exponential_distribution<long double> exd2(0.5L);
325    verify_return_type(exd2.lambda(), (long double)(0));
326    check_random_distribution(&exd2);
327    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::exponential_distribution<long double>::result_type, long double>::value));
328    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::exponential_distribution<long double>::input_type, long double>::value));
329 
330    std::tr1::normal_distribution<> normd;
331    check_random_distribution(&normd);
332    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::normal_distribution<>::result_type, double>::value));
333    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::normal_distribution<>::input_type, double>::value));
334    std::tr1::normal_distribution<long double> normd2(0.5L, 0.1L);
335    verify_return_type(normd2.mean(), (long double)(0));
336    verify_return_type(normd2.sigma(), (long double)(0));
337    check_random_distribution(&normd2);
338    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::normal_distribution<long double>::result_type, long double>::value));
339    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::normal_distribution<long double>::input_type, long double>::value));
340 
341    std::tr1::gamma_distribution<> gammad;
342    check_random_distribution(&gammad);
343    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::gamma_distribution<>::result_type, double>::value));
344    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::gamma_distribution<>::input_type, double>::value));
345    std::tr1::gamma_distribution<long double> gammad2(0.5L);
346    verify_return_type(gammad2.alpha(), (long double)(0));
347    check_random_distribution(&gammad2);
348    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::gamma_distribution<long double>::result_type, long double>::value));
349    BOOST_STATIC_ASSERT((::boost::is_same<std::tr1::gamma_distribution<long double>::input_type, long double>::value));
350 
351    //
352    // variate_generator:
353    //
354    std::tr1::variate_generator<uniform_random_generator_architype&, random_distribution_architype> vg1(uniform_random_generator_architype::get(), random_distribution_architype());
355    check_generator(&vg1);
356    std::tr1::variate_generator<uniform_random_generator_architype&, std::tr1::uniform_int<> > vg2(uniform_random_generator_architype::get(), std::tr1::uniform_int<>());
357    check_generator_extended(&vg2);
358    std::tr1::variate_generator<uniform_random_generator_architype*, std::tr1::uniform_int<> > vg3(&uniform_random_generator_architype::get(), std::tr1::uniform_int<>());
359    check_generator_extended(&vg3);
360    return 0;
361 }
362 
363 
364 
365