From 43a2d0286b45b46ea90a71d858805080b485bfc6 Mon Sep 17 00:00:00 2001 From: Jakub Szuppe Date: Sun, 24 Apr 2016 20:58:19 +0200 Subject: [PATCH 1/3] Fix range of values generated by uniform real dist Now generated floating-point values are uniformly distributed on the interval [a, b). Before this commit it was possible to produce values equal to b. --- include/boost/compute/random/uniform_real_distribution.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/boost/compute/random/uniform_real_distribution.hpp b/include/boost/compute/random/uniform_real_distribution.hpp index 231b0dba0..8d5dee62a 100644 --- a/include/boost/compute/random/uniform_real_distribution.hpp +++ b/include/boost/compute/random/uniform_real_distribution.hpp @@ -20,7 +20,7 @@ namespace boost { namespace compute { /// \class uniform_real_distribution -/// \brief Produces uniformily distributed random floating-point numbers. +/// \brief Produces uniformly distributed random floating-point numbers. /// /// The following example shows how to setup a uniform real distribution to /// produce random \c float values between \c 1 and \c 100. @@ -59,7 +59,7 @@ class uniform_real_distribution return m_b; } - /// Generates uniformily distributed floating-point numbers and stores + /// Generates uniformly distributed floating-point numbers and stores /// them to the range [\p first, \p last). template void generate(OutputIterator first, @@ -69,7 +69,7 @@ class uniform_real_distribution { BOOST_COMPUTE_FUNCTION(RealType, scale_random, (const uint_ x), { - return LO + (convert_RealType(x) / MAX_RANDOM) * (HI - LO); + return nextafter(LO + (convert_RealType(x) / MAX_RANDOM) * (HI - LO), (RealType) LO); }); scale_random.define("LO", detail::make_literal(m_a)); @@ -78,6 +78,7 @@ class uniform_real_distribution scale_random.define( "convert_RealType", std::string("convert_") + type_name() ); + scale_random.define("RealType", type_name()); generator.generate( first, last, scale_random, queue From 55bea5879072182be33a26936ebf301e02ab4311 Mon Sep 17 00:00:00 2001 From: Jakub Szuppe Date: Sun, 24 Apr 2016 20:58:38 +0200 Subject: [PATCH 2/3] Add test for values generated by uniform real dist New test checks if values generated by uniform real distribution are in the [a,b) interval. --- test/test_uniform_real_distribution.cpp | 58 ++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/test/test_uniform_real_distribution.cpp b/test/test_uniform_real_distribution.cpp index 65a74f314..d5394427d 100644 --- a/test/test_uniform_real_distribution.cpp +++ b/test/test_uniform_real_distribution.cpp @@ -14,10 +14,13 @@ #include #include #include +#include +#include #include #include #include #include +#include #include "context_setup.hpp" @@ -40,7 +43,60 @@ distribution.generate(vec.begin(), vec.end(), engine, queue); BOOST_CHECK_EQUAL( boost::compute::count_if( - vec.begin(), vec.end(), _1 < 1.0f || _1 > 100.0f, queue + vec.begin(), vec.end(), _1 < 1.0f || _1 >= 100.0f, queue + ), + size_t(0) + ); +} + +template +class range_test_engine +{ +public: + explicit range_test_engine(boost::compute::command_queue &queue) { + (void) queue; + } + + template + void generate(OutputIterator first, OutputIterator last, Function op, boost::compute::command_queue &queue) + { + boost::compute::vector tmp(std::distance(first, last), queue.get_context()); + + BOOST_COMPUTE_FUNCTION(T, max_random, (const T x), + { + if(get_global_id(0) < 1) + return (ValueType) MAX_RANDOM; + else + return (ValueType) 0; + }); + + max_random.define("MAX_RANDOM", "UINT_MAX"); + max_random.define("ValueType", boost::compute::type_name()); + + boost::compute::transform(tmp.begin(), tmp.end(), tmp.begin(), max_random, queue); + boost::compute::transform(tmp.begin(), tmp.end(), first, op, queue); + } +}; + +// For checking if result is in the correct range [low, hi) +BOOST_AUTO_TEST_CASE(uniform_real_distribution_range) +{ + using boost::compute::lambda::_1; + + boost::compute::vector vec(32, context); + + // initialize the range_test_engine + range_test_engine engine(queue); + + // setup the uniform distribution to produce floats between 0.9 and 1.0 + boost::compute::uniform_real_distribution distribution(0.9f, 1.0f); + + // generate the random values and store them to 'vec' + distribution.generate(vec.begin(), vec.end(), engine, queue); + + BOOST_CHECK_EQUAL( + boost::compute::count_if( + vec.begin(), vec.end(), _1 < 0.9f || _1 >= 1.0f, queue ), size_t(0) ); From 8aea29032044072080668898ac46bc4393e13cd7 Mon Sep 17 00:00:00 2001 From: Jakub Szuppe Date: Sun, 24 Apr 2016 21:55:14 +0200 Subject: [PATCH 3/3] Make sure a < b in uniform real distribution Making sure that the left endpoint (a) of the range in uniform real distribution is less than the right endpoint (b). --- include/boost/compute/random/uniform_real_distribution.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/compute/random/uniform_real_distribution.hpp b/include/boost/compute/random/uniform_real_distribution.hpp index 8d5dee62a..d72d18d20 100644 --- a/include/boost/compute/random/uniform_real_distribution.hpp +++ b/include/boost/compute/random/uniform_real_distribution.hpp @@ -11,6 +11,8 @@ #ifndef BOOST_COMPUTE_RANDOM_UNIFORM_REAL_DISTRIBUTION_HPP #define BOOST_COMPUTE_RANDOM_UNIFORM_REAL_DISTRIBUTION_HPP +#include + #include #include #include @@ -36,10 +38,12 @@ class uniform_real_distribution /// Creates a new uniform distribution producing numbers in the range /// [\p a, \p b). + /// Requires a < b uniform_real_distribution(RealType a = 0.f, RealType b = 1.f) : m_a(a), m_b(b) { + BOOST_ASSERT(a < b); } /// Destroys the uniform_real_distribution object.