12#ifndef EIGENRAND_DISTS_DISCRETE_H
13#define EIGENRAND_DISTS_DISCRETE_H
23 template<
typename _Precision = u
int32_t,
typename _Size = u
int32_t>
26 std::unique_ptr<_Precision[]> arr;
27 std::unique_ptr<_Size[]> alias;
28 size_t msize = 0, bitsize = 0, bitmask = 0;
35 AliasMethod(
const AliasMethod& o)
40 AliasMethod(AliasMethod&& o)
45 AliasMethod& operator=(
const AliasMethod& o)
52 arr = std::unique_ptr<_Precision[]>(
new _Precision[(
size_t)1 << bitsize]);
53 alias = std::unique_ptr<_Size[]>(
new _Size[(
size_t)1 << bitsize]);
55 std::copy(o.arr.get(), o.arr.get() + ((
size_t)1 << bitsize), arr.get());
56 std::copy(o.alias.get(), o.alias.get() + ((
size_t)1 << bitsize), alias.get());
61 AliasMethod& operator=(AliasMethod&& o)
66 std::swap(arr, o.arr);
67 std::swap(alias, o.alias);
71 template<
typename _Iter>
72 AliasMethod(_Iter first, _Iter last)
74 buildTable(first, last);
77 template<
typename _Iter>
78 void buildTable(_Iter first, _Iter last)
83 for (
auto it = first; it != last; ++it, ++msize)
88 if (!std::isfinite(sum))
throw std::invalid_argument{
"cannot build NaN value distribution" };
91 nbsize = (size_t)std::ceil(std::log2(msize));
92 psize = (size_t)1 << nbsize;
94 if (nbsize != bitsize)
96 arr = std::unique_ptr<_Precision[]>(
new _Precision[psize]);
97 std::fill(arr.get(), arr.get() + psize, 0);
98 alias = std::unique_ptr<_Size[]>(
new _Size[psize]);
100 bitmask = ((size_t)(-1)) >> (
sizeof(
size_t) * 8 - bitsize);
105 auto f = std::unique_ptr<double[]>(
new double[psize]);
107 for (
auto it = first; it != last; ++it, ++pf)
111 std::fill(pf, pf + psize - msize, 0);
113 size_t over = 0, under = 0, mm;
114 while (over < psize && f[over] < 1) ++over;
115 while (under < psize && f[under] >= 1) ++under;
118 while (over < psize && under < psize)
120 if (std::is_integral<_Precision>::value)
122 arr[under] = (_Precision)(f[under] * (std::numeric_limits<_Precision>::max() + 1.0));
126 arr[under] = (_Precision)f[under];
128 alias[under] = (_Size)over;
129 f[over] += f[under] - 1;
130 if (f[over] >= 1 || mm <= over)
132 for (under = mm; under < psize && f[under] >= 1; ++under);
140 while (over < psize && f[over] < 1) ++over;
143 for (; over < psize; ++over)
147 if (std::is_integral<_Precision>::value)
149 arr[over] = std::numeric_limits<_Precision>::max();
155 alias[over] = (_Size)over;
161 if (std::is_integral<_Precision>::value)
163 arr[under] = std::numeric_limits<_Precision>::max();
169 alias[under] = (_Size)under;
170 for (under = mm; under < msize; ++under)
174 if (std::is_integral<_Precision>::value)
176 arr[under] = std::numeric_limits<_Precision>::max();
182 alias[under] = (_Size)under;
188 size_t get_bitsize()
const
193 size_t get_bitmask()
const
198 const _Precision* get_prob()
const
203 const _Size* get_alias()
const
214 template<
typename _Scalar>
217 static_assert(std::is_same<_Scalar, int32_t>::value,
"uniformInt needs integral types.");
218 int cache_rest_cnt = 0;
221 size_t pdiff, bitsize, bitmask;
224 using Scalar = _Scalar;
232 : pmin{ _min }, pdiff{ (size_t)(_max - _min) }
234 if ((pdiff + 1) > pdiff)
236 bitsize = (size_t)std::ceil(std::log2(pdiff + 1));
240 bitsize = (size_t)std::ceil(std::log2(pdiff));
242 bitmask = (_Scalar)(((
size_t)-1) >> (
sizeof(
size_t) * 8 - bitsize));
251 template<
typename Rng>
252 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
254 using namespace Eigen::internal;
255 auto rx = randbits(rng);
256 if (pdiff == bitmask)
258 return (_Scalar)(rx & bitmask) + pmin;
262 size_t bitcnt = bitsize;
263 for (
int _i = 0; ; ++_i)
265 EIGENRAND_CHECK_INFINITY_LOOP();
266 _Scalar cands = (_Scalar)(rx & bitmask);
267 if (cands <= pdiff)
return cands + pmin;
268 if (bitcnt + bitsize < 32)
282 template<
typename Packet,
typename Rng>
283 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
285 using namespace Eigen::internal;
286 auto rx = randbits.template packetOp<Packet>(rng);
287 auto pbitmask = pset1<Packet>(bitmask);
288 if (pdiff == bitmask)
290 return padd(pand(rx, pbitmask), pset1<Packet>(pmin));
294 auto& cm = Rand::detail::CompressMask<
sizeof(Packet)>::get_inst();
295 auto plen = pset1<Packet>(pdiff + 1);
296 size_t bitcnt = bitsize;
297 for (
int _i = 0; ; ++_i)
299 EIGENRAND_CHECK_INFINITY_LOOP();
301 auto cands = pand(rx, pbitmask);
303 cache_rest_cnt = cm.compress_append(cands, pcmplt(cands, plen),
304 OptCacheStore::template get<Packet>(), cache_rest_cnt, full);
305 if (full)
return padd(cands, pset1<Packet>(pmin));
307 if (bitcnt + bitsize < 32)
309 rx = psrl<-1>(rx, bitsize);
314 rx = randbits.template packetOp<Packet>(rng);
328 template<
typename _Scalar,
typename Precision =
float>
336 template<
typename _Scalar>
339 static_assert(std::is_same<_Scalar, int32_t>::value,
"discreteDist needs integral types.");
340#ifdef EIGEN_VECTORIZE_AVX2
345 std::vector<uint32_t> cdf;
346 AliasMethod<int32_t, _Scalar> alias_table;
349 using Scalar = _Scalar;
358 template<
typename RealIter>
361 if (std::distance(first, last) < 16)
364 std::vector<double> _cdf;
366 for (; first != last; ++first)
368 _cdf.emplace_back(acc += *first);
373 cdf.emplace_back((uint32_t)(p / _cdf.back() * 0x80000000));
379 alias_table = AliasMethod<int32_t, _Scalar>{ first, last };
390 template<
typename Real,
391 typename std::enable_if<std::is_arithmetic<Real>::value,
int>::type = 0>
402 DiscreteGen(
const DiscreteGen&) =
default;
403 DiscreteGen(DiscreteGen&&) =
default;
405 DiscreteGen& operator=(
const DiscreteGen&) =
default;
406 DiscreteGen& operator=(DiscreteGen&&) =
default;
408 template<
typename Rng>
409 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
411 using namespace Eigen::internal;
414 auto rx = randbits(std::forward<Rng>(rng)) & 0x7FFFFFFF;
415 return (_Scalar)(std::lower_bound(cdf.begin(), cdf.end() - 1, rx) - cdf.begin());
419 auto rx = randbits(std::forward<Rng>(rng));
420 auto albit = rx & alias_table.get_bitmask();
421 uint32_t alx = (uint32_t)(rx >> (
sizeof(rx) * 8 - 31));
422 if (alx < alias_table.get_prob()[albit])
return (_Scalar)albit;
423 return alias_table.get_alias()[albit];
427 template<
typename Packet,
typename Rng>
428 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
430 using namespace Eigen::internal;
431#ifdef EIGEN_VECTORIZE_AVX2
435 return cache.template get<Packet>();
437 using PacketType = Packet8i;
439 using PacketType = Packet;
445 ret = pset1<PacketType>(cdf.size() - 1);
446 auto rx = pand(randbits.template packetOp<PacketType>(std::forward<Rng>(rng)), pset1<PacketType>(0x7FFFFFFF));
447 for (
size_t i = 0; i < cdf.size() - 1; ++i)
449 ret = padd(ret, pcmplt(rx, pset1<PacketType>(cdf[i])));
454 auto rx = randbits.template packetOp<PacketType>(std::forward<Rng>(rng));
455 auto albit = pand(rx, pset1<PacketType>(alias_table.get_bitmask()));
456 auto c = pcmplt(psrl<1>(rx), pgather(alias_table.get_prob(), albit));
457 ret = pblendv(c, albit, pgather(alias_table.get_alias(), albit));
460#ifdef EIGEN_VECTORIZE_AVX2
462 cache.template get<Packet>() = _mm256_extractf128_si256(ret, 1);
463 return _mm256_extractf128_si256(ret, 0);
475 template<
typename _Scalar>
478 static_assert(std::is_same<_Scalar, int32_t>::value,
"discreteDist needs integral types.");
480 std::vector<float> cdf;
481 AliasMethod<float, _Scalar> alias_table;
484 using Scalar = _Scalar;
493 template<
typename RealIter>
496 if (std::distance(first, last) < 16)
499 std::vector<double> _cdf;
501 for (; first != last; ++first)
503 _cdf.emplace_back(acc += *first);
508 cdf.emplace_back(p / _cdf.back());
514 alias_table = AliasMethod<float, _Scalar>{ first, last };
525 template<
typename Real,
526 typename std::enable_if<std::is_arithmetic<Real>::value,
int>::type = 0>
537 DiscreteGen(
const DiscreteGen&) =
default;
538 DiscreteGen(DiscreteGen&&) =
default;
540 DiscreteGen& operator=(
const DiscreteGen&) =
default;
541 DiscreteGen& operator=(DiscreteGen&&) =
default;
543 template<
typename Rng>
544 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
546 using namespace Eigen::internal;
549 auto rx = ur(std::forward<Rng>(rng));
550 return (_Scalar)(std::lower_bound(cdf.begin(), cdf.end() - 1, rx) - cdf.begin());
554 auto albit = pfirst(rng()) & alias_table.get_bitmask();
556 if (alx < alias_table.get_prob()[albit])
return albit;
557 return alias_table.get_alias()[albit];
561 template<
typename Packet,
typename Rng>
562 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
564 using namespace Eigen::internal;
565 using PacketType =
decltype(reinterpret_to_float(std::declval<Packet>()));
569 auto ret = pset1<Packet>(cdf.size());
570 auto rx = ur.template packetOp<PacketType>(std::forward<Rng>(rng));
573 ret = padd(ret, reinterpret_to_int(pcmplt(rx, pset1<PacketType>(p))));
579 using RUtils = RawbitsMaker<Packet, Rng>;
580 auto albit = pand(RUtils{}.rawbits(rng), pset1<Packet>(alias_table.get_bitmask()));
581 auto c = reinterpret_to_int(pcmplt(ur.template packetOp<PacketType>(rng), pgather(alias_table.get_prob(), albit)));
582 return pblendv(c, albit, pgather(alias_table.get_alias(), albit));
592 template<
typename _Scalar>
595 static_assert(std::is_same<_Scalar, int32_t>::value,
"discreteDist needs integral types.");
597 std::vector<double> cdf;
598 AliasMethod<double, _Scalar> alias_table;
601 using Scalar = _Scalar;
610 template<
typename RealIter>
613 if (std::distance(first, last) < 16)
616 std::vector<double> _cdf;
618 for (; first != last; ++first)
620 _cdf.emplace_back(acc += *first);
625 cdf.emplace_back(p / _cdf.back());
631 alias_table = AliasMethod<double, _Scalar>{ first, last };
642 template<
typename Real,
643 typename std::enable_if<std::is_arithmetic<Real>::value,
int>::type = 0>
654 DiscreteGen(
const DiscreteGen&) =
default;
655 DiscreteGen(DiscreteGen&&) =
default;
657 DiscreteGen& operator=(
const DiscreteGen&) =
default;
658 DiscreteGen& operator=(DiscreteGen&&) =
default;
660 template<
typename Rng>
661 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
663 using namespace Eigen::internal;
666 auto rx = ur(std::forward<Rng>(rng));
667 return (_Scalar)(std::lower_bound(cdf.begin(), cdf.end() - 1, rx) - cdf.begin());
671 auto albit = pfirst(rng()) & alias_table.get_bitmask();
673 if (alx < alias_table.get_prob()[albit])
return albit;
674 return alias_table.get_alias()[albit];
678#ifdef EIGEN_VECTORIZE_NEON
680 template<
typename Packet,
typename Rng>
681 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
683 using namespace Eigen::internal;
684 using DPacket =
decltype(reinterpret_to_double(std::declval<Packet>()));
687 auto ret = pset1<Packet>(cdf.size());
688 #ifdef EIGEN_VECTORIZE_AVX
689 auto rx = ur.template packetOp<Packet4d>(std::forward<Rng>(rng));
692 auto c = reinterpret_to_int(pcmplt(rx, pset1<
decltype(rx)>(p)));
693 auto r = combine_low32(c);
697 auto rx1 = ur.template packetOp<DPacket>(rng),
698 rx2 = ur.template packetOp<DPacket>(rng);
701 auto pp = pset1<decltype(rx1)>(p);
702 ret = padd(ret, combine_low32(reinterpret_to_int(pcmplt(rx1, pp)), reinterpret_to_int(pcmplt(rx2, pp))));
709 #ifdef EIGEN_VECTORIZE_AVX
710 using RUtils = RawbitsMaker<Packet, Rng>;
711 auto albit = pand(RUtils{}.rawbits(rng), pset1<Packet>(alias_table.get_bitmask()));
712 auto c = reinterpret_to_int(pcmplt(ur.template packetOp<Packet4d>(rng), pgather(alias_table.get_prob(), _mm256_castsi128_si256(albit))));
713 return pblendv(combine_low32(c), albit, pgather(alias_table.get_alias(), albit));
715 using RUtils = RawbitsMaker<Packet, Rng>;
716 auto albit = pand(RUtils{}.rawbits(rng), pset1<Packet>(alias_table.get_bitmask()));
717 auto c1 = reinterpret_to_int(pcmplt(ur.template packetOp<DPacket>(rng), pgather(alias_table.get_prob(), albit)));
718 auto c2 = reinterpret_to_int(pcmplt(ur.template packetOp<DPacket>(rng), pgather(alias_table.get_prob(), albit,
true)));
719 return pblendv(combine_low32(c1, c2), albit, pgather(alias_table.get_alias(), albit));
726 template<
typename>
class BinomialGen;
733 template<
typename _Scalar>
737 static_assert(std::is_same<_Scalar, int32_t>::value,
"poisson needs integral types.");
738 int cache_rest_cnt = 0;
742 double mean, ne_mean, sqrt_tmean, log_mean, g1;
745 using Scalar = _Scalar;
753 : mean{ _mean }, ne_mean{ std::exp(-_mean) }
755 sqrt_tmean = std::sqrt(2 * mean);
756 log_mean = std::log(mean);
757 g1 = mean * log_mean - std::lgamma(mean + 1);
766 template<
typename Rng>
767 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
769 using namespace Eigen::internal;
777 if (val <= ne_mean)
break;
785 for (
int _i = 0; ; ++_i)
787 EIGENRAND_CHECK_INFINITY_LOOP();
788 yx = std::tan(constant::pi * ur(rng));
789 res = (_Scalar)(sqrt_tmean * yx + mean);
790 if (res >= 0 && ur(rng) <= 0.9 * (1.0 + yx * yx)
791 * std::exp(res * log_mean - std::lgamma(res + 1.0) - g1))
799 template<
typename Packet,
typename Rng>
800 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
802 using namespace Eigen::internal;
803 using PacketType =
decltype(reinterpret_to_float(std::declval<Packet>()));
807 Packet res = pset1<Packet>(0);
808 PacketType val = pset1<PacketType>(1), pne_mean = pset1<PacketType>(ne_mean);
809 for (
int _i = 0; ; ++_i)
811 EIGENRAND_CHECK_INFINITY_LOOP();
812 val = pmul(val, ur.template packetOp<PacketType>(rng));
813 auto c = reinterpret_to_int(pcmplt(pne_mean, val));
814 if (pmovemask(c) == 0)
break;
815 res = padd(res, pnegate(c));
821 auto& cm = Rand::detail::CompressMask<
sizeof(Packet)>::get_inst();
822 const PacketType ppi = pset1<PacketType>(constant::pi),
823 psqrt_tmean = pset1<PacketType>(sqrt_tmean),
824 pmean = pset1<PacketType>(mean),
825 plog_mean = pset1<PacketType>(log_mean),
826 pg1 = pset1<PacketType>(g1);
827 for (
int _i = 0; ; ++_i)
829 EIGENRAND_CHECK_INFINITY_LOOP();
830 PacketType fres, yx, psin, pcos;
831 psincos(pmul(ppi, ur.template packetOp<PacketType>(rng)), psin, pcos);
832 yx = pdiv(psin, pcos);
833 fres = ptruncate(padd(pmul(psqrt_tmean, yx), pmean));
835 auto p1 = pmul(padd(pmul(yx, yx), pset1<PacketType>(1)), pset1<PacketType>(0.9));
836 auto p2 = pexp(psub(psub(pmul(fres, plog_mean), plgamma_approx(padd(fres, pset1<PacketType>(1)))), pg1));
838 auto c1 = pcmple(pset1<PacketType>(0), fres);
839 auto c2 = pcmple(ur.template packetOp<PacketType>(rng), pmul(p1, p2));
843 cache_rest_cnt = cm.compress_append(cands, pand(c1, c2),
844 OptCacheStore::template get<PacketType>(), cache_rest_cnt, full);
845 if (full)
return pcast<PacketType, Packet>(cands);
856 template<
typename _Scalar>
859 static_assert(std::is_same<_Scalar, int32_t>::value,
"binomial needs integral types.");
863 double p = 0, small_p = 0, g1 = 0, sqrt_v = 0, log_small_p = 0, log_small_q = 0;
866 using Scalar = _Scalar;
875 :
poisson{ _trials * std::min(_p, 1 - _p) },
876 trials{ _trials }, p{ _p }, small_p{ std::min(p, 1 - p) }
879 if (!(trials < 25 ||
poisson.mean < 1.0))
881 g1 = std::lgamma(trials + 1);
882 sqrt_v = std::sqrt(2 *
poisson.mean * (1 - small_p));
883 log_small_p = std::log(small_p);
884 log_small_q = std::log(1 - small_p);
894 template<
typename Rng>
895 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
897 using namespace Eigen::internal;
902 for (
int i = 0; i < trials; ++i)
904 if (
poisson.ur(rng) < p) ++res;
908 else if (poisson.mean < 1.0)
914 for (
int _i = 0; ; ++_i)
916 EIGENRAND_CHECK_INFINITY_LOOP();
918 ys = std::tan(constant::pi *
poisson.ur(rng));
919 res = (_Scalar)(sqrt_v * ys +
poisson.mean);
920 if (0 <= res && res <= trials &&
poisson.ur(rng) <= 1.2 * sqrt_v
922 * std::exp(g1 - std::lgamma(res + 1)
923 - std::lgamma(trials - res + 1.0)
925 + (trials - res) * log_small_q)
932 return p == small_p ? res : trials - res;
935 template<
typename Packet,
typename Rng>
936 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
938 using namespace Eigen::internal;
939 using PacketType =
decltype(reinterpret_to_float(std::declval<Packet>()));
943 PacketType pp = pset1<PacketType>(p);
944 res = pset1<Packet>(trials);
945 for (
int i = 0; i < trials; ++i)
947 auto c = reinterpret_to_int(pcmple(pp,
poisson.ur.template packetOp<PacketType>(rng)));
954 res =
poisson.template packetOp<Packet>(rng);
958 auto& cm = Rand::detail::CompressMask<
sizeof(Packet)>::get_inst();
959 const PacketType ppi = pset1<PacketType>(constant::pi),
960 ptrials = pset1<PacketType>(trials),
961 psqrt_v = pset1<PacketType>(sqrt_v),
962 pmean = pset1<PacketType>(
poisson.mean),
963 plog_small_p = pset1<PacketType>(log_small_p),
964 plog_small_q = pset1<PacketType>(log_small_q),
965 pg1 = pset1<PacketType>(g1);
966 for (
int _i = 0; ; ++_i)
968 EIGENRAND_CHECK_INFINITY_LOOP();
969 PacketType fres, ys, psin, pcos;
970 psincos(pmul(ppi,
poisson.ur.template packetOp<PacketType>(rng)), psin, pcos);
971 ys = pdiv(psin, pcos);
972 fres = ptruncate(padd(pmul(psqrt_v, ys), pmean));
974 auto p1 = pmul(pmul(pset1<PacketType>(1.2), psqrt_v), padd(pset1<PacketType>(1), pmul(ys, ys)));
977 psub(pg1, plgamma_approx(padd(fres, pset1<PacketType>(1)))),
978 plgamma_approx(psub(padd(ptrials, pset1<PacketType>(1)), fres))
979 ), pmul(fres, plog_small_p)), pmul(psub(ptrials, fres), plog_small_q))
982 auto c1 = pand(pcmple(pset1<PacketType>(0), fres), pcmple(fres, ptrials));
983 auto c2 = pcmple(
poisson.ur.template packetOp<PacketType>(rng), pmul(p1, p2));
987 poisson.cache_rest_cnt = cm.compress_append(cands, pand(c1, c2),
988 poisson.template get<PacketType>(),
poisson.cache_rest_cnt, full);
991 res = pcast<PacketType, Packet>(cands);
996 return p == small_p ? res : psub(pset1<Packet>(trials), res);
1000 template<
typename _Scalar>
1003 static_assert(std::is_same<_Scalar, int32_t>::value,
"binomial needs integral types.");
1007 class BinomialVGen<int32_t> :
public BinaryGenBase<BinomialVGen<int32_t>, int32_t, int32_t, float>
1009 StdUniformRealGen<float> ur;
1012 using Scalar = int32_t;
1014 template<
typename Rng>
1015 EIGEN_STRONG_INLINE
const Scalar operator() (Rng&& rng, Scalar trials,
float p)
1017 using namespace Eigen::internal;
1019 float small_p = std::min(p, 1 - p);
1020 float mean = trials * small_p;
1021 float g1 = std::lgamma(trials + 1);
1022 float sqrt_v = std::sqrt(2 * mean * (1 - small_p));
1023 float log_small_p = std::log(small_p);
1024 float log_small_q = std::log(1 - small_p);
1030 for (
int i = 0; i < trials; ++i)
1032 if (ur(rng) < p) ++res;
1038 float ne_mean = std::exp(-mean);
1043 if (val <= ne_mean)
break;
1048 for (
int _i = 0; ; ++_i)
1050 EIGENRAND_CHECK_INFINITY_LOOP();
1052 ys = std::tan(constant::pi * ur(rng));
1053 res = (Scalar)(sqrt_v * ys + mean);
1054 if (0 <= res && res <= trials && ur(rng) <= 1.2 * sqrt_v
1056 * std::exp(g1 - std::lgamma(res + 1)
1057 - std::lgamma(trials - res + 1.0)
1059 + (trials - res) * log_small_q)
1066 return p == small_p ? res : trials - res;
1069 template<
typename Packet,
typename FPacket,
typename Rng>
1070 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng,
const Packet& trials,
const FPacket& p)
1072 using namespace Eigen::internal;
1073 Packet valid = pset1<Packet>(0);
1076 const auto psmall_p = pmin(p, psub(pset1<FPacket>(1), p));
1077 const auto ptrials = pcast<Packet, FPacket>(trials);
1078 const auto pmean = pmul(ptrials, psmall_p);
1079 const auto pg1 = plgamma_approx(padd(ptrials, pset1<FPacket>(1)));
1080 const auto psqrt_v = psqrt(pmul(pmul(pset1<FPacket>(2), pmean), psub(pset1<FPacket>(1), psmall_p)));
1081 const auto plog_small_p = plog(psmall_p);
1082 const auto plog_small_q = plog(psub(pset1<FPacket>(1), psmall_p));
1083 const auto ppi = pset1<FPacket>(constant::pi);
1084 valid = reinterpret_to_int(pcmplt(pmean, pset1<FPacket>(1)));
1085 if (predux_any(valid))
1087 Packet res = pset1<Packet>(0);
1088 FPacket val = pset1<FPacket>(1), pne_mean = pexp(pnegate(pmean));
1089 for (
int _i = 0; ; ++_i)
1091 EIGENRAND_CHECK_INFINITY_LOOP();
1092 val = pmul(val, ur.template packetOp<FPacket>(rng));
1093 auto c = pand(reinterpret_to_int(pcmplt(pne_mean, val)), valid);
1094 if (!predux_any(c))
break;
1095 res = padd(res, pnegate(c));
1097 valid_res = pcast<Packet, FPacket>(res);
1100 if (!predux_all(valid))
1102 for (
int _i = 0; ; ++_i)
1104 EIGENRAND_CHECK_INFINITY_LOOP();
1105 FPacket fres, ys, psin, pcos;
1106 psincos(pmul(ppi, ur.template packetOp<FPacket>(rng)), psin, pcos);
1107 ys = pdiv(psin, pcos);
1108 fres = ptruncate(padd(pmul(psqrt_v, ys), pmean));
1110 auto p1 = pmul(pmul(pset1<FPacket>(1.2), psqrt_v), padd(pset1<FPacket>(1), pmul(ys, ys)));
1113 psub(pg1, plgamma_approx(padd(fres, pset1<FPacket>(1)))),
1114 plgamma_approx(psub(padd(ptrials, pset1<FPacket>(1)), fres))
1115 ), pmul(fres, plog_small_p)), pmul(psub(ptrials, fres), plog_small_q))
1118 auto c1 = pand(pcmple(pset1<FPacket>(0), fres), pcmple(fres, ptrials));
1119 auto c2 = pcmple(ur.template packetOp<FPacket>(rng), pmul(p1, p2));
1121 auto fvalid = pand(c1, c2);
1122 valid_res = pblendv(pnew_andnot(fvalid, reinterpret_to_float(valid)), fres, valid_res);
1123 valid = por(reinterpret_to_int(fvalid), valid);
1125 if (predux_all(valid))
1133 reinterpret_to_int(pcmpeq(p, psmall_p)),
1134 pcast<FPacket, Packet>(valid_res),
1135 psub(trials, pcast<FPacket, Packet>(valid_res))
1141 class BinomialVGen<float> :
public BinaryGenBase<BinomialVGen<float>, float, float, float>
1143 StdUniformRealGen<float> ur;
1146 using Scalar = float;
1148 template<
typename Rng>
1149 EIGEN_STRONG_INLINE
const Scalar operator() (Rng&& rng, Scalar _trials,
float p)
1151 using namespace Eigen::internal;
1153 auto trials =
reinterpret_cast<int32_t&
>(_trials);
1155 float small_p = std::min(p, 1 - p);
1156 float mean = trials * small_p;
1157 float g1 = std::lgamma(trials + 1);
1158 float sqrt_v = std::sqrt(2 * mean * (1 - small_p));
1159 float log_small_p = std::log(small_p);
1160 float log_small_q = std::log(1 - small_p);
1166 for (
int i = 0; i < trials; ++i)
1168 if (ur(rng) < p) ++res;
1174 float ne_mean = std::exp(-mean);
1179 if (val <= ne_mean)
break;
1184 for (
int _i = 0; ; ++_i)
1186 EIGENRAND_CHECK_INFINITY_LOOP();
1188 ys = std::tan(constant::pi * ur(rng));
1189 res = (int32_t)(sqrt_v * ys + mean);
1190 if (0 <= res && res <= trials && ur(rng) <= 1.2 * sqrt_v
1192 * std::exp(g1 - std::lgamma(res + 1)
1193 - std::lgamma(trials - res + 1.0)
1195 + (trials - res) * log_small_q)
1202 res = p == small_p ? res : trials - res;
1203 return reinterpret_cast<Scalar&
>(res);
1206 template<
typename Packet,
typename Rng>
1207 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng,
const Packet& _trials,
const Packet& p)
1209 using namespace Eigen::internal;
1210 using IPacket =
decltype(reinterpret_to_int(std::declval<Packet>()));
1211 IPacket valid = pset1<IPacket>(0);
1214 const auto trials = reinterpret_to_int(_trials);
1215 const auto psmall_p = pmin(p, psub(pset1<Packet>(1), p));
1216 const auto ptrials = pcast<IPacket, Packet>(trials);
1217 const auto pmean = pmul(ptrials, psmall_p);
1218 const auto pg1 = plgamma_approx(padd(ptrials, pset1<Packet>(1)));
1219 const auto psqrt_v = psqrt(pmul(pmul(pset1<Packet>(2), pmean), psub(pset1<Packet>(1), psmall_p)));
1220 const auto plog_small_p = plog(psmall_p);
1221 const auto plog_small_q = plog(psub(pset1<Packet>(1), psmall_p));
1222 const auto ppi = pset1<Packet>(constant::pi);
1223 valid = reinterpret_to_int(pcmplt(pmean, pset1<Packet>(1)));
1224 if (predux_any(reinterpret_to_float(valid)))
1226 Packet res = pset1<Packet>(0);
1227 Packet val = pset1<Packet>(1), pne_mean = pexp(pnegate(pmean));
1228 for (
int _i = 0; ; ++_i)
1230 EIGENRAND_CHECK_INFINITY_LOOP();
1231 val = pmul(val, ur.template packetOp<Packet>(rng));
1232 auto c = pand(reinterpret_to_int(pcmplt(pne_mean, val)), valid);
1233 if (!predux_any(reinterpret_to_float(c)))
break;
1234 res = padd(res, pcast<IPacket, Packet>(pnegate(c)));
1239 if (!predux_all(reinterpret_to_float(valid)))
1241 for (
int _i = 0; ; ++_i)
1243 EIGENRAND_CHECK_INFINITY_LOOP();
1244 Packet fres, ys, psin, pcos;
1245 psincos(pmul(ppi, ur.template packetOp<Packet>(rng)), psin, pcos);
1246 ys = pdiv(psin, pcos);
1247 fres = ptruncate(padd(pmul(psqrt_v, ys), pmean));
1249 auto p1 = pmul(pmul(pset1<Packet>(1.2), psqrt_v), padd(pset1<Packet>(1), pmul(ys, ys)));
1252 psub(pg1, plgamma_approx(padd(fres, pset1<Packet>(1)))),
1253 plgamma_approx(psub(padd(ptrials, pset1<Packet>(1)), fres))
1254 ), pmul(fres, plog_small_p)), pmul(psub(ptrials, fres), plog_small_q))
1257 auto c1 = pand(pcmple(pset1<Packet>(0), fres), pcmple(fres, ptrials));
1258 auto c2 = pcmple(ur.template packetOp<Packet>(rng), pmul(p1, p2));
1260 auto fvalid = pand(c1, c2);
1261 valid_res = pblendv(pnew_andnot(fvalid, reinterpret_to_float(valid)), fres, valid_res);
1262 valid = por(reinterpret_to_int(fvalid), valid);
1264 if (predux_all(reinterpret_to_float(valid)))
1271 pcmpeq(p, psmall_p),
1272 reinterpret_to_float(pcast<Packet, IPacket>(valid_res)),
1273 reinterpret_to_float(psub(trials, pcast<Packet, IPacket>(valid_res)))
1283 template<
typename _Scalar>
1286 static_assert(std::is_same<_Scalar, int32_t>::value,
"geomtric needs integral types.");
1291 using Scalar = _Scalar;
1299 : p{ _p }, rlog_q{ 1 / std::log(1 - p) }
1309 template<
typename Rng>
1310 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
1312 using namespace Eigen::internal;
1313 return (_Scalar)(std::log(1 - ur(std::forward<Rng>(rng))) * rlog_q);
1316 template<
typename Packet,
typename Rng>
1317 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
1319 using namespace Eigen::internal;
1320 using PacketType =
decltype(reinterpret_to_float(std::declval<Packet>()));
1322 return pcast<PacketType, Packet>(ptruncate(pmul(plog(
1323 psub(pset1<PacketType>(1), ur.template packetOp<PacketType>(std::forward<Rng>(rng)))
1324 ), pset1<PacketType>(rlog_q))));
1329 template<
typename Derived,
typename Urng>
1330 using UniformIntType = CwiseNullaryOp<internal::scalar_rng_adaptor<UniformIntGen<typename Derived::Scalar>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
1345 template<
typename Derived,
typename Urng>
1346 inline const UniformIntType<Derived, Urng>
1347 uniformInt(Index rows, Index cols, Urng&& urng,
typename Derived::Scalar min,
typename Derived::Scalar max)
1366 template<
typename Derived,
typename Urng>
1367 inline const UniformIntType<Derived, Urng>
1368 uniformIntLike(Derived& o, Urng&& urng,
typename Derived::Scalar min,
typename Derived::Scalar max)
1375 template<
typename Derived,
typename Urng>
1376 using DiscreteFType = CwiseNullaryOp<internal::scalar_rng_adaptor<DiscreteGen<typename Derived::Scalar, float>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
1392 template<
typename Derived,
typename Urng,
typename RealIter>
1393 inline const DiscreteFType<Derived, Urng>
1394 discreteF(Index rows, Index cols, Urng&& urng, RealIter first, RealIter last)
1414 template<
typename Derived,
typename Urng,
typename RealIter>
1415 inline const DiscreteFType<Derived, Urng>
1437 template<
typename Derived,
typename Urng,
typename Real>
1438 inline const DiscreteFType<Derived, Urng>
1439 discreteF(Index rows, Index cols, Urng&& urng,
const std::initializer_list<Real>& il)
1459 template<
typename Derived,
typename Urng,
typename Real>
1460 inline const DiscreteFType<Derived, Urng>
1468 template<
typename Derived,
typename Urng>
1469 using DiscreteDType = CwiseNullaryOp<internal::scalar_rng_adaptor<DiscreteGen<typename Derived::Scalar, double>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
1485 template<
typename Derived,
typename Urng,
typename RealIter>
1486 inline const DiscreteDType<Derived, Urng>
1487 discreteD(Index rows, Index cols, Urng&& urng, RealIter first, RealIter last)
1507 template<
typename Derived,
typename Urng,
typename RealIter>
1508 inline const DiscreteDType<Derived, Urng>
1530 template<
typename Derived,
typename Urng,
typename Real>
1531 inline const DiscreteDType<Derived, Urng>
1532 discreteD(Index rows, Index cols, Urng&& urng,
const std::initializer_list<Real>& il)
1552 template<
typename Derived,
typename Urng,
typename Real>
1553 inline const DiscreteDType<Derived, Urng>
1561 template<
typename Derived,
typename Urng>
1562 using DiscreteType = CwiseNullaryOp<internal::scalar_rng_adaptor<DiscreteGen<typename Derived::Scalar, int32_t>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
1578 template<
typename Derived,
typename Urng,
typename RealIter>
1579 inline const DiscreteType<Derived, Urng>
1580 discrete(Index rows, Index cols, Urng&& urng, RealIter first, RealIter last)
1600 template<
typename Derived,
typename Urng,
typename RealIter>
1601 inline const DiscreteType<Derived, Urng>
1623 template<
typename Derived,
typename Urng,
typename Real>
1624 inline const DiscreteType<Derived, Urng>
1625 discrete(Index rows, Index cols, Urng&& urng,
const std::initializer_list<Real>& il)
1645 template<
typename Derived,
typename Urng,
typename Real>
1646 inline const DiscreteType<Derived, Urng>
1647 discreteLike(Derived& o, Urng&& urng,
const std::initializer_list<Real>& il)
1654 template<
typename Derived,
typename Urng>
1655 using PoissonType = CwiseNullaryOp<internal::scalar_rng_adaptor<PoissonGen<typename Derived::Scalar>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
1670 template<
typename Derived,
typename Urng>
1671 inline const PoissonType<Derived, Urng>
1672 poisson(Index rows, Index cols, Urng&& urng,
double mean = 1)
1691 template<
typename Derived,
typename Urng>
1692 inline const PoissonType<Derived, Urng>
1700 template<
typename Derived,
typename Urng>
1701 using BinomialType = CwiseNullaryOp<internal::scalar_rng_adaptor<BinomialGen<typename Derived::Scalar>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
1717 template<
typename Derived,
typename Urng>
1718 inline const BinomialType<Derived, Urng>
1719 binomial(Index rows, Index cols, Urng&& urng,
typename Derived::Scalar trials = 1,
double p = 0.5)
1739 template<
typename Derived,
typename Urng>
1740 inline const BinomialType<Derived, Urng>
1741 binomialLike(Derived& o, Urng&& urng,
typename Derived::Scalar trials = 1,
double p = 0.5)
1749 template<
typename Lhs,
typename Rhs,
typename Urng>
1751 internal::scalar_binary_rng_adaptor<BinomialVGen<typename Lhs::Scalar>,
typename Lhs::Scalar,
typename Lhs::Scalar,
typename Rhs::Scalar, Urng,
true>,
1752 const Lhs,
const Rhs
1768 template<
typename Lhs,
typename Rhs,
typename Urng>
1769 inline const BinomialVVType<Lhs, Rhs, Urng>
1770 binomial(Urng&& urng,
const ArrayBase<Lhs>& trials,
const ArrayBase<Rhs>& p)
1773 static_cast<const Lhs&
>(trials),
static_cast<const Rhs&
>(p),
1774 { std::forward<Urng>(urng), BinomialVGen<typename Lhs::Scalar>{} }
1779 template<
class Derived,
class NewType>
struct CastType
1781 using type =
typename internal::eval<
1782 typename std::remove_reference<
1783 typename internal::cast_return_type<Derived, const CwiseUnaryOp<internal::scalar_cast_op<typename Derived::Scalar, NewType>,
const Derived> >::type
1789 template<
typename Lhs,
typename Urng>
1791 internal::scalar_binary_rng_adaptor<BinomialVGen<typename Lhs::Scalar>,
typename Lhs::Scalar,
typename Lhs::Scalar, float, Urng,
true>,
1792 const Lhs, CwiseNullaryOp<internal::scalar_constant_op<float>,
const typename impl::CastType<Lhs, float>::type>
1795 template<
typename Lhs,
typename Urng>
1796 inline const BinomialVSType<Lhs, Urng>
1797 binomial(Urng&& urng,
const ArrayBase<Lhs>& trials,
float p)
1800 static_cast<const Lhs&
>(trials),
1801 { trials.rows(), trials.cols(), internal::scalar_constant_op<float>{p} },
1802 { std::forward<Urng>(urng), BinomialVGen<typename Lhs::Scalar>{} }
1808 template<
typename Lhs,
typename Urng>
1809 using BinomialVType = CwiseBinaryOp<
1810 internal::scalar_binary_rng_adaptor<BinomialVGen<typename Lhs::Scalar>,
typename Lhs::Scalar,
typename Lhs::Scalar,
typename Lhs::Scalar, Urng,
true>,
1811 const Lhs, CwiseNullaryOp<internal::scalar_constant_op<float>,
const Lhs>
1814 template<
typename Lhs,
typename Urng>
1815 inline const BinomialVType<Lhs, Urng>
1816 binomial(Urng&& urng,
const ArrayBase<Lhs>& trials,
float p)
1818 static_assert(std::is_same<typename Lhs::Scalar, float>::value,
"Lhs must have float scalar type.");
1820 static_cast<const Lhs&
>(trials),
1821 { trials.rows(), trials.cols(), internal::scalar_constant_op<float>{p} },
1822 { std::forward<Urng>(urng), BinomialVGen<typename Lhs::Scalar>{} }
1827 template<
typename Rhs,
typename Urng>
1829 internal::scalar_binary_rng_adaptor<BinomialVGen<int32_t>, int32_t, int32_t,
typename Rhs::Scalar, Urng,
true>,
1830 CwiseNullaryOp<internal::scalar_constant_op<int32_t>,
const typename impl::CastType<Rhs, int32_t>::type>,
const Rhs
1833 template<
typename Rhs,
typename Urng>
1834 inline const BinomialSVType<Rhs, Urng>
1835 binomial(Urng&& urng, int32_t trials,
const ArrayBase<Rhs>& p)
1838 { p.rows(), p.cols(), internal::scalar_constant_op<int32_t>{trials} },
1839 static_cast<const Rhs&
>(p),
1840 { std::forward<Urng>(urng), BinomialVGen<int32_t>{} }
1844 template<
typename Derived,
typename Urng>
1845 using GeometricType = CwiseNullaryOp<internal::scalar_rng_adaptor<GeometricGen<typename Derived::Scalar>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
1860 template<
typename Derived,
typename Urng>
1861 inline const GeometricType<Derived, Urng>
1862 geometric(Index rows, Index cols, Urng&& urng,
double p = 0.5)
1881 template<
typename Derived,
typename Urng>
1882 inline const GeometricType<Derived, Urng>
1891#ifdef EIGEN_VECTORIZE_NEON
1894 template<
typename _Scalar,
typename Urng,
bool _mutable>
1895 struct functor_traits<scalar_rng_adaptor<Rand::DiscreteGen<_Scalar, double>, _Scalar, Urng, _mutable> >
1897 enum { Cost = HugeCost, PacketAccess = 0, IsRepeatable =
false };
Generic expression where a coefficient-wise binary operator is applied to two expressions.
Definition: CwiseHeteroBinaryOp.h:87
Generator of integers on a binomial distribution.
Definition: Discrete.h:858
BinomialGen(_Scalar _trials=1, double _p=0.5)
Construct a new Binomial Generator.
Definition: Discrete.h:874
DiscreteGen(RealIter first, RealIter last)
Construct a new Discrete Generator.
Definition: Discrete.h:611
DiscreteGen(const std::initializer_list< Real > &il)
Construct a new Discrete Generator.
Definition: Discrete.h:644
DiscreteGen(RealIter first, RealIter last)
Construct a new Discrete Generator.
Definition: Discrete.h:494
DiscreteGen(const std::initializer_list< Real > &il)
Construct a new Discrete Generator.
Definition: Discrete.h:527
DiscreteGen(RealIter first, RealIter last)
Construct a new Discrete Generator.
Definition: Discrete.h:359
DiscreteGen(const std::initializer_list< Real > &il)
Construct a new Discrete Generator.
Definition: Discrete.h:392
Generator of integers on the interval [0, n), where the probability of each individual integer i is p...
Definition: Discrete.h:329
Base class of all univariate random generators.
Definition: Basic.h:33
Generator of integers on a geometric distribution.
Definition: Discrete.h:1285
GeometricGen(double _p=0.5)
Construct a new Geometric Generator.
Definition: Discrete.h:1298
Generator of integers on a Poisson distribution.
Definition: Discrete.h:735
PoissonGen(double _mean=1)
Construct a new Poisson Generator.
Definition: Discrete.h:752
Generator of random bits for integral scalars.
Definition: Basic.h:349
const PoissonType< Derived, Urng > poissonLike(Derived &o, Urng &&urng, double mean=1)
generates reals on the Poisson distribution.
Definition: Discrete.h:1693
const DiscreteFType< Derived, Urng > discreteFLike(Derived &o, Urng &&urng, RealIter first, RealIter last)
generates random integers on the interval [0, n), where the probability of each individual integer i ...
Definition: Discrete.h:1416
const UniformIntType< Derived, Urng > uniformInt(Index rows, Index cols, Urng &&urng, typename Derived::Scalar min, typename Derived::Scalar max)
generates integers with a given range [min, max]
Definition: Discrete.h:1347
const GeometricType< Derived, Urng > geometricLike(Derived &o, Urng &&urng, double p=0.5)
generates reals on the geometric distribution.
Definition: Discrete.h:1883
const BinomialType< Derived, Urng > binomialLike(Derived &o, Urng &&urng, typename Derived::Scalar trials=1, double p=0.5)
generates reals on the binomial distribution.
Definition: Discrete.h:1741
const DiscreteType< Derived, Urng > discreteLike(Derived &o, Urng &&urng, RealIter first, RealIter last)
generates random integers on the interval [0, n), where the probability of each individual integer i ...
Definition: Discrete.h:1602
const BinomialType< Derived, Urng > binomial(Index rows, Index cols, Urng &&urng, typename Derived::Scalar trials=1, double p=0.5)
generates reals on the binomial distribution.
Definition: Discrete.h:1719
const GeometricType< Derived, Urng > geometric(Index rows, Index cols, Urng &&urng, double p=0.5)
generates reals on the geometric distribution.
Definition: Discrete.h:1862
const PoissonType< Derived, Urng > poisson(Index rows, Index cols, Urng &&urng, double mean=1)
generates reals on the Poisson distribution.
Definition: Discrete.h:1672
const UniformIntType< Derived, Urng > uniformIntLike(Derived &o, Urng &&urng, typename Derived::Scalar min, typename Derived::Scalar max)
generates integers with a given range [min, max]
Definition: Discrete.h:1368
const DiscreteType< Derived, Urng > discrete(Index rows, Index cols, Urng &&urng, RealIter first, RealIter last)
generates random integers on the interval [0, n), where the probability of each individual integer i ...
Definition: Discrete.h:1580
const DiscreteFType< Derived, Urng > discreteF(Index rows, Index cols, Urng &&urng, RealIter first, RealIter last)
generates random integers on the interval [0, n), where the probability of each individual integer i ...
Definition: Discrete.h:1394
const DiscreteDType< Derived, Urng > discreteD(Index rows, Index cols, Urng &&urng, RealIter first, RealIter last)
generates random integers on the interval [0, n), where the probability of each individual integer i ...
Definition: Discrete.h:1487
const DiscreteDType< Derived, Urng > discreteDLike(Derived &o, Urng &&urng, RealIter first, RealIter last)
generates random integers on the interval [0, n), where the probability of each individual integer i ...
Definition: Discrete.h:1509