27#define PRRNG_PCG32_INITSTATE 0x853c49e6748fea9bULL
33#define PRRNG_PCG32_INITSEQ 0xda3e39cb94b95bdbULL
39#define PRRNG_PCG32_MULT 6364136223846793005ULL
42#include <xtensor/xarray.hpp>
43#include <xtensor/xnoalias.hpp>
44#include <xtensor/xtensor.hpp>
46#ifndef PRRNG_USE_BOOST
55#define PRRNG_USE_BOOST 1
59#include <boost/math/special_functions/erf.hpp>
60#include <boost/math/special_functions/gamma.hpp>
61#include <xtensor/xvectorize.hpp>
67#define PRRNG_QUOTE_HELPER(x) #x
68#define PRRNG_QUOTE(x) PRRNG_QUOTE_HELPER(x)
70#define PRRNG_ASSERT_IMPL(expr, file, line) \
72 throw std::runtime_error( \
73 std::string(file) + ':' + std::to_string(line) + ": assertion failed (" #expr ") \n\t" \
77#define PRRNG_WARNING_IMPL(message, file, line, function) \
78 std::cout << std::string(file) + ":" + std::to_string(line) + " (" + std::string(function) + \
79 ")" + ": " message ") \n\t";
106#define PRRNG_VERSION "@PROJECT_VERSION@"
126#ifdef PRRNG_ENABLE_ASSERT
127#define PRRNG_ASSERT(expr) PRRNG_ASSERT_IMPL(expr, __FILE__, __LINE__)
129#define PRRNG_ASSERT(expr)
149#ifdef PRRNG_ENABLE_DEBUG
150#define PRRNG_DEBUG(expr) PRRNG_ASSERT_IMPL(expr, __FILE__, __LINE__)
152#define PRRNG_DEBUG(expr)
164#ifdef PRRNG_DISABLE_WARNING
165#define PRRNG_WARNING(message)
167#define PRRNG_WARNING(message) PRRNG_WARNING_IMPL(message, __FILE__, __LINE__, __FUNCTION__)
179#ifdef PRRNG_ENABLE_WARNING_PYTHON
180#define PRRNG_WARNING_PYTHON(message) PRRNG_WARNING_IMPL(message, __FILE__, __LINE__, __FUNCTION__)
182#define PRRNG_WARNING_PYTHON(message)
227 const std::vector<double>& parameters = std::vector<double>{}
230 std::vector<double> ret;
233 ret = std::vector<double>{1, 0};
236 ret = std::vector<double>{1, 0};
239 ret = std::vector<double>{1, 0};
242 ret = std::vector<double>{1, 0};
245 ret = std::vector<double>{1, 1, 0};
248 ret = std::vector<double>{1, 1, 0};
251 ret = std::vector<double>{1, 1, 0};
254 ret = std::vector<double>{1, 0, 0};
257 std::vector<double>{};
262 std::copy(parameters.begin(), parameters.end(), ret.begin());
278 return parameters.size() == 2;
280 return parameters.size() == 2;
282 return parameters.size() == 2;
284 return parameters.size() == 2;
286 return parameters.size() == 3;
288 return parameters.size() == 3;
290 return parameters.size() == 3;
292 return parameters.size() == 3;
306inline std::string unquote(
const std::string& arg)
308 std::string ret = arg;
309 ret.erase(std::remove(ret.begin(), ret.end(),
'\"'), ret.end());
320inline std::string replace(std::string str,
const std::string& from,
const std::string& to)
322 size_t start_pos = 0;
323 while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
324 str.replace(start_pos, from.length(), to);
325 start_pos += to.length();
331struct is_std_array : std::false_type {};
333template <
class T,
size_t N>
334struct is_std_array<std::array<T, N>> : std::true_type {};
339template <
size_t N,
class T,
typename =
void>
340struct check_fixed_rank {
341 constexpr static bool value =
false;
344template <
size_t N,
class T>
345struct check_fixed_rank<N, T, typename std::enable_if_t<xt::get_rank<T>::value != SIZE_MAX>> {
346 constexpr static bool value = (N == xt::get_rank<T>::value);
349template <
size_t N,
class T>
350struct check_fixed_rank<N, T, typename std::enable_if_t<is_std_array<T>::value>> {
351 constexpr static bool value = (N == std::tuple_size<T>::value);
357template <
typename R,
typename =
void>
358struct get_value_type {
359 using type =
typename R::value_type;
363struct get_value_type<R, typename std::enable_if_t<std::is_arithmetic<R>::value>> {
370template <
typename R,
size_t N>
371struct return_type_fixed {
372 using type =
typename xt::xtensor<R, N>;
378template <
typename R,
class S,
typename =
void>
380 using type =
typename xt::xarray<R>;
383template <
typename R,
class S>
384struct return_type<R, S, typename std::enable_if_t<is_std_array<S>::value>> {
385 using type =
typename xt::xtensor<R, std::tuple_size<S>::value>;
388template <
typename R,
class S>
389struct return_type<R, S, typename std::enable_if_t<xt::has_fixed_rank_t<S>::value>> {
390 using type =
typename xt::xtensor<R, xt::get_rank<S>::value>;
396template <
typename R,
class S,
class T,
typename =
void>
397struct composite_return_type {
398 using type =
typename xt::xarray<R>;
401template <
typename R,
class S,
class T>
402struct composite_return_type<
406 typename std::enable_if_t<is_std_array<S>::value && is_std_array<T>::value>> {
407 constexpr static size_t N = std::tuple_size<S>::value + std::tuple_size<T>::value;
408 using type =
typename xt::xtensor<R, N>;
414template <
typename R,
typename =
void>
415struct allocate_return {
417 using value_type =
typename R::value_type;
421 allocate_return(
const S& shape)
423#if (XTENSOR_PYTHON_VERSION_MINOR == 26 && XTENSOR_PYTHON_VERSION_PATCH <= 1) || \
424 (XTENSOR_PYTHON_VERSION_MINOR < 26)
425 if (shape.size() == 0) {
426 std::array<typename R::size_type, 1> shape_ = {1};
427 value.resize(shape_);
437 template <
class I, std::
size_t L>
438 allocate_return(
const I (&shape)[L])
440 std::array<I, L> shape_;
441 std::copy(shape, shape + L, shape_.begin());
442 value.resize(shape_);
445 typename R::value_type* data()
447 return &value.front();
457struct allocate_return<R, typename std::enable_if_t<std::is_arithmetic<R>::value>> {
459 using value_type = R;
463 allocate_return(
const S& shape)
465#ifdef PRRNG_ENABLE_ASSERT
467 if (shape.size() == 1) {
493template <
class S,
class T,
typename =
void>
495 static auto two(
const S& s,
const T& t)
497 std::vector<size_t> r;
498 r.insert(r.begin(), s.cbegin(), s.cend());
499 r.insert(r.end(), t.cbegin(), t.cend());
504template <
class S,
class T>
508 typename std::enable_if_t<is_std_array<S>::value && is_std_array<T>::value>> {
509 static auto two(
const S& s,
const T& t)
511 std::array<size_t, std::tuple_size<S>::value + std::tuple_size<T>::value> r;
512 std::copy(s.cbegin(), s.cend(), r.begin());
513 std::copy(t.cbegin(), t.cend(), r.begin() + std::tuple_size<S>::value);
525inline size_t size(
const S& shape)
527 using ST =
typename S::value_type;
528 return std::accumulate(shape.cbegin(), shape.cend(), ST(1), std::multiplies<ST>());
534template <
class I, std::
size_t L>
535std::array<I, L> to_array(
const I (&shape)[L])
538 std::copy(&shape[0], &shape[0] + L, r.begin());
549 return detail::unquote(std::string(PRRNG_QUOTE(
PRRNG_VERSION)));
565 std::vector<std::string> ret;
567 ret.push_back(
"prrng=" +
version());
570 "xtensor=" + detail::unquote(std::string(PRRNG_QUOTE(XTENSOR_VERSION_MAJOR))) +
"." +
571 detail::unquote(std::string(PRRNG_QUOTE(XTENSOR_VERSION_MINOR))) +
"." +
572 detail::unquote(std::string(PRRNG_QUOTE(XTENSOR_VERSION_PATCH)))
575#ifdef XSIMD_VERSION_MAJOR
577 "xsimd=" + detail::unquote(std::string(PRRNG_QUOTE(XSIMD_VERSION_MAJOR))) +
"." +
578 detail::unquote(std::string(PRRNG_QUOTE(XSIMD_VERSION_MINOR))) +
"." +
579 detail::unquote(std::string(PRRNG_QUOTE(XSIMD_VERSION_PATCH)))
583#ifdef XTL_VERSION_MAJOR
585 "xtl=" + detail::unquote(std::string(PRRNG_QUOTE(XTL_VERSION_MAJOR))) +
"." +
586 detail::unquote(std::string(PRRNG_QUOTE(XTL_VERSION_MINOR))) +
"." +
587 detail::unquote(std::string(PRRNG_QUOTE(XTL_VERSION_PATCH)))
591#if defined(XTENSOR_PYTHON_VERSION_MAJOR)
594 detail::unquote(std::string(PRRNG_QUOTE(XTENSOR_PYTHON_VERSION_MAJOR))) +
"." +
595 detail::unquote(std::string(PRRNG_QUOTE(XTENSOR_PYTHON_VERSION_MINOR))) +
"." +
596 detail::unquote(std::string(PRRNG_QUOTE(XTENSOR_PYTHON_VERSION_PATCH)))
602 "boost=" + detail::unquote(std::to_string(BOOST_VERSION / 100000)) +
"." +
603 detail::unquote(std::to_string((BOOST_VERSION / 100) % 1000)) +
"." +
604 detail::unquote(std::to_string(BOOST_VERSION % 100))
608 std::sort(ret.begin(), ret.end(), std::greater<std::string>());
619 std::vector<std::string> ret;
622 std::string date = detail::unquote(std::string(PRRNG_QUOTE(__DATE__)));
623 ret.push_back(
"date=" + detail::replace(detail::replace(date,
" ",
"-"),
"--",
"-"));
627 ret.push_back(
"platform=apple");
631 ret.push_back(
"platform=mingw");
635 ret.push_back(
"platform=linux");
639 ret.push_back(
"platform=windows");
642 ret.push_back(
"platform=windows");
646#ifdef __clang_version__
648 "clang=" + detail::unquote(std::string(PRRNG_QUOTE(__clang_major__))) +
"." +
649 detail::unquote(std::string(PRRNG_QUOTE(__clang_minor__))) +
"." +
650 detail::unquote(std::string(PRRNG_QUOTE(__clang_patchlevel__)))
656 "gcc=" + detail::unquote(std::string(PRRNG_QUOTE(__GNUC__))) +
"." +
657 detail::unquote(std::string(PRRNG_QUOTE(__GNUC_MINOR__))) +
"." +
658 detail::unquote(std::string(PRRNG_QUOTE(__GNUC_PATCHLEVEL__)))
663 ret.push_back(
"msvc=" + std::to_string(_MSC_VER));
669 ret.push_back(
"c++=" + detail::unquote(std::string(PRRNG_QUOTE(__cplusplus))));
672 std::sort(ret.begin(), ret.end(), std::greater<std::string>());
693template <
class It,
class T,
class R =
size_t>
694inline R
lower_bound(
const It first,
const It last,
const T& value, R guess = 0, R proximity = 10)
696 if (proximity == 0) {
697 if (value <= *(first)) {
700 return std::lower_bound(first, last, value) - first - 1;
703 if (*(first + guess) < value && value <= *(first + guess + 1)) {
707 R l = guess > proximity ? guess - proximity : 0;
708 R r = std::min(guess + proximity,
static_cast<R
>(last - first - 1));
710 if (*(first + l) < value && *(first + r) >= value) {
711 return std::lower_bound(first + l, first + r, value) - first - 1;
713 else if (value <= *(first)) {
717 return std::lower_bound(first, last, value) - first - 1;
734template <
class T,
class V,
class R>
736lower_bound(
const T& matrix,
const V& value, R& index,
typename R::value_type proximity = 10)
738 PRRNG_ASSERT(value.dimension() == matrix.dimension() - 1);
741 auto nd = value.dimension();
742 auto stride = matrix.shape(nd);
743 auto n = value.size();
745#ifdef PRRNG_ENABLE_ASSERT
746 for (
decltype(nd) i = 0; i < nd; ++i) {
752 for (
decltype(n) i = 0; i < n; ++i) {
753 index.flat(i) = iterator::lower_bound(
754 &matrix.flat(i * stride),
755 &matrix.flat(i * stride) + stride,
770template <
class V,
class I>
776 if (
delta.size() == 0) {
780 size_t dim = cumsum.dimension();
781 size_t n = cumsum.shape(dim - 1);
782 size_t ndelta =
delta.shape(dim - 1);
784 for (
size_t i = 0; i < shift.size(); ++i) {
786 if (shift.flat(i) == 0) {
790 auto* d = &
delta.flat(i * ndelta);
791 auto* c = &cumsum.flat(i * n);
793 if (shift.flat(i) > 0) {
794 PRRNG_ASSERT(shift.flat(i) <=
static_cast<typename I::value_type
>(n));
795 PRRNG_ASSERT(
static_cast<typename I::value_type
>(ndelta) >= shift.flat(i));
796 size_t nadd =
static_cast<size_t>(shift.flat(i));
797 size_t nkeep = n - nadd;
798 auto offset = *(c + n - 1);
799 std::copy(c + n - nkeep, c + n, c);
800 std::copy(d, d + nadd, c + nkeep);
801 *(c + nkeep) += offset;
802 std::partial_sum(c + nkeep, c + n, c + nkeep);
805 PRRNG_ASSERT(-shift.flat(i) <
static_cast<typename I::value_type
>(n));
806 PRRNG_ASSERT(
static_cast<typename I::value_type
>(ndelta) > -shift.flat(i));
807 size_t nadd =
static_cast<size_t>(-shift.flat(i));
808 size_t nkeep = n - nadd;
810 std::copy(c, c + nkeep, c + nadd);
811 std::copy(d, d + nadd + 1, c);
812 std::partial_sum(c, c + nadd + 1, c);
813 offset -= *(c + nadd);
814 std::transform(c, c + nadd + 1, c, [&](
auto& v) {
return v + offset; });
836template <
class T,
class V,
class R>
837inline R
lower_bound(
const T& matrix,
const V& value,
const R& index,
size_t proximity = 10)
840 inplace::lower_bound(matrix, value, ret, proximity);
853template <
class T,
class V,
class R>
856 R ret = xt::zeros<typename R::value_type>(value.shape());
857 inplace::lower_bound(matrix, value, ret, 0);
897template <
class V,
class I>
901 inplace::cumsum_chunk(ret,
delta, shift);
918template <
class G,
class D,
class P>
929 ptrdiff_t ichunk = index - *start;
931 if (ichunk > param.buffer && ichunk < size - param.buffer) {
935 using R =
decltype(get_chunk(
size_t{}));
937 ptrdiff_t offset = 0;
938 ichunk -= param.margin;
940 if (ichunk < 0 && ichunk > -size) {
942 std::copy(data, data + size + ichunk, data + n);
944 else if (ichunk > 0 && ichunk < size) {
946 offset = size - ichunk;
947 std::copy(data + n, data + size, data);
950 *start = index - param.margin;
951 generator.jump_to(*start + offset);
952 R extra = get_chunk(
static_cast<size_t>(n));
954 std::copy(extra.begin(), extra.end(), data + offset);
961template <
class G,
class D,
class S,
class P>
973 ptrdiff_t ichunk = index - *start;
975 if (ichunk > param.buffer && ichunk < size - param.buffer) {
979 using R =
decltype(get_chunk(
size_t{}));
980 ichunk -= param.margin;
982 if (ichunk > 0 && ichunk < size) {
983 ptrdiff_t n = ichunk;
984 ptrdiff_t offset = size - ichunk;
985 double back = data[size - 1];
986 std::copy(data + n, data + size, data);
988 *start = index - param.margin;
989 generator.jump_to(*start + offset);
990 R extra = get_chunk(
static_cast<size_t>(n));
993 extra.front() += back;
994 std::partial_sum(extra.begin(), extra.end(), extra.begin());
995 std::copy(extra.begin(), extra.end(), data + offset);
999 if (ichunk < 0 && ichunk > -size) {
1000 ptrdiff_t n = -ichunk;
1001 double front = data[0];
1002 std::copy(data, data + size + ichunk, data + n);
1004 *start = index - param.margin;
1005 generator.jump_to(*start);
1006 R extra = get_chunk(
static_cast<size_t>(n + 1));
1007 generator.drawn(n + 1);
1009 std::partial_sum(extra.begin(), extra.end(), extra.begin());
1010 extra -= extra.back() - front;
1011 std::copy(extra.begin(), extra.end(), data);
1016 ptrdiff_t n = *start - (index - param.margin + size) + 1;
1017 *start = index - param.margin;
1018 generator.jump_to(*start);
1019 R extra = get_chunk(
static_cast<size_t>(size));
1020 generator.drawn(size);
1022 double front = data[0] - get_sum(n);
1025 std::partial_sum(extra.begin(), extra.end(), extra.begin());
1026 extra -= extra.back() - front;
1027 std::copy(extra.begin(), extra.end(), data);
1031 generator.jump_to(*start + size);
1032 ptrdiff_t n = index - param.margin - (*start + size);
1033 *start = index - param.margin;
1034 double back = get_sum(n) + data[size - 1];
1037 R extra = get_chunk(
static_cast<size_t>(size));
1038 generator.drawn(size);
1039 extra.front() += back;
1040 std::partial_sum(extra.begin(), extra.end(), extra.begin());
1041 std::copy(extra.begin(), extra.end(), data);
1054template <
class G,
class D>
1064 using R =
decltype(get_chunk(
size_t{}));
1066 generator.jump_to(*start - size + margin);
1068 double front = data[0];
1069 ptrdiff_t m = size - margin + 1;
1070 R extra = get_chunk(
static_cast<size_t>(m));
1072 std::partial_sum(extra.begin(), extra.end(), extra.begin());
1073 extra -= extra.back() - front;
1075 std::copy(data, data + margin, data + size - margin);
1076 std::copy(extra.begin(), extra.end() - 1, data);
1078 *start -= size - margin;
1091template <
class G,
class D>
1101 using R =
decltype(get_chunk(
size_t{}));
1104 generator.jump_to(*start + size);
1106 double back = data[size - 1];
1107 ptrdiff_t n = size - margin;
1108 R extra = get_chunk(
static_cast<size_t>(n));
1110 extra.front() += back;
1111 std::partial_sum(extra.begin(), extra.end(), extra.begin());
1112 std::copy(data + size - margin, data + size, data);
1113 std::copy(extra.begin(), extra.end(), data + margin);
1131template <
class G,
class D,
class S,
class P>
1142 bool recursive =
false
1145 using R =
decltype(get_chunk(
size_t{}));
1147 if (target > data[size - 1]) {
1148 double delta = data[size - 1] - data[0];
1150 generator.jump_to(*start + size);
1151 double back = data[size - 1];
1152 double j = (target - data[size - 1]) /
delta - (
double)(param.margin) / (
double)(n);
1155 ptrdiff_t m =
static_cast<ptrdiff_t
>((j - 1) *
static_cast<double>(n));
1156 back += get_sum(
static_cast<size_t>(m));
1159 R extra = get_chunk(
static_cast<size_t>(n));
1161 extra.front() += back;
1162 std::partial_sum(extra.begin(), extra.end(), data);
1163 return align(generator, get_chunk, get_sum, param, data, size, start, i, target,
true);
1166 next(generator, get_chunk, 1 + param.margin, data, size, start);
1167 return align(generator, get_chunk, get_sum, param, data, size, start, i, target,
true);
1170 if (target < data[0]) {
1171 prev(generator, get_chunk, 0, data, size, start);
1172 return align(generator, get_chunk, get_sum, param, data, size, start, i, target,
true);
1175 if (recursive || *i >= size) {
1176 *i = std::lower_bound(data, data + size, target) - data - 1;
1179 *i = iterator::lower_bound(data, data + size, target, *i);
1182 if (*i == param.margin) {
1185 if (!recursive && param.buffer > 0 && *i >= param.buffer && *i + param.buffer < size) {
1188 if (*i < param.margin) {
1189 if (!param.strict && *i >= param.min_margin) {
1192 prev(generator, get_chunk, 0, data, size, start);
1193 return align(generator, get_chunk, get_sum, param, data, size, start, i, target,
true);
1196 generator.jump_to(*start + size);
1197 ptrdiff_t n = *i - param.margin;
1198 R extra = get_chunk(
static_cast<size_t>(n));
1202 extra.front() += data[size - 1];
1203 std::partial_sum(extra.begin(), extra.end(), extra.begin());
1204 std::copy(data + n, data + size, data);
1205 std::copy(extra.begin(), extra.end(), data + size - n);
1238 double rate = 1.0 / m_scale;
1239 return rate * xt::exp(-rate * x);
1251 double rate = 1.0 / m_scale;
1252 return 1.0 - xt::exp(-rate * x);
1264 return -xt::log(1.0 - p) * m_scale;
1303 return m_k * xt::pow(x, m_k - 1.0);
1315 return xt::pow(x, m_k);
1327 return xt::pow(1.0 - p, 1.0 / m_k);
1368 using value_type =
typename T::value_type;
1371 auto f = xt::vectorize(boost::math::gamma_p_derivative<value_type, value_type>);
1372 T ret = f(m_shape, x / m_scale);
1373 return xt::where(xt::equal(x, 0), 0.0, ret);
1376 ret.fill(std::numeric_limits<value_type>::quiet_NaN());
1392 using value_type =
typename T::value_type;
1395 auto f = xt::vectorize(boost::math::gamma_p<value_type, value_type>);
1396 return f(m_shape, x / m_scale);
1399 ret.fill(std::numeric_limits<value_type>::quiet_NaN());
1415 using value_type =
typename T::value_type;
1418 auto f = xt::vectorize(boost::math::gamma_p_inv<value_type, value_type>);
1419 return m_scale * f(m_shape, p);
1422 ret.fill(std::numeric_limits<value_type>::quiet_NaN());
1469 return m_k * std::pow(m_scale, m_k) * xt::pow(x, -(m_k + 1.0));
1481 return 1.0 - std::pow(m_scale, m_k) * xt::pow(x, -m_k);
1493 return m_scale * xt::pow(1.0 - p, -1.0 / m_k);
1532 T ret = xt::exp(-xt::pow(x / m_scale, m_shape));
1533 ret *= xt::pow(x / m_scale, m_shape - 1.0) * m_shape / m_scale;
1535 if (xt::any(xt::equal(x, 0))) {
1537 ret = xt::where(xt::equal(x, 0), 1.0 / m_scale, ret);
1539 else if (m_shape > 1) {
1540 ret = xt::where(xt::equal(x, 0), 0.0, ret);
1543 throw std::runtime_error(
"[prrng::weibull_distribution::pdf] Overflow error");
1561 return -xt::expm1(-xt::pow(x / m_scale, m_shape));
1576 return m_scale * xt::pow(-xt::log1p(-p), 1.0 / m_shape);
1605 m_sigma_sqrt2 = m_sigma * std::sqrt(2.0);
1617 return xt::exp(-0.5 * xt::pow((x - m_mu) / m_sigma, 2.0)) /
1618 (m_sigma_sqrt2 * std::sqrt(xt::numeric_constants<double>::PI));
1636 return 0.5 * (1.0 + xt::erf((x - m_mu) / m_sigma_sqrt2));
1651 using value_type =
typename detail::get_value_type<T>::type;
1654 auto f = xt::vectorize(boost::math::erf_inv<value_type>);
1655 return m_mu + m_sigma_sqrt2 * f(2.0 * p - 1.0);
1657 static_assert(xt::is_xexpression<T>::value,
"T must be an xexpression");
1659 ret.fill(std::numeric_limits<value_type>::quiet_NaN());
1667 double m_sigma_sqrt2;
1689template <
class Derived>
1700 for (
size_t i = 0; i < n; ++i) {
1701 ret +=
static_cast<Derived*
>(
this)->next_double();
1715 return static_cast<double>(n) * scale;
1728 for (
size_t i = 0; i < n; ++i) {
1729 ret -= std::log(1.0 -
static_cast<Derived*
>(
this)->next_double());
1744 double exponent = 1.0 / k;
1745 for (
size_t i = 0; i < n; ++i) {
1746 ret += std::pow(1.0 -
static_cast<Derived*
>(
this)->next_double(), exponent);
1763 for (
size_t i = 0; i < n; ++i) {
1764 ret += boost::math::gamma_p_inv<double, double>(
1765 k,
static_cast<Derived*
>(
this)->next_double()
1770 return std::numeric_limits<double>::quiet_NaN();
1785 double exponent = -1.0 / k;
1786 for (
size_t i = 0; i < n; ++i) {
1787 ret += std::pow(1.0 -
static_cast<Derived*
>(
this)->next_double(), exponent);
1803 double k_inv = 1.0 / k;
1804 for (
size_t i = 0; i < n; ++i) {
1805 ret += std::pow(-std::log(1.0 -
static_cast<Derived*
>(
this)->next_double()), k_inv);
1822 for (
size_t i = 0; i < n; ++i) {
1823 ret += boost::math::erf_inv<double>(
1824 2.0 *
static_cast<Derived*
>(
this)->next_double() - 1.0
1827 return static_cast<double>(n) * mu + sigma * std::sqrt(2.0) * ret;
1829 return std::numeric_limits<double>::quiet_NaN();
1843 template <
typename Iterator>
1846 for (Iterator it = end - 1; it > begin; --it) {
1848 it, begin +
static_cast<Derived*
>(
this)->next_uint32((uint32_t)(it - begin + 1))
1862 auto decide(
const P& p) ->
typename detail::return_type<bool, P>::type
1864 using R =
typename detail::return_type<bool, P>::type;
1865 R ret = xt::empty<bool>(p.shape());
1873 template <
class P,
class R>
1876 using value_type =
typename detail::get_value_type<R>::type;
1877 R ret = xt::empty<value_type>(p.shape());
1890 template <
class P,
class R>
1894 using value_type =
typename detail::get_value_type<R>::type;
1896 for (
size_t i = 0; i < p.size(); ++i) {
1897 if (
static_cast<Derived*
>(
this)->next_double() < p.flat(i)) {
1898 ret.flat(i) =
static_cast<value_type
>(
true);
1901 ret.flat(i) =
static_cast<value_type
>(
false);
1915 template <
class P,
class T>
1916 auto decide_masked(
const P& p,
const T& mask) ->
typename detail::return_type<bool, P>::type
1918 using R =
typename detail::return_type<bool, P>::type;
1919 R ret = xt::empty<bool>(p.shape());
1927 template <
class P,
class T,
class R>
1930 using value_type =
typename detail::get_value_type<R>::type;
1931 R ret = xt::empty<value_type>(p.shape());
1945 template <
class P,
class T,
class R>
1949 using value_type =
typename detail::get_value_type<R>::type;
1951 for (
size_t i = 0; i < p.size(); ++i) {
1953 ret.flat(i) =
static_cast<value_type
>(
false);
1955 else if (
static_cast<Derived*
>(
this)->next_double() < p.flat(i)) {
1956 ret.flat(i) =
static_cast<value_type
>(
true);
1959 ret.flat(i) =
static_cast<value_type
>(
false);
1971 return static_cast<Derived*
>(
this)->next_double();
1981 auto random(
const S& shape) ->
typename detail::return_type<double, S>::type
1983 using R =
typename detail::return_type<double, S>::type;
1984 return this->random_impl<R>(shape);
1991 template <
class R,
class S>
1994 return this->random_impl<R>(shape);
2000 template <
class I, std::
size_t L>
2001 auto random(
const I (&shape)[L]) ->
typename detail::return_type_fixed<double, L>::type
2003 using R =
typename detail::return_type_fixed<double, L>::type;
2004 return this->random_impl<R>(shape);
2011 template <
class R,
class I, std::
size_t L>
2014 return this->random_impl<R>(shape);
2023 template <
typename T>
2027 PRRNG_ASSERT(
static_cast<uint32_t
>(high) < std::numeric_limits<uint32_t>::max());
2030 this->draw_list_uint32(&ret,
static_cast<uint32_t
>(high), 1);
2031 return static_cast<T
>(ret);
2041 template <
class S,
typename T>
2042 auto randint(
const S& shape, T high) ->
typename detail::return_type<T, S>::type
2044 using R =
typename detail::return_type<T, S>::type;
2045 return this->randint_impl<R>(shape, high);
2052 template <
class R,
class S,
typename T>
2055 return this->randint_impl<R>(shape, high);
2061 template <
class I, std::
size_t L,
typename T>
2062 auto randint(
const I (&shape)[L], T high) ->
typename detail::return_type_fixed<T, L>::type
2064 using R =
typename detail::return_type_fixed<T, L>::type;
2065 return this->randint_impl<R>(shape, high);
2072 template <
class R,
class I, std::
size_t L,
typename T>
2075 return this->randint_impl<R>(shape, high);
2086 template <
class S,
typename T,
typename U>
2087 auto randint(
const S& shape, T low, U high) ->
typename detail::return_type<T, S>::type
2089 using R =
typename detail::return_type<T, S>::type;
2090 return this->randint_impl<R>(shape, low, high);
2097 template <
class R,
class S,
typename T,
typename U>
2100 return this->randint_impl<R>(shape, low, high);
2106 template <
class I, std::
size_t L,
typename T,
typename U>
2107 auto randint(
const I (&shape)[L], T low, U high) ->
2108 typename detail::return_type_fixed<T, L>::type
2110 using R =
typename detail::return_type_fixed<T, L>::type;
2111 return this->randint_impl<R>(shape, low, high);
2118 template <
class R,
class I, std::
size_t L,
typename T,
typename U>
2121 return this->randint_impl<R>(shape, low, high);
2145 auto delta(
const S& shape,
double scale = 1) ->
typename detail::return_type<double, S>::type
2147 using R =
typename detail::return_type<double, S>::type;
2148 return this->delta_impl<R>(shape, scale);
2155 template <
class R,
class S>
2156 R
delta(
const S& shape,
double scale = 1)
2158 return this->delta_impl<R>(shape, scale);
2164 template <
class I, std::
size_t L>
2165 auto delta(
const I (&shape)[L],
double scale = 1) ->
2166 typename detail::return_type_fixed<double, L>::type
2168 using R =
typename detail::return_type_fixed<double, L>::type;
2169 return this->delta_impl<R>(shape, scale);
2176 template <
class R,
class I, std::
size_t L>
2177 R
delta(
const I (&shape)[L],
double scale = 1)
2179 return this->delta_impl<R>(shape, scale);
2190 return -std::log(1.0 -
static_cast<Derived*
>(
this)->next_double()) * scale;
2202 typename detail::return_type<double, S>::type
2204 using R =
typename detail::return_type<double, S>::type;
2205 return this->exponential_impl<R>(shape, scale);
2212 template <
class R,
class S>
2215 return this->exponential_impl<R>(shape, scale);
2221 template <
class I, std::
size_t L>
2223 typename detail::return_type_fixed<double, L>::type
2225 using R =
typename detail::return_type_fixed<double, L>::type;
2226 return this->exponential_impl<R>(shape, scale);
2233 template <
class R,
class I, std::
size_t L>
2236 return this->exponential_impl<R>(shape, scale);
2247 return std::pow(1.0 -
static_cast<Derived*
>(
this)->next_double(), 1.0 / k);
2258 auto power(
const S& shape,
double k = 1) ->
typename detail::return_type<double, S>::type
2260 using R =
typename detail::return_type<double, S>::type;
2261 return this->power_impl<R>(shape, k);
2268 template <
class R,
class S>
2271 return this->power_impl<R>(shape, k);
2277 template <
class I, std::
size_t L>
2278 auto power(
const I (&shape)[L],
double k = 1) ->
2279 typename detail::return_type_fixed<double, L>::type
2281 using R =
typename detail::return_type_fixed<double, L>::type;
2282 return this->power_impl<R>(shape, k);
2289 template <
class R,
class I, std::
size_t L>
2290 R
power(
const I (&shape)[L],
double k = 1)
2292 return this->power_impl<R>(shape, k);
2302 double gamma(
double k = 1,
double scale = 1)
2305 return scale * boost::math::gamma_p_inv<double, double>(
2306 k,
static_cast<Derived*
>(
this)->next_double()
2309 return std::numeric_limits<double>::quiet_NaN();
2323 auto gamma(
const S& shape,
double k = 1,
double scale = 1) ->
2324 typename detail::return_type<double, S>::type
2326 using R =
typename detail::return_type<double, S>::type;
2327 return this->gamma_impl<R>(shape, k, scale);
2334 template <
class R,
class S>
2335 R
gamma(
const S& shape,
double k = 1,
double scale = 1)
2337 return this->gamma_impl<R>(shape, k, scale);
2343 template <
class I, std::
size_t L>
2344 auto gamma(
const I (&shape)[L],
double k = 1,
double scale = 1) ->
2345 typename detail::return_type_fixed<double, L>::type
2347 using R =
typename detail::return_type_fixed<double, L>::type;
2348 return this->gamma_impl<R>(shape, k, scale);
2355 template <
class R,
class I, std::
size_t L>
2356 R
gamma(
const I (&shape)[L],
double k = 1,
double scale = 1)
2358 return this->gamma_impl<R>(shape, k, scale);
2368 double pareto(
double k = 1,
double scale = 1)
2370 return scale * std::pow(1.0 -
static_cast<Derived*
>(
this)->next_double(), -1.0 / k);
2382 auto pareto(
const S& shape,
double k = 1,
double scale = 1) ->
2383 typename detail::return_type<double, S>::type
2385 using R =
typename detail::return_type<double, S>::type;
2386 return this->pareto_impl<R>(shape, k, scale);
2393 template <
class R,
class S>
2394 R
pareto(
const S& shape,
double k = 1,
double scale = 1)
2396 return this->pareto_impl<R>(shape, k, scale);
2402 template <
class I, std::
size_t L>
2403 auto pareto(
const I (&shape)[L],
double k = 1,
double scale = 1) ->
2404 typename detail::return_type_fixed<double, L>::type
2406 using R =
typename detail::return_type_fixed<double, L>::type;
2407 return this->pareto_impl<R>(shape, k, scale);
2414 template <
class R,
class I, std::
size_t L>
2415 R
pareto(
const I (&shape)[L],
double k = 1,
double scale = 1)
2417 return this->pareto_impl<R>(shape, k, scale);
2430 std::pow(-std::log(1.0 -
static_cast<Derived*
>(
this)->next_double()), 1.0 / k);
2442 auto weibull(
const S& shape,
double k = 1,
double scale = 1) ->
2443 typename detail::return_type<double, S>::type
2445 using R =
typename detail::return_type<double, S>::type;
2446 return this->weibull_impl<R>(shape, k, scale);
2453 template <
class R,
class S>
2454 R
weibull(
const S& shape,
double k = 1,
double scale = 1)
2456 return this->weibull_impl<R>(shape, k, scale);
2462 template <
class I, std::
size_t L>
2463 auto weibull(
const I (&shape)[L],
double k = 1,
double scale = 1) ->
2464 typename detail::return_type_fixed<double, L>::type
2466 using R =
typename detail::return_type_fixed<double, L>::type;
2467 return this->weibull_impl<R>(shape, k, scale);
2474 template <
class R,
class I, std::
size_t L>
2475 R
weibull(
const I (&shape)[L],
double k = 1,
double scale = 1)
2477 return this->weibull_impl<R>(shape, k, scale);
2487 double normal(
double mu = 0,
double sigma = 1)
2490 return mu + sigma * std::sqrt(2.0) *
2491 boost::math::erf_inv<double>(
2492 2.0 *
static_cast<Derived*
>(
this)->next_positive_double() - 1.0
2495 return std::numeric_limits<double>::quiet_NaN();
2508 auto normal(
const S& shape,
double mu = 0,
double sigma = 1) ->
2509 typename detail::return_type<double, S>::type
2511 using R =
typename detail::return_type<double, S>::type;
2512 return this->normal_impl<R>(shape, mu, sigma);
2519 template <
class R,
class S>
2520 R
normal(
const S& shape,
double mu = 0,
double sigma = 1)
2522 return this->normal_impl<R>(shape, mu, sigma);
2528 template <
class I, std::
size_t L>
2529 auto normal(
const I (&shape)[L],
double mu = 0,
double sigma = 1) ->
2530 typename detail::return_type_fixed<double, L>::type
2532 using R =
typename detail::return_type_fixed<double, L>::type;
2533 return this->normal_impl<R>(shape, mu, sigma);
2540 template <
class R,
class I, std::
size_t L>
2541 R
normal(
const I (&shape)[L],
double mu = 0,
double sigma = 1)
2543 return this->normal_impl<R>(shape, mu, sigma);
2555 std::vector<double> parameters = std::vector<double>{},
2556 bool append_default = true
2559 if (append_default) {
2568 return this->
random() * parameters[0] + parameters[1];
2570 return this->
delta(parameters[0]) + parameters[1];
2572 return this->
exponential(parameters[0]) + parameters[1];
2574 return this->
power(parameters[0]) + parameters[1];
2576 return this->
pareto(parameters[0], parameters[1]) + parameters[2];
2578 return this->
weibull(parameters[0], parameters[1]) + parameters[2];
2580 return this->
gamma(parameters[0], parameters[1]) + parameters[2];
2582 return this->
normal(parameters[0], parameters[1]) + parameters[2];
2584 throw std::runtime_error(
"Unknown distribution");
2587 throw std::runtime_error(
"Unknown distribution");
2598 template <
class R,
class S>
2602 std::vector<double> parameters = std::vector<double>{},
2603 bool append_default = true
2606 if (append_default) {
2615 return this->random<R>(shape) * parameters[0] + parameters[1];
2617 return this->delta<R>(shape, parameters[0]) + parameters[1];
2619 return this->exponential<R>(shape, parameters[0]) + parameters[1];
2621 return this->power<R>(shape, parameters[0]) + parameters[1];
2623 return this->pareto<R>(shape, parameters[0], parameters[1]) + parameters[2];
2625 return this->weibull<R>(shape, parameters[0], parameters[1]) + parameters[2];
2627 return this->gamma<R>(shape, parameters[0], parameters[1]) + parameters[2];
2629 return this->normal<R>(shape, parameters[0], parameters[1]) + parameters[2];
2631 throw std::runtime_error(
"Unknown distribution");
2634 throw std::runtime_error(
"Unknown distribution");
2648 std::vector<double> parameters = std::vector<double>{},
2649 bool append_default = true
2652 if (append_default) {
2659 double m =
static_cast<double>(n);
2663 return this->
cumsum_random(n) * parameters[0] + m * parameters[1];
2665 return this->
cumsum_delta(n, parameters[0]) + m * parameters[1];
2669 return this->
cumsum_power(n, parameters[0]) + m * parameters[1];
2671 return this->
cumsum_pareto(n, parameters[0], parameters[1]) + m * parameters[2];
2673 return this->
cumsum_weibull(n, parameters[0], parameters[1]) + m * parameters[2];
2675 return this->
cumsum_gamma(n, parameters[0], parameters[1]) + m * parameters[2];
2677 return this->
cumsum_normal(n, parameters[0], parameters[1]) + m * parameters[2];
2679 throw std::runtime_error(
"Unknown distribution");
2682 throw std::runtime_error(
"Unknown distribution");
2686 void draw_list_double(
double* data,
size_t n)
2688 for (
size_t i = 0; i < n; ++i) {
2689 data[i] =
static_cast<Derived*
>(
this)->next_double();
2693 void draw_list_positive_double(
double* data,
size_t n)
2695 for (
size_t i = 0; i < n; ++i) {
2696 data[i] =
static_cast<Derived*
>(
this)->next_positive_double();
2700 void draw_list_uint32(uint32_t* data, uint32_t bound,
size_t n)
2702 for (
size_t i = 0; i < n; ++i) {
2703 data[i] =
static_cast<Derived*
>(
this)->next_uint32(bound);
2707 template <
class R,
class S>
2708 R positive_random_impl(
const S& shape)
2711 std::is_same<typename detail::allocate_return<R>::value_type,
double>::value,
2712 "Return value_type must be double"
2715 detail::allocate_return<R> ret(shape);
2716 this->draw_list_positive_double(ret.data(), ret.size());
2717 return std::move(ret.value);
2720 template <
class R,
class S>
2721 R random_impl(
const S& shape)
2724 std::is_same<typename detail::allocate_return<R>::value_type,
double>::value,
2725 "Return value_type must be double"
2728 detail::allocate_return<R> ret(shape);
2729 this->draw_list_double(ret.data(), ret.size());
2730 return std::move(ret.value);
2733 template <
class R,
class S,
typename T>
2734 R randint_impl(
const S& shape, T high)
2737 std::numeric_limits<typename detail::allocate_return<R>::value_type>::max() >=
2738 std::numeric_limits<T>::max(),
2739 "Return value_type must must be able to accommodate the bound"
2743 PRRNG_ASSERT(
static_cast<uint32_t
>(high) < std::numeric_limits<uint32_t>::max());
2745 detail::allocate_return<R> ret(shape);
2746 std::vector<uint32_t> tmp(ret.size());
2747 this->draw_list_uint32(&tmp.front(),
static_cast<uint32_t
>(high), ret.size());
2748 std::copy(tmp.begin(), tmp.end(), ret.data());
2749 return std::move(ret.value);
2752 template <
class R,
class S,
typename T,
typename U>
2753 R randint_impl(
const S& shape, T low, U high)
2756 std::numeric_limits<typename detail::allocate_return<R>::value_type>::min() >=
2757 std::numeric_limits<T>::min(),
2758 "Return value_type must must be able to accommodate the bound"
2762 std::numeric_limits<typename detail::allocate_return<R>::value_type>::max() >=
2763 std::numeric_limits<T>::max(),
2764 "Return value_type must must be able to accommodate the bound"
2768 std::numeric_limits<typename detail::allocate_return<R>::value_type>::min() >=
2769 std::numeric_limits<U>::min(),
2770 "Return value_type must must be able to accommodate the bound"
2774 std::numeric_limits<typename detail::allocate_return<R>::value_type>::max() >=
2775 std::numeric_limits<U>::max(),
2776 "Return value_type must must be able to accommodate the bound"
2780 PRRNG_ASSERT(
static_cast<uint32_t
>(high - low) < std::numeric_limits<uint32_t>::max());
2782 detail::allocate_return<R> ret(shape);
2783 std::vector<uint32_t> tmp(ret.size());
2784 this->draw_list_uint32(&tmp.front(),
static_cast<uint32_t
>(high - low), ret.size());
2785 std::copy(tmp.begin(), tmp.end(), ret.data());
2786 return ret.value + low;
2789 template <
class R,
class S>
2790 R delta_impl(
const S& shape,
double scale)
2792 detail::allocate_return<R> ret(shape);
2793 ret.value.fill(scale);
2794 return std::move(ret.value);
2797 template <
class R,
class S>
2798 R exponential_impl(
const S& shape,
double scale)
2800 R r = this->random_impl<R>(shape);
2801 return exponential_distribution(scale).quantile(r);
2804 template <
class R,
class S>
2805 R power_impl(
const S& shape,
double k)
2807 R r = this->random_impl<R>(shape);
2808 return power_distribution(k).quantile(r);
2811 template <
class R,
class S>
2812 R gamma_impl(
const S& shape,
double k,
double scale)
2814 R r = this->random_impl<R>(shape);
2815 return gamma_distribution(k, scale).quantile(r);
2818 template <
class R,
class S>
2819 R pareto_impl(
const S& shape,
double k,
double scale)
2821 R r = this->random_impl<R>(shape);
2822 return pareto_distribution(k, scale).quantile(r);
2825 template <
class R,
class S>
2826 R weibull_impl(
const S& shape,
double k,
double scale)
2828 R r = this->random_impl<R>(shape);
2829 return weibull_distribution(k, scale).quantile(r);
2832 template <
class R,
class S>
2833 R normal_impl(
const S& shape,
double mu,
double sigma)
2835 R r = this->positive_random_impl<R>(shape);
2836 return normal_distribution(mu, sigma).quantile(r);
2881 template <
typename T = u
int64_t,
typename S = u
int64_t>
2884 static_assert(
sizeof(uint64_t) >=
sizeof(T),
"Down-casting not allowed.");
2885 static_assert(
sizeof(uint64_t) >=
sizeof(S),
"Down-casting not allowed.");
2919 uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
2920 uint32_t rot = oldstate >> 59u;
2921 return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
2961 uint32_t threshold = (~bound + 1u) % bound;
2972 if (r >= threshold) {
3015 x.u = ((uint64_t)
next_uint32() << 20) | 0x3ff0000000000000ULL;
3031 x.u = ((uint64_t)
next_uint32() << 20) | 0x3ff0000000000000ULL;
3033 if (x.u == 0x3ff0000000000000ULL) {
3057 template <
typename R>
3061 std::numeric_limits<R>::max() >= std::numeric_limits<
decltype(
m_state)>::max(),
3062 "Down-casting not allowed."
3066 std::numeric_limits<R>::min() <= std::numeric_limits<
decltype(
m_state)>::min(),
3067 "Down-casting not allowed."
3070 return static_cast<R
>(
m_state);
3089 template <
typename R>
3093 std::numeric_limits<R>::max() >= std::numeric_limits<
decltype(
m_initstate)>::max(),
3094 "Down-casting not allowed."
3098 std::numeric_limits<R>::min() <= std::numeric_limits<
decltype(
m_initstate)>::min(),
3099 "Down-casting not allowed."
3121 template <
typename R>
3125 std::numeric_limits<R>::max() >= std::numeric_limits<
decltype(
m_initseq)>::max(),
3126 "Down-casting not allowed."
3130 std::numeric_limits<R>::min() <= std::numeric_limits<
decltype(
m_initseq)>::min(),
3131 "Down-casting not allowed."
3143 template <
typename T>
3146 static_assert(
sizeof(uint64_t) >=
sizeof(T),
"Down-casting not allowed.");
3158 uint64_t cur_plus =
m_inc;
3159 uint64_t cur_state = other.
m_state;
3160 uint64_t the_bit = 1u;
3163 while (
m_state != cur_state) {
3164 if ((
m_state & the_bit) != (cur_state & the_bit)) {
3165 cur_state = cur_state * cur_mult + cur_plus;
3170 cur_plus = (cur_mult + 1ULL) * cur_plus;
3171 cur_mult *= cur_mult;
3188 template <
typename R =
int64_t>
3191 static_assert(
sizeof(R) >=
sizeof(int64_t),
"Down-casting not allowed.");
3194#ifdef PRRNG_ENABLE_DEBUG
3195 bool u = std::is_unsigned<R>::value;
3199 return static_cast<R
>(r);
3217 typename R = int64_t,
3219 std::enable_if_t<std::is_integral<T>::value,
bool> =
true>
3222 static_assert(
sizeof(R) >=
sizeof(int64_t),
"Down-casting not allowed.");
3225 uint64_t cur_plus =
m_inc;
3226 uint64_t cur_state = other_state;
3227 uint64_t the_bit = 1u;
3230 while (
m_state != cur_state) {
3231 if ((
m_state & the_bit) != (cur_state & the_bit)) {
3232 cur_state = cur_state * cur_mult + cur_plus;
3237 cur_plus = (cur_mult + 1ULL) * cur_plus;
3238 cur_mult *= cur_mult;
3243#ifdef PRRNG_ENABLE_DEBUG
3244 bool u = std::is_unsigned<R>::value;
3248 return static_cast<R
>(r);
3263 template <
typename T>
3266 static_assert(
sizeof(int64_t) >=
sizeof(T),
"Down-casting not allowed.");
3268 int64_t delta_ =
static_cast<int64_t
>(
distance);
3271 uint64_t cur_plus =
m_inc;
3272 uint64_t acc_mult = 1u;
3273 uint64_t acc_plus = 0u;
3277 uint64_t
delta = (uint64_t)delta_;
3281 acc_mult *= cur_mult;
3282 acc_plus = acc_plus * cur_mult + cur_plus;
3284 cur_plus = (cur_mult + 1) * cur_plus;
3285 cur_mult *= cur_mult;
3340 template <
typename T = u
int64_t,
typename S = u
int64_t>
3347 static_assert(
sizeof(uint64_t) >=
sizeof(T),
"Down-casting not allowed.");
3348 static_assert(
sizeof(uint64_t) >=
sizeof(S),
"Down-casting not allowed.");
3369 this->
advance(index - m_index);
3384 this->
advance(index - m_index);
3503template <
class Data>
3508 std::function<Data(
size_t)> m_draw;
3509 std::function<double(
size_t)> m_sum;
3513 std::array<double, 3> m_param;
3520 void auto_functions()
3522 m_extendible =
true;
3526 m_draw = [
this](
size_t n) -> Data {
3527 return m_gen.
random<Data>(std::array<size_t, 1>{n}) * m_param[0] + m_param[1];
3529 m_sum = [
this](
size_t n) ->
double {
3530 return m_gen.
cumsum_random(n) * m_param[0] +
static_cast<double>(n) * m_param[1];
3534 m_draw = [
this](
size_t n) -> Data {
3535 return m_gen.
delta<Data>(std::array<size_t, 1>{n}, m_param[0]) + m_param[1];
3537 m_sum = [
this](
size_t n) ->
double {
3538 return m_gen.
cumsum_delta(n, m_param[0]) +
static_cast<double>(n) * m_param[1];
3542 m_draw = [
this](
size_t n) -> Data {
3543 return m_gen.
exponential<Data>(std::array<size_t, 1>{n}, m_param[0]) + m_param[1];
3545 m_sum = [
this](
size_t n) ->
double {
3547 static_cast<double>(n) * m_param[1];
3551 m_draw = [
this](
size_t n) -> Data {
3552 return m_gen.
power<Data>(std::array<size_t, 1>{n}, m_param[0]) + m_param[1];
3554 m_sum = [
this](
size_t n) ->
double {
3555 return m_gen.
cumsum_power(n, m_param[0]) +
static_cast<double>(n) * m_param[1];
3559 m_draw = [
this](
size_t n) -> Data {
3560 return m_gen.
gamma<Data>(std::array<size_t, 1>{n}, m_param[0], m_param[1]) +
3563 m_sum = [
this](
size_t n) ->
double {
3565 static_cast<double>(n) * m_param[2];
3569 m_draw = [
this](
size_t n) -> Data {
3570 return m_gen.
pareto<Data>(std::array<size_t, 1>{n}, m_param[0], m_param[1]) +
3573 m_sum = [
this](
size_t n) ->
double {
3575 static_cast<double>(n) * m_param[2];
3579 m_draw = [
this](
size_t n) -> Data {
3580 return m_gen.
weibull<Data>(std::array<size_t, 1>{n}, m_param[0], m_param[1]) +
3583 m_sum = [
this](
size_t n) ->
double {
3585 static_cast<double>(n) * m_param[2];
3589 m_draw = [
this](
size_t n) -> Data {
3590 return m_gen.
normal<Data>(std::array<size_t, 1>{n}, m_param[0], m_param[1]) +
3593 m_sum = [
this](
size_t n) ->
double {
3595 static_cast<double>(n) * m_param[2];
3599 m_extendible =
false;
3612 m_data = other.m_data;
3613 m_gen = other.m_gen;
3614 m_align = other.m_align;
3615 m_distro = other.m_distro;
3616 m_param = other.m_param;
3617 m_start = other.m_start;
3619 this->auto_functions();
3647 template <
class R,
typename T = u
int64_t,
typename S = u
int64_t>
3653 const std::vector<double>& parameters = std::vector<double>{},
3657 m_data = xt::empty<typename Data::value_type>(
shape);
3659 m_start = m_gen.
index();
3660 m_i =
static_cast<ptrdiff_t
>(m_data.size());
3663 std::copy(parameters.begin(), parameters.end(), m_param.begin());
3664 this->auto_functions();
3666 if (!m_extendible) {
3670 using E =
decltype(m_draw(
size_t{}));
3671 E extra = m_draw(m_data.size());
3672 m_gen.
drawn(m_data.size());
3673 std::partial_sum(extra.begin(), extra.end(), m_data.begin());
3683 std::function<Data(
size_t)> get_chunk,
3684 std::function<
double(
size_t)> get_cumsum,
3685 bool uses_generator =
true
3688 m_extendible =
true;
3693 using E =
decltype(m_draw(
size_t{}));
3694 E extra = m_draw(m_data.size());
3695 m_gen.
drawn(m_data.size());
3696 std::partial_sum(extra.begin(), extra.end(), m_data.begin());
3704 this->copy_from(other);
3712 this->copy_from(other);
3721 return m_extendible;
3739 return m_data.shape();
3748 return m_data.size();
3758 xt::noalias(m_data) += value;
3769 xt::noalias(m_data) -= value;
3791 xt::noalias(m_data) =
data;
3828 return m_start + m_i;
3868 return m_data[m_i + 1];
3886 void restore(uint64_t state,
double value, ptrdiff_t index)
3892 using E =
decltype(m_draw(
size_t{}));
3893 E extra = m_draw(m_data.size());
3894 m_gen.
drawn(m_data.size());
3895 extra.front() += value - extra.front();
3896 std::partial_sum(extra.begin(), extra.end(), m_data.begin());
3906 return target >= m_data.front() && target <= m_data.back();
3916 m_i =
static_cast<ptrdiff_t
>(m_data.size());
3917 detail::prev(m_gen, m_draw, margin, m_data.data(), m_data.size(), &m_start);
3927 m_i =
static_cast<ptrdiff_t
>(m_data.size());
3928 detail::next(m_gen, m_draw, margin, m_data.data(), m_data.size(), &m_start);
3947 if (!m_extendible) {
3949 m_i = iterator::lower_bound(m_data.begin(), m_data.end(), target, m_i);
3954 m_gen, m_draw, m_sum, m_align, m_data.data(), m_data.size(), &m_start, &m_i, target
3966template <
class Derived,
class M>
4024 return std::inner_product(index.cbegin(), index.cend(),
m_strides.cbegin(), 0);
4039 for (
size_t i = 0; i <
m_strides.size(); ++i) {
4055 auto random(
const S& ishape) ->
typename detail::composite_return_type<double, M, S>::type
4057 using R =
typename detail::composite_return_type<double, M, S>::type;
4058 return this->random_impl<R>(ishape);
4065 template <
class R,
class S>
4068 return this->random_impl<R>(ishape);
4074 template <
class I, std::
size_t L>
4076 typename detail::composite_return_type<double, M, std::array<size_t, L>>::type
4078 using R =
typename detail::composite_return_type<double, M, std::array<size_t, L>>::type;
4079 return this->random_impl<R>(detail::to_array(ishape));
4086 template <
class R,
class I, std::
size_t L>
4089 return this->random_impl<R>(detail::to_array(ishape));
4099 template <
class S,
typename T>
4100 auto randint(
const S& ishape, T high) ->
typename detail::composite_return_type<T, M, S>::type
4102 using R =
typename detail::composite_return_type<T, M, S>::type;
4103 return this->randint_impl<R>(ishape, high);
4110 template <
class R,
class S,
typename T>
4113 return this->randint_impl<R>(ishape, high);
4119 template <
class I, std::
size_t L,
typename T>
4121 typename detail::composite_return_type<T, M, std::array<size_t, L>>::type
4123 using R =
typename detail::composite_return_type<T, M, std::array<size_t, L>>::type;
4124 return this->randint_impl<R>(detail::to_array(ishape), high);
4131 template <
class R,
class I, std::
size_t L,
typename T>
4134 return this->randint_impl<R>(detail::to_array(ishape), high);
4145 template <
class S,
typename T,
typename U>
4147 typename detail::composite_return_type<T, M, S>::type
4149 using R =
typename detail::composite_return_type<T, M, S>::type;
4150 return this->randint_impl<R>(ishape, low, high);
4157 template <
class R,
class S,
typename T,
typename U>
4160 return this->randint_impl<R>(ishape, low, high);
4166 template <
class I, std::
size_t L,
typename T,
typename U>
4167 auto randint(
const I (&ishape)[L], T low, U high) ->
4168 typename detail::composite_return_type<T, M, std::array<size_t, L>>::type
4170 using R =
typename detail::composite_return_type<T, M, std::array<size_t, L>>::type;
4171 return this->randint_impl<R>(detail::to_array(ishape), low, high);
4178 template <
class R,
class I, std::
size_t L,
typename T,
typename U>
4181 return this->randint_impl<R>(detail::to_array(ishape), low, high);
4194 auto delta(
const S& ishape,
double scale = 1) ->
4195 typename detail::composite_return_type<double, M, S>::type
4197 using R =
typename detail::composite_return_type<double, M, S>::type;
4198 return this->delta_impl<R>(ishape, scale);
4205 template <
class R,
class S>
4206 R
delta(
const S& ishape,
double scale = 1)
4208 return this->delta_impl<R>(ishape, scale);
4214 template <
class I, std::
size_t L>
4215 auto delta(
const I (&ishape)[L],
double scale = 1) ->
4216 typename detail::composite_return_type<double, M, std::array<size_t, L>>::type
4218 using R =
typename detail::composite_return_type<double, M, std::array<size_t, L>>::type;
4219 return this->delta_impl<R>(detail::to_array(ishape), scale);
4226 template <
class R,
class I, std::
size_t L>
4227 R
delta(
const I (&ishape)[L],
double scale = 1)
4229 return this->delta_impl<R>(detail::to_array(ishape), scale);
4242 typename detail::composite_return_type<double, M, S>::type
4244 using R =
typename detail::composite_return_type<double, M, S>::type;
4245 return this->exponential_impl<R>(ishape, scale);
4252 template <
class R,
class S>
4255 return this->exponential_impl<R>(ishape, scale);
4261 template <
class I, std::
size_t L>
4263 typename detail::composite_return_type<double, M, std::array<size_t, L>>::type
4265 using R =
typename detail::composite_return_type<double, M, std::array<size_t, L>>::type;
4266 return this->exponential_impl<R>(detail::to_array(ishape), scale);
4273 template <
class R,
class I, std::
size_t L>
4276 return this->exponential_impl<R>(detail::to_array(ishape), scale);
4288 auto power(
const S& ishape,
double k = 1) ->
4289 typename detail::composite_return_type<double, M, S>::type
4291 using R =
typename detail::composite_return_type<double, M, S>::type;
4292 return this->power_impl<R>(ishape, k);
4299 template <
class R,
class S>
4302 return this->power_impl<R>(ishape, k);
4308 template <
class I, std::
size_t L>
4309 auto power(
const I (&ishape)[L],
double k = 1) ->
4310 typename detail::composite_return_type<double, M, std::array<size_t, L>>::type
4312 using R =
typename detail::composite_return_type<double, M, std::array<size_t, L>>::type;
4313 return this->power_impl<R>(detail::to_array(ishape), k);
4320 template <
class R,
class I, std::
size_t L>
4321 R
power(
const I (&ishape)[L],
double k = 1)
4323 return this->power_impl<R>(detail::to_array(ishape), k);
4338 auto gamma(
const S& ishape,
double k = 1,
double scale = 1) ->
4339 typename detail::composite_return_type<double, M, S>::type
4341 using R =
typename detail::composite_return_type<double, M, S>::type;
4342 return this->gamma_impl<R>(ishape, k, scale);
4349 template <
class R,
class S>
4350 R
gamma(
const S& ishape,
double k = 1,
double scale = 1)
4352 return this->gamma_impl<R>(ishape, k, scale);
4358 template <
class I, std::
size_t L>
4359 auto gamma(
const I (&ishape)[L],
double k = 1,
double scale = 1) ->
4360 typename detail::composite_return_type<double, M, std::array<size_t, L>>::type
4362 using R =
typename detail::composite_return_type<double, M, std::array<size_t, L>>::type;
4363 return this->gamma_impl<R>(detail::to_array(ishape), k, scale);
4370 template <
class R,
class I, std::
size_t L>
4371 R
gamma(
const I (&ishape)[L],
double k = 1,
double scale = 1)
4373 return this->gamma_impl<R>(detail::to_array(ishape), k, scale);
4386 auto pareto(
const S& ishape,
double k = 1,
double scale = 1) ->
4387 typename detail::composite_return_type<double, M, S>::type
4389 using R =
typename detail::composite_return_type<double, M, S>::type;
4390 return this->pareto_impl<R>(ishape, k, scale);
4397 template <
class R,
class S>
4398 R
pareto(
const S& ishape,
double k = 1,
double scale = 1)
4400 return this->pareto_impl<R>(ishape, k, scale);
4406 template <
class I, std::
size_t L>
4407 auto pareto(
const I (&ishape)[L],
double k = 1,
double scale = 1) ->
4408 typename detail::composite_return_type<double, M, std::array<size_t, L>>::type
4410 using R =
typename detail::composite_return_type<double, M, std::array<size_t, L>>::type;
4411 return this->pareto_impl<R>(detail::to_array(ishape), k, scale);
4418 template <
class R,
class I, std::
size_t L>
4419 R
pareto(
const I (&ishape)[L],
double k = 1,
double scale = 1)
4421 return this->pareto_impl<R>(detail::to_array(ishape), k, scale);
4441 auto weibull(
const S& ishape,
double k = 1,
double scale = 1) ->
4442 typename detail::composite_return_type<double, M, S>::type
4444 using R =
typename detail::composite_return_type<double, M, S>::type;
4445 return this->weibull_impl<R>(ishape, k, scale);
4452 template <
class R,
class S>
4453 R
weibull(
const S& ishape,
double k = 1,
double scale = 1)
4455 return this->weibull_impl<R>(ishape, k, scale);
4461 template <
class I, std::
size_t L>
4462 auto weibull(
const I (&ishape)[L],
double k = 1,
double scale = 1) ->
4463 typename detail::composite_return_type<double, M, std::array<size_t, L>>::type
4465 using R =
typename detail::composite_return_type<double, M, std::array<size_t, L>>::type;
4466 return this->weibull_impl<R>(detail::to_array(ishape), k, scale);
4473 template <
class R,
class I, std::
size_t L>
4474 R
weibull(
const I (&ishape)[L],
double k = 1,
double scale = 1)
4476 return this->weibull_impl<R>(detail::to_array(ishape), k, scale);
4498 auto normal(
const S& ishape,
double mu = 0,
double sigma = 1) ->
4499 typename detail::composite_return_type<double, M, S>::type
4501 using R =
typename detail::composite_return_type<double, M, S>::type;
4502 return this->normal_impl<R>(ishape, mu, sigma);
4509 template <
class R,
class S>
4510 R
normal(
const S& ishape,
double mu = 0,
double sigma = 1)
4512 return this->normal_impl<R>(ishape, mu, sigma);
4518 template <
class I, std::
size_t L>
4519 auto normal(
const I (&ishape)[L],
double mu = 0,
double sigma = 1) ->
4520 typename detail::composite_return_type<double, M, std::array<size_t, L>>::type
4522 using R =
typename detail::composite_return_type<double, M, std::array<size_t, L>>::type;
4523 return this->normal_impl<R>(detail::to_array(ishape), mu, sigma);
4530 template <
class R,
class I, std::
size_t L>
4531 R
normal(
const I (&ishape)[L],
double mu = 0,
double sigma = 1)
4533 return this->normal_impl<R>(detail::to_array(ishape), mu, sigma);
4544 using R =
typename detail::return_type<double, M>::type;
4545 R ret = R::from_shape(
m_shape);
4546 static_cast<Derived*
>(
this)->cumsum_random_impl(ret.data(), n.data());
4555 template <
class R,
class T>
4558 R ret = R::from_shape(
m_shape);
4559 static_cast<Derived*
>(
this)->cumsum_random_impl(ret.data(), n.data());
4571 auto cumsum_delta(
const T& n,
double scale = 1) ->
typename detail::return_type<double, M>::type
4573 using R =
typename detail::return_type<double, M>::type;
4574 R ret = R::from_shape(
m_shape);
4575 for (
size_t i = 0; i < ret.size(); ++i) {
4576 ret.flat(i) =
static_cast<double>(n.flat(i)) * scale;
4588 template <
class R,
class T>
4591 R ret = R::from_shape(
m_shape);
4592 for (
size_t i = 0; i < ret.size(); ++i) {
4593 ret.flat(i) =
static_cast<double>(n.flat(i)) * scale;
4607 typename detail::return_type<double, M>::type
4609 using R =
typename detail::return_type<double, M>::type;
4610 R ret = R::from_shape(
m_shape);
4611 static_cast<Derived*
>(
this)->cumsum_exponential_impl(ret.data(), n.data(), scale);
4622 template <
class R,
class T>
4625 R ret = R::from_shape(
m_shape);
4626 static_cast<Derived*
>(
this)->cumsum_exponential_impl(ret.data(), n.data(), scale);
4638 auto cumsum_power(
const T& n,
double k = 1) ->
typename detail::return_type<double, M>::type
4640 using R =
typename detail::return_type<double, M>::type;
4641 R ret = R::from_shape(
m_shape);
4642 static_cast<Derived*
>(
this)->cumsum_power_impl(ret.data(), n.data(), k);
4653 template <
class R,
class T>
4656 R ret = R::from_shape(
m_shape);
4657 static_cast<Derived*
>(
this)->cumsum_power_impl(ret.data(), n.data(), k);
4671 typename detail::return_type<double, M>::type
4673 using R =
typename detail::return_type<double, M>::type;
4674 R ret = R::from_shape(
m_shape);
4675 static_cast<Derived*
>(
this)->cumsum_gamma_impl(ret.data(), n.data(), k, scale);
4687 template <
class R,
class T>
4690 R ret = R::from_shape(
m_shape);
4691 static_cast<Derived*
>(
this)->cumsum_gamma_impl(ret.data(), n.data(), k, scale);
4705 typename detail::return_type<double, M>::type
4707 using R =
typename detail::return_type<double, M>::type;
4708 R ret = R::from_shape(
m_shape);
4709 static_cast<Derived*
>(
this)->cumsum_pareto_impl(ret.data(), n.data(), k, scale);
4721 template <
class R,
class T>
4724 R ret = R::from_shape(
m_shape);
4725 static_cast<Derived*
>(
this)->cumsum_pareto_impl(ret.data(), n.data(), k, scale);
4739 typename detail::return_type<double, M>::type
4741 using R =
typename detail::return_type<double, M>::type;
4742 R ret = R::from_shape(
m_shape);
4743 static_cast<Derived*
>(
this)->cumsum_weibull_impl(ret.data(), n.data(), k, scale);
4755 template <
class R,
class T>
4758 R ret = R::from_shape(
m_shape);
4759 static_cast<Derived*
>(
this)->cumsum_weibull_impl(ret.data(), n.data(), k, scale);
4773 typename detail::return_type<double, M>::type
4775 using R =
typename detail::return_type<double, M>::type;
4776 R ret = R::from_shape(
m_shape);
4777 static_cast<Derived*
>(
this)->cumsum_normal_impl(ret.data(), n.data(), mu, sigma);
4789 template <
class R,
class T>
4792 R ret = R::from_shape(
m_shape);
4793 static_cast<Derived*
>(
this)->cumsum_normal_impl(ret.data(), n.data(), mu, sigma);
4806 auto decide(
const P& p) ->
typename detail::return_type<bool, P>::type
4809 using R =
typename detail::return_type<bool, P>::type;
4810 R ret = R::from_shape(
m_shape);
4811 static_cast<Derived*
>(
this)->decide_impl(p.data(), ret.data());
4818 template <
class P,
class R>
4822 R ret = R::from_shape(
m_shape);
4823 static_cast<Derived*
>(
this)->decide_impl(p.data(), ret.data());
4835 template <
class P,
class R>
4839 std::is_same<typename R::value_type, bool>::value,
"Return value_type must be bool"
4844 static_cast<Derived*
>(
this)->decide_impl(p.data(), ret.data());
4856 template <
class P,
class T>
4857 auto decide_masked(
const P& p,
const T& mask) ->
typename detail::return_type<bool, P>::type
4861 using R =
typename detail::return_type<bool, P>::type;
4862 R ret = R::from_shape(
m_shape);
4863 static_cast<Derived*
>(
this)->decide_masked_impl(p.data(), mask.data(), ret.data());
4870 template <
class P,
class T,
class R>
4875 R ret = R::from_shape(
m_shape);
4876 static_cast<Derived*
>(
this)->decide_masked_impl(p.data(), mask.data(), ret.data());
4889 template <
class P,
class T,
class R>
4893 std::is_same<typename R::value_type, bool>::value,
"Return value_type must be bool"
4899 static_cast<Derived*
>(
this)->decide_masked_impl(p.data(), mask.data(), ret.data());
4903 template <
class R,
class S>
4904 R positive_random_impl(
const S& ishape)
4907 std::is_same<typename R::value_type, double>::value,
"Return value_type must be double"
4910 auto n = detail::size(ishape);
4911 R ret = R::from_shape(detail::concatenate<M, S>::two(
m_shape, ishape));
4912 static_cast<Derived*
>(
this)->draw_list_positive_double(&ret.front(), n);
4916 template <
class R,
class S>
4917 R random_impl(
const S& ishape)
4920 std::is_same<typename R::value_type, double>::value,
"Return value_type must be double"
4923 auto n = detail::size(ishape);
4924 R ret = R::from_shape(detail::concatenate<M, S>::two(
m_shape, ishape));
4925 static_cast<Derived*
>(
this)->draw_list_double(&ret.front(), n);
4929 template <
class R,
class S,
typename T>
4930 R randint_impl(
const S& ishape, T high)
4933 std::numeric_limits<typename R::value_type>::max() >= std::numeric_limits<T>::max(),
4934 "Return value_type must must be able to accommodate the bound"
4938 std::numeric_limits<T>::max() <= std::numeric_limits<uint32_t>::max(),
"Bound too large"
4941 auto n = detail::size(ishape);
4942 R ret = R::from_shape(detail::concatenate<M, S>::two(
m_shape, ishape));
4943 std::vector<uint32_t> tmp(ret.size());
4944 static_cast<Derived*
>(
this)->draw_list_uint32(&tmp.front(),
static_cast<uint32_t
>(high), n);
4945 std::copy(tmp.begin(), tmp.end(), ret.begin());
4949 template <
class R,
class S,
typename T,
typename U>
4950 R randint_impl(
const S& ishape, T low, U high)
4953 std::numeric_limits<typename R::value_type>::max() >= std::numeric_limits<T>::max(),
4954 "Return value_type must must be able to accommodate the bound"
4958 std::numeric_limits<typename R::value_type>::min() >= std::numeric_limits<T>::min(),
4959 "Return value_type must must be able to accommodate the bound"
4963 std::numeric_limits<typename R::value_type>::max() >= std::numeric_limits<U>::max(),
4964 "Return value_type must must be able to accommodate the bound"
4968 std::numeric_limits<typename R::value_type>::min() >= std::numeric_limits<U>::min(),
4969 "Return value_type must must be able to accommodate the bound"
4973 static_cast<uint32_t
>(std::numeric_limits<T>::max()) <
4974 std::numeric_limits<uint32_t>::max(),
4978 auto n = detail::size(ishape);
4979 R ret = R::from_shape(detail::concatenate<M, S>::two(
m_shape, ishape));
4980 std::vector<uint32_t> tmp(ret.size());
4981 static_cast<Derived*
>(
this)->draw_list_uint32(
4982 &tmp.front(),
static_cast<uint32_t
>(high - low), n
4984 std::copy(tmp.begin(), tmp.end(), ret.begin());
4988 template <
class R,
class S>
4989 R delta_impl(
const S& ishape,
double scale)
4991 R ret = R::from_shape(detail::concatenate<M, S>::two(
m_shape, ishape));
4996 template <
class R,
class S>
4997 R exponential_impl(
const S& ishape,
double scale)
4999 R r = this->random_impl<R>(ishape);
5000 return exponential_distribution(scale).quantile(r);
5003 template <
class R,
class S>
5004 R power_impl(
const S& ishape,
double k)
5006 R r = this->random_impl<R>(ishape);
5007 return power_distribution(k).quantile(r);
5010 template <
class R,
class S>
5011 R gamma_impl(
const S& ishape,
double k,
double scale)
5013 R r = this->random_impl<R>(ishape);
5014 return gamma_distribution(k, scale).quantile(r);
5017 template <
class R,
class S>
5018 R pareto_impl(
const S& ishape,
double k,
double scale)
5020 R r = this->random_impl<R>(ishape);
5021 return pareto_distribution(k, scale).quantile(r);
5024 template <
class R,
class S>
5025 R weibull_impl(
const S& ishape,
double k,
double scale)
5027 R r = this->random_impl<R>(ishape);
5028 return weibull_distribution(k, scale).quantile(r);
5031 template <
class R,
class S>
5032 R normal_impl(
const S& ishape,
double mu,
double sigma)
5034 R r = this->positive_random_impl<R>(ishape);
5035 return normal_distribution(mu, sigma).quantile(r);
5047template <
class Generator,
class Shape>
5085 template <
class T,
class U>
5109 template <
class... Args>
5112 return m_gen[this->get_item(0, 0, args...)];
5121 template <
class... Args>
5124 return m_gen[this->get_item(0, 0, args...)];
5169 const Generator&
flat(
size_t i)
const
5181 auto state() ->
typename detail::return_type<uint64_t, Shape>::type
5183 using R =
typename detail::return_type<uint64_t, Shape>::type;
5184 return this->state<R>();
5196 using value_type =
typename R::value_type;
5197 R ret = R::from_shape(
m_shape);
5200 ret.flat(i) =
m_gen[i].template state<value_type>();
5212 auto initstate() ->
typename detail::return_type<uint64_t, Shape>::type
5214 using R =
typename detail::return_type<uint64_t, Shape>::type;
5215 return this->initstate<R>();
5226 using value_type =
typename R::value_type;
5227 R ret = R::from_shape(
m_shape);
5230 ret.flat(i) =
m_gen[i].template initstate<value_type>();
5242 auto initseq() ->
typename detail::return_type<uint64_t, Shape>::type
5244 using R =
typename detail::return_type<uint64_t, Shape>::type;
5245 return this->initseq<R>();
5257 using value_type =
typename R::value_type;
5258 R ret = R::from_shape(
m_shape);
5261 ret.flat(i) =
m_gen[i].template initseq<value_type>();
5275 auto distance(
const T& arg) ->
typename detail::return_type<int64_t, Shape>::type
5277 using R =
typename detail::return_type<int64_t, Shape>::type;
5278 return this->distance<R, T>(arg);
5289 template <
class R,
class T>
5292 using value_type =
typename R::value_type;
5293 R ret = R::from_shape(
m_shape);
5296 ret.flat(i) =
m_gen[i].template distance<value_type>(arg.flat(i));
5314 m_gen[i].advance(arg.flat(i));
5331 m_gen[i].restore(arg.flat(i));
5344 ret[i] =
m_gen[i].next_double() < p[i];
5361 ret[i] =
m_gen[i].next_double() < p[i];
5374 ret[i] =
m_gen[i].cumsum_random(n[i]);
5387 ret[i] =
m_gen[i].cumsum_exponential(n[i], scale);
5400 ret[i] =
m_gen[i].cumsum_power(n[i], k);
5414 ret[i] =
m_gen[i].cumsum_gamma(n[i], k, scale);
5428 ret[i] =
m_gen[i].cumsum_pareto(n[i], k, scale);
5442 ret[i] =
m_gen[i].cumsum_weibull(n[i], k, scale);
5456 ret[i] =
m_gen[i].cumsum_normal(n[i], mu, sigma);
5470 for (
size_t j = 0; j < n; ++j) {
5471 data[i * n + j] =
m_gen[i].next_double();
5486 for (
size_t j = 0; j < n; ++j) {
5487 data[i * n + j] =
m_gen[i].next_positive_double();
5503 for (
size_t j = 0; j < n; ++j) {
5504 data[i * n + j] =
m_gen[i].next_uint32(bound);
5515 size_t get_item(
size_t sum,
size_t d, T arg)
5524 template <
class T,
class... Args>
5525 size_t get_item(
size_t sum,
size_t d, T arg, Args... args)
5527 return get_item(sum + arg *
m_strides[d], d + 1, args...);
5579 this->
init(initstate);
5589 template <
class T,
class U>
5627 static_assert(detail::check_fixed_rank<N, T>::value,
"Ranks to not match");
5628 this->
init(initstate);
5638 template <
class T,
class U>
5641 static_assert(detail::check_fixed_rank<N, T>::value,
"Ranks to not match");
5669 template <
class T,
class U>
5702 template <
class T,
class U>
5705 static_assert(detail::check_fixed_rank<N, T>::value,
"Ranks to not match");
5718template <
class T,
typename =
void>
5720 static auto get(
const T& initseq)
5722 return pcg32_array(initseq);
5726 static auto get(
const T& initseq,
const S& initstate)
5728 return pcg32_array(initseq, initstate);
5733struct auto_pcg32<T, typename std::enable_if_t<xt::has_fixed_rank_t<T>::value>> {
5734 static auto get(
const T& initseq)
5736 return pcg32_tensor<xt::get_rank<T>::value>(initseq);
5740 static auto get(
const T& initseq,
const S& initstate)
5742 return pcg32_tensor<xt::get_rank<T>::value>(initseq, initstate);
5747struct auto_pcg32<T, typename std::enable_if_t<std::is_integral<T>::value>> {
5748 static auto get(
const T& initseq)
5750 return pcg32(initseq);
5754 static auto get(
const T& initseq,
const S& initstate)
5756 return pcg32(initseq, initstate);
5771 return detail::auto_pcg32<T>::get(initstate);
5781template <
class T,
class S>
5784 return detail::auto_pcg32<T>::get(initstate, initseq);
5794template <
class Generator,
class Data,
class Index,
bool is_cumsum>
5796 static_assert(std::is_signed<typename Index::value_type>::value,
"Index must be signed");
5810 std::vector<std::function<xt::xtensor<double, 1>(
size_t)>>
m_draw;
5817 std::vector<std::function<double(
size_t)>>
m_sum;
5841 template <
class S,
class T,
class U>
5847 const std::vector<double>& parameters,
5851 PRRNG_ASSERT(xt::has_shape(initstate, initseq.shape()));
5855 m_gen = Generator(initstate, initseq);
5857 for (
size_t i = 0; i <
m_gen.size(); ++i) {
5861 std::vector<size_t> data_shape;
5862 data_shape.resize(initstate.dimension() + shape.size());
5863 std::copy(initstate.shape().begin(), initstate.shape().end(), data_shape.begin());
5864 std::copy(shape.begin(), shape.end(), data_shape.begin() + initstate.dimension());
5865 m_data = xt::empty<typename Data::value_type>(data_shape);
5868 m_start = xt::zeros<typename Index::value_type>(
m_gen.shape());
5869 m_i =
m_n * xt::ones<typename Index::value_type>(
m_gen.shape());
5872 std::copy(par.begin(), par.end(),
m_param.begin());
5876 using E =
decltype(
m_draw[
size_t{}](
size_t{}));
5880 for (
size_t i = 0; i <
m_gen.size(); ++i) {
5883 if constexpr (is_cumsum) {
5884 std::partial_sum(extra.begin(), extra.end(), &
m_data.flat(i *
m_n));
5887 std::copy(extra.begin(), extra.end(), &
m_data.flat(i *
m_n));
5898 using R =
decltype(
m_draw[
size_t{}](
size_t{}));
5903 if constexpr (is_cumsum) {
5910 for (
size_t i = 0; i <
m_gen.size(); ++i) {
5911 m_draw[i] = [
this, i](
size_t n) -> R {
5912 return m_gen[i].template random<R>(std::array<size_t, 1>{n}) *
m_param[0] +
5915 if constexpr (is_cumsum) {
5916 m_sum[i] = [
this, i](
size_t n) ->
double {
5918 static_cast<double>(n) *
m_param[1];
5924 for (
size_t i = 0; i <
m_gen.size(); ++i) {
5925 m_draw[i] = [
this, i](
size_t n) -> R {
5926 return m_gen[i].template delta<R>(std::array<size_t, 1>{n},
m_param[0]) +
5929 if constexpr (is_cumsum) {
5930 m_sum[i] = [
this, i](
size_t n) ->
double {
5932 static_cast<double>(n) *
m_param[1];
5938 for (
size_t i = 0; i <
m_gen.size(); ++i) {
5939 m_draw[i] = [
this, i](
size_t n) -> R {
5940 return m_gen[i].template exponential<R>(std::array<size_t, 1>{n},
m_param[0]) +
5943 if constexpr (is_cumsum) {
5944 m_sum[i] = [
this, i](
size_t n) ->
double {
5946 static_cast<double>(n) *
m_param[1];
5952 for (
size_t i = 0; i <
m_gen.size(); ++i) {
5953 m_draw[i] = [
this, i](
size_t n) -> R {
5954 return m_gen[i].template power<R>(std::array<size_t, 1>{n},
m_param[0]) +
5957 if constexpr (is_cumsum) {
5958 m_sum[i] = [
this, i](
size_t n) ->
double {
5960 static_cast<double>(n) *
m_param[1];
5966 for (
size_t i = 0; i <
m_gen.size(); ++i) {
5967 m_draw[i] = [
this, i](
size_t n) -> R {
5968 return m_gen[i].template gamma<R>(
5973 if constexpr (is_cumsum) {
5974 m_sum[i] = [
this, i](
size_t n) ->
double {
5976 static_cast<double>(n) *
m_param[2];
5982 for (
size_t i = 0; i <
m_gen.size(); ++i) {
5983 m_draw[i] = [
this, i](
size_t n) -> R {
5984 return m_gen[i].template pareto<R>(
5989 if constexpr (is_cumsum) {
5990 m_sum[i] = [
this, i](
size_t n) ->
double {
5992 static_cast<double>(n) *
m_param[2];
5998 for (
size_t i = 0; i <
m_gen.size(); ++i) {
5999 m_draw[i] = [
this, i](
size_t n) -> R {
6000 return m_gen[i].template weibull<R>(
6005 if constexpr (is_cumsum) {
6006 m_sum[i] = [
this, i](
size_t n) ->
double {
6008 static_cast<double>(n) *
m_param[2];
6014 for (
size_t i = 0; i <
m_gen.size(); ++i) {
6015 m_draw[i] = [
this, i](
size_t n) -> R {
6016 return m_gen[i].template normal<R>(
6021 if constexpr (is_cumsum) {
6022 m_sum[i] = [
this, i](
size_t n) ->
double {
6024 static_cast<double>(n) *
m_param[2];
6080 xt::noalias(
m_data) += values;
6091 xt::noalias(
m_data) -= values;
6169 for (
size_t i = 0; i <
m_gen.size(); ++i) {
6170 if constexpr (!is_cumsum) {
6171 detail::chunk_align_at(
6182 detail::cumsum_align_at(
6222 using value_type =
typename R::value_type;
6224 for (
size_t i = 0; i <
m_gen.size(); ++i) {
6225 ret.flat(i) =
static_cast<value_type
>(
m_data.flat(i *
m_n +
m_i.flat(i)));
6237 using value_type =
typename R::value_type;
6239 for (
size_t i = 0; i <
m_gen.size(); ++i) {
6240 ret.flat(i) =
static_cast<value_type
>(
m_data.flat(i *
m_n +
m_i.flat(i) + 1));
6250 R ret = R::from_shape(
m_gen.shape());
6261 R ret = R::from_shape(
m_gen.shape());
6269 template <
class R,
class T>
6274 using value_type =
typename R::value_type;
6275 R ret = R::from_shape(
m_gen.shape());
6277 for (
size_t i = 0; i <
m_gen.size(); ++i) {
6278 ret.flat(i) =
static_cast<value_type
>(
m_gen[i].state_at(index.flat(i)));
6288template <
class Generator,
class Data,
class Index>
6311 template <
class S,
class T>
6318 for (
size_t i = 0; i <
m_gen.size(); ++i) {
6319 m_gen[i].set_index(index.flat(i));
6320 m_gen[i].restore(state.flat(i));
6322 using E =
decltype(
m_draw[i](
size_t{}));
6325 std::copy(extra.begin(), extra.end(), &
m_data.flat(i *
m_n));
6342template <
class Generator,
class Data,
class Index>
6371 inplace::lower_bound(
m_data, target,
m_i);
6375 for (
size_t i = 0; i <
m_gen.size(); ++i) {
6402 m_i.flat(i) = iterator::lower_bound(
6424 template <
class S,
class V,
class T>
6425 void restore(
const S& state,
const V& value,
const T& index)
6432 for (
size_t i = 0; i <
m_gen.size(); ++i) {
6433 m_gen[i].set_index(index.flat(i));
6434 m_gen[i].restore(state.flat(i));
6436 using E =
decltype(
m_draw[i](
size_t{}));
6439 extra.front() += value.flat(i) - extra.front();
6440 std::partial_sum(extra.begin(), extra.end(), &
m_data.flat(i *
m_n));
6452 for (
size_t i = 0; i <
m_gen.size(); ++i) {
6453 if (target.flat(i) <
m_data.flat(i *
m_n) ||
6454 target.flat(i) >
m_data.flat((i + 1) *
m_n - 1)) {
6467template <
class Data,
class Index>
6475 template <
class S,
class T,
class U>
6481 const std::vector<double>& parameters,
6493template <
class Data,
class Index,
size_t N>
6501 template <
class S,
class T,
class U>
6507 const std::vector<double>& parameters,
6527template <
class Data,
class Index>
6539 template <
class S,
class T,
class U>
6545 const std::vector<double>& parameters,
6566template <
class Data,
class Index,
size_t N>
6574 template <
class S,
class T,
class U>
6580 const std::vector<double>& parameters,
Base class of an array of pseudorandom number generators.
R cumsum_weibull(const T &n, double k=1, double scale=1)
Per generator, return the result of the cumulative sum of n random numbers, distributed according to ...
R cumsum_exponential(const T &n, double scale=1)
Per generator, return the result of the cumulative sum of n random numbers, distributed according to ...
auto normal(const S &ishape, double mu=0, double sigma=1) -> typename detail::composite_return_type< double, M, S >::type
Per generator, generate an nd-array of random numbers distributed according to a normal distribution.
auto random(const I(&ishape)[L]) -> typename detail::composite_return_type< double, M, std::array< size_t, L > >::type
Per generator, generate an nd-array of random numbers .
R randint(const I(&ishape)[L], T low, U high)
Per generator, generate an nd-array of random integers .
auto cumsum_pareto(const T &n, double k=1, double scale=1) -> typename detail::return_type< double, M >::type
Per generator, return the result of the cumulative sum of n random numbers, distributed according to ...
auto decide_masked(const P &p, const T &mask) -> typename detail::return_type< bool, P >::type
Decide based on probability per generator.
R cumsum_normal(const T &n, double mu=0, double sigma=1)
Per generator, return the result of the cumulative sum of n random numbers, distributed according to ...
auto weibull(const I(&ishape)[L], double k=1, double scale=1) -> typename detail::composite_return_type< double, M, std::array< size_t, L > >::type
Per generator, generate an nd-array of random numbers distributed according to a Weibull distribution...
R randint(const I(&ishape)[L], T high)
Per generator, generate an nd-array of random integers .
M shape_type
Type of the shape and strides lists.
R random(const S &ishape)
Per generator, generate an nd-array of random numbers .
auto randint(const I(&ishape)[L], T high) -> typename detail::composite_return_type< T, M, std::array< size_t, L > >::type
Per generator, generate an nd-array of random integers .
bool inbounds(const T &index) const
Check if an index is in bounds (and of the correct rank).
auto cumsum_power(const T &n, double k=1) -> typename detail::return_type< double, M >::type
Per generator, return the result of the cumulative sum of n random numbers, distributed according to ...
R power(const S &ishape, double k=1)
Per generator, generate an nd-array of random numbers distributed according to an power distribution.
R pareto(const I(&ishape)[L], double k=1, double scale=1)
Per generator, generate an nd-array of random numbers distributed according to a Pareto distribution.
void decide_masked(const P &p, const T &mask, R &ret)
Decide based on probability per generator.
R decide(const P &p)
Decide based on probability per generator.
R exponential(const S &ishape, double scale=1)
Per generator, generate an nd-array of random numbers distributed according to an exponential distrib...
R cumsum_random(const T &n)
Per generator, return the result of the cumulative sum of n random numbers.
auto normal(const I(&ishape)[L], double mu=0, double sigma=1) -> typename detail::composite_return_type< double, M, std::array< size_t, L > >::type
Per generator, generate an nd-array of random numbers distributed according to a normal distribution.
auto cumsum_weibull(const T &n, double k=1, double scale=1) -> typename detail::return_type< double, M >::type
Per generator, return the result of the cumulative sum of n random numbers, distributed according to ...
auto weibull(const S &ishape, double k=1, double scale=1) -> typename detail::composite_return_type< double, M, S >::type
Per generator, generate an nd-array of random numbers distributed according to a Weibull distribution...
R exponential(const I(&ishape)[L], double scale=1)
Per generator, generate an nd-array of random numbers distributed according to an exponential distrib...
R randint(const S &ishape, T high)
Per generator, generate an nd-array of random integers .
auto shape(T axis) const
Return the shape of the array of generators along a specific axis.
auto exponential(const S &ishape, double scale=1) -> typename detail::composite_return_type< double, M, S >::type
Per generator, generate an nd-array of random numbers distributed according to an exponential distrib...
R cumsum_delta(const T &n, double scale=1)
Per generator, return the result of the cumulative sum of n random numbers, distributed according to ...
auto cumsum_normal(const T &n, double mu=0, double sigma=1) -> typename detail::return_type< double, M >::type
Per generator, return the result of the cumulative sum of n random numbers, distributed according to ...
R random(const I(&ishape)[L])
Per generator, generate an nd-array of random numbers .
auto pareto(const S &ishape, double k=1, double scale=1) -> typename detail::composite_return_type< double, M, S >::type
Per generator, generate an nd-array of random numbers distributed according to a Pareto distribution.
auto delta(const I(&ishape)[L], double scale=1) -> typename detail::composite_return_type< double, M, std::array< size_t, L > >::type
Per generator, generate an nd-array of numbers that are delta distribution.
auto randint(const S &ishape, T low, U high) -> typename detail::composite_return_type< T, M, S >::type
Per generator, generate an nd-array of random integers .
auto cumsum_exponential(const T &n, double scale=1) -> typename detail::return_type< double, M >::type
Per generator, return the result of the cumulative sum of n random numbers, distributed according to ...
typename M::value_type size_type
Type of sizes.
R randint(const S &ishape, T low, U high)
Per generator, generate an nd-array of random integers .
R weibull(const S &ishape, double k=1, double scale=1)
Per generator, generate an nd-array of random numbers distributed according to a Weibull distribution...
R gamma(const I(&ishape)[L], double k=1, double scale=1)
Per generator, generate an nd-array of random numbers distributed according to a Gamma distribution.
const shape_type & strides() const
Return the strides of the array of generators.
R decide_masked(const P &p, const T &mask)
Decide based on probability per generator.
size_type size() const
Return the size of the array of generators.
shape_type m_strides
The strides of the array of generators.
auto randint(const S &ishape, T high) -> typename detail::composite_return_type< T, M, S >::type
Per generator, generate an nd-array of random integers .
R weibull(const I(&ishape)[L], double k=1, double scale=1)
Per generator, generate an nd-array of random numbers distributed according to a Weibull distribution...
auto power(const S &ishape, double k=1) -> typename detail::composite_return_type< double, M, S >::type
Per generator, generate an nd-array of random numbers distributed according to an power distribution.
const shape_type & shape() const
Return the shape of the array of generators.
R cumsum_power(const T &n, double k=1)
Per generator, return the result of the cumulative sum of n random numbers, distributed according to ...
auto cumsum_random(const T &n) -> typename detail::return_type< double, M >::type
Per generator, return the result of the cumulative sum of n random numbers.
auto delta(const S &ishape, double scale=1) -> typename detail::composite_return_type< double, M, S >::type
Per generator, generate an nd-array of numbers that are delta distribution.
auto gamma(const I(&ishape)[L], double k=1, double scale=1) -> typename detail::composite_return_type< double, M, std::array< size_t, L > >::type
Per generator, generate an nd-array of random numbers distributed according to a Gamma distribution.
R gamma(const S &ishape, double k=1, double scale=1)
Per generator, generate an nd-array of random numbers distributed according to a Gamma distribution.
R delta(const S &ishape, double scale=1)
Per generator, generate an nd-array of numbers that are delta distribution.
auto flat_index(const T &index) const
Return a flat index based on an array index specified as a list.
R cumsum_pareto(const T &n, double k=1, double scale=1)
Per generator, return the result of the cumulative sum of n random numbers, distributed according to ...
R cumsum_gamma(const T &n, double k=1, double scale=1)
Per generator, return the result of the cumulative sum of n random numbers, distributed according to ...
R normal(const S &ishape, double mu=0, double sigma=1)
Per generator, generate an nd-array of random numbers distributed according to a normal distribution.
size_type m_size
See size().
R delta(const I(&ishape)[L], double scale=1)
Per generator, generate an nd-array of numbers that are delta distribution.
R normal(const I(&ishape)[L], double mu=0, double sigma=1)
Per generator, generate an nd-array of random numbers distributed according to a normal distribution.
auto exponential(const I(&ishape)[L], double scale=1) -> typename detail::composite_return_type< double, M, std::array< size_t, L > >::type
Per generator, generate an nd-array of random numbers distributed according to an exponential distrib...
auto random(const S &ishape) -> typename detail::composite_return_type< double, M, S >::type
Per generator, generate an nd-array of random numbers .
shape_type m_shape
See shape().
auto pareto(const I(&ishape)[L], double k=1, double scale=1) -> typename detail::composite_return_type< double, M, std::array< size_t, L > >::type
Per generator, generate an nd-array of random numbers distributed according to a Pareto distribution.
void decide(const P &p, R &ret)
Decide based on probability per generator.
auto decide(const P &p) -> typename detail::return_type< bool, P >::type
Decide based on probability per generator.
auto cumsum_delta(const T &n, double scale=1) -> typename detail::return_type< double, M >::type
Per generator, return the result of the cumulative sum of n random numbers, distributed according to ...
auto power(const I(&ishape)[L], double k=1) -> typename detail::composite_return_type< double, M, std::array< size_t, L > >::type
Per generator, generate an nd-array of random numbers distributed according to an power distribution.
R power(const I(&ishape)[L], double k=1)
Per generator, generate an nd-array of random numbers distributed according to an power distribution.
auto cumsum_gamma(const T &n, double k=1, double scale=1) -> typename detail::return_type< double, M >::type
Per generator, return the result of the cumulative sum of n random numbers, distributed according to ...
auto gamma(const S &ishape, double k=1, double scale=1) -> typename detail::composite_return_type< double, M, S >::type
Per generator, generate an nd-array of random numbers distributed according to a Gamma distribution.
R pareto(const S &ishape, double k=1, double scale=1)
Per generator, generate an nd-array of random numbers distributed according to a Pareto distribution.
auto randint(const I(&ishape)[L], T low, U high) -> typename detail::composite_return_type< T, M, std::array< size_t, L > >::type
Per generator, generate an nd-array of random integers .
Base class of the pseudorandom number generators providing common methods.
R pareto(const S &shape, double k=1, double scale=1)
Generate an nd-array of random numbers distributed according to a Pareto distribution.
R randint(const S &shape, T high)
Generate an nd-array of random integers .
R random(const S &shape)
Generate an nd-array of random numbers .
R randint(const I(&shape)[L], T high)
Generate an nd-array of random integers .
void decide(const P &p, R &ret)
Decide based on probability per value.
double cumsum_power(size_t n, double k=1)
Result of the cumulative sum of n random numbers, distributed according to a power distribution,...
auto randint(const I(&shape)[L], T low, U high) -> typename detail::return_type_fixed< T, L >::type
Generate an nd-array of random integers .
auto pareto(const S &shape, double k=1, double scale=1) -> typename detail::return_type< double, S >::type
Generate an nd-array of random numbers distributed according to a Pareto distribution.
double exponential(double scale=1)
Return a random number distributed according to an exponential distribution.
R random(const I(&shape)[L])
Generate an nd-array of random numbers .
auto normal(const I(&shape)[L], double mu=0, double sigma=1) -> typename detail::return_type_fixed< double, L >::type
Generate an nd-array of random numbers distributed according to a normal distribution.
double normal(double mu=0, double sigma=1)
Return a random number distributed according to a normal distribution.
double pareto(double k=1, double scale=1)
Return a random number distributed according to a Pareto distribution.
double cumsum_exponential(size_t n, double scale=1)
Result of the cumulative sum of n random numbers, distributed according to an exponential distributio...
auto power(const I(&shape)[L], double k=1) -> typename detail::return_type_fixed< double, L >::type
Generate an nd-array of random numbers distributed according to an power distribution.
R gamma(const I(&shape)[L], double k=1, double scale=1)
Generate an nd-array of random numbers distributed according to a Gamma distribution.
auto delta(const S &shape, double scale=1) -> typename detail::return_type< double, S >::type
Generate an nd-array of numbers that are delta distribution.
R gamma(const S &shape, double k=1, double scale=1)
Generate an nd-array of random numbers distributed according to a Gamma distribution.
T randint(T high)
Generate a random integer .
auto exponential(const I(&shape)[L], double scale=1) -> typename detail::return_type_fixed< double, L >::type
Generate an nd-array of random numbers distributed according to an exponential distribution.
auto randint(const I(&shape)[L], T high) -> typename detail::return_type_fixed< T, L >::type
Generate an nd-array of random integers .
auto decide(const P &p) -> typename detail::return_type< bool, P >::type
Decide based on probability per value.
R delta(const I(&shape)[L], double scale=1)
Generate an nd-array of numbers that are delta distribution.
auto random(const S &shape) -> typename detail::return_type< double, S >::type
Generate an nd-array of random numbers .
R exponential(const I(&shape)[L], double scale=1)
Generate an nd-array of random numbers distributed according to an exponential distribution.
auto random(const I(&shape)[L]) -> typename detail::return_type_fixed< double, L >::type
Generate an nd-array of random numbers .
double cumsum(size_t n, enum prrng::distribution distribution, std::vector< double > parameters=std::vector< double >{}, bool append_default=true)
Get the cumulative sum of n random numbers according to some distribution.
R exponential(const S &shape, double scale=1)
Generate an nd-array of random numbers distributed according to an exponential distribution.
R draw(const S &shape, enum prrng::distribution distribution, std::vector< double > parameters=std::vector< double >{}, bool append_default=true)
Get an nd-array of random numbers according to some distribution.
auto gamma(const S &shape, double k=1, double scale=1) -> typename detail::return_type< double, S >::type
Generate an nd-array of random numbers distributed according to a Gamma distribution.
R delta(const S &shape, double scale=1)
Generate an nd-array of numbers that are delta distribution.
double cumsum_random(size_t n)
Result of the cumulative sum of n random numbers.
R power(const I(&shape)[L], double k=1)
Generate an nd-array of random numbers distributed according to an power distribution.
auto weibull(const I(&shape)[L], double k=1, double scale=1) -> typename detail::return_type_fixed< double, L >::type
Generate an nd-array of random numbers distributed according to a Weibull distribution.
R randint(const S &shape, T low, U high)
Generate an nd-array of random integers .
auto weibull(const S &shape, double k=1, double scale=1) -> typename detail::return_type< double, S >::type
Generate an nd-array of random numbers distributed according to a Weibull distribution.
auto normal(const S &shape, double mu=0, double sigma=1) -> typename detail::return_type< double, S >::type
Generate an nd-array of random numbers distributed according to a normal distribution.
double cumsum_pareto(size_t n, double k=1, double scale=1)
Result of the cumulative sum of n random numbers, distributed according to a Pareto distribution,...
R power(const S &shape, double k=1)
Generate an nd-array of random numbers distributed according to an power distribution.
R weibull(const I(&shape)[L], double k=1, double scale=1)
Generate an nd-array of random numbers distributed according to a Weibull distribution.
auto randint(const S &shape, T low, U high) -> typename detail::return_type< T, S >::type
Generate an nd-array of random integers .
double random()
Generate a random number .
R pareto(const I(&shape)[L], double k=1, double scale=1)
Generate an nd-array of random numbers distributed according to a Pareto distribution.
auto gamma(const I(&shape)[L], double k=1, double scale=1) -> typename detail::return_type_fixed< double, L >::type
Generate an nd-array of random numbers distributed according to a Gamma distribution.
R randint(const I(&shape)[L], T low, U high)
Generate an nd-array of random integers .
auto delta(const I(&shape)[L], double scale=1) -> typename detail::return_type_fixed< double, L >::type
Generate an nd-array of numbers that are delta distribution.
void shuffle(Iterator begin, Iterator end)
Draw uniformly distributed permutation and permute the given STL container.
double gamma(double k=1, double scale=1)
Return a random number distributed according to a Gamma distribution.
R weibull(const S &shape, double k=1, double scale=1)
Generate an nd-array of random numbers distributed according to a Weibull distribution.
R decide_masked(const P &p, const T &mask)
Decide based on probability per value.
R normal(const I(&shape)[L], double mu=0, double sigma=1)
Generate an nd-array of random numbers distributed according to a normal distribution.
auto pareto(const I(&shape)[L], double k=1, double scale=1) -> typename detail::return_type_fixed< double, L >::type
Generate an nd-array of random numbers distributed according to a Pareto distribution.
void decide_masked(const P &p, const T &mask, R &ret)
Decide based on probability per value.
double cumsum_delta(size_t n, double scale=1)
Result of the cumulative sum of n 'random' numbers, distributed according to a delta distribution,...
double weibull(double k=1, double scale=1)
Return a random number distributed according to a Weibull distribution.
auto randint(const S &shape, T high) -> typename detail::return_type< T, S >::type
Generate an nd-array of random integers .
double draw(enum prrng::distribution distribution, std::vector< double > parameters=std::vector< double >{}, bool append_default=true)
Get a random number according to some distribution.
R normal(const S &shape, double mu=0, double sigma=1)
Generate an nd-array of random numbers distributed according to a normal distribution.
auto power(const S &shape, double k=1) -> typename detail::return_type< double, S >::type
Generate an nd-array of random numbers distributed according to an power distribution.
double cumsum_normal(size_t n, double mu=0, double sigma=1)
Result of the cumulative sum of n random numbers, distributed according to a normal distribution,...
double cumsum_weibull(size_t n, double k=1, double scale=1)
Result of the cumulative sum of n random numbers, distributed according to a weibull distribution,...
double power(double k=1)
Return a random number distributed according to an power distribution.
auto decide_masked(const P &p, const T &mask) -> typename detail::return_type< bool, P >::type
Decide based on probability per value.
double cumsum_gamma(size_t n, double k=1, double scale=1)
Result of the cumulative sum of n random numbers, distributed according to a gamma distribution,...
R decide(const P &p)
Decide based on probability per value.
double delta(double scale=1)
Return a number distributed according to a delta distribution.
auto exponential(const S &shape, double scale=1) -> typename detail::return_type< double, S >::type
Generate an nd-array of random numbers distributed according to an exponential distribution.
Exponential distribution.
T quantile(const T &p)
Quantile (the inverse of the cumulative density function).
T pdf(const T &x)
Probability density function.
exponential_distribution(double scale=1)
Constructor.
T cdf(const T &x)
Cumulative density function.
T cdf(const T &x)
Cumulative density function.
T quantile(const T &p)
Quantile (the inverse of the cumulative density function).
gamma_distribution(double k=1, double scale=1)
Constructor.
T pdf(const T &x)
Probability density function.
normal_distribution(double mu=0, double sigma=1)
Constructor.
T pdf(const T &x)
Probability density function.
T quantile(const T &p)
Quantile (the inverse of the cumulative density function).
T cdf(const T &x)
Cumulative density function.
T cdf(const T &x)
Cumulative density function.
T quantile(const T &p)
Quantile (the inverse of the cumulative density function).
pareto_distribution(double k=1, double scale=1)
Constructor.
T pdf(const T &x)
Probability density function.
Array of generators of which a chunk of random numbers is kept in memory.
void auto_functions()
Set draw function.
pcg32_arrayBase_chunkBase & operator-=(const T &values)
Subtract values from each chunk.
std::array< double, 3 > m_param
Distribution parameters.
void align_at(const Index &index)
Get the index random number, which index specified per generator.
const Index & start() const
Global index of the first element in the chunk.
Index index_at_align() const
Global index of target (the last time prrng::pcg32_cumsum::align() was called).
const Index & chunk_index_at_align() const
Index of target relative to the beginning of the chunk (the last time prrng::pcg32_cumsum::align() wa...
void left_of_align(R &ret) const
Return the value of the cumsum left of the target (the last time prrng::pcg32_cumsum::align() was cal...
void operator=(const pcg32_arrayBase_chunkBase &other)
Copy constructor.
bool m_extendible
Signal if the drawing functions are specified, implying that the chunk can be changed.
size_t m_n
Size of the chunk.
pcg32_arrayBase_chunkBase(const pcg32_arrayBase_chunkBase &other)
Copy constructor.
void set_data(const Data &data)
Overwrite the current chunk of the cumsum of random numbers.
void right_of_align(R &ret) const
Return the value of the cumsum right of the target (the last time prrng::pcg32_cumsum::align() was ca...
std::vector< std::function< double(size_t)> > m_sum
Function to get the cumsum of n random numbers starting from the curent state of the generator (used ...
void init(const S &shape, const T &initstate, const U &initseq, enum distribution distribution, const std::vector< double > ¶meters, const alignment &align=alignment())
Constructor.
pcg32_arrayBase_chunkBase & operator+=(const T &values)
Add values to each chunk.
void copy_from(const pcg32_arrayBase_chunkBase &other)
Copy constructor.
alignment m_align
alignment settings, see prrng::alignment().
Generator m_gen
Array of generators.
R right_of_align() const
Return the value of the cumsum right of the target (the last time prrng::pcg32_cumsum::align() was ca...
const Generator & generators() const
Reference to the underlying generators.
void set_start(const Index &index)
Set global index of the first element in the chunk.
const Data & data() const
The current chunk of the cumsum of random numbers.
Index m_start
Start index of the chunk.
R state_at(const T &index)
The current "state" of the generator.
std::vector< std::function< xt::xtensor< double, 1 >(size_t)> > m_draw
Function to draw the next chunk of n random numbers starting from the curent state of the generator.
Index m_i
Last known index of target in align.
typename Data::size_type size_type
Size type of the data container.
size_type chunk_size() const
Size of the chunk per generator.
R left_of_align() const
Return the value of the cumsum left of the target (the last time prrng::pcg32_cumsum::align() was cal...
bool is_extendible() const
true if the chunk is extendible.
distribution m_distro
Distribution name, see prrng::distribution().
Data m_data
Data container.
Array of generators of which a chunk of random numbers is kept in memory.
typename Data::value_type value_type
Value type of the data container.
void restore(const S &state, const T &index)
Restore the generator somewhere in the sequence.
typename Data::size_type size_type
Size type of the data container.
typename Data::size_type size_type
Size type of the data container.
void restore(const S &state, const V &value, const T &index)
Restore a specific state in the cumulative sum.
bool contains(const T &target) const
Check if the chunk contains a target.
void align(size_t i, double target)
Align the chunk to encompass a target value.
void align(const T &target)
Align the chunk to encompass a target value.
Base class, see pcg32_array for description.
Generator & flat(size_t i)
Return a reference to one generator, using a flat index.
Generator & operator()(Args... args)
Return a reference to one generator, using an array index.
void advance(const T &arg)
Advance generators.
auto initstate() -> typename detail::return_type< uint64_t, Shape >::type
Return the state initiator of all generators.
void draw_list_uint32(uint32_t *data, uint32_t bound, size_t n)
Draw n random numbers per array item, and write them to the correct position in data (assuming row-ma...
std::vector< Generator > m_gen
Underlying storage: one generator per array item.
R initstate()
Return the state initiator of all generators.
auto state() -> typename detail::return_type< uint64_t, Shape >::type
Return the state of all generators.
void cumsum_weibull_impl(double *ret, const size_t *n, double k, double scale)
Return the result of the cumulative sum of n random numbers.
auto distance(const T &arg) -> typename detail::return_type< int64_t, Shape >::type
Distance between two states.
void decide_masked_impl(const double *p, const bool *mask, bool *ret)
For each p take a decision.
void decide_impl(const double *p, bool *ret)
For each p take a decision.
R state()
Return the state of all generators.
auto initseq() -> typename detail::return_type< uint64_t, Shape >::type
Return the sequence initiator of all generators.
void draw_list_double(double *data, size_t n)
Draw n random numbers per array item, and write them to the correct position in data (assuming row-ma...
void cumsum_power_impl(double *ret, const size_t *n, double k)
Return the result of the cumulative sum of n random numbers.
void init(const T &initstate)
Constructor alias.
typename Shape::value_type size_type
Size type.
void cumsum_normal_impl(double *ret, const size_t *n, double mu, double sigma)
Return the result of the cumulative sum of n random numbers.
void cumsum_gamma_impl(double *ret, const size_t *n, double k, double scale)
Return the result of the cumulative sum of n random numbers.
Generator & operator[](size_t i)
Return a reference to one generator, using a flat index.
R initseq()
Return the sequence initiator of all generators.
void cumsum_pareto_impl(double *ret, const size_t *n, double k, double scale)
Return the result of the cumulative sum of n random numbers.
void restore(const T &arg)
Restore generators from a state.
const Generator & flat(size_t i) const
Return a constant reference to one generator, using a flat index.
Shape shape_type
Shape type.
void cumsum_random_impl(double *ret, const size_t *n)
Return the result of the cumulative sum of n random numbers.
const Generator & operator[](size_t i) const
Return a constant reference to one generator, using a flat index.
R distance(const T &arg)
Distance between two states.
const Generator & operator()(Args... args) const
Return a constant reference to one generator, using an array index.
void draw_list_positive_double(double *data, size_t n)
Draw n random numbers per array item, and write them to the correct position in data (assuming row-ma...
void init(const T &initstate, const U &initseq)
Constructor alias.
void cumsum_exponential_impl(double *ret, const size_t *n, double scale)
Return the result of the cumulative sum of n random numbers.
Array of generators of which a chunk of the random sequence is kept in memory.
pcg32_array_chunk(const S &shape, const T &initstate, const U &initseq, enum distribution distribution, const std::vector< double > ¶meters, const alignment &align=alignment())
Array of generators of a random cumulative sum, see prrng::pcg32_cumsum().
pcg32_array_cumsum(const S &shape, const T &initstate, const U &initseq, enum distribution distribution, const std::vector< double > ¶meters, const alignment &align=alignment())
Array of independent generators.
pcg32_array(const T &initstate, const U &initseq)
Constructor.
std::vector< size_t > shape_type
Shape type.
size_t size_type
Size type.
pcg32_array(const T &initstate)
Constructor.
Generator of a random cumulative sum of which a chunk is kept in memory.
double right_of_align() const
Return the value of the cumsum right of the target (the last time prrng::pcg32_cumsum::align() was ca...
const auto & shape() const
Shape of the chunk.
void restore(uint64_t state, double value, ptrdiff_t index)
Restore a specific state in the cumulative sum.
const Data & data() const
The current chunk of the cumsum of random numbers.
pcg32_cumsum(const R &shape, T initstate=0x853c49e6748fea9bULL, S initseq=0xda3e39cb94b95bdbULL, enum distribution distribution=distribution::custom, const std::vector< double > ¶meters=std::vector< double >{}, const alignment &align=alignment())
pcg32_cumsum & operator-=(const T &value)
Subtract value(s) from the chunk.
pcg32_cumsum & operator+=(const T &value)
Add value(s) to the chunk.
ptrdiff_t chunk_index_at_align() const
Index of target relative to the beginning of the chunk (the last time prrng::pcg32_cumsum::align() wa...
const pcg32_index & generator() const
Pointer to the generator.
void operator=(const pcg32_cumsum &other)
Copy constructor.
void set_functions(std::function< Data(size_t)> get_chunk, std::function< double(size_t)> get_cumsum, bool uses_generator=true)
Use external functions to draw the random numbers.
void align(double target)
Align the chunk to encompass a target value.
ptrdiff_t start() const
Global index of the first element in the chunk.
bool contains(double target) const
Check if the chunk contains a target.
void set_data(const Data &data)
Overwrite the current chunk of the cumsum of random numbers.
void next(size_t margin=0)
Shift chunk right.
ptrdiff_t index_at_align() const
Global index of target (the last time prrng::pcg32_cumsum::align() was called).
auto size() const
Size of the chunk.
void set_start(ptrdiff_t index)
Set global index of the first element in the chunk.
double left_of_align() const
Return the value of the cumsum left of the target (the last time prrng::pcg32_cumsum::align() was cal...
bool is_extendible() const
true if the chunk is extendible.
pcg32_cumsum(const pcg32_cumsum &other)
Copy constructor.
uint64_t state_at(ptrdiff_t index)
The current "state" of the generator.
void prev(size_t margin=0)
Shift chunk left.
Array of prrng::pcg32_index().
pcg32_index_array(const T &initstate, const U &initseq)
Constructor.
Fixed rank version of pcg32_index_array.
pcg32_index_tensor(const T &initstate, const U &initseq)
Constructor.
Overload of prrng::pcg32() that keeps track of the current index of the generator in the sequence.
void jump_to(ptrdiff_t index)
Move to a certain index.
void set_delta(bool delta)
Signal if the generator is uniquely used to draw a delta distribution.
uint64_t state_at(ptrdiff_t index)
State at a specific index of the sequence.
void set_index(ptrdiff_t index)
Overwrite the generator index.
pcg32_index(T initstate=0x853c49e6748fea9bULL, S initseq=0xda3e39cb94b95bdbULL, bool delta=false)
ptrdiff_t index() const
Get the generator index.
void drawn(ptrdiff_t n)
Update the generator index with the number of items you have drawn.
Array of generators of which a chunk of the random sequence is kept in memory.
pcg32_tensor_chunk(const S &shape, const T &initstate, const U &initseq, enum distribution distribution, const std::vector< double > ¶meters, const alignment &align=alignment())
Array of generators of a random cumulative sum, see prrng::pcg32_cumsum().
pcg32_tensor_cumsum(const S &shape, const T &initstate, const U &initseq, enum distribution distribution, const std::vector< double > ¶meters, const alignment &align=alignment())
Fixed rank version of pcg32_array.
std::array< size_t, N > shape_type
Shape type.
pcg32_tensor(const T &initstate, const U &initseq)
Constructor.
pcg32_tensor(const T &initstate)
Constructor.
size_t size_type
Size type.
Random number generate using the pcg32 algorithm.
R distance(T other_state) const
The distance between two states.
bool operator==(const pcg32 &other) const
Equality operator.
uint32_t operator()()
Draw new random number (uniformly distributed, 0 <= r <= max(uint32_t)).
uint64_t m_initseq
Sequence initiator.
int64_t operator-(const pcg32 &other) const
The distance between two PCG32 pseudorandom number generators.
uint64_t initstate() const
The state initiator that was used upon construction.
double next_double()
Generate a double precision floating point value on the interval [0, 1).
R distance(const pcg32 &other) const
The distance between two PCG32 pseudorandom number generators.
uint32_t next_uint32()
Draw new random number (uniformly distributed, 0 <= r <= max(uint32_t)).
uint64_t state() const
The current "state" of the generator.
uint32_t next_uint32(uint32_t bound)
Draw new random number (uniformly distributed, 0 <= r <= bound).
void restore(T state)
Restore a given state in the sequence.
double next_positive_double()
Generate a double precision floating point value on the interval (0, 1).
R state()
The current "state" of the generator.
float next_float()
Generate a single precision floating point value on the interval [0, 1).
R initseq() const
The sequence initiator that was used upon construction.
bool operator!=(const pcg32 &other) const
Inequality operator.
void seed(uint64_t initstate=0x853c49e6748fea9bULL, uint64_t initseq=0xda3e39cb94b95bdbULL)
Seed the generator (constructor alias).
uint64_t m_initstate
State initiator.
uint64_t m_state
RNG state. All values are possible.
void advance(T distance)
Multi-step advance function (jump-ahead, jump-back).
R initstate() const
The state initiator that was used upon construction.
pcg32(T initstate=0x853c49e6748fea9bULL, S initseq=0xda3e39cb94b95bdbULL)
Constructor.
uint64_t initseq() const
The sequence initiator that was used upon construction.
uint64_t m_inc
Controls which RNG sequence (stream) is selected. Must always be odd.
power_distribution(double k=1)
Constructor.
T cdf(const T &x)
Cumulative density function.
T quantile(const T &p)
Quantile (the inverse of the cumulative density function).
T pdf(const T &x)
Probability density function.
T cdf(const T &x)
Cumulative density function.
weibull_distribution(double k=1, double scale=1)
Constructor.
T quantile(const T &p)
Quantile (the inverse of the cumulative density function).
T pdf(const T &x)
Probability density function.
Portable Reconstructible (Pseudo!) Random Number Generator.
std::vector< std::string > version_compiler()
Information on the compiler, the platform, the C++ standard, and the compilation date.
std::vector< double > default_parameters(enum distribution distribution, const std::vector< double > ¶meters=std::vector< double >{})
distribution
Distribution identifier.
std::string version()
Version string, e.g.
std::vector< std::string > version_dependencies()
Versions of this library and of all of its dependencies.
auto auto_pcg32(const T &initstate)
Return a pcg32, a pcg32_array, or a pcg32_tensor based on input.
R lower_bound(const T &matrix, const V &value, const R &index, size_t proximity=10)
Iterating on the last axis of an nd-array (e.g.
V cumsum_chunk(const V &cumsum, const V &delta, const I &shift)
Update the chunk of a cumsum computed and stored in chunks.
#define PRRNG_PCG32_MULT
Multiplicative factor for pcg32() (used internally, cannot be overwritten at run-time).
#define PRRNG_PCG32_INITSTATE
Default initialisation state for pcg32() (used as constructor parameter that can be overwritten at ru...
R lower_bound(const It first, const It last, const T &value, R guess=0, R proximity=10)
Return index of the first element in the range [first, last) such that element < value is false (i....
#define PRRNG_VERSION
Library version.
void cumsum_chunk(V &cumsum, const V &delta, const I &shift)
Update the chunk of a cumsum computed and stored in chunks.
#define PRRNG_DEBUG(expr)
All debug assertions are implementation as:
#define PRRNG_PCG32_INITSEQ
Default initialisation sequence for pcg32() (used as constructor parameter that can be overwritten at...
#define PRRNG_ASSERT(expr)
All assertions are implementation as:
Structure to assemble the alignment parameters.
bool strict
If true, margin is respected strictly: argmin(target > chunk) == margin.
ptrdiff_t margin
Index of the chunk to place the target.
ptrdiff_t min_margin
Minimal index to accept if strict = false.
ptrdiff_t buffer
If positive, only change the chunk if target is in chunk[:buffer] or chunk[-buffer:].
alignment(ptrdiff_t buffer=0, ptrdiff_t margin=0, ptrdiff_t min_margin=0, bool strict=false)