stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2014 Roshan <thisisroshansmail@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_RANDOM_BERNOULLI_DISTRIBUTION_HPP
|
||||
#define BOOST_COMPUTE_RANDOM_BERNOULLI_DISTRIBUTION_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
#include <boost/compute/command_queue.hpp>
|
||||
#include <boost/compute/function.hpp>
|
||||
#include <boost/compute/types/fundamental.hpp>
|
||||
#include <boost/compute/detail/iterator_range_size.hpp>
|
||||
#include <boost/compute/detail/literal.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
///
|
||||
/// \class bernoulli_distribution
|
||||
/// \brief Produces random boolean values according to the following
|
||||
/// discrete probability function with parameter p :
|
||||
/// P(true/p) = p and P(false/p) = (1 - p)
|
||||
///
|
||||
/// The following example shows how to setup a bernoulli distribution to
|
||||
/// produce random boolean values with parameter p = 0.25
|
||||
///
|
||||
/// \snippet test/test_bernoulli_distribution.cpp generate
|
||||
///
|
||||
template<class RealType = float>
|
||||
class bernoulli_distribution
|
||||
{
|
||||
public:
|
||||
|
||||
/// Creates a new bernoulli distribution
|
||||
bernoulli_distribution(RealType p = 0.5f)
|
||||
: m_p(p)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destroys the bernoulli_distribution object
|
||||
~bernoulli_distribution()
|
||||
{
|
||||
}
|
||||
|
||||
/// Returns the value of the parameter p
|
||||
RealType p() const
|
||||
{
|
||||
return m_p;
|
||||
}
|
||||
|
||||
/// Generates bernoulli distributed booleans and stores
|
||||
/// them in the range [\p first, \p last).
|
||||
template<class OutputIterator, class Generator>
|
||||
void generate(OutputIterator first,
|
||||
OutputIterator last,
|
||||
Generator &generator,
|
||||
command_queue &queue)
|
||||
{
|
||||
size_t count = detail::iterator_range_size(first, last);
|
||||
|
||||
vector<uint_> tmp(count, queue.get_context());
|
||||
generator.generate(tmp.begin(), tmp.end(), queue);
|
||||
|
||||
BOOST_COMPUTE_FUNCTION(bool, scale_random, (const uint_ x),
|
||||
{
|
||||
return (convert_RealType(x) / MAX_RANDOM) < PARAM;
|
||||
});
|
||||
|
||||
scale_random.define("PARAM", detail::make_literal(m_p));
|
||||
scale_random.define("MAX_RANDOM", "UINT_MAX");
|
||||
scale_random.define(
|
||||
"convert_RealType", std::string("convert_") + type_name<RealType>()
|
||||
);
|
||||
|
||||
transform(
|
||||
tmp.begin(), tmp.end(), first, scale_random, queue
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
RealType m_p;
|
||||
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
boost::is_floating_point<RealType>::value,
|
||||
"Template argument must be a floating point type"
|
||||
);
|
||||
};
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_RANDOM_BERNOULLI_DISTRIBUTION_HPP
|
||||
@@ -0,0 +1,24 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_RANDOM_DEFAULT_RANDOM_ENGINE_HPP
|
||||
#define BOOST_COMPUTE_RANDOM_DEFAULT_RANDOM_ENGINE_HPP
|
||||
|
||||
#include <boost/compute/random/mersenne_twister_engine.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
typedef mt19937 default_random_engine;
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_RANDOM_DEFAULT_RANDOM_ENGINE_HPP
|
||||
@@ -0,0 +1,160 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2014 Roshan <thisisroshansmail@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_RANDOM_DISCRETE_DISTRIBUTION_HPP
|
||||
#define BOOST_COMPUTE_RANDOM_DISCRETE_DISTRIBUTION_HPP
|
||||
|
||||
#include <numeric>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#include <boost/compute/command_queue.hpp>
|
||||
#include <boost/compute/function.hpp>
|
||||
#include <boost/compute/algorithm/accumulate.hpp>
|
||||
#include <boost/compute/algorithm/copy.hpp>
|
||||
#include <boost/compute/algorithm/transform.hpp>
|
||||
#include <boost/compute/detail/literal.hpp>
|
||||
#include <boost/compute/types/fundamental.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
/// \class discrete_distribution
|
||||
/// \brief Produces random integers on the interval [0, n), where
|
||||
/// probability of each integer is given by the weight of the ith
|
||||
/// integer divided by the sum of all weights.
|
||||
///
|
||||
/// The following example shows how to setup a discrete distribution to
|
||||
/// produce 0 and 1 with equal probability
|
||||
///
|
||||
/// \snippet test/test_discrete_distribution.cpp generate
|
||||
///
|
||||
template<class IntType = uint_>
|
||||
class discrete_distribution
|
||||
{
|
||||
public:
|
||||
typedef IntType result_type;
|
||||
|
||||
/// Creates a new discrete distribution with a single weight p = { 1 }.
|
||||
/// This distribution produces only zeroes.
|
||||
discrete_distribution()
|
||||
: m_probabilities(1, double(1)),
|
||||
m_scanned_probabilities(1, double(1))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// Creates a new discrete distribution with weights given by
|
||||
/// the range [\p first, \p last).
|
||||
template<class InputIterator>
|
||||
discrete_distribution(InputIterator first, InputIterator last)
|
||||
: m_probabilities(first, last),
|
||||
m_scanned_probabilities(std::distance(first, last))
|
||||
{
|
||||
if(first != last) {
|
||||
// after this m_scanned_probabilities.back() is a sum of all
|
||||
// weights from the range [first, last)
|
||||
std::partial_sum(first, last, m_scanned_probabilities.begin());
|
||||
|
||||
std::vector<double>::iterator i = m_probabilities.begin();
|
||||
std::vector<double>::iterator j = m_scanned_probabilities.begin();
|
||||
for(; i != m_probabilities.end(); ++i, ++j)
|
||||
{
|
||||
// dividing each weight by sum of all weights to
|
||||
// get probabilities
|
||||
*i = *i / m_scanned_probabilities.back();
|
||||
// dividing each partial sum of weights by sum of
|
||||
// all weights to get partial sums of probabilities
|
||||
*j = *j / m_scanned_probabilities.back();
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_probabilities.push_back(double(1));
|
||||
m_scanned_probabilities.push_back(double(1));
|
||||
}
|
||||
}
|
||||
|
||||
/// Destroys the discrete_distribution object.
|
||||
~discrete_distribution()
|
||||
{
|
||||
}
|
||||
|
||||
/// Returns the probabilities
|
||||
::std::vector<double> probabilities() const
|
||||
{
|
||||
return m_probabilities;
|
||||
}
|
||||
|
||||
/// Returns the minimum potentially generated value.
|
||||
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const
|
||||
{
|
||||
return result_type(0);
|
||||
}
|
||||
|
||||
/// Returns the maximum potentially generated value.
|
||||
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const
|
||||
{
|
||||
size_t type_max = static_cast<size_t>(
|
||||
(std::numeric_limits<result_type>::max)()
|
||||
);
|
||||
if(m_probabilities.size() - 1 > type_max) {
|
||||
return (std::numeric_limits<result_type>::max)();
|
||||
}
|
||||
return static_cast<result_type>(m_probabilities.size() - 1);
|
||||
}
|
||||
|
||||
/// Generates uniformly distributed integers and stores
|
||||
/// them to the range [\p first, \p last).
|
||||
template<class OutputIterator, class Generator>
|
||||
void generate(OutputIterator first,
|
||||
OutputIterator last,
|
||||
Generator &generator,
|
||||
command_queue &queue)
|
||||
{
|
||||
std::string source = "inline IntType scale_random(uint x)\n";
|
||||
|
||||
source = source +
|
||||
"{\n" +
|
||||
"float rno = convert_float(x) / UINT_MAX;\n";
|
||||
for(size_t i = 0; i < m_scanned_probabilities.size() - 1; i++)
|
||||
{
|
||||
source = source +
|
||||
"if(rno <= " + detail::make_literal<float>(m_scanned_probabilities[i]) + ")\n" +
|
||||
" return " + detail::make_literal(i) + ";\n";
|
||||
}
|
||||
|
||||
source = source +
|
||||
"return " + detail::make_literal(m_scanned_probabilities.size() - 1) + ";\n" +
|
||||
"}\n";
|
||||
|
||||
BOOST_COMPUTE_FUNCTION(IntType, scale_random, (const uint_ x), {});
|
||||
|
||||
scale_random.set_source(source);
|
||||
scale_random.define("IntType", type_name<IntType>());
|
||||
|
||||
generator.generate(first, last, scale_random, queue);
|
||||
}
|
||||
|
||||
private:
|
||||
::std::vector<double> m_probabilities;
|
||||
::std::vector<double> m_scanned_probabilities;
|
||||
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
boost::is_integral<IntType>::value,
|
||||
"Template argument must be integral"
|
||||
);
|
||||
};
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_RANDOM_UNIFORM_INT_DISTRIBUTION_HPP
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2014 Roshan <thisisroshansmail@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_RANDOM_LINEAR_CONGRUENTIAL_ENGINE_HPP
|
||||
#define BOOST_COMPUTE_RANDOM_LINEAR_CONGRUENTIAL_ENGINE_HPP
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/compute/types.hpp>
|
||||
#include <boost/compute/buffer.hpp>
|
||||
#include <boost/compute/kernel.hpp>
|
||||
#include <boost/compute/context.hpp>
|
||||
#include <boost/compute/program.hpp>
|
||||
#include <boost/compute/command_queue.hpp>
|
||||
#include <boost/compute/algorithm/transform.hpp>
|
||||
#include <boost/compute/container/vector.hpp>
|
||||
#include <boost/compute/detail/iterator_range_size.hpp>
|
||||
#include <boost/compute/iterator/discard_iterator.hpp>
|
||||
#include <boost/compute/utility/program_cache.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
///
|
||||
/// \class linear_congruential_engine
|
||||
/// \brief 'Quick and Dirty' linear congruential engine
|
||||
///
|
||||
/// Quick and dirty linear congruential engine to generate low quality
|
||||
/// random numbers very quickly. For uses in which good quality of random
|
||||
/// numbers is required(Monte-Carlo Simulations), use other engines like
|
||||
/// Mersenne Twister instead.
|
||||
///
|
||||
template<class T = uint_>
|
||||
class linear_congruential_engine
|
||||
{
|
||||
public:
|
||||
typedef T result_type;
|
||||
static const T default_seed = 1;
|
||||
static const T a = 1099087573;
|
||||
static const size_t threads = 1024;
|
||||
|
||||
/// Creates a new linear_congruential_engine and seeds it with \p value.
|
||||
explicit linear_congruential_engine(command_queue &queue,
|
||||
result_type value = default_seed)
|
||||
: m_context(queue.get_context()),
|
||||
m_multiplicands(m_context, threads * sizeof(result_type))
|
||||
{
|
||||
// setup program
|
||||
load_program();
|
||||
|
||||
// seed state
|
||||
seed(value, queue);
|
||||
|
||||
// generate multiplicands
|
||||
generate_multiplicands(queue);
|
||||
}
|
||||
|
||||
/// Creates a new linear_congruential_engine object as a copy of \p other.
|
||||
linear_congruential_engine(const linear_congruential_engine<T> &other)
|
||||
: m_context(other.m_context),
|
||||
m_program(other.m_program),
|
||||
m_seed(other.m_seed),
|
||||
m_multiplicands(other.m_multiplicands)
|
||||
{
|
||||
}
|
||||
|
||||
/// Copies \p other to \c *this.
|
||||
linear_congruential_engine<T>&
|
||||
operator=(const linear_congruential_engine<T> &other)
|
||||
{
|
||||
if(this != &other){
|
||||
m_context = other.m_context;
|
||||
m_program = other.m_program;
|
||||
m_seed = other.m_seed;
|
||||
m_multiplicands = other.m_multiplicands;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Destroys the linear_congruential_engine object.
|
||||
~linear_congruential_engine()
|
||||
{
|
||||
}
|
||||
|
||||
/// Seeds the random number generator with \p value.
|
||||
///
|
||||
/// \param value seed value for the random-number generator
|
||||
/// \param queue command queue to perform the operation
|
||||
///
|
||||
/// If no seed value is provided, \c default_seed is used.
|
||||
void seed(result_type value, command_queue &queue)
|
||||
{
|
||||
(void) queue;
|
||||
|
||||
m_seed = value;
|
||||
}
|
||||
|
||||
/// \overload
|
||||
void seed(command_queue &queue)
|
||||
{
|
||||
seed(default_seed, queue);
|
||||
}
|
||||
|
||||
/// Generates random numbers and stores them to the range [\p first, \p last).
|
||||
template<class OutputIterator>
|
||||
void generate(OutputIterator first, OutputIterator last, command_queue &queue)
|
||||
{
|
||||
size_t size = detail::iterator_range_size(first, last);
|
||||
|
||||
kernel fill_kernel(m_program, "fill");
|
||||
fill_kernel.set_arg(1, m_multiplicands);
|
||||
fill_kernel.set_arg(2, first.get_buffer());
|
||||
|
||||
size_t offset = 0;
|
||||
|
||||
for(;;){
|
||||
size_t count = 0;
|
||||
if(size > threads){
|
||||
count = (std::min)(static_cast<size_t>(threads), size - offset);
|
||||
}
|
||||
else {
|
||||
count = size;
|
||||
}
|
||||
fill_kernel.set_arg(0, static_cast<const uint_>(m_seed));
|
||||
fill_kernel.set_arg(3, static_cast<const uint_>(offset));
|
||||
queue.enqueue_1d_range_kernel(fill_kernel, 0, count, 0);
|
||||
|
||||
offset += count;
|
||||
|
||||
if(offset >= size){
|
||||
break;
|
||||
}
|
||||
|
||||
update_seed(queue);
|
||||
}
|
||||
}
|
||||
|
||||
/// \internal_
|
||||
void generate(discard_iterator first, discard_iterator last, command_queue &queue)
|
||||
{
|
||||
(void) queue;
|
||||
|
||||
size_t size = detail::iterator_range_size(first, last);
|
||||
uint_ max_mult =
|
||||
detail::read_single_value<T>(m_multiplicands, threads-1, queue);
|
||||
while(size >= threads) {
|
||||
m_seed *= max_mult;
|
||||
size -= threads;
|
||||
}
|
||||
m_seed *=
|
||||
detail::read_single_value<T>(m_multiplicands, size-1, queue);
|
||||
}
|
||||
|
||||
/// Generates random numbers, transforms them with \p op, and then stores
|
||||
/// them to the range [\p first, \p last).
|
||||
template<class OutputIterator, class Function>
|
||||
void generate(OutputIterator first, OutputIterator last, Function op, command_queue &queue)
|
||||
{
|
||||
vector<T> tmp(std::distance(first, last), queue.get_context());
|
||||
generate(tmp.begin(), tmp.end(), queue);
|
||||
transform(tmp.begin(), tmp.end(), first, op, queue);
|
||||
}
|
||||
|
||||
/// Generates \p z random numbers and discards them.
|
||||
void discard(size_t z, command_queue &queue)
|
||||
{
|
||||
generate(discard_iterator(0), discard_iterator(z), queue);
|
||||
}
|
||||
|
||||
private:
|
||||
/// \internal_
|
||||
/// Generates the multiplicands for each thread
|
||||
void generate_multiplicands(command_queue &queue)
|
||||
{
|
||||
kernel multiplicand_kernel =
|
||||
m_program.create_kernel("multiplicand");
|
||||
multiplicand_kernel.set_arg(0, m_multiplicands);
|
||||
|
||||
queue.enqueue_task(multiplicand_kernel);
|
||||
}
|
||||
|
||||
/// \internal_
|
||||
void update_seed(command_queue &queue)
|
||||
{
|
||||
m_seed *=
|
||||
detail::read_single_value<T>(m_multiplicands, threads-1, queue);
|
||||
}
|
||||
|
||||
/// \internal_
|
||||
void load_program()
|
||||
{
|
||||
boost::shared_ptr<program_cache> cache =
|
||||
program_cache::get_global_cache(m_context);
|
||||
|
||||
std::string cache_key =
|
||||
std::string("__boost_linear_congruential_engine_") + type_name<T>();
|
||||
|
||||
const char source[] =
|
||||
"__kernel void multiplicand(__global uint *multiplicands)\n"
|
||||
"{\n"
|
||||
" uint a = 1099087573;\n"
|
||||
" multiplicands[0] = a;\n"
|
||||
" for(uint i = 1; i < 1024; i++){\n"
|
||||
" multiplicands[i] = a * multiplicands[i-1];\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
|
||||
"__kernel void fill(const uint seed,\n"
|
||||
" __global uint *multiplicands,\n"
|
||||
" __global uint *result,"
|
||||
" const uint offset)\n"
|
||||
"{\n"
|
||||
" const uint i = get_global_id(0);\n"
|
||||
" result[offset+i] = seed * multiplicands[i];\n"
|
||||
"}\n";
|
||||
|
||||
m_program = cache->get_or_build(cache_key, std::string(), source, m_context);
|
||||
}
|
||||
|
||||
private:
|
||||
context m_context;
|
||||
program m_program;
|
||||
T m_seed;
|
||||
buffer m_multiplicands;
|
||||
};
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_RANDOM_LINEAR_CONGRUENTIAL_ENGINE_HPP
|
||||
@@ -0,0 +1,254 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_RANDOM_MERSENNE_TWISTER_ENGINE_HPP
|
||||
#define BOOST_COMPUTE_RANDOM_MERSENNE_TWISTER_ENGINE_HPP
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/compute/types.hpp>
|
||||
#include <boost/compute/buffer.hpp>
|
||||
#include <boost/compute/kernel.hpp>
|
||||
#include <boost/compute/context.hpp>
|
||||
#include <boost/compute/program.hpp>
|
||||
#include <boost/compute/command_queue.hpp>
|
||||
#include <boost/compute/algorithm/transform.hpp>
|
||||
#include <boost/compute/container/vector.hpp>
|
||||
#include <boost/compute/detail/iterator_range_size.hpp>
|
||||
#include <boost/compute/iterator/discard_iterator.hpp>
|
||||
#include <boost/compute/utility/program_cache.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
/// \class mersenne_twister_engine
|
||||
/// \brief Mersenne twister pseudorandom number generator.
|
||||
template<class T>
|
||||
class mersenne_twister_engine
|
||||
{
|
||||
public:
|
||||
typedef T result_type;
|
||||
static const T default_seed = 5489U;
|
||||
static const T n = 624;
|
||||
static const T m = 397;
|
||||
|
||||
/// Creates a new mersenne_twister_engine and seeds it with \p value.
|
||||
explicit mersenne_twister_engine(command_queue &queue,
|
||||
result_type value = default_seed)
|
||||
: m_context(queue.get_context()),
|
||||
m_state_buffer(m_context, n * sizeof(result_type))
|
||||
{
|
||||
// setup program
|
||||
load_program();
|
||||
|
||||
// seed state
|
||||
seed(value, queue);
|
||||
}
|
||||
|
||||
/// Creates a new mersenne_twister_engine object as a copy of \p other.
|
||||
mersenne_twister_engine(const mersenne_twister_engine<T> &other)
|
||||
: m_context(other.m_context),
|
||||
m_state_index(other.m_state_index),
|
||||
m_program(other.m_program),
|
||||
m_state_buffer(other.m_state_buffer)
|
||||
{
|
||||
}
|
||||
|
||||
/// Copies \p other to \c *this.
|
||||
mersenne_twister_engine<T>& operator=(const mersenne_twister_engine<T> &other)
|
||||
{
|
||||
if(this != &other){
|
||||
m_context = other.m_context;
|
||||
m_state_index = other.m_state_index;
|
||||
m_program = other.m_program;
|
||||
m_state_buffer = other.m_state_buffer;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Destroys the mersenne_twister_engine object.
|
||||
~mersenne_twister_engine()
|
||||
{
|
||||
}
|
||||
|
||||
/// Seeds the random number generator with \p value.
|
||||
///
|
||||
/// \param value seed value for the random-number generator
|
||||
/// \param queue command queue to perform the operation
|
||||
///
|
||||
/// If no seed value is provided, \c default_seed is used.
|
||||
void seed(result_type value, command_queue &queue)
|
||||
{
|
||||
kernel seed_kernel = m_program.create_kernel("seed");
|
||||
seed_kernel.set_arg(0, value);
|
||||
seed_kernel.set_arg(1, m_state_buffer);
|
||||
|
||||
queue.enqueue_task(seed_kernel);
|
||||
|
||||
m_state_index = 0;
|
||||
}
|
||||
|
||||
/// \overload
|
||||
void seed(command_queue &queue)
|
||||
{
|
||||
seed(default_seed, queue);
|
||||
}
|
||||
|
||||
/// Generates random numbers and stores them to the range [\p first, \p last).
|
||||
template<class OutputIterator>
|
||||
void generate(OutputIterator first, OutputIterator last, command_queue &queue)
|
||||
{
|
||||
const size_t size = detail::iterator_range_size(first, last);
|
||||
|
||||
kernel fill_kernel(m_program, "fill");
|
||||
fill_kernel.set_arg(0, m_state_buffer);
|
||||
fill_kernel.set_arg(2, first.get_buffer());
|
||||
|
||||
size_t offset = 0;
|
||||
size_t &p = m_state_index;
|
||||
|
||||
for(;;){
|
||||
size_t count = 0;
|
||||
if(size > n){
|
||||
count = (std::min)(static_cast<size_t>(n), size - offset);
|
||||
}
|
||||
else {
|
||||
count = size;
|
||||
}
|
||||
fill_kernel.set_arg(1, static_cast<const uint_>(p));
|
||||
fill_kernel.set_arg(3, static_cast<const uint_>(offset));
|
||||
queue.enqueue_1d_range_kernel(fill_kernel, 0, count, 0);
|
||||
|
||||
p += count;
|
||||
offset += count;
|
||||
|
||||
if(offset >= size){
|
||||
break;
|
||||
}
|
||||
|
||||
generate_state(queue);
|
||||
p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// \internal_
|
||||
void generate(discard_iterator first, discard_iterator last, command_queue &queue)
|
||||
{
|
||||
(void) queue;
|
||||
|
||||
m_state_index += std::distance(first, last);
|
||||
}
|
||||
|
||||
/// Generates random numbers, transforms them with \p op, and then stores
|
||||
/// them to the range [\p first, \p last).
|
||||
template<class OutputIterator, class Function>
|
||||
void generate(OutputIterator first, OutputIterator last, Function op, command_queue &queue)
|
||||
{
|
||||
vector<T> tmp(std::distance(first, last), queue.get_context());
|
||||
generate(tmp.begin(), tmp.end(), queue);
|
||||
transform(tmp.begin(), tmp.end(), first, op, queue);
|
||||
}
|
||||
|
||||
/// Generates \p z random numbers and discards them.
|
||||
void discard(size_t z, command_queue &queue)
|
||||
{
|
||||
generate(discard_iterator(0), discard_iterator(z), queue);
|
||||
}
|
||||
|
||||
/// \internal_ (deprecated)
|
||||
template<class OutputIterator>
|
||||
void fill(OutputIterator first, OutputIterator last, command_queue &queue)
|
||||
{
|
||||
generate(first, last, queue);
|
||||
}
|
||||
|
||||
private:
|
||||
/// \internal_
|
||||
void generate_state(command_queue &queue)
|
||||
{
|
||||
kernel generate_state_kernel =
|
||||
m_program.create_kernel("generate_state");
|
||||
generate_state_kernel.set_arg(0, m_state_buffer);
|
||||
queue.enqueue_task(generate_state_kernel);
|
||||
}
|
||||
|
||||
/// \internal_
|
||||
void load_program()
|
||||
{
|
||||
boost::shared_ptr<program_cache> cache =
|
||||
program_cache::get_global_cache(m_context);
|
||||
|
||||
std::string cache_key =
|
||||
std::string("__boost_mersenne_twister_engine_") + type_name<T>();
|
||||
|
||||
const char source[] =
|
||||
"static uint twiddle(uint u, uint v)\n"
|
||||
"{\n"
|
||||
" return (((u & 0x80000000U) | (v & 0x7FFFFFFFU)) >> 1) ^\n"
|
||||
" ((v & 1U) ? 0x9908B0DFU : 0x0U);\n"
|
||||
"}\n"
|
||||
|
||||
"__kernel void generate_state(__global uint *state)\n"
|
||||
"{\n"
|
||||
" const uint n = 624;\n"
|
||||
" const uint m = 397;\n"
|
||||
" for(uint i = 0; i < (n - m); i++)\n"
|
||||
" state[i] = state[i+m] ^ twiddle(state[i], state[i+1]);\n"
|
||||
" for(uint i = n - m; i < (n - 1); i++)\n"
|
||||
" state[i] = state[i+m-n] ^ twiddle(state[i], state[i+1]);\n"
|
||||
" state[n-1] = state[m-1] ^ twiddle(state[n-1], state[0]);\n"
|
||||
"}\n"
|
||||
|
||||
"__kernel void seed(const uint s, __global uint *state)\n"
|
||||
"{\n"
|
||||
" const uint n = 624;\n"
|
||||
" state[0] = s & 0xFFFFFFFFU;\n"
|
||||
" for(uint i = 1; i < n; i++){\n"
|
||||
" state[i] = 1812433253U * (state[i-1] ^ (state[i-1] >> 30)) + i;\n"
|
||||
" state[i] &= 0xFFFFFFFFU;\n"
|
||||
" }\n"
|
||||
" generate_state(state);\n"
|
||||
"}\n"
|
||||
|
||||
"static uint random_number(__global uint *state, const uint p)\n"
|
||||
"{\n"
|
||||
" uint x = state[p];\n"
|
||||
" x ^= (x >> 11);\n"
|
||||
" x ^= (x << 7) & 0x9D2C5680U;\n"
|
||||
" x ^= (x << 15) & 0xEFC60000U;\n"
|
||||
" return x ^ (x >> 18);\n"
|
||||
"}\n"
|
||||
|
||||
"__kernel void fill(__global uint *state,\n"
|
||||
" const uint state_index,\n"
|
||||
" __global uint *vector,\n"
|
||||
" const uint offset)\n"
|
||||
"{\n"
|
||||
" const uint i = get_global_id(0);\n"
|
||||
" vector[offset+i] = random_number(state, state_index + i);\n"
|
||||
"}\n";
|
||||
|
||||
m_program = cache->get_or_build(cache_key, std::string(), source, m_context);
|
||||
}
|
||||
|
||||
private:
|
||||
context m_context;
|
||||
size_t m_state_index;
|
||||
program m_program;
|
||||
buffer m_state_buffer;
|
||||
};
|
||||
|
||||
typedef mersenne_twister_engine<uint_> mt19937;
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_RANDOM_MERSENNE_TWISTER_ENGINE_HPP
|
||||
@@ -0,0 +1,140 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_RANDOM_NORMAL_DISTRIBUTION_HPP
|
||||
#define BOOST_COMPUTE_RANDOM_NORMAL_DISTRIBUTION_HPP
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
#include <boost/compute/command_queue.hpp>
|
||||
#include <boost/compute/function.hpp>
|
||||
#include <boost/compute/types/fundamental.hpp>
|
||||
#include <boost/compute/type_traits/make_vector_type.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
/// \class normal_distribution
|
||||
/// \brief Produces random, normally-distributed floating-point numbers.
|
||||
///
|
||||
/// The following example shows how to setup a normal distribution to
|
||||
/// produce random \c float values centered at \c 5:
|
||||
///
|
||||
/// \snippet test/test_normal_distribution.cpp generate
|
||||
///
|
||||
/// \see default_random_engine, uniform_real_distribution
|
||||
template<class RealType = float>
|
||||
class normal_distribution
|
||||
{
|
||||
public:
|
||||
typedef RealType result_type;
|
||||
|
||||
/// Creates a new normal distribution producing numbers with the given
|
||||
/// \p mean and \p stddev.
|
||||
normal_distribution(RealType mean = 0.f, RealType stddev = 1.f)
|
||||
: m_mean(mean),
|
||||
m_stddev(stddev)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destroys the normal distribution object.
|
||||
~normal_distribution()
|
||||
{
|
||||
}
|
||||
|
||||
/// Returns the mean value of the distribution.
|
||||
result_type mean() const
|
||||
{
|
||||
return m_mean;
|
||||
}
|
||||
|
||||
/// Returns the standard-deviation of the distribution.
|
||||
result_type stddev() const
|
||||
{
|
||||
return m_stddev;
|
||||
}
|
||||
|
||||
/// Returns the minimum value of the distribution.
|
||||
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const
|
||||
{
|
||||
return -std::numeric_limits<RealType>::infinity();
|
||||
}
|
||||
|
||||
/// Returns the maximum value of the distribution.
|
||||
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const
|
||||
{
|
||||
return std::numeric_limits<RealType>::infinity();
|
||||
}
|
||||
|
||||
/// Generates normally-distributed floating-point numbers and stores
|
||||
/// them to the range [\p first, \p last).
|
||||
template<class OutputIterator, class Generator>
|
||||
void generate(OutputIterator first,
|
||||
OutputIterator last,
|
||||
Generator &generator,
|
||||
command_queue &queue)
|
||||
{
|
||||
typedef typename make_vector_type<RealType, 2>::type RealType2;
|
||||
|
||||
size_t count = detail::iterator_range_size(first, last);
|
||||
|
||||
vector<uint_> tmp(count, queue.get_context());
|
||||
generator.generate(tmp.begin(), tmp.end(), queue);
|
||||
|
||||
BOOST_COMPUTE_FUNCTION(RealType2, box_muller, (const uint2_ x),
|
||||
{
|
||||
const RealType one = 1;
|
||||
const RealType two = 2;
|
||||
|
||||
// Use nextafter to push values down into [0,1) range; without this, floating point rounding can
|
||||
// lead to have x1 = 1, but that would lead to taking the log of 0, which would result in negative
|
||||
// infinities; by pushing the values off 1 towards 0, we ensure this won't happen.
|
||||
const RealType x1 = nextafter(x.x / (RealType) UINT_MAX, (RealType) 0);
|
||||
const RealType x2 = x.y / (RealType) UINT_MAX;
|
||||
|
||||
const RealType rho = sqrt(-two * log(one-x1));
|
||||
|
||||
const RealType z1 = rho * cos(two * M_PI_F * x2);
|
||||
const RealType z2 = rho * sin(two * M_PI_F * x2);
|
||||
|
||||
return (RealType2)(MEAN, MEAN) + (RealType2)(z1, z2) * (RealType2)(STDDEV, STDDEV);
|
||||
});
|
||||
|
||||
box_muller.define("MEAN", boost::lexical_cast<std::string>(m_mean));
|
||||
box_muller.define("STDDEV", boost::lexical_cast<std::string>(m_stddev));
|
||||
box_muller.define("RealType", type_name<RealType>());
|
||||
box_muller.define("RealType2", type_name<RealType2>());
|
||||
|
||||
transform(
|
||||
make_buffer_iterator<uint2_>(tmp.get_buffer(), 0),
|
||||
make_buffer_iterator<uint2_>(tmp.get_buffer(), count / 2),
|
||||
make_buffer_iterator<RealType2>(first.get_buffer(), 0),
|
||||
box_muller,
|
||||
queue
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
RealType m_mean;
|
||||
RealType m_stddev;
|
||||
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
boost::is_floating_point<RealType>::value,
|
||||
"Template argument must be a floating point type"
|
||||
);
|
||||
};
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_RANDOM_NORMAL_DISTRIBUTION_HPP
|
||||
@@ -0,0 +1,311 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2015 Muhammad Junaid Muzammil <mjunaidmuzammil@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_RANDOM_THREEFRY_HPP
|
||||
#define BOOST_COMPUTE_RANDOM_THREEFRY_HPP
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/compute/types.hpp>
|
||||
#include <boost/compute/buffer.hpp>
|
||||
#include <boost/compute/kernel.hpp>
|
||||
#include <boost/compute/context.hpp>
|
||||
#include <boost/compute/program.hpp>
|
||||
#include <boost/compute/command_queue.hpp>
|
||||
#include <boost/compute/algorithm/transform.hpp>
|
||||
#include <boost/compute/detail/iterator_range_size.hpp>
|
||||
#include <boost/compute/utility/program_cache.hpp>
|
||||
#include <boost/compute/container/vector.hpp>
|
||||
#include <boost/compute/iterator/discard_iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
/// \class threefry_engine
|
||||
/// \brief Threefry pseudorandom number generator.
|
||||
template<class T = uint_>
|
||||
class threefry_engine
|
||||
{
|
||||
public:
|
||||
static const size_t threads = 1024;
|
||||
typedef T result_type;
|
||||
|
||||
/// Creates a new threefry_engine and seeds it with \p value.
|
||||
explicit threefry_engine(command_queue &queue)
|
||||
: m_context(queue.get_context())
|
||||
{
|
||||
// setup program
|
||||
load_program();
|
||||
}
|
||||
|
||||
/// Creates a new threefry_engine object as a copy of \p other.
|
||||
threefry_engine(const threefry_engine<T> &other)
|
||||
: m_context(other.m_context),
|
||||
m_program(other.m_program)
|
||||
{
|
||||
}
|
||||
|
||||
/// Copies \p other to \c *this.
|
||||
threefry_engine<T>& operator=(const threefry_engine<T> &other)
|
||||
{
|
||||
if(this != &other){
|
||||
m_context = other.m_context;
|
||||
m_program = other.m_program;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Destroys the threefry_engine object.
|
||||
~threefry_engine()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
/// \internal_
|
||||
void load_program()
|
||||
{
|
||||
boost::shared_ptr<program_cache> cache =
|
||||
program_cache::get_global_cache(m_context);
|
||||
std::string cache_key =
|
||||
std::string("threefry_engine_32x2");
|
||||
|
||||
// Copyright 2010-2012, D. E. Shaw Research.
|
||||
// All rights reserved.
|
||||
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions, and the following disclaimer.
|
||||
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions, and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
|
||||
// * Neither the name of D. E. Shaw Research nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
const char source[] =
|
||||
"#define THREEFRY2x32_DEFAULT_ROUNDS 20\n"
|
||||
"#define SKEIN_KS_PARITY_32 0x1BD11BDA\n"
|
||||
|
||||
"enum r123_enum_threefry32x2 {\n"
|
||||
" R_32x2_0_0=13,\n"
|
||||
" R_32x2_1_0=15,\n"
|
||||
" R_32x2_2_0=26,\n"
|
||||
" R_32x2_3_0= 6,\n"
|
||||
" R_32x2_4_0=17,\n"
|
||||
" R_32x2_5_0=29,\n"
|
||||
" R_32x2_6_0=16,\n"
|
||||
" R_32x2_7_0=24\n"
|
||||
"};\n"
|
||||
|
||||
"static uint RotL_32(uint x, uint N)\n"
|
||||
"{\n"
|
||||
" return (x << (N & 31)) | (x >> ((32-N) & 31));\n"
|
||||
"}\n"
|
||||
|
||||
"struct r123array2x32 {\n"
|
||||
" uint v[2];\n"
|
||||
"};\n"
|
||||
"typedef struct r123array2x32 threefry2x32_ctr_t;\n"
|
||||
"typedef struct r123array2x32 threefry2x32_key_t;\n"
|
||||
|
||||
"threefry2x32_ctr_t threefry2x32_R(unsigned int Nrounds, threefry2x32_ctr_t in, threefry2x32_key_t k)\n"
|
||||
"{\n"
|
||||
" threefry2x32_ctr_t X;\n"
|
||||
" uint ks[3];\n"
|
||||
" uint i; \n"
|
||||
" ks[2] = SKEIN_KS_PARITY_32;\n"
|
||||
" for (i=0;i < 2; i++) {\n"
|
||||
" ks[i] = k.v[i];\n"
|
||||
" X.v[i] = in.v[i];\n"
|
||||
" ks[2] ^= k.v[i];\n"
|
||||
" }\n"
|
||||
" X.v[0] += ks[0]; X.v[1] += ks[1];\n"
|
||||
" if(Nrounds>0){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_0_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>1){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_1_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>2){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_2_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>3){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_3_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>3){\n"
|
||||
" X.v[0] += ks[1]; X.v[1] += ks[2];\n"
|
||||
" X.v[1] += 1;\n"
|
||||
" }\n"
|
||||
" if(Nrounds>4){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_4_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>5){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_5_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>6){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_6_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>7){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_7_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>7){\n"
|
||||
" X.v[0] += ks[2]; X.v[1] += ks[0];\n"
|
||||
" X.v[1] += 2;\n"
|
||||
" }\n"
|
||||
" if(Nrounds>8){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_0_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>9){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_1_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>10){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_2_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>11){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_3_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>11){\n"
|
||||
" X.v[0] += ks[0]; X.v[1] += ks[1];\n"
|
||||
" X.v[1] += 3;\n"
|
||||
" }\n"
|
||||
" if(Nrounds>12){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_4_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>13){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_5_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>14){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_6_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>15){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_7_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>15){\n"
|
||||
" X.v[0] += ks[1]; X.v[1] += ks[2];\n"
|
||||
" X.v[1] += 4;\n"
|
||||
" }\n"
|
||||
" if(Nrounds>16){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_0_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>17){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_1_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>18){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_2_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>19){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_3_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>19){\n"
|
||||
" X.v[0] += ks[2]; X.v[1] += ks[0];\n"
|
||||
" X.v[1] += 5;\n"
|
||||
" }\n"
|
||||
" if(Nrounds>20){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_4_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>21){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_5_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>22){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_6_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>23){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_7_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>23){\n"
|
||||
" X.v[0] += ks[0]; X.v[1] += ks[1];\n"
|
||||
" X.v[1] += 6;\n"
|
||||
" }\n"
|
||||
" if(Nrounds>24){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_0_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>25){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_1_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>26){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_2_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>27){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_3_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>27){\n"
|
||||
" X.v[0] += ks[1]; X.v[1] += ks[2];\n"
|
||||
" X.v[1] += 7;\n"
|
||||
" }\n"
|
||||
" if(Nrounds>28){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_4_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>29){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_5_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>30){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_6_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>31){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_7_0); X.v[1] ^= X.v[0]; }\n"
|
||||
" if(Nrounds>31){\n"
|
||||
" X.v[0] += ks[2]; X.v[1] += ks[0];\n"
|
||||
" X.v[1] += 8;\n"
|
||||
" }\n"
|
||||
" return X;\n"
|
||||
"}\n"
|
||||
|
||||
"__kernel void generate_rng(__global uint *ctr, __global uint *key, const uint offset) {\n"
|
||||
" threefry2x32_ctr_t in;\n"
|
||||
" threefry2x32_key_t k;\n"
|
||||
" const uint i = get_global_id(0);\n"
|
||||
" in.v[0] = ctr[2 * (offset + i)];\n"
|
||||
" in.v[1] = ctr[2 * (offset + i) + 1];\n"
|
||||
" k.v[0] = key[2 * (offset + i)];\n"
|
||||
" k.v[1] = key[2 * (offset + i) + 1];\n"
|
||||
" in = threefry2x32_R(20, in, k);\n"
|
||||
" ctr[2 * (offset + i)] = in.v[0];\n"
|
||||
" ctr[2 * (offset + i) + 1] = in.v[1];\n"
|
||||
"}\n";
|
||||
|
||||
m_program = cache->get_or_build(cache_key, std::string(), source, m_context);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/// Generates Threefry random numbers using both the counter and key values, and then stores
|
||||
/// them to the range [\p first_ctr, \p last_ctr).
|
||||
template<class OutputIterator>
|
||||
void generate(OutputIterator first_ctr, OutputIterator last_ctr, OutputIterator first_key, OutputIterator last_key, command_queue &queue) {
|
||||
const size_t size_ctr = detail::iterator_range_size(first_ctr, last_ctr);
|
||||
const size_t size_key = detail::iterator_range_size(first_key, last_key);
|
||||
if(!size_ctr || !size_key || (size_ctr != size_key)) {
|
||||
return;
|
||||
}
|
||||
kernel rng_kernel = m_program.create_kernel("generate_rng");
|
||||
|
||||
rng_kernel.set_arg(0, first_ctr.get_buffer());
|
||||
rng_kernel.set_arg(1, first_key.get_buffer());
|
||||
size_t offset = 0;
|
||||
|
||||
for(;;){
|
||||
size_t count = 0;
|
||||
size_t size = size_ctr/2;
|
||||
if(size > threads){
|
||||
count = (std::min)(static_cast<size_t>(threads), size - offset);
|
||||
}
|
||||
else {
|
||||
count = size;
|
||||
}
|
||||
rng_kernel.set_arg(2, static_cast<const uint_>(offset));
|
||||
queue.enqueue_1d_range_kernel(rng_kernel, 0, count, 0);
|
||||
|
||||
offset += count;
|
||||
|
||||
if(offset >= size){
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template<class OutputIterator>
|
||||
void generate(OutputIterator first_ctr, OutputIterator last_ctr, command_queue &queue) {
|
||||
const size_t size_ctr = detail::iterator_range_size(first_ctr, last_ctr);
|
||||
if(!size_ctr) {
|
||||
return;
|
||||
}
|
||||
boost::compute::vector<uint_> vector_key(size_ctr, m_context);
|
||||
vector_key.assign(size_ctr, 0, queue);
|
||||
kernel rng_kernel = m_program.create_kernel("generate_rng");
|
||||
|
||||
rng_kernel.set_arg(0, first_ctr.get_buffer());
|
||||
rng_kernel.set_arg(1, vector_key);
|
||||
size_t offset = 0;
|
||||
|
||||
for(;;){
|
||||
size_t count = 0;
|
||||
size_t size = size_ctr/2;
|
||||
if(size > threads){
|
||||
count = (std::min)(static_cast<size_t>(threads), size - offset);
|
||||
}
|
||||
else {
|
||||
count = size;
|
||||
}
|
||||
rng_kernel.set_arg(2, static_cast<const uint_>(offset));
|
||||
queue.enqueue_1d_range_kernel(rng_kernel, 0, count, 0);
|
||||
|
||||
offset += count;
|
||||
|
||||
if(offset >= size){
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
private:
|
||||
context m_context;
|
||||
program m_program;
|
||||
};
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_RANDOM_THREEFRY_HPP
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2014 Roshan <thisisroshansmail@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_RANDOM_UNIFORM_INT_DISTRIBUTION_HPP
|
||||
#define BOOST_COMPUTE_RANDOM_UNIFORM_INT_DISTRIBUTION_HPP
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#include <boost/compute/command_queue.hpp>
|
||||
#include <boost/compute/container/vector.hpp>
|
||||
#include <boost/compute/function.hpp>
|
||||
#include <boost/compute/types/fundamental.hpp>
|
||||
#include <boost/compute/algorithm/copy_if.hpp>
|
||||
#include <boost/compute/algorithm/transform.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
/// \class uniform_int_distribution
|
||||
/// \brief Produces uniformily distributed random integers
|
||||
///
|
||||
/// The following example shows how to setup a uniform int distribution to
|
||||
/// produce random integers 0 and 1.
|
||||
///
|
||||
/// \snippet test/test_uniform_int_distribution.cpp generate
|
||||
///
|
||||
template<class IntType = uint_>
|
||||
class uniform_int_distribution
|
||||
{
|
||||
public:
|
||||
typedef IntType result_type;
|
||||
|
||||
/// Creates a new uniform distribution producing numbers in the range
|
||||
/// [\p a, \p b].
|
||||
explicit uniform_int_distribution(IntType a = 0,
|
||||
IntType b = (std::numeric_limits<IntType>::max)())
|
||||
: m_a(a),
|
||||
m_b(b)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destroys the uniform_int_distribution object.
|
||||
~uniform_int_distribution()
|
||||
{
|
||||
}
|
||||
|
||||
/// Returns the minimum value of the distribution.
|
||||
result_type a() const
|
||||
{
|
||||
return m_a;
|
||||
}
|
||||
|
||||
/// Returns the maximum value of the distribution.
|
||||
result_type b() const
|
||||
{
|
||||
return m_b;
|
||||
}
|
||||
|
||||
/// Generates uniformily distributed integers and stores
|
||||
/// them to the range [\p first, \p last).
|
||||
template<class OutputIterator, class Generator>
|
||||
void generate(OutputIterator first,
|
||||
OutputIterator last,
|
||||
Generator &generator,
|
||||
command_queue &queue)
|
||||
{
|
||||
size_t size = std::distance(first, last);
|
||||
typedef typename Generator::result_type g_result_type;
|
||||
|
||||
vector<g_result_type> tmp(size, queue.get_context());
|
||||
vector<g_result_type> tmp2(size, queue.get_context());
|
||||
|
||||
uint_ bound = ((uint_(-1))/(m_b-m_a+1))*(m_b-m_a+1);
|
||||
|
||||
buffer_iterator<g_result_type> tmp2_iter;
|
||||
|
||||
while(size>0)
|
||||
{
|
||||
generator.generate(tmp.begin(), tmp.begin() + size, queue);
|
||||
tmp2_iter = copy_if(tmp.begin(), tmp.begin() + size, tmp2.begin(),
|
||||
_1 <= bound, queue);
|
||||
size = std::distance(tmp2_iter, tmp2.end());
|
||||
}
|
||||
|
||||
BOOST_COMPUTE_FUNCTION(IntType, scale_random, (const g_result_type x),
|
||||
{
|
||||
return LO + (x % (HI-LO+1));
|
||||
});
|
||||
|
||||
scale_random.define("LO", boost::lexical_cast<std::string>(m_a));
|
||||
scale_random.define("HI", boost::lexical_cast<std::string>(m_b));
|
||||
|
||||
transform(tmp2.begin(), tmp2.end(), first, scale_random, queue);
|
||||
}
|
||||
|
||||
private:
|
||||
IntType m_a;
|
||||
IntType m_b;
|
||||
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
boost::is_integral<IntType>::value,
|
||||
"Template argument must be integral"
|
||||
);
|
||||
};
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_RANDOM_UNIFORM_INT_DISTRIBUTION_HPP
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_RANDOM_UNIFORM_REAL_DISTRIBUTION_HPP
|
||||
#define BOOST_COMPUTE_RANDOM_UNIFORM_REAL_DISTRIBUTION_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
#include <boost/compute/command_queue.hpp>
|
||||
#include <boost/compute/function.hpp>
|
||||
#include <boost/compute/detail/literal.hpp>
|
||||
#include <boost/compute/types/fundamental.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
/// \class uniform_real_distribution
|
||||
/// \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.
|
||||
///
|
||||
/// \snippet test/test_uniform_real_distribution.cpp generate
|
||||
///
|
||||
/// \see default_random_engine, normal_distribution
|
||||
template<class RealType = float>
|
||||
class uniform_real_distribution
|
||||
{
|
||||
public:
|
||||
typedef RealType result_type;
|
||||
|
||||
/// 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.
|
||||
~uniform_real_distribution()
|
||||
{
|
||||
}
|
||||
|
||||
/// Returns the minimum value of the distribution.
|
||||
result_type a() const
|
||||
{
|
||||
return m_a;
|
||||
}
|
||||
|
||||
/// Returns the maximum value of the distribution.
|
||||
result_type b() const
|
||||
{
|
||||
return m_b;
|
||||
}
|
||||
|
||||
/// 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,
|
||||
OutputIterator last,
|
||||
Generator &generator,
|
||||
command_queue &queue)
|
||||
{
|
||||
BOOST_COMPUTE_FUNCTION(RealType, scale_random, (const uint_ x),
|
||||
{
|
||||
return nextafter(LO + (convert_RealType(x) / MAX_RANDOM) * (HI - LO), (RealType) LO);
|
||||
});
|
||||
|
||||
scale_random.define("LO", detail::make_literal(m_a));
|
||||
scale_random.define("HI", detail::make_literal(m_b));
|
||||
scale_random.define("MAX_RANDOM", "UINT_MAX");
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
/// \internal_ (deprecated)
|
||||
template<class OutputIterator, class Generator>
|
||||
void fill(OutputIterator first,
|
||||
OutputIterator last,
|
||||
Generator &g,
|
||||
command_queue &queue)
|
||||
{
|
||||
generate(first, last, g, queue);
|
||||
}
|
||||
|
||||
private:
|
||||
RealType m_a;
|
||||
RealType m_b;
|
||||
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
boost::is_floating_point<RealType>::value,
|
||||
"Template argument must be a floating point type"
|
||||
);
|
||||
};
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_RANDOM_UNIFORM_REAL_DISTRIBUTION_HPP
|
||||
Reference in New Issue
Block a user