random.hpp 6.5 KB

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