Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions include/boost/compute/random/uniform_real_distribution.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#ifndef BOOST_COMPUTE_RANDOM_UNIFORM_REAL_DISTRIBUTION_HPP
#define BOOST_COMPUTE_RANDOM_UNIFORM_REAL_DISTRIBUTION_HPP

#include <boost/assert.hpp>

#include <boost/compute/command_queue.hpp>
#include <boost/compute/function.hpp>
#include <boost/compute/detail/literal.hpp>
Expand All @@ -20,7 +22,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.
Expand All @@ -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.
Expand All @@ -59,7 +63,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<class OutputIterator, class Generator>
void generate(OutputIterator first,
Expand All @@ -69,7 +73,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));
Expand All @@ -78,6 +82,7 @@ class uniform_real_distribution
scale_random.define(
"convert_RealType", std::string("convert_") + type_name<RealType>()
);
scale_random.define("RealType", type_name<RealType>());

generator.generate(
first, last, scale_random, queue
Expand Down
58 changes: 57 additions & 1 deletion test/test_uniform_real_distribution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@
#include <boost/compute/system.hpp>
#include <boost/compute/command_queue.hpp>
#include <boost/compute/algorithm/count_if.hpp>
#include <boost/compute/algorithm/transform.hpp>
#include <boost/compute/function.hpp>
#include <boost/compute/container/vector.hpp>
#include <boost/compute/random/default_random_engine.hpp>
#include <boost/compute/random/uniform_real_distribution.hpp>
#include <boost/compute/lambda.hpp>
#include <boost/compute/types/fundamental.hpp>

#include "context_setup.hpp"

Expand All @@ -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 T>
class range_test_engine
{
public:
explicit range_test_engine(boost::compute::command_queue &queue) {
(void) queue;
}

template<class OutputIterator, class Function>
void generate(OutputIterator first, OutputIterator last, Function op, boost::compute::command_queue &queue)
{
boost::compute::vector<T> 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<T>());

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<float> vec(32, context);

// initialize the range_test_engine
range_test_engine<boost::compute::uint_> engine(queue);

// setup the uniform distribution to produce floats between 0.9 and 1.0
boost::compute::uniform_real_distribution<float> 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)
);
Expand Down