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 11 #ifndef BOOST_COMPUTE_RANDOM_UNIFORM_INT_DISTRIBUTION_HPP 12 #define BOOST_COMPUTE_RANDOM_UNIFORM_INT_DISTRIBUTION_HPP 13 14 #include <limits> 15 16 #include <boost/type_traits.hpp> 17 #include <boost/static_assert.hpp> 18 19 #include <boost/compute/command_queue.hpp> 20 #include <boost/compute/container/vector.hpp> 21 #include <boost/compute/function.hpp> 22 #include <boost/compute/types/fundamental.hpp> 23 #include <boost/compute/algorithm/copy_if.hpp> 24 #include <boost/compute/algorithm/transform.hpp> 25 26 namespace boost { 27 namespace compute { 28 29 /// \class uniform_int_distribution 30 /// \brief Produces uniformily distributed random integers 31 /// 32 /// The following example shows how to setup a uniform int distribution to 33 /// produce random integers 0 and 1. 34 /// 35 /// \snippet test/test_uniform_int_distribution.cpp generate 36 /// 37 template<class IntType = uint_> 38 class uniform_int_distribution 39 { 40 public: 41 typedef IntType result_type; 42 43 /// Creates a new uniform distribution producing numbers in the range 44 /// [\p a, \p b]. uniform_int_distribution(IntType a=0,IntType b=(std::numeric_limits<IntType>::max)())45 explicit uniform_int_distribution(IntType a = 0, 46 IntType b = (std::numeric_limits<IntType>::max)()) 47 : m_a(a), 48 m_b(b) 49 { 50 } 51 52 /// Destroys the uniform_int_distribution object. ~uniform_int_distribution()53 ~uniform_int_distribution() 54 { 55 } 56 57 /// Returns the minimum value of the distribution. a() const58 result_type a() const 59 { 60 return m_a; 61 } 62 63 /// Returns the maximum value of the distribution. b() const64 result_type b() const 65 { 66 return m_b; 67 } 68 69 /// Generates uniformily distributed integers and stores 70 /// them to the range [\p first, \p last). 71 template<class OutputIterator, class Generator> generate(OutputIterator first,OutputIterator last,Generator & generator,command_queue & queue)72 void generate(OutputIterator first, 73 OutputIterator last, 74 Generator &generator, 75 command_queue &queue) 76 { 77 size_t size = std::distance(first, last); 78 typedef typename Generator::result_type g_result_type; 79 80 vector<g_result_type> tmp(size, queue.get_context()); 81 vector<g_result_type> tmp2(size, queue.get_context()); 82 83 uint_ bound = ((uint_(-1))/(m_b-m_a+1))*(m_b-m_a+1); 84 85 buffer_iterator<g_result_type> tmp2_iter; 86 87 while(size>0) 88 { 89 generator.generate(tmp.begin(), tmp.begin() + size, queue); 90 tmp2_iter = copy_if(tmp.begin(), tmp.begin() + size, tmp2.begin(), 91 _1 <= bound, queue); 92 size = std::distance(tmp2_iter, tmp2.end()); 93 } 94 95 BOOST_COMPUTE_FUNCTION(IntType, scale_random, (const g_result_type x), 96 { 97 return LO + (x % (HI-LO+1)); 98 }); 99 100 scale_random.define("LO", boost::lexical_cast<std::string>(m_a)); 101 scale_random.define("HI", boost::lexical_cast<std::string>(m_b)); 102 103 transform(tmp2.begin(), tmp2.end(), first, scale_random, queue); 104 } 105 106 private: 107 IntType m_a; 108 IntType m_b; 109 110 BOOST_STATIC_ASSERT_MSG( 111 boost::is_integral<IntType>::value, 112 "Template argument must be integral" 113 ); 114 }; 115 116 } // end compute namespace 117 } // end boost namespace 118 119 #endif // BOOST_COMPUTE_RANDOM_UNIFORM_INT_DISTRIBUTION_HPP 120