13 #ifndef EIGENRAND_DISTS_NORMAL_EXP_H
14 #define EIGENRAND_DISTS_NORMAL_EXP_H
25 template<
typename _Scalar>
28 static_assert(std::is_floating_point<_Scalar>::value,
"normalDist needs floating point types.");
33 using Scalar = _Scalar;
35 template<
typename Rng>
36 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
38 using namespace Eigen::internal;
42 return OptCacheStore::get<_Scalar>();
51 sx = v1 * v1 + v2 * v2;
52 if (sx && sx < 1)
break;
54 _Scalar fx = std::sqrt((_Scalar)-2.0 * std::log(sx) / sx);
55 OptCacheStore::get<_Scalar>() = fx * v2;
59 template<
typename Packet,
typename Rng>
60 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
62 using namespace Eigen::internal;
66 return OptCacheStore::template get<Packet>();
69 Packet u1 = ur.template packetOp<Packet>(rng),
70 u2 = ur.template packetOp<Packet>(rng);
72 u1 = psub(pset1<Packet>(1), u1);
74 auto radius = psqrt(pmul(pset1<Packet>(-2), plog(u1)));
75 auto theta = pmul(pset1<Packet>(2 * constant::pi), u2);
76 Packet sintheta, costheta;
78 psincos(theta, sintheta, costheta);
79 OptCacheStore::template get<Packet>() = pmul(radius, costheta);
80 return pmul(radius, sintheta);
89 template<
typename _Scalar>
92 static_assert(std::is_floating_point<_Scalar>::value,
"normalDist needs floating point types.");
94 _Scalar mean = 0, stdev = 1;
97 using Scalar = _Scalar;
106 : mean{ _mean }, stdev{ _stdev }
110 NormalGen(
const NormalGen&) =
default;
111 NormalGen(NormalGen&&) =
default;
113 template<
typename Rng>
114 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
116 using namespace Eigen::internal;
117 return stdnorm(std::forward<Rng>(rng)) * stdev + mean;
120 template<
typename Packet,
typename Rng>
121 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
123 using namespace Eigen::internal;
125 stdnorm.template packetOp<Packet>(std::forward<Rng>(rng)),
127 ), pset1<Packet>(mean));
136 template<
typename _Scalar>
139 static_assert(std::is_floating_point<_Scalar>::value,
"lognormalDist needs floating point types.");
143 using Scalar = _Scalar;
152 : norm{ _mean, _stdev }
156 LognormalGen(
const LognormalGen&) =
default;
157 LognormalGen(LognormalGen&&) =
default;
159 template<
typename Rng>
160 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
162 using namespace Eigen::internal;
163 return std::exp(norm(std::forward<Rng>(rng)));
166 template<
typename Packet,
typename Rng>
167 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
169 using namespace Eigen::internal;
170 return pexp(norm.template packetOp<Packet>(std::forward<Rng>(rng)));
179 template<
typename _Scalar>
182 static_assert(std::is_floating_point<_Scalar>::value,
"studentT needs floating point types.");
187 using Scalar = _Scalar;
199 StudentTGen(
const StudentTGen&) =
default;
200 StudentTGen(StudentTGen&&) =
default;
202 template<
typename Rng>
203 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
205 using namespace Eigen::internal;
209 v1 = 2 * ur(rng) - 1;
210 v2 = 2 * ur(rng) - 1;
211 sx = v1 * v1 + v2 * v2;
212 if (sx && sx < 1)
break;
215 _Scalar fx = std::sqrt(n * (std::pow(sx, -2 / n) - 1) / sx);
219 template<
typename Packet,
typename Rng>
220 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
222 using namespace Eigen::internal;
223 Packet u1 = ur.template packetOp<Packet>(rng),
224 u2 = ur.template packetOp<Packet>(rng);
226 u1 = psub(pset1<Packet>(1), u1);
227 auto pn = pset1<Packet>(n);
228 auto radius = psqrt(pmul(pn,
229 psub(pexp(pmul(plog(u1), pset1<Packet>(-2 / n))), pset1<Packet>(1))
231 auto theta = pmul(pset1<Packet>(2 * constant::pi), u2);
232 Packet sintheta, costheta;
235 return pmul(radius, psin(theta));
239 template<
typename>
class GammaGen;
246 template<
typename _Scalar>
250 static_assert(std::is_floating_point<_Scalar>::value,
"expDist needs floating point types.");
255 using Scalar = _Scalar;
267 ExponentialGen(
const ExponentialGen&) =
default;
268 ExponentialGen(ExponentialGen&&) =
default;
270 template<
typename Rng>
271 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
273 using namespace Eigen::internal;
274 return -std::log(1 - ur(std::forward<Rng>(rng))) / lambda;
277 template<
typename Packet,
typename Rng>
278 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
280 using namespace Eigen::internal;
281 return pnegate(pdiv(plog(
282 psub(pset1<Packet>(1), ur.template packetOp<Packet>(std::forward<Rng>(rng)))
283 ), pset1<Packet>(lambda)));
287 template<
typename>
class NegativeBinomialGen;
294 template<
typename _Scalar>
297 template<
typename _Ty>
299 static_assert(std::is_floating_point<_Scalar>::value,
"gammaDist needs floating point types.");
300 int cache_rest_cnt = 0;
302 _Scalar alpha,
beta, px, sqrt;
305 using Scalar = _Scalar;
314 : alpha{ _alpha },
beta{ _beta }
316 px = constant::e / (alpha + constant::e);
317 sqrt = std::sqrt(2 * alpha - 1);
320 GammaGen(
const GammaGen&) =
default;
321 GammaGen(GammaGen&&) =
default;
323 template<
typename Rng>
324 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
326 using namespace Eigen::internal;
329 _Scalar ux, vx, xx, qx;
333 vx = expon.ur.nzur_scalar(rng);
337 xx = std::pow(vx, 1 / alpha);
342 xx = 1 - std::log(vx);
343 qx = std::pow(xx, alpha - 1);
346 if (expon.ur(rng) < qx)
354 return beta * expon(rng);
357 if ((count = alpha) == alpha && count < 20)
360 yx = expon.ur.nzur_scalar(rng);
363 yx *= expon.ur.nzur_scalar(rng);
365 return -
beta * std::log(yx);
371 yx = std::tan(constant::pi * expon.ur(rng));
372 xx = sqrt * yx + alpha - 1;
373 if (xx <= 0)
continue;
374 if (expon.ur(rng) <= (1 + yx * yx)
375 * std::exp((alpha - 1) * std::log(xx / (alpha - 1)) - sqrt * yx))
382 template<
typename Packet,
typename Rng>
383 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
385 using namespace Eigen::internal;
386 using RUtils = RandUtils<Packet, Rng>;
387 auto& cm = Rand::detail::CompressMask<
sizeof(Packet)>::get_inst();
394 Packet ux = ru.uniform_real(rng);
395 Packet vx = ru.nonzero_uniform_real(rng);
397 Packet xx = pexp(pmul(pset1<Packet>(1 / alpha), plog(vx)));
398 Packet qx = pexp(pnegate(xx));
400 Packet xx2 = psub(pset1<Packet>(1), plog(vx));
401 Packet qx2 = pexp(pmul(plog(xx2), pset1<Packet>(alpha - 1)));
403 auto c = pcmplt(ux, pset1<Packet>(px));
404 xx = pblendv(c, xx, xx2);
405 qx = pblendv(c, qx, qx2);
407 ux = ru.uniform_real(rng);
408 Packet cands = pmul(pset1<Packet>(
beta), xx);
410 cache_rest_cnt = cm.compress_append(cands, pcmplt(ux, qx),
411 OptCacheStore::template get<Packet>(), cache_rest_cnt, full);
412 if (full)
return cands;
417 return pmul(pset1<Packet>(
beta),
418 expon.template packetOp<Packet>(rng)
422 if ((count = alpha) == alpha && count < 20)
426 yx = ru.nonzero_uniform_real(rng);
429 yx = pmul(yx, ru.nonzero_uniform_real(rng));
431 return pnegate(pmul(pset1<Packet>(
beta), plog(yx)));
437 Packet alpha_1 = pset1<Packet>(alpha - 1);
439 psincos(pmul(pset1<Packet>(constant::pi), ru.uniform_real(rng)), ys, yc);
440 Packet yx = pdiv(ys, yc);
441 Packet xx = padd(pmul(pset1<Packet>(sqrt), yx), alpha_1);
442 auto c = pcmplt(pset1<Packet>(0), xx);
443 Packet ux = ru.uniform_real(rng);
444 Packet ub = pmul(padd(pmul(yx, yx), pset1<Packet>(1)),
446 pmul(alpha_1, plog(pdiv(xx, alpha_1))),
447 pmul(yx, pset1<Packet>(sqrt))
450 c = pand(c, pcmple(ux, ub));
451 Packet cands = pmul(pset1<Packet>(
beta), xx);
453 cache_rest_cnt = cm.compress_append(cands, c,
454 OptCacheStore::template get<Packet>(), cache_rest_cnt, full);
455 if (full)
return cands;
466 template<
typename _Scalar>
469 static_assert(std::is_floating_point<_Scalar>::value,
"weilbullDist needs floating point types.");
471 _Scalar a = 1, b = 1;
474 using Scalar = _Scalar;
487 WeibullGen(
const WeibullGen&) =
default;
488 WeibullGen(WeibullGen&&) =
default;
490 template<
typename Rng>
491 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
493 using namespace Eigen::internal;
494 return std::pow(-std::log(1 - ur(std::forward<Rng>(rng))), 1 / a) * b;
497 template<
typename Packet,
typename Rng>
498 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
500 using namespace Eigen::internal;
501 return pmul(pexp(pmul(plog(pnegate(plog(
502 psub(pset1<Packet>(1), ur.template packetOp<Packet>(std::forward<Rng>(rng)))
503 ))), pset1<Packet>(1 / a))), pset1<Packet>(b));
512 template<
typename _Scalar>
515 static_assert(std::is_floating_point<_Scalar>::value,
"extremeValueDist needs floating point types.");
517 _Scalar a = 0, b = 1;
520 using Scalar = _Scalar;
533 ExtremeValueGen(
const ExtremeValueGen&) =
default;
534 ExtremeValueGen(ExtremeValueGen&&) =
default;
536 template<
typename Rng>
537 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
539 using namespace Eigen::internal;
540 return (a - b * std::log(-std::log(ur.nzur_scalar(std::forward<Rng>(rng)))));
543 template<
typename Packet,
typename Rng>
544 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
546 using namespace Eigen::internal;
547 using RUtils = RandUtils<Packet, Rng>;
548 return psub(pset1<Packet>(a),
549 pmul(plog(pnegate(plog(RUtils{}.nonzero_uniform_real(std::forward<Rng>(rng))))), pset1<Packet>(b))
559 template<
typename _Scalar>
562 static_assert(std::is_floating_point<_Scalar>::value,
"chiSquaredDist needs floating point types.");
565 using Scalar = _Scalar;
573 :
gamma{ n * _Scalar(0.5), 2 }
577 ChiSquaredGen(
const ChiSquaredGen&) =
default;
578 ChiSquaredGen(ChiSquaredGen&&) =
default;
580 template<
typename Rng>
581 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
586 template<
typename Packet,
typename Rng>
587 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
589 return gamma.template packetOp<Packet>(rng);
598 template<
typename _Scalar>
601 static_assert(std::is_floating_point<_Scalar>::value,
"cauchyDist needs floating point types.");
603 _Scalar a = 0, b = 1;
606 using Scalar = _Scalar;
619 CauchyGen(
const CauchyGen&) =
default;
620 CauchyGen(CauchyGen&&) =
default;
622 template<
typename Rng>
623 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
625 using namespace Eigen::internal;
626 return a + b * std::tan(constant::pi * (ur(std::forward<Rng>(rng)) - 0.5));
629 template<
typename Packet,
typename Rng>
630 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
632 using namespace Eigen::internal;
634 psincos(pmul(pset1<Packet>(constant::pi),
635 psub(ur.template packetOp<Packet>(std::forward<Rng>(rng)), pset1<Packet>(0.5))
637 return padd(pset1<Packet>(a),
638 pmul(pset1<Packet>(b), pdiv(s, c))
643 template<
typename>
class FisherFGen;
650 template<
typename _Scalar>
654 static_assert(std::is_floating_point<_Scalar>::value,
"betaDist needs floating point types.");
655 int cache_rest_cnt = 0;
661 using Scalar = _Scalar;
674 BetaGen(
const BetaGen&) =
default;
675 BetaGen(BetaGen&&) =
default;
677 template<
typename Rng>
678 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
680 using namespace Eigen::internal;
686 p1 = std::pow(ur(rng), 1 / a);
687 p2 = std::pow(ur(rng), 1 / b);
695 _Scalar p1 = gd1(rng), p2 = gd2(rng);
696 return p1 / (p1 + p2);
700 template<
typename Packet,
typename Rng>
701 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
703 using namespace Eigen::internal;
706 auto& cm = Rand::detail::CompressMask<
sizeof(Packet)>::get_inst();
710 p1 = pexp(pmul(plog(ur.template packetOp<Packet>(rng)), pset1<Packet>(1 / a)));
711 p2 = pexp(pmul(plog(ur.template packetOp<Packet>(rng)), pset1<Packet>(1 / b)));
713 Packet cands = pdiv(p1, x);
715 cache_rest_cnt = cm.compress_append(cands, pcmple(x, pset1<Packet>(1)),
716 OptCacheStore::template get<Packet>(), cache_rest_cnt, full);
717 if (full)
return cands;
722 auto p1 = gd1.template packetOp<Packet>(rng),
723 p2 = gd2.template packetOp<Packet>(rng);
724 return pdiv(p1, padd(p1, p2));
734 template<
typename _Scalar>
737 static_assert(std::is_floating_point<_Scalar>::value,
"fisherF needs floating point types.");
740 using Scalar = _Scalar;
748 :
beta{ m * _Scalar(0.5), n * _Scalar(0.5) }
752 FisherFGen(
const FisherFGen&) =
default;
753 FisherFGen(FisherFGen&&) =
default;
755 template<
typename Rng>
756 EIGEN_STRONG_INLINE
const _Scalar operator() (Rng&& rng)
758 using namespace Eigen::internal;
759 auto x =
beta(std::forward<Rng>(rng));
760 return beta.b /
beta.a * x / (1 - x);
763 template<
typename Packet,
typename Rng>
764 EIGEN_STRONG_INLINE
const Packet packetOp(Rng&& rng)
766 using namespace Eigen::internal;
767 auto x =
beta.template packetOp<Packet>(std::forward<Rng>(rng));
768 return pdiv(pmul(pset1<Packet>(
beta.b /
beta.a), x), psub(pset1<Packet>(1), x));
773 template<
typename Derived,
typename Urng>
774 using BetaType = CwiseNullaryOp<internal::scalar_rng_adaptor<BetaGen<typename Derived::Scalar>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
789 template<
typename Derived,
typename Urng>
790 inline const BetaType<Derived, Urng>
791 beta(Index rows, Index cols, Urng&& urng,
typename Derived::Scalar a = 1,
typename Derived::Scalar b = 1)
810 template<
typename Derived,
typename Urng>
811 inline const BetaType<Derived, Urng>
812 betaLike(Derived& o, Urng&& urng,
typename Derived::Scalar a = 1,
typename Derived::Scalar b = 1)
819 template<
typename Derived,
typename Urng>
820 using CauchyType = CwiseNullaryOp<internal::scalar_rng_adaptor<CauchyGen<typename Derived::Scalar>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
836 template<
typename Derived,
typename Urng>
837 inline const CauchyType<Derived, Urng>
838 cauchy(Index rows, Index cols, Urng&& urng,
typename Derived::Scalar a = 0,
typename Derived::Scalar b = 1)
858 template<
typename Derived,
typename Urng>
859 inline const CauchyType<Derived, Urng>
860 cauchyLike(Derived& o, Urng&& urng,
typename Derived::Scalar a = 0,
typename Derived::Scalar b = 1)
867 template<
typename Derived,
typename Urng>
868 using NormalType = CwiseNullaryOp<internal::scalar_rng_adaptor<StdNormalGen<typename Derived::Scalar>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
882 template<
typename Derived,
typename Urng>
883 inline const NormalType<Derived, Urng>
884 normal(Index rows, Index cols, Urng&& urng)
887 rows, cols, { std::forward<Urng>(urng) }
902 template<
typename Derived,
typename Urng>
903 inline const NormalType<Derived, Urng>
907 o.rows(), o.cols(), { std::forward<Urng>(urng) }
911 template<
typename Derived,
typename Urng>
912 using Normal2Type = CwiseNullaryOp<internal::scalar_rng_adaptor<NormalGen<typename Derived::Scalar>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
928 template<
typename Derived,
typename Urng>
929 inline const Normal2Type<Derived, Urng>
930 normal(Index rows, Index cols, Urng&& urng,
typename Derived::Scalar mean,
typename Derived::Scalar stdev = 1)
950 template<
typename Derived,
typename Urng>
951 inline const Normal2Type<Derived, Urng>
952 normalLike(Derived& o, Urng&& urng,
typename Derived::Scalar mean,
typename Derived::Scalar stdev = 1)
959 template<
typename Derived,
typename Urng>
960 using LognormalType = CwiseNullaryOp<internal::scalar_rng_adaptor<LognormalGen<typename Derived::Scalar>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
976 template<
typename Derived,
typename Urng>
977 inline const LognormalType<Derived, Urng>
978 lognormal(Index rows, Index cols, Urng&& urng,
typename Derived::Scalar mean = 0,
typename Derived::Scalar stdev = 1)
998 template<
typename Derived,
typename Urng>
999 inline const LognormalType<Derived, Urng>
1000 lognormalLike(Derived& o, Urng&& urng,
typename Derived::Scalar mean = 0,
typename Derived::Scalar stdev = 1)
1007 template<
typename Derived,
typename Urng>
1008 using StudentTType = CwiseNullaryOp<internal::scalar_rng_adaptor<StudentTGen<typename Derived::Scalar>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
1023 template<
typename Derived,
typename Urng>
1024 inline const StudentTType<Derived, Urng>
1025 studentT(Index rows, Index cols, Urng&& urng,
typename Derived::Scalar n = 1)
1044 template<
typename Derived,
typename Urng>
1045 inline const StudentTType<Derived, Urng>
1053 template<
typename Derived,
typename Urng>
1054 using ExponentialType = CwiseNullaryOp<internal::scalar_rng_adaptor<ExponentialGen<typename Derived::Scalar>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
1069 template<
typename Derived,
typename Urng>
1070 inline const ExponentialType<Derived, Urng>
1071 exponential(Index rows, Index cols, Urng&& urng,
typename Derived::Scalar lambda = 1)
1090 template<
typename Derived,
typename Urng>
1091 inline const ExponentialType<Derived, Urng>
1099 template<
typename Derived,
typename Urng>
1100 using GammaType = CwiseNullaryOp<internal::scalar_rng_adaptor<GammaGen<typename Derived::Scalar>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
1116 template<
typename Derived,
typename Urng>
1117 inline const GammaType<Derived, Urng>
1118 gamma(Index rows, Index cols, Urng&& urng,
typename Derived::Scalar alpha = 1,
typename Derived::Scalar
beta = 1)
1138 template<
typename Derived,
typename Urng>
1139 inline const GammaType<Derived, Urng>
1140 gammaLike(Derived& o, Urng&& urng,
typename Derived::Scalar alpha = 1,
typename Derived::Scalar
beta = 1)
1147 template<
typename Derived,
typename Urng>
1148 using WeibullType = CwiseNullaryOp<internal::scalar_rng_adaptor<WeibullGen<typename Derived::Scalar>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
1164 template<
typename Derived,
typename Urng>
1165 inline const WeibullType<Derived, Urng>
1166 weibull(Index rows, Index cols, Urng&& urng,
typename Derived::Scalar a = 1,
typename Derived::Scalar b = 1)
1186 template<
typename Derived,
typename Urng>
1187 inline const WeibullType<Derived, Urng>
1188 weibullLike(Derived& o, Urng&& urng,
typename Derived::Scalar a = 1,
typename Derived::Scalar b = 1)
1195 template<
typename Derived,
typename Urng>
1196 using ExtremeValueType = CwiseNullaryOp<internal::scalar_rng_adaptor<ExtremeValueGen<typename Derived::Scalar>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
1213 template<
typename Derived,
typename Urng>
1214 inline const ExtremeValueType<Derived, Urng>
1215 extremeValue(Index rows, Index cols, Urng&& urng,
typename Derived::Scalar a = 0,
typename Derived::Scalar b = 1)
1236 template<
typename Derived,
typename Urng>
1237 inline const ExtremeValueType<Derived, Urng>
1238 extremeValueLike(Derived& o, Urng&& urng,
typename Derived::Scalar a = 0,
typename Derived::Scalar b = 1)
1245 template<
typename Derived,
typename Urng>
1246 using ChiSquaredType = CwiseNullaryOp<internal::scalar_rng_adaptor<ChiSquaredGen<typename Derived::Scalar>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
1261 template<
typename Derived,
typename Urng>
1262 inline const ChiSquaredType<Derived, Urng>
1263 chiSquared(Index rows, Index cols, Urng&& urng,
typename Derived::Scalar n = 1)
1282 template<
typename Derived,
typename Urng>
1283 inline const ChiSquaredType<Derived, Urng>
1291 template<
typename Derived,
typename Urng>
1292 using FisherFType = CwiseNullaryOp<internal::scalar_rng_adaptor<FisherFGen<typename Derived::Scalar>,
typename Derived::Scalar, Urng,
true>,
const Derived>;
1308 template<
typename Derived,
typename Urng>
1309 inline const FisherFType<Derived, Urng>
1310 fisherF(Index rows, Index cols, Urng&& urng,
typename Derived::Scalar m = 1,
typename Derived::Scalar n = 1)
1330 template<
typename Derived,
typename Urng>
1331 inline const FisherFType<Derived, Urng>
1332 fisherFLike(Derived& o, Urng&& urng,
typename Derived::Scalar m = 1,
typename Derived::Scalar n = 1)