]>
Commit | Line | Data |
---|---|---|
1 | // (C) Copyright Gennadiy Rozental 2001. | |
2 | // Distributed under the Boost Software License, Version 1.0. | |
3 | // (See accompanying file LICENSE_1_0.txt or copy at | |
4 | // http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | // See http://www.boost.org/libs/test for the library home page. | |
7 | // | |
8 | //!@file | |
9 | //!@brief Random generator | |
10 | // *************************************************************************** | |
11 | ||
12 | #ifndef BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_RANDOM_HPP_101512GER | |
13 | #define BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_RANDOM_HPP_101512GER | |
14 | ||
15 | // Boost.Test | |
16 | #include <boost/test/data/config.hpp> | |
17 | ||
18 | ||
19 | ||
20 | ||
21 | #if !defined(BOOST_TEST_NO_RANDOM_DATASET_AVAILABLE) || defined(BOOST_TEST_DOXYGEN_DOC__) | |
22 | ||
23 | #include <boost/test/data/monomorphic/generate.hpp> | |
24 | #include <boost/test/data/monomorphic/generators/keywords.hpp> | |
25 | ||
26 | // STL | |
27 | #include <random> | |
28 | ||
29 | #include <boost/test/detail/suppress_warnings.hpp> | |
30 | ||
31 | //____________________________________________________________________________// | |
32 | ||
33 | namespace boost { | |
34 | namespace unit_test { | |
35 | namespace data { | |
36 | ||
37 | namespace { | |
38 | nfp::keyword<struct seed_t> seed; | |
39 | nfp::keyword<struct distribution_t> distribution; | |
40 | nfp::keyword<struct engine_t> engine; | |
41 | } // local namespace | |
42 | ||
43 | namespace monomorphic { | |
44 | ||
45 | namespace ds_detail { | |
46 | template<typename SampleType> | |
47 | struct default_distribution { | |
48 | typedef typename mpl::if_<std::is_integral<SampleType>, | |
49 | std::uniform_int_distribution<SampleType>, | |
50 | std::uniform_real_distribution<SampleType>>::type type; | |
51 | }; | |
52 | ||
53 | } // namespace ds_detail | |
54 | ||
55 | // ************************************************************************** // | |
56 | // ************** random_t ************** // | |
57 | // ************************************************************************** // | |
58 | ||
59 | /*!@brief Generator for the random sequences | |
60 | * | |
61 | * This class implements the generator concept (see @ref boost::unit_test::data::monomorphic::generated_by) for implementing | |
62 | * a random number generator. | |
63 | */ | |
64 | template<typename SampleType = double, | |
65 | typename DistributionType = typename ds_detail::default_distribution<SampleType>::type, | |
66 | typename EngineType = std::default_random_engine> | |
67 | class random_t { | |
68 | public: | |
69 | typedef SampleType sample; | |
70 | typedef DistributionType distr_type; | |
71 | typedef EngineType engine_type; | |
72 | ||
73 | random_t() | |
74 | : m_distribution() | |
75 | , m_engine( std::random_device()() ) | |
76 | {} | |
77 | explicit random_t( distr_type&& d ) | |
78 | : m_distribution( std::forward<distr_type>(d) ) | |
79 | , m_engine( std::random_device()() ){} | |
80 | random_t( engine_type&& e, distr_type&& d ) | |
81 | : m_distribution( std::forward<distr_type>(d) ) | |
82 | , m_engine( std::forward<engine_type>(e) ){} | |
83 | ||
84 | // Generator interface | |
85 | data::size_t capacity() const { return BOOST_TEST_DS_INFINITE_SIZE; } | |
86 | SampleType next() | |
87 | { | |
88 | return m_distribution( m_engine ); | |
89 | } | |
90 | void reset() {} | |
91 | ||
92 | //! Sets the seed of the pseudo-random number engine. | |
93 | template<typename SeedType> | |
94 | void seed( SeedType&& seed ) { m_engine.seed( std::forward<SeedType>( seed ) ); } | |
95 | ||
96 | private: | |
97 | // Data members | |
98 | DistributionType m_distribution; | |
99 | EngineType m_engine; | |
100 | }; | |
101 | ||
102 | //____________________________________________________________________________// | |
103 | ||
104 | } // namespace monomorphic | |
105 | ||
106 | ||
107 | //! @brief Returns an infinite sequence of random numbers. | |
108 | //! | |
109 | //! The following overloads are available: | |
110 | //! @code | |
111 | //! auto d = random(); | |
112 | //! auto d = random(begin, end); | |
113 | //! auto d = random(params); | |
114 | //! @endcode | |
115 | //! | |
116 | //! | |
117 | //! - The first overload uses the default distribution, which is uniform and which elements | |
118 | //! are @c double type (the values are in [0, 1) ). | |
119 | //! - The second overload generates numbers in the given interval. The distribution is uniform (in [begin, end) | |
120 | //! for real numbers, and in [begin, end] for integers). The type of the distribution is deduced from the type | |
121 | //! of the @c begin and @c end parameters. | |
122 | //! - The third overload generates numbers using the named parameter inside @c params , which are: | |
123 | //! - @c distribution: the distribution used. In this overload, since the type of the samples cannot be deduced, | |
124 | //! the samples are of type @c double and the distribution is uniform real in [0, 1). | |
125 | //! - @c seed: the seed for generating the values | |
126 | //! - @c engine: the random number generator engine | |
127 | //! | |
128 | //! The function returns an object that implements the dataset API. | |
129 | //! @note This function is available only for C++11 capable compilers. | |
130 | inline monomorphic::generated_by< monomorphic::random_t<>> random() | |
131 | { | |
132 | return monomorphic::generated_by<monomorphic::random_t<>>( monomorphic::random_t<>() ); | |
133 | } | |
134 | ||
135 | //____________________________________________________________________________// | |
136 | ||
137 | /// @overload boost::unit_test::data::random() | |
138 | template<typename SampleType> | |
139 | inline monomorphic::generated_by< monomorphic::random_t<SampleType>> | |
140 | random( SampleType begin, SampleType end ) | |
141 | { | |
142 | typedef monomorphic::random_t<SampleType> Gen; | |
143 | typedef typename Gen::distr_type distr_type; | |
144 | return monomorphic::generated_by<Gen>( Gen( distr_type(begin,end) ) ); | |
145 | } | |
146 | ||
147 | //____________________________________________________________________________// | |
148 | ||
149 | namespace ds_detail { | |
150 | template<typename Params> | |
151 | struct random_gen_type { | |
152 | typedef typename nfp::param_type<Params,decltype(distribution),std::uniform_real_distribution<>>::type distr_type; | |
153 | typedef typename nfp::param_type<Params,decltype(engine),std::default_random_engine>::type engine_type; | |
154 | typedef typename distr_type::result_type sample_type; | |
155 | ||
156 | typedef monomorphic::random_t<sample_type,distr_type,engine_type> type; | |
157 | }; | |
158 | ||
159 | } | |
160 | ||
161 | ||
162 | /// @overload boost::unit_test::data::random() | |
163 | template<typename Params> | |
164 | inline monomorphic::generated_by<typename ds_detail::random_gen_type<Params>::type> | |
165 | random( Params const& params ) | |
166 | { | |
167 | typedef typename ds_detail::random_gen_type<Params>::type Gen; | |
168 | typedef typename Gen::distr_type distr_type; | |
169 | typedef typename Gen::engine_type engine_type; | |
170 | ||
171 | std::random_device rd; | |
172 | engine_type E; | |
173 | // engine_type E( rd ); | |
174 | if( params.has(engine) ) | |
175 | E = params[engine]; | |
176 | ||
177 | distr_type D; | |
178 | if( params.has(distribution) ) | |
179 | D = params[distribution]; | |
180 | ||
181 | Gen G( std::move(E), std::move(D) ); | |
182 | ||
183 | if( params.has(seed) ) | |
184 | G.seed( params[seed] ); | |
185 | ||
186 | return monomorphic::generated_by<Gen>( std::move(G) ); | |
187 | } | |
188 | ||
189 | } // namespace data | |
190 | } // namespace unit_test | |
191 | } // namespace boost | |
192 | ||
193 | #include <boost/test/detail/enable_warnings.hpp> | |
194 | ||
195 | #endif // BOOST_TEST_NO_RANDOM_DATASET_AVAILABLE | |
196 | ||
197 | ||
198 | #endif // BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_RANDOM_HPP_101512GER |