Program Listing for File rocrand.hpp
↰ Return to documentation for file (library/include/rocrand/rocrand.hpp
)
// Copyright (c) 2017-2022 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef ROCRAND_HPP_
#define ROCRAND_HPP_
// At least C++11 required
#if defined(__cplusplus) && __cplusplus >= 201103L
#include "rocrand/rocrand.h"
#include "rocrand/rocrand_kernel.h"
#include <exception>
#include <limits>
#include <random>
#include <sstream>
#include <string>
#include <type_traits>
namespace rocrand_cpp {
class error : public std::exception
{
public:
typedef rocrand_status error_type;
error(error_type error) noexcept
: m_error(error),
m_error_string(to_string(error))
{
}
~error() noexcept
{
}
error_type error_code() const noexcept
{
return m_error;
}
std::string error_string() const noexcept
{
return m_error_string;
}
const char* what() const noexcept
{
return m_error_string.c_str();
}
static std::string to_string(error_type error)
{
switch(error)
{
case ROCRAND_STATUS_SUCCESS:
return "Success";
case ROCRAND_STATUS_VERSION_MISMATCH:
return "Header file and linked library version do not match";
case ROCRAND_STATUS_NOT_CREATED:
return "Generator was not created using rocrand_create_generator";
case ROCRAND_STATUS_ALLOCATION_FAILED:
return "Memory allocation failed during execution";
case ROCRAND_STATUS_TYPE_ERROR:
return "Generator type is wrong";
case ROCRAND_STATUS_OUT_OF_RANGE:
return "Argument out of range";
case ROCRAND_STATUS_LENGTH_NOT_MULTIPLE:
return "Length requested is not a multiple of dimension";
case ROCRAND_STATUS_DOUBLE_PRECISION_REQUIRED:
return "GPU does not have double precision";
case ROCRAND_STATUS_LAUNCH_FAILURE:
return "Kernel launch failure";
case ROCRAND_STATUS_INTERNAL_ERROR:
return "Internal library error";
default: {
std::stringstream s;
s << "Unknown rocRAND error (" << error << ")";
return s.str();
}
}
}
friend
bool operator==(const error& l, const error& r)
{
return l.error_code() == r.error_code();
}
friend
bool operator!=(const error& l, const error& r)
{
return !(l == r);
}
private:
error_type m_error;
std::string m_error_string;
};
template<class IntType = unsigned int>
class uniform_int_distribution
{
static_assert(std::is_same<unsigned char, IntType>::value
|| std::is_same<unsigned short, IntType>::value
|| std::is_same<unsigned long long int, IntType>::value
|| std::is_same<unsigned int, IntType>::value,
"Only unsigned char, unsigned short, unsigned int and unsigned long long int "
"types are supported in uniform_int_distribution");
public:
typedef IntType result_type;
uniform_int_distribution()
{
}
void reset()
{
}
IntType min() const
{
return 0;
}
IntType max() const
{
return std::numeric_limits<IntType>::max();
}
template<class Generator>
void operator()(Generator& g, IntType * output, size_t size)
{
rocrand_status status;
status = this->generate(g, output, size);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
bool operator==(const uniform_int_distribution<IntType>& other)
{
(void) other;
return true;
}
bool operator!=(const uniform_int_distribution<IntType>& other)
{
return !(*this == other);
}
private:
template<class Generator>
rocrand_status generate(Generator& g, unsigned char * output, size_t size)
{
return rocrand_generate_char(g.m_generator, output, size);
}
template<class Generator>
rocrand_status generate(Generator& g, unsigned short * output, size_t size)
{
return rocrand_generate_short(g.m_generator, output, size);
}
template<class Generator>
rocrand_status generate(Generator& g, unsigned int * output, size_t size)
{
return rocrand_generate(g.m_generator, output, size);
}
template<class Generator>
rocrand_status generate(Generator& g, unsigned long long int* output, size_t size)
{
return rocrand_generate_long_long(g.m_generator, output, size);
}
};
template<class RealType = float>
class uniform_real_distribution
{
static_assert(
std::is_same<float, RealType>::value
|| std::is_same<double, RealType>::value
|| std::is_same<half, RealType>::value,
"Only float, double, and half types are supported in uniform_real_distribution"
);
public:
typedef RealType result_type;
uniform_real_distribution()
{
}
void reset()
{
}
RealType min() const
{
if(std::is_same<float, RealType>::value)
{
return static_cast<RealType>(ROCRAND_2POW32_INV);
}
return static_cast<RealType>(ROCRAND_2POW32_INV_DOUBLE);
}
RealType max() const
{
return 1.0;
}
template<class Generator>
void operator()(Generator& g, RealType * output, size_t size)
{
rocrand_status status;
status = this->generate(g, output, size);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
bool operator==(const uniform_real_distribution<RealType>& other)
{
(void) other;
return true;
}
bool operator!=(const uniform_real_distribution<RealType>& other)
{
return !(*this == other);
}
private:
template<class Generator>
rocrand_status generate(Generator& g, float * output, size_t size)
{
return rocrand_generate_uniform(g.m_generator, output, size);
}
template<class Generator>
rocrand_status generate(Generator& g, double * output, size_t size)
{
return rocrand_generate_uniform_double(g.m_generator, output, size);
}
template<class Generator>
rocrand_status generate(Generator& g, half * output, size_t size)
{
return rocrand_generate_uniform_half(g.m_generator, output, size);
}
};
template<class RealType = float>
class normal_distribution
{
static_assert(
std::is_same<float, RealType>::value
|| std::is_same<double, RealType>::value
|| std::is_same<half, RealType>::value,
"Only float, double and half types are supported in normal_distribution"
);
public:
typedef RealType result_type;
class param_type
{
public:
using distribution_type = normal_distribution<RealType>;
param_type(RealType mean = 0.0, RealType stddev = 1.0)
: m_mean(mean), m_stddev(stddev)
{
}
param_type(const param_type& params) = default;
RealType mean() const
{
return m_mean;
}
RealType stddev() const
{
return m_stddev;
}
bool operator==(const param_type& other)
{
return m_mean == other.m_mean && m_stddev == other.m_stddev;
}
bool operator!=(const param_type& other)
{
return !(*this == other);
}
private:
RealType m_mean;
RealType m_stddev;
};
normal_distribution(RealType mean = 0.0, RealType stddev = 1.0)
: m_params(mean, stddev)
{
}
normal_distribution(const param_type& params)
: m_params(params)
{
}
void reset()
{
}
RealType mean() const
{
return m_params.mean();
}
RealType stddev() const
{
return m_params.stddev();
}
RealType min() const
{
return std::numeric_limits<RealType>::lowest();
}
RealType max() const
{
return std::numeric_limits<RealType>::max();
}
param_type param() const
{
return m_params;
}
void param(const param_type& params)
{
m_params = params;
}
template<class Generator>
void operator()(Generator& g, RealType * output, size_t size)
{
rocrand_status status;
status = this->generate(g, output, size);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
bool operator==(const normal_distribution<RealType>& other)
{
return this->m_params == other.m_params;
}
bool operator!=(const normal_distribution<RealType>& other)
{
return !(*this == other);
}
private:
template<class Generator>
rocrand_status generate(Generator& g, float * output, size_t size)
{
return rocrand_generate_normal(
g.m_generator, output, size, this->mean(), this->stddev()
);
}
template<class Generator>
rocrand_status generate(Generator& g, double * output, size_t size)
{
return rocrand_generate_normal_double(
g.m_generator, output, size, this->mean(), this->stddev()
);
}
template<class Generator>
rocrand_status generate(Generator& g, half * output, size_t size)
{
return rocrand_generate_normal_half(
g.m_generator, output, size, this->mean(), this->stddev()
);
}
param_type m_params;
};
template<class RealType = float>
class lognormal_distribution
{
static_assert(
std::is_same<float, RealType>::value
|| std::is_same<double, RealType>::value
|| std::is_same<half, RealType>::value,
"Only float, double and half types are supported in lognormal_distribution"
);
public:
typedef RealType result_type;
class param_type
{
public:
using distribution_type = lognormal_distribution<RealType>;
param_type(RealType m = 0.0, RealType s = 1.0)
: m_mean(m), m_stddev(s)
{
}
param_type(const param_type& params) = default;
RealType m() const
{
return m_mean;
}
RealType s() const
{
return m_stddev;
}
bool operator==(const param_type& other)
{
return m_mean == other.m_mean && m_stddev == other.m_stddev;
}
bool operator!=(const param_type& other)
{
return !(*this == other);
}
private:
RealType m_mean;
RealType m_stddev;
};
lognormal_distribution(RealType m = 0.0, RealType s = 1.0)
: m_params(m, s)
{
}
lognormal_distribution(const param_type& params)
: m_params(params)
{
}
void reset()
{
}
RealType m() const
{
return m_params.m();
}
RealType s() const
{
return m_params.s();
}
param_type param() const
{
return m_params;
}
void param(const param_type& params)
{
m_params = params;
}
RealType min() const
{
return 0;
}
RealType max() const
{
return std::numeric_limits<RealType>::max();
}
template<class Generator>
void operator()(Generator& g, RealType * output, size_t size)
{
rocrand_status status;
status = this->generate(g, output, size);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
bool operator==(const lognormal_distribution<RealType>& other)
{
return this->m_params == other.m_params;
}
bool operator!=(const lognormal_distribution<RealType>& other)
{
return !(*this == other);
}
private:
template<class Generator>
rocrand_status generate(Generator& g, float * output, size_t size)
{
return rocrand_generate_log_normal(
g.m_generator, output, size, this->m(), this->s()
);
}
template<class Generator>
rocrand_status generate(Generator& g, double * output, size_t size)
{
return rocrand_generate_log_normal_double(
g.m_generator, output, size, this->m(), this->s()
);
}
template<class Generator>
rocrand_status generate(Generator& g, half * output, size_t size)
{
return rocrand_generate_log_normal_half(
g.m_generator, output, size, this->m(), this->s()
);
}
param_type m_params;
};
template<class IntType = unsigned int>
class poisson_distribution
{
static_assert(
std::is_same<unsigned int, IntType>::value,
"Only unsigned int type is supported in poisson_distribution"
);
public:
typedef IntType result_type;
class param_type
{
public:
using distribution_type = poisson_distribution<IntType>;
param_type(double mean = 1.0)
: m_mean(mean)
{
}
param_type(const param_type& params) = default;
double mean() const
{
return m_mean;
}
bool operator==(const param_type& other)
{
return m_mean == other.m_mean;
}
bool operator!=(const param_type& other)
{
return !(*this == other);
}
private:
double m_mean;
};
poisson_distribution(double mean = 1.0)
: m_params(mean)
{
}
poisson_distribution(const param_type& params)
: m_params(params)
{
}
void reset()
{
}
double mean() const
{
return m_params.mean();
}
IntType min() const
{
return 0;
}
IntType max() const
{
return std::numeric_limits<IntType>::max();
}
param_type param() const
{
return m_params;
}
void param(const param_type& params)
{
m_params = params;
}
template<class Generator>
void operator()(Generator& g, IntType * output, size_t size)
{
rocrand_status status;
status = rocrand_generate_poisson(g.m_generator, output, size, this->mean());
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
bool operator==(const poisson_distribution<IntType>& other)
{
return this->m_params == other.m_params;
}
bool operator!=(const poisson_distribution<IntType>& other)
{
return !(*this == other);
}
private:
param_type m_params;
};
template<unsigned long long DefaultSeed = ROCRAND_PHILOX4x32_DEFAULT_SEED>
class philox4x32_10_engine
{
public:
typedef unsigned int result_type;
// \typedef order_type
typedef rocrand_ordering order_type;
typedef unsigned long long offset_type;
typedef unsigned long long seed_type;
static constexpr seed_type default_seed = DefaultSeed;
philox4x32_10_engine(seed_type seed_value = DefaultSeed,
offset_type offset_value = 0,
order_type order_value = ROCRAND_ORDERING_PSEUDO_DEFAULT)
{
rocrand_status status;
status = rocrand_create_generator(&m_generator, this->type());
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
try
{
if(offset_value > 0)
{
this->offset(offset_value);
}
this->order(order_value);
this->seed(seed_value);
}
catch(...)
{
(void)rocrand_destroy_generator(m_generator);
throw;
}
}
philox4x32_10_engine(rocrand_generator& generator)
: m_generator(generator)
{
if(generator == NULL)
{
throw rocrand_cpp::error(ROCRAND_STATUS_NOT_CREATED);
}
generator = NULL;
}
~philox4x32_10_engine() noexcept(false)
{
rocrand_status status = rocrand_destroy_generator(m_generator);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
void stream(hipStream_t value)
{
rocrand_status status = rocrand_set_stream(m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
void order(order_type value)
{
rocrand_status status = rocrand_set_ordering(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void offset(offset_type value)
{
rocrand_status status = rocrand_set_offset(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
void seed(seed_type value)
{
rocrand_status status = rocrand_set_seed(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
template<class Generator>
void operator()(result_type * output, size_t size)
{
rocrand_status status;
status = rocrand_generate(m_generator, output, size);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
result_type min() const
{
return 0;
}
result_type max() const
{
return std::numeric_limits<unsigned int>::max();
}
static constexpr rocrand_rng_type type()
{
return ROCRAND_RNG_PSEUDO_PHILOX4_32_10;
}
private:
rocrand_generator m_generator;
template<class T>
friend class ::rocrand_cpp::uniform_int_distribution;
template<class T>
friend class ::rocrand_cpp::uniform_real_distribution;
template<class T>
friend class ::rocrand_cpp::normal_distribution;
template<class T>
friend class ::rocrand_cpp::lognormal_distribution;
template<class T>
friend class ::rocrand_cpp::poisson_distribution;
};
template<unsigned long long DefaultSeed>
constexpr typename philox4x32_10_engine<DefaultSeed>::seed_type philox4x32_10_engine<DefaultSeed>::default_seed;
template<unsigned long long DefaultSeed = ROCRAND_XORWOW_DEFAULT_SEED>
class xorwow_engine
{
public:
typedef unsigned int result_type;
typedef rocrand_ordering order_type;
typedef unsigned long long offset_type;
typedef unsigned long long seed_type;
static constexpr seed_type default_seed = DefaultSeed;
xorwow_engine(seed_type seed_value = DefaultSeed,
offset_type offset_value = 0,
order_type order_value = ROCRAND_ORDERING_PSEUDO_DEFAULT)
{
rocrand_status status;
status = rocrand_create_generator(&m_generator, this->type());
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
try
{
this->order(order_value);
if(offset_value > 0)
{
this->offset(offset_value);
}
this->seed(seed_value);
}
catch(...)
{
(void)rocrand_destroy_generator(m_generator);
throw;
}
}
xorwow_engine(rocrand_generator& generator)
: m_generator(generator)
{
if(generator == NULL)
{
throw rocrand_cpp::error(ROCRAND_STATUS_NOT_CREATED);
}
generator = NULL;
}
~xorwow_engine() noexcept(false)
{
rocrand_status status = rocrand_destroy_generator(m_generator);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
void stream(hipStream_t value)
{
rocrand_status status = rocrand_set_stream(m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
void order(order_type value)
{
rocrand_status status = rocrand_set_ordering(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void offset(offset_type value)
{
rocrand_status status = rocrand_set_offset(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
void seed(seed_type value)
{
rocrand_status status = rocrand_set_seed(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
template<class Generator>
void operator()(result_type * output, size_t size)
{
rocrand_status status;
status = rocrand_generate(m_generator, output, size);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
result_type min() const
{
return 0;
}
result_type max() const
{
return std::numeric_limits<unsigned int>::max();
}
static constexpr rocrand_rng_type type()
{
return ROCRAND_RNG_PSEUDO_XORWOW;
}
private:
rocrand_generator m_generator;
template<class T>
friend class ::rocrand_cpp::uniform_int_distribution;
template<class T>
friend class ::rocrand_cpp::uniform_real_distribution;
template<class T>
friend class ::rocrand_cpp::normal_distribution;
template<class T>
friend class ::rocrand_cpp::lognormal_distribution;
template<class T>
friend class ::rocrand_cpp::poisson_distribution;
};
template<unsigned long long DefaultSeed>
constexpr typename xorwow_engine<DefaultSeed>::seed_type xorwow_engine<DefaultSeed>::default_seed;
template<unsigned long long DefaultSeed = ROCRAND_MRG31K3P_DEFAULT_SEED>
class mrg31k3p_engine
{
public:
typedef unsigned int result_type;
typedef rocrand_ordering order_type;
typedef unsigned long long offset_type;
typedef unsigned long long seed_type;
static constexpr seed_type default_seed = DefaultSeed;
mrg31k3p_engine(seed_type seed_value = DefaultSeed,
offset_type offset_value = 0,
order_type order_value = ROCRAND_ORDERING_PSEUDO_DEFAULT)
{
rocrand_status status;
status = rocrand_create_generator(&m_generator, this->type());
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
try
{
this->order(order_value);
if(offset_value > 0)
{
this->offset(offset_value);
}
this->seed(seed_value);
}
catch(...)
{
(void)rocrand_destroy_generator(m_generator);
throw;
}
}
mrg31k3p_engine(rocrand_generator& generator) : m_generator(generator)
{
if(generator == NULL)
{
throw rocrand_cpp::error(ROCRAND_STATUS_NOT_CREATED);
}
generator = NULL;
}
~mrg31k3p_engine() noexcept(false)
{
rocrand_status status = rocrand_destroy_generator(m_generator);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void stream(hipStream_t value)
{
rocrand_status status = rocrand_set_stream(m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void order(order_type value)
{
rocrand_status status = rocrand_set_ordering(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void offset(offset_type value)
{
rocrand_status status = rocrand_set_offset(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void seed(seed_type value)
{
rocrand_status status = rocrand_set_seed(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
template<class Generator>
void operator()(result_type* output, size_t size)
{
rocrand_status status;
status = rocrand_generate(m_generator, output, size);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
result_type min() const
{
return 1;
}
result_type max() const
{
return std::numeric_limits<unsigned int>::max();
}
static constexpr rocrand_rng_type type()
{
return ROCRAND_RNG_PSEUDO_MRG31K3P;
}
private:
rocrand_generator m_generator;
template<class T>
friend class ::rocrand_cpp::uniform_int_distribution;
template<class T>
friend class ::rocrand_cpp::uniform_real_distribution;
template<class T>
friend class ::rocrand_cpp::normal_distribution;
template<class T>
friend class ::rocrand_cpp::lognormal_distribution;
template<class T>
friend class ::rocrand_cpp::poisson_distribution;
};
template<unsigned long long DefaultSeed>
constexpr
typename mrg31k3p_engine<DefaultSeed>::seed_type mrg31k3p_engine<DefaultSeed>::default_seed;
template<unsigned long long DefaultSeed = ROCRAND_MRG32K3A_DEFAULT_SEED>
class mrg32k3a_engine
{
public:
typedef unsigned int result_type;
typedef rocrand_ordering order_type;
typedef unsigned long long offset_type;
typedef unsigned long long seed_type;
static constexpr seed_type default_seed = DefaultSeed;
mrg32k3a_engine(seed_type seed_value = DefaultSeed,
offset_type offset_value = 0,
order_type order_value = ROCRAND_ORDERING_PSEUDO_DEFAULT)
{
rocrand_status status;
status = rocrand_create_generator(&m_generator, this->type());
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
try
{
this->order(order_value);
if(offset_value > 0)
{
this->offset(offset_value);
}
this->seed(seed_value);
}
catch(...)
{
(void)rocrand_destroy_generator(m_generator);
throw;
}
}
mrg32k3a_engine(rocrand_generator& generator)
: m_generator(generator)
{
if(generator == NULL)
{
throw rocrand_cpp::error(ROCRAND_STATUS_NOT_CREATED);
}
generator = NULL;
}
~mrg32k3a_engine() noexcept(false)
{
rocrand_status status = rocrand_destroy_generator(m_generator);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
void stream(hipStream_t value)
{
rocrand_status status = rocrand_set_stream(m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
void order(order_type value)
{
rocrand_status status = rocrand_set_ordering(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void offset(offset_type value)
{
rocrand_status status = rocrand_set_offset(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
void seed(seed_type value)
{
rocrand_status status = rocrand_set_seed(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
template<class Generator>
void operator()(result_type * output, size_t size)
{
rocrand_status status;
status = rocrand_generate(m_generator, output, size);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
result_type min() const
{
return 1;
}
result_type max() const
{
return std::numeric_limits<unsigned int>::max();
}
static constexpr rocrand_rng_type type()
{
return ROCRAND_RNG_PSEUDO_MRG32K3A;
}
private:
rocrand_generator m_generator;
template<class T>
friend class ::rocrand_cpp::uniform_int_distribution;
template<class T>
friend class ::rocrand_cpp::uniform_real_distribution;
template<class T>
friend class ::rocrand_cpp::normal_distribution;
template<class T>
friend class ::rocrand_cpp::lognormal_distribution;
template<class T>
friend class ::rocrand_cpp::poisson_distribution;
};
template<unsigned long long DefaultSeed>
constexpr typename mrg32k3a_engine<DefaultSeed>::seed_type mrg32k3a_engine<DefaultSeed>::default_seed;
template<unsigned long long DefaultSeed = 0>
class mtgp32_engine
{
public:
typedef unsigned int result_type;
typedef rocrand_ordering order_type;
typedef unsigned long long offset_type;
typedef unsigned long long seed_type;
static constexpr seed_type default_seed = DefaultSeed;
mtgp32_engine(seed_type seed_value = DefaultSeed,
order_type order_value = ROCRAND_ORDERING_PSEUDO_DEFAULT)
{
rocrand_status status;
status = rocrand_create_generator(&m_generator, this->type());
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
try
{
this->order(order_value);
this->seed(seed_value);
}
catch(...)
{
(void)rocrand_destroy_generator(m_generator);
throw;
}
}
mtgp32_engine(rocrand_generator& generator)
: m_generator(generator)
{
if(generator == NULL)
{
throw rocrand_cpp::error(ROCRAND_STATUS_NOT_CREATED);
}
generator = NULL;
}
~mtgp32_engine() noexcept(false)
{
rocrand_status status = rocrand_destroy_generator(m_generator);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
void stream(hipStream_t value)
{
rocrand_status status = rocrand_set_stream(m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
void order(order_type value)
{
rocrand_status status = rocrand_set_ordering(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void seed(seed_type value)
{
rocrand_status status = rocrand_set_seed(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
template<class Generator>
void operator()(result_type * output, size_t size)
{
rocrand_status status;
status = rocrand_generate(m_generator, output, size);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
result_type min() const
{
return 0;
}
result_type max() const
{
return std::numeric_limits<unsigned int>::max();
}
static constexpr rocrand_rng_type type()
{
return ROCRAND_RNG_PSEUDO_MTGP32;
}
private:
rocrand_generator m_generator;
template<class T>
friend class ::rocrand_cpp::uniform_int_distribution;
template<class T>
friend class ::rocrand_cpp::uniform_real_distribution;
template<class T>
friend class ::rocrand_cpp::normal_distribution;
template<class T>
friend class ::rocrand_cpp::lognormal_distribution;
template<class T>
friend class ::rocrand_cpp::poisson_distribution;
};
template<unsigned long long DefaultSeed>
constexpr typename mtgp32_engine<DefaultSeed>::seed_type mtgp32_engine<DefaultSeed>::default_seed;
template<unsigned int DefaultSeedX = ROCRAND_LFSR113_DEFAULT_SEED_X,
unsigned int DefaultSeedY = ROCRAND_LFSR113_DEFAULT_SEED_Y,
unsigned int DefaultSeedZ = ROCRAND_LFSR113_DEFAULT_SEED_Z,
unsigned int DefaultSeedW = ROCRAND_LFSR113_DEFAULT_SEED_W>
class lfsr113_engine
{
public:
typedef unsigned int result_type;
typedef rocrand_ordering order_type;
typedef uint4 seed_type;
static constexpr seed_type default_seed
= {DefaultSeedX, DefaultSeedY, DefaultSeedZ, DefaultSeedW};
lfsr113_engine(seed_type seed_value = {DefaultSeedX, DefaultSeedY, DefaultSeedZ, DefaultSeedW},
order_type order_value = ROCRAND_ORDERING_QUASI_DEFAULT)
{
rocrand_status status;
status = rocrand_create_generator(&m_generator, this->type());
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
try
{
this->order(order_value);
this->seed(seed_value);
}
catch(...)
{
(void)rocrand_destroy_generator(m_generator);
throw;
}
}
lfsr113_engine(rocrand_generator& generator) : m_generator(generator)
{
if(generator == NULL)
{
throw rocrand_cpp::error(ROCRAND_STATUS_NOT_CREATED);
}
generator = NULL;
}
~lfsr113_engine() noexcept(false)
{
rocrand_status status = rocrand_destroy_generator(m_generator);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void stream(hipStream_t value)
{
rocrand_status status = rocrand_set_stream(m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void order(order_type value)
{
rocrand_status status = rocrand_set_ordering(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void seed(unsigned long long value)
{
rocrand_status status = rocrand_set_seed(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void seed(seed_type value)
{
rocrand_status status = rocrand_set_seed_uint4(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
template<class Generator>
void operator()(result_type* output, size_t size)
{
rocrand_status status;
status = rocrand_generate(m_generator, output, size);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
result_type min() const
{
return 0;
}
result_type max() const
{
return std::numeric_limits<unsigned int>::max();
}
static constexpr rocrand_rng_type type()
{
return ROCRAND_RNG_PSEUDO_LFSR113;
}
private:
rocrand_generator m_generator;
template<class T>
friend class ::rocrand_cpp::uniform_int_distribution;
template<class T>
friend class ::rocrand_cpp::uniform_real_distribution;
template<class T>
friend class ::rocrand_cpp::normal_distribution;
template<class T>
friend class ::rocrand_cpp::lognormal_distribution;
template<class T>
friend class ::rocrand_cpp::poisson_distribution;
};
template<unsigned int DefaultSeedX,
unsigned int DefaultSeedY,
unsigned int DefaultSeedZ,
unsigned int DefaultSeedW>
constexpr typename lfsr113_engine<DefaultSeedX, DefaultSeedY, DefaultSeedZ, DefaultSeedW>::seed_type
lfsr113_engine<DefaultSeedX, DefaultSeedY, DefaultSeedZ, DefaultSeedW>::default_seed;
template<unsigned long long DefaultSeed = 0ULL>
class mt19937_engine
{
public:
typedef unsigned int result_type;
typedef unsigned long long seed_type;
static constexpr seed_type default_seed = DefaultSeed;
mt19937_engine(seed_type seed_value = DefaultSeed)
{
rocrand_status status;
status = rocrand_create_generator(&m_generator, this->type());
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
try
{
this->seed(seed_value);
}
catch(...)
{
(void)rocrand_destroy_generator(m_generator);
throw;
}
}
mt19937_engine(rocrand_generator& generator) : m_generator(generator)
{
if(generator == NULL)
{
throw rocrand_cpp::error(ROCRAND_STATUS_NOT_CREATED);
}
generator = NULL;
}
mt19937_engine(const mt19937_engine&) = delete;
mt19937_engine(mt19937_engine&&) = delete;
mt19937_engine& operator=(const mt19937_engine&) = delete;
mt19937_engine& operator=(mt19937_engine&&) = delete;
~mt19937_engine() noexcept(false)
{
rocrand_status status = rocrand_destroy_generator(m_generator);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void stream(hipStream_t value)
{
rocrand_status status = rocrand_set_stream(m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void seed(seed_type value)
{
rocrand_status status = rocrand_set_seed(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
template<class Generator>
void operator()(result_type* output, size_t size)
{
rocrand_status status;
status = rocrand_generate(m_generator, output, size);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
result_type min() const
{
return 0;
}
result_type max() const
{
return std::numeric_limits<unsigned int>::max();
}
static constexpr rocrand_rng_type type()
{
return ROCRAND_RNG_PSEUDO_MT19937;
}
private:
rocrand_generator m_generator;
template<class T>
friend class ::rocrand_cpp::uniform_int_distribution;
template<class T>
friend class ::rocrand_cpp::uniform_real_distribution;
template<class T>
friend class ::rocrand_cpp::normal_distribution;
template<class T>
friend class ::rocrand_cpp::lognormal_distribution;
template<class T>
friend class ::rocrand_cpp::poisson_distribution;
};
template<unsigned long long DefaultSeed>
constexpr typename mt19937_engine<DefaultSeed>::seed_type mt19937_engine<DefaultSeed>::default_seed;
template<unsigned int DefaultNumDimensions = 1>
class sobol32_engine
{
public:
typedef unsigned int result_type;
typedef rocrand_ordering order_type;
typedef unsigned long long offset_type;
typedef unsigned int dimensions_num_type;
static constexpr dimensions_num_type default_num_dimensions = DefaultNumDimensions;
sobol32_engine(dimensions_num_type num_of_dimensions = DefaultNumDimensions,
offset_type offset_value = 0,
order_type order_value = ROCRAND_ORDERING_QUASI_DEFAULT)
{
rocrand_status status;
status = rocrand_create_generator(&m_generator, this->type());
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
try
{
this->order(order_value);
if(offset_value > 0)
{
this->offset(offset_value);
}
this->dimensions(num_of_dimensions);
}
catch(...)
{
(void)rocrand_destroy_generator(m_generator);
throw;
}
}
sobol32_engine(rocrand_generator& generator)
: m_generator(generator)
{
if(generator == NULL)
{
throw rocrand_cpp::error(ROCRAND_STATUS_NOT_CREATED);
}
generator = NULL;
}
~sobol32_engine() noexcept(false)
{
rocrand_status status = rocrand_destroy_generator(m_generator);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
void stream(hipStream_t value)
{
rocrand_status status = rocrand_set_stream(m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
void order(order_type value)
{
rocrand_status status = rocrand_set_ordering(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void offset(offset_type value)
{
rocrand_status status = rocrand_set_offset(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
void dimensions(dimensions_num_type value)
{
rocrand_status status =
rocrand_set_quasi_random_generator_dimensions(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
template<class Generator>
void operator()(result_type * output, size_t size)
{
rocrand_status status;
status = rocrand_generate(m_generator, output, size);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
result_type min() const
{
return 0;
}
result_type max() const
{
return std::numeric_limits<unsigned int>::max();
}
static constexpr rocrand_rng_type type()
{
return ROCRAND_RNG_QUASI_SOBOL32;
}
private:
rocrand_generator m_generator;
template<class T>
friend class ::rocrand_cpp::uniform_int_distribution;
template<class T>
friend class ::rocrand_cpp::uniform_real_distribution;
template<class T>
friend class ::rocrand_cpp::normal_distribution;
template<class T>
friend class ::rocrand_cpp::lognormal_distribution;
template<class T>
friend class ::rocrand_cpp::poisson_distribution;
};
template<unsigned int DefaultNumDimensions>
constexpr typename sobol32_engine<DefaultNumDimensions>::dimensions_num_type
sobol32_engine<DefaultNumDimensions>::default_num_dimensions;
template<unsigned int DefaultNumDimensions = 1>
class scrambled_sobol32_engine
{
public:
typedef unsigned int result_type;
typedef unsigned long long offset_type;
typedef rocrand_ordering order_type;
typedef unsigned int dimensions_num_type;
static constexpr dimensions_num_type default_num_dimensions = DefaultNumDimensions;
scrambled_sobol32_engine(dimensions_num_type num_of_dimensions = DefaultNumDimensions,
offset_type offset_value = 0,
order_type order_value = ROCRAND_ORDERING_QUASI_DEFAULT)
{
rocrand_status status;
status = rocrand_create_generator(&m_generator, this->type());
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
try
{
this->order(order_value);
if(offset_value > 0)
{
this->offset(offset_value);
}
this->dimensions(num_of_dimensions);
}
catch(...)
{
(void)rocrand_destroy_generator(m_generator);
throw;
}
}
scrambled_sobol32_engine(rocrand_generator& generator) : m_generator(generator)
{
if(generator == NULL)
{
throw rocrand_cpp::error(ROCRAND_STATUS_NOT_CREATED);
}
generator = NULL;
}
~scrambled_sobol32_engine() noexcept(false)
{
rocrand_status status = rocrand_destroy_generator(m_generator);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void stream(hipStream_t value)
{
rocrand_status status = rocrand_set_stream(m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void order(order_type value)
{
rocrand_status status = rocrand_set_ordering(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void offset(offset_type value)
{
rocrand_status status = rocrand_set_offset(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void dimensions(dimensions_num_type value)
{
rocrand_status status
= rocrand_set_quasi_random_generator_dimensions(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
template<class Generator>
void operator()(result_type* output, size_t size)
{
rocrand_status status;
status = rocrand_generate(m_generator, output, size);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
result_type min() const
{
return 0;
}
result_type max() const
{
return std::numeric_limits<unsigned int>::max();
}
static constexpr rocrand_rng_type type()
{
return ROCRAND_RNG_QUASI_SCRAMBLED_SOBOL32;
}
private:
rocrand_generator m_generator;
template<class T>
friend class ::rocrand_cpp::uniform_int_distribution;
template<class T>
friend class ::rocrand_cpp::uniform_real_distribution;
template<class T>
friend class ::rocrand_cpp::normal_distribution;
template<class T>
friend class ::rocrand_cpp::lognormal_distribution;
template<class T>
friend class ::rocrand_cpp::poisson_distribution;
};
template<unsigned int DefaultNumDimensions>
constexpr typename scrambled_sobol32_engine<DefaultNumDimensions>::dimensions_num_type
scrambled_sobol32_engine<DefaultNumDimensions>::default_num_dimensions;
template<unsigned int DefaultNumDimensions = 1>
class sobol64_engine
{
public:
typedef unsigned long long int result_type;
typedef unsigned long long int offset_type;
typedef rocrand_ordering order_type;
typedef unsigned int dimensions_num_type;
static constexpr dimensions_num_type default_num_dimensions = DefaultNumDimensions;
sobol64_engine(dimensions_num_type num_of_dimensions = DefaultNumDimensions,
offset_type offset_value = 0,
order_type order_value = ROCRAND_ORDERING_QUASI_DEFAULT)
{
rocrand_status status;
status = rocrand_create_generator(&m_generator, this->type());
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
try
{
this->order(order_value);
if(offset_value > 0)
{
this->offset(offset_value);
}
this->dimensions(num_of_dimensions);
}
catch(...)
{
(void)rocrand_destroy_generator(m_generator);
throw;
}
}
sobol64_engine(rocrand_generator& generator)
: m_generator(generator)
{
if(generator == NULL)
{
throw rocrand_cpp::error(ROCRAND_STATUS_NOT_CREATED);
}
generator = NULL;
}
~sobol64_engine() noexcept(false)
{
rocrand_status status = rocrand_destroy_generator(m_generator);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
void stream(hipStream_t value)
{
rocrand_status status = rocrand_set_stream(m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
void order(order_type value)
{
rocrand_status status = rocrand_set_ordering(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void offset(offset_type value)
{
rocrand_status status = rocrand_set_offset(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
void dimensions(dimensions_num_type value)
{
rocrand_status status =
rocrand_set_quasi_random_generator_dimensions(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
template<class Generator>
void operator()(result_type * output, size_t size)
{
rocrand_status status;
status = rocrand_generate_long_long(m_generator, output, size);
if(status != ROCRAND_STATUS_SUCCESS) throw rocrand_cpp::error(status);
}
result_type min() const
{
return 0;
}
result_type max() const
{
return std::numeric_limits<result_type>::max();
}
static constexpr rocrand_rng_type type()
{
return ROCRAND_RNG_QUASI_SOBOL64;
}
private:
rocrand_generator m_generator;
template<class T>
friend class ::rocrand_cpp::uniform_int_distribution;
template<class T>
friend class ::rocrand_cpp::uniform_real_distribution;
template<class T>
friend class ::rocrand_cpp::normal_distribution;
template<class T>
friend class ::rocrand_cpp::lognormal_distribution;
template<class T>
friend class ::rocrand_cpp::poisson_distribution;
};
template<unsigned int DefaultNumDimensions>
constexpr typename sobol64_engine<DefaultNumDimensions>::dimensions_num_type
sobol64_engine<DefaultNumDimensions>::default_num_dimensions;
template<unsigned int DefaultNumDimensions = 1>
class scrambled_sobol64_engine
{
public:
typedef unsigned long long int result_type;
typedef rocrand_ordering order_type;
typedef unsigned long long int offset_type;
typedef unsigned int dimensions_num_type;
static constexpr dimensions_num_type default_num_dimensions = DefaultNumDimensions;
scrambled_sobol64_engine(dimensions_num_type num_of_dimensions = DefaultNumDimensions,
offset_type offset_value = 0,
order_type order_value = ROCRAND_ORDERING_QUASI_DEFAULT)
{
rocrand_status status;
status = rocrand_create_generator(&m_generator, this->type());
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
try
{
this->order(order_value);
if(offset_value > 0)
{
this->offset(offset_value);
}
this->dimensions(num_of_dimensions);
}
catch(...)
{
(void)rocrand_destroy_generator(m_generator);
throw;
}
}
scrambled_sobol64_engine(rocrand_generator& generator) : m_generator(generator)
{
if(generator == NULL)
{
throw rocrand_cpp::error(ROCRAND_STATUS_NOT_CREATED);
}
generator = NULL;
}
~scrambled_sobol64_engine() noexcept(false)
{
rocrand_status status = rocrand_destroy_generator(m_generator);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void stream(hipStream_t value)
{
rocrand_status status = rocrand_set_stream(m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void order(order_type value)
{
rocrand_status status = rocrand_set_ordering(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void offset(offset_type value)
{
rocrand_status status = rocrand_set_offset(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void dimensions(dimensions_num_type value)
{
rocrand_status status
= rocrand_set_quasi_random_generator_dimensions(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
template<class Generator>
void operator()(result_type* output, size_t size)
{
rocrand_status status;
status = rocrand_generate_long_long(m_generator, output, size);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
result_type min() const
{
return 0;
}
result_type max() const
{
return std::numeric_limits<result_type>::max();
}
static constexpr rocrand_rng_type type()
{
return ROCRAND_RNG_QUASI_SCRAMBLED_SOBOL64;
}
private:
rocrand_generator m_generator;
template<class T>
friend class ::rocrand_cpp::uniform_int_distribution;
template<class T>
friend class ::rocrand_cpp::uniform_real_distribution;
template<class T>
friend class ::rocrand_cpp::normal_distribution;
template<class T>
friend class ::rocrand_cpp::lognormal_distribution;
template<class T>
friend class ::rocrand_cpp::poisson_distribution;
};
template<unsigned int DefaultNumDimensions>
constexpr typename scrambled_sobol64_engine<DefaultNumDimensions>::dimensions_num_type
scrambled_sobol64_engine<DefaultNumDimensions>::default_num_dimensions;
template<unsigned long long DefaultSeed = 0>
class threefry2x32_20_engine
{
public:
typedef unsigned int result_type;
typedef rocrand_ordering order_type;
typedef unsigned long long offset_type;
typedef unsigned long long seed_type;
static constexpr seed_type default_seed = DefaultSeed;
threefry2x32_20_engine(seed_type seed_value = DefaultSeed,
offset_type offset_value = 0,
order_type order_value = ROCRAND_ORDERING_PSEUDO_DEFAULT)
{
rocrand_status status;
status = rocrand_create_generator(&m_generator, this->type());
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
try
{
if(offset_value > 0)
{
this->offset(offset_value);
}
this->order(order_value);
this->seed(seed_value);
}
catch(...)
{
(void)rocrand_destroy_generator(m_generator);
throw;
}
}
threefry2x32_20_engine(rocrand_generator& generator) : m_generator(generator)
{
if(generator == NULL)
{
throw rocrand_cpp::error(ROCRAND_STATUS_NOT_CREATED);
}
generator = NULL;
}
~threefry2x32_20_engine() noexcept(false)
{
rocrand_status status = rocrand_destroy_generator(m_generator);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void stream(hipStream_t value)
{
rocrand_status status = rocrand_set_stream(m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void order(order_type value)
{
rocrand_status status = rocrand_set_ordering(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void offset(offset_type value)
{
rocrand_status status = rocrand_set_offset(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void seed(seed_type value)
{
rocrand_status status = rocrand_set_seed(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
template<class Generator>
void operator()(result_type* output, size_t size)
{
rocrand_status status;
status = rocrand_generate(m_generator, output, size);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
result_type min() const
{
return 0;
}
result_type max() const
{
return std::numeric_limits<unsigned int>::max();
}
static constexpr rocrand_rng_type type()
{
return ROCRAND_RNG_PSEUDO_THREEFRY2_32_20;
}
private:
rocrand_generator m_generator;
template<class T>
friend class ::rocrand_cpp::uniform_int_distribution;
template<class T>
friend class ::rocrand_cpp::uniform_real_distribution;
template<class T>
friend class ::rocrand_cpp::normal_distribution;
template<class T>
friend class ::rocrand_cpp::lognormal_distribution;
template<class T>
friend class ::rocrand_cpp::poisson_distribution;
};
template<unsigned long long DefaultSeed>
constexpr typename threefry2x32_20_engine<DefaultSeed>::seed_type
threefry2x32_20_engine<DefaultSeed>::default_seed;
template<unsigned long long DefaultSeed = 0>
class threefry2x64_20_engine
{
public:
typedef unsigned long long result_type;
typedef rocrand_ordering order_type;
typedef unsigned long long offset_type;
typedef unsigned long long seed_type;
static constexpr seed_type default_seed = DefaultSeed;
threefry2x64_20_engine(seed_type seed_value = DefaultSeed,
offset_type offset_value = 0,
order_type order_value = ROCRAND_ORDERING_PSEUDO_DEFAULT)
{
rocrand_status status;
status = rocrand_create_generator(&m_generator, this->type());
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
try
{
if(offset_value > 0)
{
this->offset(offset_value);
}
this->order(order_value);
this->seed(seed_value);
}
catch(...)
{
(void)rocrand_destroy_generator(m_generator);
throw;
}
}
threefry2x64_20_engine(rocrand_generator& generator) : m_generator(generator)
{
if(generator == NULL)
{
throw rocrand_cpp::error(ROCRAND_STATUS_NOT_CREATED);
}
generator = NULL;
}
~threefry2x64_20_engine() noexcept(false)
{
rocrand_status status = rocrand_destroy_generator(m_generator);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void stream(hipStream_t value)
{
rocrand_status status = rocrand_set_stream(m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void order(order_type value)
{
rocrand_status status = rocrand_set_ordering(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void offset(offset_type value)
{
rocrand_status status = rocrand_set_offset(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void seed(seed_type value)
{
rocrand_status status = rocrand_set_seed(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
template<class Generator>
void operator()(result_type* output, size_t size)
{
rocrand_status status;
status = rocrand_generate_long_long(m_generator, output, size);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
result_type min() const
{
return 0;
}
result_type max() const
{
return std::numeric_limits<unsigned int>::max();
}
static constexpr rocrand_rng_type type()
{
return ROCRAND_RNG_PSEUDO_THREEFRY2_64_20;
}
private:
rocrand_generator m_generator;
template<class T>
friend class ::rocrand_cpp::uniform_int_distribution;
template<class T>
friend class ::rocrand_cpp::uniform_real_distribution;
template<class T>
friend class ::rocrand_cpp::normal_distribution;
template<class T>
friend class ::rocrand_cpp::lognormal_distribution;
template<class T>
friend class ::rocrand_cpp::poisson_distribution;
};
template<unsigned long long DefaultSeed>
constexpr typename threefry2x64_20_engine<DefaultSeed>::seed_type
threefry2x64_20_engine<DefaultSeed>::default_seed;
template<unsigned long long DefaultSeed = 0>
class threefry4x32_20_engine
{
public:
typedef unsigned int result_type;
typedef rocrand_ordering order_type;
typedef unsigned long long offset_type;
typedef unsigned long long seed_type;
static constexpr seed_type default_seed = DefaultSeed;
threefry4x32_20_engine(seed_type seed_value = DefaultSeed,
offset_type offset_value = 0,
order_type order_value = ROCRAND_ORDERING_PSEUDO_DEFAULT)
{
rocrand_status status;
status = rocrand_create_generator(&m_generator, this->type());
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
try
{
if(offset_value > 0)
{
this->offset(offset_value);
}
this->order(order_value);
this->seed(seed_value);
}
catch(...)
{
(void)rocrand_destroy_generator(m_generator);
throw;
}
}
threefry4x32_20_engine(rocrand_generator& generator) : m_generator(generator)
{
if(generator == NULL)
{
throw rocrand_cpp::error(ROCRAND_STATUS_NOT_CREATED);
}
generator = NULL;
}
~threefry4x32_20_engine() noexcept(false)
{
rocrand_status status = rocrand_destroy_generator(m_generator);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void stream(hipStream_t value)
{
rocrand_status status = rocrand_set_stream(m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void order(order_type value)
{
rocrand_status status = rocrand_set_ordering(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void offset(offset_type value)
{
rocrand_status status = rocrand_set_offset(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void seed(seed_type value)
{
rocrand_status status = rocrand_set_seed(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
template<class Generator>
void operator()(result_type* output, size_t size)
{
rocrand_status status;
status = rocrand_generate(m_generator, output, size);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
result_type min() const
{
return 0;
}
result_type max() const
{
return std::numeric_limits<unsigned int>::max();
}
static constexpr rocrand_rng_type type()
{
return ROCRAND_RNG_PSEUDO_THREEFRY4_32_20;
}
private:
rocrand_generator m_generator;
template<class T>
friend class ::rocrand_cpp::uniform_int_distribution;
template<class T>
friend class ::rocrand_cpp::uniform_real_distribution;
template<class T>
friend class ::rocrand_cpp::normal_distribution;
template<class T>
friend class ::rocrand_cpp::lognormal_distribution;
template<class T>
friend class ::rocrand_cpp::poisson_distribution;
};
template<unsigned long long DefaultSeed>
constexpr typename threefry4x32_20_engine<DefaultSeed>::seed_type
threefry4x32_20_engine<DefaultSeed>::default_seed;
template<unsigned long long DefaultSeed = 0>
class threefry4x64_20_engine
{
public:
typedef unsigned long long result_type;
typedef rocrand_ordering order_type;
typedef unsigned long long offset_type;
typedef unsigned long long seed_type;
static constexpr seed_type default_seed = DefaultSeed;
threefry4x64_20_engine(seed_type seed_value = DefaultSeed,
offset_type offset_value = 0,
order_type order_value = ROCRAND_ORDERING_PSEUDO_DEFAULT)
{
rocrand_status status;
status = rocrand_create_generator(&m_generator, this->type());
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
try
{
if(offset_value > 0)
{
this->offset(offset_value);
}
this->order(order_value);
this->seed(seed_value);
}
catch(...)
{
(void)rocrand_destroy_generator(m_generator);
throw;
}
}
threefry4x64_20_engine(rocrand_generator& generator) : m_generator(generator)
{
if(generator == NULL)
{
throw rocrand_cpp::error(ROCRAND_STATUS_NOT_CREATED);
}
generator = NULL;
}
~threefry4x64_20_engine() noexcept(false)
{
rocrand_status status = rocrand_destroy_generator(m_generator);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void stream(hipStream_t value)
{
rocrand_status status = rocrand_set_stream(m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void offset(offset_type value)
{
rocrand_status status = rocrand_set_offset(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
void seed(seed_type value)
{
rocrand_status status = rocrand_set_seed(this->m_generator, value);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
template<class Generator>
void operator()(result_type* output, size_t size)
{
rocrand_status status;
status = rocrand_generate_long_long(m_generator, output, size);
if(status != ROCRAND_STATUS_SUCCESS)
throw rocrand_cpp::error(status);
}
result_type min() const
{
return 0;
}
result_type max() const
{
return std::numeric_limits<unsigned int>::max();
}
static constexpr rocrand_rng_type type()
{
return ROCRAND_RNG_PSEUDO_THREEFRY4_64_20;
}
private:
rocrand_generator m_generator;
template<class T>
friend class ::rocrand_cpp::uniform_int_distribution;
template<class T>
friend class ::rocrand_cpp::uniform_real_distribution;
template<class T>
friend class ::rocrand_cpp::normal_distribution;
template<class T>
friend class ::rocrand_cpp::lognormal_distribution;
template<class T>
friend class ::rocrand_cpp::poisson_distribution;
};
template<unsigned long long DefaultSeed>
constexpr typename threefry4x64_20_engine<DefaultSeed>::seed_type
threefry4x64_20_engine<DefaultSeed>::default_seed;
typedef philox4x32_10_engine<> philox4x32_10;
typedef xorwow_engine<> xorwow;
typedef mrg31k3p_engine<> mrg31k3a;
typedef mrg32k3a_engine<> mrg32k3a;
typedef mtgp32_engine<> mtgp32;
typedef lfsr113_engine<> lfsr113;
typedef mt19937_engine<> mt19937;
typedef threefry2x32_20_engine<> threefry2x32;
typedef threefry2x64_20_engine<> threefry2x64;
typedef threefry4x32_20_engine<> threefry4x32;
typedef threefry4x64_20_engine<> threefry4x64;
typedef sobol32_engine<> sobol32;
typedef scrambled_sobol32_engine<> scrambled_sobol32;
typedef sobol64_engine<> sobol64;
typedef scrambled_sobol64_engine<> scrambled_sobol64;
typedef xorwow default_random_engine;
typedef std::random_device random_device;
inline int version()
{
int x;
rocrand_status status = rocrand_get_version(&x);
if(status != ROCRAND_STATUS_SUCCESS)
{
throw rocrand_cpp::error(status);
}
return x;
}
} // end namespace rocrand_cpp
#endif // #if __cplusplus >= 201103L
#endif // ROCRAND_HPP_