discrete_distribution.hpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. //---------------------------------------------------------------------------//
  2. // Copyright (c) 2014 Roshan <thisisroshansmail@gmail.com>
  3. //
  4. // Distributed under the Boost Software License, Version 1.0
  5. // See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt
  7. //
  8. // See http://boostorg.github.com/compute for more information.
  9. //---------------------------------------------------------------------------//
  10. #ifndef BOOST_COMPUTE_RANDOM_DISCRETE_DISTRIBUTION_HPP
  11. #define BOOST_COMPUTE_RANDOM_DISCRETE_DISTRIBUTION_HPP
  12. #include <boost/compute/command_queue.hpp>
  13. #include <boost/compute/function.hpp>
  14. #include <boost/compute/algorithm/accumulate.hpp>
  15. #include <boost/compute/algorithm/copy.hpp>
  16. #include <boost/compute/algorithm/transform.hpp>
  17. #include <boost/compute/detail/literal.hpp>
  18. #include <boost/compute/types/fundamental.hpp>
  19. namespace boost {
  20. namespace compute {
  21. /// \class discrete_distribution
  22. /// \brief Produces random integers on the interval [0, n), where
  23. /// probability of each integer is given by the weight of the ith
  24. /// integer divided by the sum of all weights.
  25. ///
  26. /// The following example shows how to setup a discrete distribution to
  27. /// produce 0 and 1 with equal probability
  28. ///
  29. /// \snippet test/test_discrete_distribution.cpp generate
  30. ///
  31. template<class IntType = uint_>
  32. class discrete_distribution
  33. {
  34. public:
  35. typedef IntType result_type;
  36. /// Creates a new discrete distribution with weights given by
  37. /// the range [\p first, \p last)
  38. template<class InputIterator>
  39. discrete_distribution(InputIterator first, InputIterator last)
  40. : m_n(std::distance(first, last)),
  41. m_probabilities(std::distance(first, last))
  42. {
  43. double sum = 0;
  44. for(InputIterator iter = first; iter!=last; iter++)
  45. {
  46. sum += *iter;
  47. }
  48. for(size_t i=0; i<m_n; i++)
  49. {
  50. m_probabilities[i] = m_probabilities[i-1] + first[i]/sum;
  51. }
  52. }
  53. /// Destroys the discrete_distribution object.
  54. ~discrete_distribution()
  55. {
  56. }
  57. /// Returns the value of n
  58. result_type n() const
  59. {
  60. return m_n;
  61. }
  62. /// Returns the probabilities
  63. ::std::vector<double> probabilities() const
  64. {
  65. return m_probabilities;
  66. }
  67. /// Generates uniformily distributed integers and stores
  68. /// them to the range [\p first, \p last).
  69. template<class OutputIterator, class Generator>
  70. void generate(OutputIterator first,
  71. OutputIterator last,
  72. Generator &generator,
  73. command_queue &queue)
  74. {
  75. std::string source = "inline uint scale_random(uint x)\n";
  76. source = source +
  77. "{\n" +
  78. "float rno = convert_float(x) / UINT_MAX;\n";
  79. for(size_t i=0; i<m_n; i++)
  80. {
  81. source = source +
  82. "if(rno <= " + detail::make_literal<float>(m_probabilities[i]) + ")\n" +
  83. " return " + detail::make_literal(i) + ";\n";
  84. }
  85. source = source +
  86. "return " + detail::make_literal(m_n - 1) + ";\n" +
  87. "}\n";
  88. BOOST_COMPUTE_FUNCTION(IntType, scale_random, (const uint_ x), {});
  89. scale_random.set_source(source);
  90. generator.generate(first, last, scale_random, queue);
  91. }
  92. private:
  93. size_t m_n;
  94. ::std::vector<double> m_probabilities;
  95. };
  96. } // end compute namespace
  97. } // end boost namespace
  98. #endif // BOOST_COMPUTE_RANDOM_UNIFORM_INT_DISTRIBUTION_HPP