tomoto 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/ext/tomoto/ct.cpp +8 -4
  4. data/ext/tomoto/dmr.cpp +10 -4
  5. data/ext/tomoto/dt.cpp +13 -4
  6. data/ext/tomoto/extconf.rb +1 -1
  7. data/ext/tomoto/gdmr.cpp +14 -6
  8. data/ext/tomoto/hdp.cpp +9 -4
  9. data/ext/tomoto/hlda.cpp +9 -4
  10. data/ext/tomoto/hpa.cpp +9 -4
  11. data/ext/tomoto/lda.cpp +8 -4
  12. data/ext/tomoto/llda.cpp +8 -4
  13. data/ext/tomoto/mglda.cpp +11 -1
  14. data/ext/tomoto/pa.cpp +9 -4
  15. data/ext/tomoto/plda.cpp +8 -4
  16. data/ext/tomoto/slda.cpp +13 -5
  17. data/lib/tomoto/gdmr.rb +2 -2
  18. data/lib/tomoto/version.rb +1 -1
  19. data/vendor/EigenRand/EigenRand/Core.h +6 -1107
  20. data/vendor/EigenRand/EigenRand/Dists/Basic.h +490 -43
  21. data/vendor/EigenRand/EigenRand/Dists/Discrete.h +916 -285
  22. data/vendor/EigenRand/EigenRand/Dists/GammaPoisson.h +85 -36
  23. data/vendor/EigenRand/EigenRand/Dists/NormalExp.h +1038 -290
  24. data/vendor/EigenRand/EigenRand/EigenRand +2 -2
  25. data/vendor/EigenRand/EigenRand/Macro.h +4 -4
  26. data/vendor/EigenRand/EigenRand/MorePacketMath.h +54 -22
  27. data/vendor/EigenRand/EigenRand/MvDists/Multinomial.h +222 -0
  28. data/vendor/EigenRand/EigenRand/MvDists/MvNormal.h +492 -0
  29. data/vendor/EigenRand/EigenRand/PacketFilter.h +2 -2
  30. data/vendor/EigenRand/EigenRand/PacketRandomEngine.h +2 -2
  31. data/vendor/EigenRand/EigenRand/RandUtils.h +65 -11
  32. data/vendor/EigenRand/EigenRand/doc.h +142 -25
  33. data/vendor/EigenRand/LICENSE +1 -1
  34. data/vendor/EigenRand/README.md +109 -24
  35. data/vendor/tomotopy/README.kr.rst +27 -6
  36. data/vendor/tomotopy/README.rst +29 -8
  37. data/vendor/tomotopy/src/Labeling/FoRelevance.cpp +60 -12
  38. data/vendor/tomotopy/src/Labeling/FoRelevance.h +2 -2
  39. data/vendor/tomotopy/src/Labeling/Phraser.hpp +33 -21
  40. data/vendor/tomotopy/src/TopicModel/CT.h +8 -5
  41. data/vendor/tomotopy/src/TopicModel/CTModel.cpp +2 -6
  42. data/vendor/tomotopy/src/TopicModel/CTModel.hpp +29 -23
  43. data/vendor/tomotopy/src/TopicModel/DMR.h +33 -4
  44. data/vendor/tomotopy/src/TopicModel/DMRModel.cpp +2 -6
  45. data/vendor/tomotopy/src/TopicModel/DMRModel.hpp +231 -57
  46. data/vendor/tomotopy/src/TopicModel/DT.h +24 -5
  47. data/vendor/tomotopy/src/TopicModel/DTModel.cpp +2 -8
  48. data/vendor/tomotopy/src/TopicModel/DTModel.hpp +41 -28
  49. data/vendor/tomotopy/src/TopicModel/GDMR.h +31 -5
  50. data/vendor/tomotopy/src/TopicModel/GDMRModel.cpp +2 -7
  51. data/vendor/tomotopy/src/TopicModel/GDMRModel.hpp +211 -104
  52. data/vendor/tomotopy/src/TopicModel/HDP.h +11 -2
  53. data/vendor/tomotopy/src/TopicModel/HDPModel.cpp +2 -6
  54. data/vendor/tomotopy/src/TopicModel/HDPModel.hpp +52 -45
  55. data/vendor/tomotopy/src/TopicModel/HLDA.h +11 -2
  56. data/vendor/tomotopy/src/TopicModel/HLDAModel.cpp +2 -6
  57. data/vendor/tomotopy/src/TopicModel/HLDAModel.hpp +13 -16
  58. data/vendor/tomotopy/src/TopicModel/HPA.h +5 -2
  59. data/vendor/tomotopy/src/TopicModel/HPAModel.cpp +2 -6
  60. data/vendor/tomotopy/src/TopicModel/HPAModel.hpp +51 -21
  61. data/vendor/tomotopy/src/TopicModel/LDA.h +9 -2
  62. data/vendor/tomotopy/src/TopicModel/LDACVB0Model.hpp +8 -8
  63. data/vendor/tomotopy/src/TopicModel/LDAModel.cpp +2 -6
  64. data/vendor/tomotopy/src/TopicModel/LDAModel.hpp +70 -28
  65. data/vendor/tomotopy/src/TopicModel/LLDA.h +1 -2
  66. data/vendor/tomotopy/src/TopicModel/LLDAModel.cpp +2 -6
  67. data/vendor/tomotopy/src/TopicModel/LLDAModel.hpp +22 -12
  68. data/vendor/tomotopy/src/TopicModel/MGLDA.h +12 -3
  69. data/vendor/tomotopy/src/TopicModel/MGLDAModel.cpp +2 -10
  70. data/vendor/tomotopy/src/TopicModel/MGLDAModel.hpp +42 -19
  71. data/vendor/tomotopy/src/TopicModel/PA.h +9 -4
  72. data/vendor/tomotopy/src/TopicModel/PAModel.cpp +2 -6
  73. data/vendor/tomotopy/src/TopicModel/PAModel.hpp +48 -25
  74. data/vendor/tomotopy/src/TopicModel/PLDA.h +13 -2
  75. data/vendor/tomotopy/src/TopicModel/PLDAModel.cpp +2 -6
  76. data/vendor/tomotopy/src/TopicModel/PLDAModel.hpp +27 -19
  77. data/vendor/tomotopy/src/TopicModel/PT.h +12 -5
  78. data/vendor/tomotopy/src/TopicModel/PTModel.cpp +2 -3
  79. data/vendor/tomotopy/src/TopicModel/PTModel.hpp +29 -14
  80. data/vendor/tomotopy/src/TopicModel/SLDA.h +18 -6
  81. data/vendor/tomotopy/src/TopicModel/SLDAModel.cpp +2 -10
  82. data/vendor/tomotopy/src/TopicModel/SLDAModel.hpp +93 -43
  83. data/vendor/tomotopy/src/TopicModel/TopicModel.hpp +58 -23
  84. data/vendor/tomotopy/src/Utils/AliasMethod.hpp +6 -6
  85. data/vendor/tomotopy/src/Utils/Dictionary.h +11 -0
  86. data/vendor/tomotopy/src/Utils/SharedString.hpp +26 -1
  87. data/vendor/tomotopy/src/Utils/Trie.hpp +46 -21
  88. data/vendor/tomotopy/src/Utils/Utils.hpp +99 -14
  89. data/vendor/tomotopy/src/Utils/exception.h +1 -1
  90. data/vendor/tomotopy/src/Utils/math.h +5 -7
  91. data/vendor/tomotopy/src/Utils/serializer.hpp +329 -201
  92. data/vendor/tomotopy/src/Utils/text.hpp +8 -0
  93. data/vendor/tomotopy/src/Utils/tvector.hpp +49 -7
  94. metadata +9 -7
@@ -1,10 +1,9 @@
1
- #pragma once
2
1
  /**
3
2
  * @file GammaPoisson.h
4
3
  * @author bab2min (bab2min@gmail.com)
5
4
  * @brief
6
- * @version 0.2.0
7
- * @date 2020-06-22
5
+ * @version 0.3.0
6
+ * @date 2020-10-07
8
7
  *
9
8
  * @copyright Copyright (c) 2020
10
9
  *
@@ -19,39 +18,57 @@
19
18
 
20
19
  namespace Eigen
21
20
  {
22
- namespace internal
21
+ namespace Rand
23
22
  {
24
- template<typename Scalar, typename Rng>
25
- struct scalar_negative_binomial_dist_op : public scalar_gamma_dist_op<float, Rng>
23
+ /**
24
+ * @brief Generator of integers on a negative binomial distribution
25
+ *
26
+ * @tparam _Scalar
27
+ */
28
+ template<typename _Scalar>
29
+ class NegativeBinomialGen : public GenBase<NegativeBinomialGen<_Scalar>, _Scalar>
26
30
  {
27
- static_assert(std::is_same<Scalar, int32_t>::value, "uniformInt needs integral types.");
31
+ static_assert(std::is_same<_Scalar, int32_t>::value, "negativeBinomial needs integral types.");
32
+ UniformRealGen<float> ur;
33
+ GammaGen<float> gamma;
34
+ public:
35
+ using Scalar = _Scalar;
28
36
 
29
- scalar_negative_binomial_dist_op(const Rng& _rng, Scalar _trials = 1, double _p = 0.5)
30
- : scalar_gamma_dist_op<float, Rng>{ _rng, (float)_trials, (float)((1 - _p) / _p) }
37
+ /**
38
+ * @brief Construct a new negative binomial generator
39
+ *
40
+ * @param _trials the number of trial successes
41
+ * @param _p probability of a trial generating true
42
+ */
43
+ NegativeBinomialGen(_Scalar _trials = 1, double _p = 0.5)
44
+ : gamma{ (float)_trials, (float)((1 - _p) / _p) }
31
45
 
32
46
  {
33
47
  }
34
48
 
35
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() () const
49
+ template<typename Rng>
50
+ EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
36
51
  {
37
- float v = scalar_gamma_dist_op<float, Rng>::operator()();
38
- return scalar_poisson_dist_op<Scalar, Rng>{ this->rng, v }();
52
+ using namespace Eigen::internal;
53
+ float v = gamma(rng);
54
+ return PoissonGen<_Scalar>{v}(rng);
39
55
  }
40
56
 
41
- template<typename Packet>
42
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp() const
57
+ template<typename Packet, typename Rng>
58
+ EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
43
59
  {
44
- using ur_base = scalar_uniform_real_op<float, Rng>;
60
+ using namespace Eigen::internal;
61
+ using ur_base = UniformRealGen<float>;
45
62
  using PacketType = decltype(reinterpret_to_float(std::declval<Packet>()));
46
-
47
- auto mean = scalar_gamma_dist_op<float, Rng>::template packetOp<PacketType>();
63
+
64
+ auto mean = gamma.template packetOp<PacketType>(rng);
48
65
  auto res = pset1<Packet>(0);
49
66
  PacketType val = pset1<PacketType>(1), pne_mean = pexp(pnegate(mean));
50
67
  if (pmovemask(pcmplt(pset1<PacketType>(12), mean)) == 0)
51
68
  {
52
69
  while (1)
53
70
  {
54
- val = pmul(val, ur_base::template packetOp<PacketType>());
71
+ val = pmul(val, ur.template packetOp<PacketType>(rng));
55
72
  auto c = reinterpret_to_int(pcmplt(pne_mean, val));
56
73
  if (pmovemask(c) == 0) break;
57
74
  res = padd(res, pnegate(c));
@@ -61,16 +78,6 @@ namespace Eigen
61
78
  else
62
79
  {
63
80
  auto& cm = Rand::detail::CompressMask<sizeof(Packet)>::get_inst();
64
- thread_local PacketType cache_rest;
65
- thread_local int cache_rest_cnt;
66
- thread_local const scalar_negative_binomial_dist_op* cache_ptr = nullptr;
67
- if (cache_ptr != this)
68
- {
69
- cache_ptr = this;
70
- cache_rest = pset1<PacketType>(0);
71
- cache_rest_cnt = 0;
72
- }
73
-
74
81
  const PacketType ppi = pset1<PacketType>(constant::pi),
75
82
  psqrt_tmean = psqrt(pmul(pset1<PacketType>(2), mean)),
76
83
  plog_mean = plog(mean),
@@ -78,7 +85,7 @@ namespace Eigen
78
85
  while (1)
79
86
  {
80
87
  PacketType fres, yx, psin, pcos;
81
- psincos(pmul(ppi, ur_base::template packetOp<PacketType>()), psin, pcos);
88
+ psincos(pmul(ppi, ur.template packetOp<PacketType>(rng)), psin, pcos);
82
89
  yx = pdiv(psin, pcos);
83
90
  fres = ptruncate(padd(pmul(psqrt_tmean, yx), mean));
84
91
 
@@ -86,23 +93,65 @@ namespace Eigen
86
93
  auto p2 = pexp(psub(psub(pmul(fres, plog_mean), plgamma(padd(fres, pset1<PacketType>(1)))), pg1));
87
94
 
88
95
  auto c1 = pcmple(pset1<PacketType>(0), fres);
89
- auto c2 = pcmple(ur_base::template packetOp<PacketType>(), pmul(p1, p2));
96
+ auto c2 = pcmple(ur.template packetOp<PacketType>(rng), pmul(p1, p2));
90
97
 
91
98
  auto cands = fres;
92
99
  bool full = false;
93
- cache_rest_cnt = cm.compress_append(cands, pand(c1, c2),
94
- cache_rest, cache_rest_cnt, full);
100
+ gamma.cache_rest_cnt = cm.compress_append(cands, pand(c1, c2),
101
+ gamma.template get<PacketType>(), gamma.cache_rest_cnt, full);
95
102
  if (full) return pcast<PacketType, Packet>(cands);
96
103
  }
97
104
  }
98
105
  }
99
106
  };
100
107
 
101
- template<typename Scalar, typename Urng>
102
- struct functor_traits<scalar_negative_binomial_dist_op<Scalar, Urng> >
108
+ template<typename Derived, typename Urng>
109
+ using NegativeBinomialType = CwiseNullaryOp<internal::scalar_rng_adaptor<NegativeBinomialGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
110
+
111
+ /**
112
+ * @brief generates reals on the negative binomial distribution.
113
+ *
114
+ * @tparam Derived
115
+ * @tparam Urng
116
+ * @param rows the number of rows being generated
117
+ * @param cols the number of columns being generated
118
+ * @param urng c++11-style random number generator
119
+ * @param trials the number of trial successes
120
+ * @param p probability of a trial generating true
121
+ * @return a random matrix expression with a shape (`rows`, `cols`)
122
+ *
123
+ * @see Eigen::Rand::NegativeBinomialGen
124
+ */
125
+ template<typename Derived, typename Urng>
126
+ inline const NegativeBinomialType<Derived, Urng>
127
+ negativeBinomial(Index rows, Index cols, Urng&& urng, typename Derived::Scalar trials = 1, double p = 0.5)
103
128
  {
104
- enum { Cost = HugeCost, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = false };
105
- };
129
+ return {
130
+ rows, cols, { std::forward<Urng>(urng), NegativeBinomialGen<typename Derived::Scalar>{trials, p} }
131
+ };
132
+ }
133
+
134
+ /**
135
+ * @brief generates reals on the negative binomial distribution.
136
+ *
137
+ * @tparam Derived
138
+ * @tparam Urng
139
+ * @param o an instance of any type of Eigen::DenseBase
140
+ * @param urng c++11-style random number generator
141
+ * @param trials the number of trial successes
142
+ * @param p probability of a trial generating true
143
+ * @return a random matrix expression of the same shape as `o`
144
+ *
145
+ * @see Eigen::Rand::NegativeBinomialGen
146
+ */
147
+ template<typename Derived, typename Urng>
148
+ inline const NegativeBinomialType<Derived, Urng>
149
+ negativeBinomialLike(Derived& o, Urng&& urng, typename Derived::Scalar trials = 1, double p = 0.5)
150
+ {
151
+ return {
152
+ o.rows(), o.cols(), { std::forward<Urng>(urng), NegativeBinomialGen<typename Derived::Scalar>{trials, p} }
153
+ };
154
+ }
106
155
  }
107
156
  }
108
157
  #endif
@@ -2,8 +2,8 @@
2
2
  * @file NormalExp.h
3
3
  * @author bab2min (bab2min@gmail.com)
4
4
  * @brief
5
- * @version 0.2.0
6
- * @date 2020-06-22
5
+ * @version 0.3.0
6
+ * @date 2020-10-07
7
7
  *
8
8
  * @copyright Copyright (c) 2020
9
9
  *
@@ -15,53 +15,59 @@
15
15
 
16
16
  namespace Eigen
17
17
  {
18
- namespace internal
18
+ namespace Rand
19
19
  {
20
- template<typename Scalar, typename Rng>
21
- struct scalar_norm_dist_op : public scalar_uniform_real_op<Scalar, Rng>
20
+ /**
21
+ * @brief Generator of reals on the standard normal distribution
22
+ *
23
+ * @tparam _Scalar
24
+ */
25
+ template<typename _Scalar>
26
+ class StdNormalGen : OptCacheStore, public GenBase<StdNormalGen<_Scalar>, _Scalar>
22
27
  {
23
- static_assert(std::is_floating_point<Scalar>::value, "normalDist needs floating point types.");
24
- using ur_base = scalar_uniform_real_op<Scalar, Rng>;
25
-
26
- using ur_base::scalar_uniform_real_op;
27
-
28
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() () const
28
+ static_assert(std::is_floating_point<_Scalar>::value, "normalDist needs floating point types.");
29
+ bool valid = false;
30
+ UniformRealGen<_Scalar> ur;
31
+
32
+ public:
33
+ using Scalar = _Scalar;
34
+
35
+ template<typename Rng>
36
+ EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
29
37
  {
30
- thread_local Scalar cache;
31
- thread_local const scalar_norm_dist_op* cache_ptr = nullptr;
32
- if (cache_ptr == this)
38
+ using namespace Eigen::internal;
39
+ if (valid)
33
40
  {
34
- cache_ptr = nullptr;
35
- return cache;
41
+ valid = false;
42
+ return OptCacheStore::get<_Scalar>();
36
43
  }
37
- cache_ptr = this;
44
+ valid = true;
38
45
 
39
- Scalar v1, v2, sx;
46
+ _Scalar v1, v2, sx;
40
47
  while (1)
41
48
  {
42
- v1 = 2 * ur_base::operator()() - 1;
43
- v2 = 2 * ur_base::operator()() - 1;
49
+ v1 = 2 * ur(rng) - 1;
50
+ v2 = 2 * ur(rng) - 1;
44
51
  sx = v1 * v1 + v2 * v2;
45
52
  if (sx && sx < 1) break;
46
53
  }
47
- Scalar fx = std::sqrt((Scalar)-2.0 * std::log(sx) / sx);
48
- cache = fx * v2;
54
+ _Scalar fx = std::sqrt((_Scalar)-2.0 * std::log(sx) / sx);
55
+ OptCacheStore::get<_Scalar>() = fx * v2;
49
56
  return fx * v1;
50
57
  }
51
58
 
52
- template<typename Packet>
53
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp() const
59
+ template<typename Packet, typename Rng>
60
+ EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
54
61
  {
55
- thread_local Packet cache;
56
- thread_local const scalar_norm_dist_op* cache_ptr = nullptr;
57
- if (cache_ptr == this)
62
+ using namespace Eigen::internal;
63
+ if (valid)
58
64
  {
59
- cache_ptr = nullptr;
60
- return cache;
65
+ valid = false;
66
+ return OptCacheStore::template get<Packet>();
61
67
  }
62
- cache_ptr = this;
63
- Packet u1 = ur_base::template packetOp<Packet>(),
64
- u2 = ur_base::template packetOp<Packet>();
68
+ valid = true;
69
+ Packet u1 = ur.template packetOp<Packet>(rng),
70
+ u2 = ur.template packetOp<Packet>(rng);
65
71
 
66
72
  u1 = psub(pset1<Packet>(1), u1);
67
73
 
@@ -70,114 +76,165 @@ namespace Eigen
70
76
  Packet sintheta, costheta;
71
77
 
72
78
  psincos(theta, sintheta, costheta);
73
- cache = pmul(radius, costheta);
79
+ OptCacheStore::template get<Packet>() = pmul(radius, costheta);
74
80
  return pmul(radius, sintheta);
75
81
  }
76
82
  };
77
83
 
78
- template<typename Scalar, typename Urng>
79
- struct functor_traits<scalar_norm_dist_op<Scalar, Urng> >
84
+ /**
85
+ * @brief Generator of reals on a normal distribution
86
+ *
87
+ * @tparam _Scalar
88
+ */
89
+ template<typename _Scalar>
90
+ class NormalGen : public GenBase<NormalGen<_Scalar>, _Scalar>
80
91
  {
81
- enum { Cost = HugeCost, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = false };
82
- };
83
-
84
- template<typename Scalar, typename Rng>
85
- struct scalar_norm_dist2_op : public scalar_norm_dist_op<Scalar, Rng>
86
- {
87
- static_assert(std::is_floating_point<Scalar>::value, "normalDist needs floating point types.");
88
-
89
- Scalar mean = 0, stdev = 1;
90
-
91
- scalar_norm_dist2_op(const Rng& _rng,
92
- Scalar _mean = 0, Scalar _stdev = 1)
93
- : scalar_norm_dist_op<Scalar, Rng>{ _rng },
94
- mean{ _mean }, stdev{ _stdev }
92
+ static_assert(std::is_floating_point<_Scalar>::value, "normalDist needs floating point types.");
93
+ StdNormalGen<_Scalar> stdnorm;
94
+ _Scalar mean = 0, stdev = 1;
95
+
96
+ public:
97
+ using Scalar = _Scalar;
98
+
99
+ /**
100
+ * @brief Construct a new normal generator
101
+ *
102
+ * @param _mean mean of the distribution
103
+ * @param _stdev standard deviation of the distribution
104
+ */
105
+ NormalGen(_Scalar _mean = 0, _Scalar _stdev = 1)
106
+ : mean{ _mean }, stdev{ _stdev }
95
107
  {
96
108
  }
97
109
 
98
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() () const
110
+ NormalGen(const NormalGen&) = default;
111
+ NormalGen(NormalGen&&) = default;
112
+
113
+ NormalGen& operator=(const NormalGen&) = default;
114
+ NormalGen& operator=(NormalGen&&) = default;
115
+
116
+ template<typename Rng>
117
+ EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
99
118
  {
100
- return scalar_norm_dist_op<Scalar, Rng>::operator()() * stdev + mean;
119
+ using namespace Eigen::internal;
120
+ return stdnorm(std::forward<Rng>(rng)) * stdev + mean;
101
121
  }
102
122
 
103
- template<typename Packet>
104
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp() const
123
+ template<typename Packet, typename Rng>
124
+ EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
105
125
  {
126
+ using namespace Eigen::internal;
106
127
  return padd(pmul(
107
- scalar_norm_dist_op<Scalar, Rng>::template packetOp<Packet>(),
128
+ stdnorm.template packetOp<Packet>(std::forward<Rng>(rng)),
108
129
  pset1<Packet>(stdev)
109
130
  ), pset1<Packet>(mean));
110
131
  }
111
132
  };
112
133
 
113
- template<typename Scalar, typename Urng>
114
- struct functor_traits<scalar_norm_dist2_op<Scalar, Urng> >
134
+ /**
135
+ * @brief Generator of reals on a lognormal distribution
136
+ *
137
+ * @tparam _Scalar
138
+ */
139
+ template<typename _Scalar>
140
+ class LognormalGen : public GenBase<LognormalGen<_Scalar>, _Scalar>
115
141
  {
116
- enum { Cost = HugeCost, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = false };
117
- };
142
+ static_assert(std::is_floating_point<_Scalar>::value, "lognormalDist needs floating point types.");
143
+ NormalGen<_Scalar> norm;
144
+
145
+ public:
146
+ using Scalar = _Scalar;
147
+
148
+ /**
149
+ * @brief Construct a new lognormal generator
150
+ *
151
+ * @param _mean mean of the log distribution
152
+ * @param _stdev standard deviation of the log distribution
153
+ */
154
+ LognormalGen(_Scalar _mean = 0, _Scalar _stdev = 1)
155
+ : norm{ _mean, _stdev }
156
+ {
157
+ }
118
158
 
119
- template<typename Scalar, typename Rng>
120
- struct scalar_lognorm_dist_op : public scalar_norm_dist2_op<Scalar, Rng>
121
- {
122
- static_assert(std::is_floating_point<Scalar>::value, "lognormalDist needs floating point types.");
159
+ LognormalGen(const LognormalGen&) = default;
160
+ LognormalGen(LognormalGen&&) = default;
123
161
 
124
- using scalar_norm_dist2_op<Scalar, Rng>::scalar_norm_dist2_op;
162
+ LognormalGen& operator=(const LognormalGen&) = default;
163
+ LognormalGen& operator=(LognormalGen&&) = default;
125
164
 
126
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() () const
165
+ template<typename Rng>
166
+ EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
127
167
  {
128
- return std::exp(scalar_norm_dist2_op<Scalar, Rng>::operator()());
168
+ using namespace Eigen::internal;
169
+ return std::exp(norm(std::forward<Rng>(rng)));
129
170
  }
130
171
 
131
- template<typename Packet>
132
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp() const
172
+ template<typename Packet, typename Rng>
173
+ EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
133
174
  {
134
- return pexp(scalar_norm_dist2_op<Scalar, Rng>::template packetOp<Packet>());
175
+ using namespace Eigen::internal;
176
+ return pexp(norm.template packetOp<Packet>(std::forward<Rng>(rng)));
135
177
  }
136
178
  };
137
179
 
138
- template<typename Scalar, typename Urng>
139
- struct functor_traits<scalar_lognorm_dist_op<Scalar, Urng> >
180
+ /**
181
+ * @brief Generator of reals on a Student's t distribution
182
+ *
183
+ * @tparam _Scalar
184
+ */
185
+ template<typename _Scalar>
186
+ class StudentTGen : public GenBase<StudentTGen<_Scalar>, _Scalar>
140
187
  {
141
- enum { Cost = HugeCost, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = false };
142
- };
143
-
144
- template<typename Scalar, typename Rng>
145
- struct scalar_student_t_dist_op : public scalar_uniform_real_op<Scalar, Rng>
146
- {
147
- static_assert(std::is_floating_point<Scalar>::value, "normalDist needs floating point types.");
148
- using ur_base = scalar_uniform_real_op<Scalar, Rng>;
149
-
150
- Scalar n;
151
-
152
- scalar_student_t_dist_op(const Rng& _rng, Scalar _n = 1)
153
- : ur_base{ _rng }, n{ _n }
188
+ static_assert(std::is_floating_point<_Scalar>::value, "studentT needs floating point types.");
189
+ UniformRealGen<_Scalar> ur;
190
+ _Scalar n;
191
+
192
+ public:
193
+ using Scalar = _Scalar;
194
+
195
+ /**
196
+ * @brief Construct a new Student's t generator
197
+ *
198
+ * @param _n degrees of freedom
199
+ */
200
+ StudentTGen(_Scalar _n = 1)
201
+ : n{ _n }
154
202
  {
155
203
  }
156
204
 
157
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() () const
205
+ StudentTGen(const StudentTGen&) = default;
206
+ StudentTGen(StudentTGen&&) = default;
207
+
208
+ StudentTGen& operator=(const StudentTGen&) = default;
209
+ StudentTGen& operator=(StudentTGen&&) = default;
210
+
211
+ template<typename Rng>
212
+ EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
158
213
  {
159
- Scalar v1, v2, sx;
214
+ using namespace Eigen::internal;
215
+ _Scalar v1, v2, sx;
160
216
  while (1)
161
217
  {
162
- v1 = 2 * ur_base::operator()() - 1;
163
- v2 = 2 * ur_base::operator()() - 1;
218
+ v1 = 2 * ur(rng) - 1;
219
+ v2 = 2 * ur(rng) - 1;
164
220
  sx = v1 * v1 + v2 * v2;
165
221
  if (sx && sx < 1) break;
166
222
  }
167
223
 
168
- Scalar fx = std::sqrt(n * (std::pow(sx, -2 / n) - 1) / sx);
224
+ _Scalar fx = std::sqrt(n * (std::pow(sx, -2 / n) - 1) / sx);
169
225
  return fx * v1;
170
226
  }
171
227
 
172
- template<typename Packet>
173
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp() const
228
+ template<typename Packet, typename Rng>
229
+ EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
174
230
  {
175
- Packet u1 = ur_base::template packetOp<Packet>(),
176
- u2 = ur_base::template packetOp<Packet>();
177
-
231
+ using namespace Eigen::internal;
232
+ Packet u1 = ur.template packetOp<Packet>(rng),
233
+ u2 = ur.template packetOp<Packet>(rng);
234
+
178
235
  u1 = psub(pset1<Packet>(1), u1);
179
236
  auto pn = pset1<Packet>(n);
180
- auto radius = psqrt(pmul(pn,
237
+ auto radius = psqrt(pmul(pn,
181
238
  psub(pexp(pmul(plog(u1), pset1<Packet>(-2 / n))), pset1<Packet>(1))
182
239
  ));
183
240
  auto theta = pmul(pset1<Packet>(2 * constant::pi), u2);
@@ -188,68 +245,107 @@ namespace Eigen
188
245
  }
189
246
  };
190
247
 
191
- template<typename Scalar, typename Urng>
192
- struct functor_traits<scalar_student_t_dist_op<Scalar, Urng> >
193
- {
194
- enum { Cost = HugeCost, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = false };
195
- };
248
+ template<typename> class GammaGen;
196
249
 
197
- template<typename Scalar, typename Rng>
198
- struct scalar_exp_dist_op : public scalar_uniform_real_op<Scalar, Rng>
250
+ /**
251
+ * @brief Generator of reals on an exponential distribution
252
+ *
253
+ * @tparam _Scalar
254
+ */
255
+ template<typename _Scalar>
256
+ class ExponentialGen : public GenBase<ExponentialGen<_Scalar>, _Scalar>
199
257
  {
200
- static_assert(std::is_floating_point<Scalar>::value, "expDist needs floating point types.");
201
-
202
- Scalar lambda = 1;
203
-
204
- scalar_exp_dist_op(const Rng& _rng, Scalar _lambda = 1)
205
- : scalar_uniform_real_op<Scalar, Rng>{ _rng }, lambda{ _lambda }
258
+ friend GammaGen<_Scalar>;
259
+ static_assert(std::is_floating_point<_Scalar>::value, "expDist needs floating point types.");
260
+ UniformRealGen<_Scalar> ur;
261
+ _Scalar lambda = 1;
262
+
263
+ public:
264
+ using Scalar = _Scalar;
265
+
266
+ /**
267
+ * @brief Construct a new exponential generator
268
+ *
269
+ * @param _lambda scale parameter of the distribution
270
+ */
271
+ ExponentialGen(_Scalar _lambda = 1)
272
+ : lambda{ _lambda }
206
273
  {
207
274
  }
275
+
276
+ ExponentialGen(const ExponentialGen&) = default;
277
+ ExponentialGen(ExponentialGen&&) = default;
278
+
279
+ ExponentialGen& operator=(const ExponentialGen&) = default;
280
+ ExponentialGen& operator=(ExponentialGen&&) = default;
208
281
 
209
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() () const
282
+ template<typename Rng>
283
+ EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
210
284
  {
211
- return -std::log(1 - scalar_uniform_real_op<Scalar, Rng>::operator()()) / lambda;
285
+ using namespace Eigen::internal;
286
+ return -std::log(1 - ur(std::forward<Rng>(rng))) / lambda;
212
287
  }
213
288
 
214
- template<typename Packet>
215
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp() const
289
+ template<typename Packet, typename Rng>
290
+ EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
216
291
  {
292
+ using namespace Eigen::internal;
217
293
  return pnegate(pdiv(plog(
218
- psub(pset1<Packet>(1), scalar_uniform_real_op<Scalar, Rng>::template packetOp<Packet>())
294
+ psub(pset1<Packet>(1), ur.template packetOp<Packet>(std::forward<Rng>(rng)))
219
295
  ), pset1<Packet>(lambda)));
220
296
  }
221
297
  };
222
298
 
223
- template<typename Scalar, typename Urng>
224
- struct functor_traits<scalar_exp_dist_op<Scalar, Urng> >
225
- {
226
- enum { Cost = HugeCost, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = false };
227
- };
299
+ template<typename> class NegativeBinomialGen;
228
300
 
229
- template<typename Scalar, typename Rng>
230
- struct scalar_gamma_dist_op : public scalar_exp_dist_op<Scalar, Rng>
301
+ /**
302
+ * @brief Generator of reals on a gamma distribution
303
+ *
304
+ * @tparam _Scalar
305
+ */
306
+ template<typename _Scalar>
307
+ class GammaGen : OptCacheStore, public GenBase<GammaGen<_Scalar>, _Scalar>
231
308
  {
232
- static_assert(std::is_floating_point<Scalar>::value, "gammaDist needs floating point types.");
233
-
234
- Scalar alpha, beta, px, sqrt;
235
-
236
- scalar_gamma_dist_op(const Rng& _rng, Scalar _alpha = 1, Scalar _beta = 1)
237
- : scalar_exp_dist_op<Scalar, Rng>{ _rng }, alpha{ _alpha }, beta{ _beta }
309
+ template<typename _Ty>
310
+ friend class NegativeBinomialGen;
311
+ static_assert(std::is_floating_point<_Scalar>::value, "gammaDist needs floating point types.");
312
+ int cache_rest_cnt = 0;
313
+ ExponentialGen<_Scalar> expon;
314
+ _Scalar alpha, beta, px, sqrt;
315
+
316
+ public:
317
+ using Scalar = _Scalar;
318
+
319
+ /**
320
+ * @brief Construct a new gamma generator
321
+ *
322
+ * @param _alpha shape parameter of the distribution
323
+ * @param _beta scale parameter of the distribution
324
+ */
325
+ GammaGen(_Scalar _alpha = 1, _Scalar _beta = 1)
326
+ : alpha{ _alpha }, beta{ _beta }
238
327
  {
239
328
  px = constant::e / (alpha + constant::e);
240
329
  sqrt = std::sqrt(2 * alpha - 1);
241
330
  }
242
331
 
243
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() () const
332
+ GammaGen(const GammaGen&) = default;
333
+ GammaGen(GammaGen&&) = default;
334
+
335
+ GammaGen& operator=(const GammaGen&) = default;
336
+ GammaGen& operator=(GammaGen&&) = default;
337
+
338
+ template<typename Rng>
339
+ EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
244
340
  {
245
- using ur_base = scalar_uniform_real_op<Scalar, Rng>;
341
+ using namespace Eigen::internal;
246
342
  if (alpha < 1)
247
343
  {
248
- Scalar ux, vx, xx, qx;
344
+ _Scalar ux, vx, xx, qx;
249
345
  while (1)
250
346
  {
251
- ux = ur_base::operator()();
252
- vx = this->nzur_scalar();
347
+ ux = expon.ur(rng);
348
+ vx = expon.ur.nzur_scalar(rng);
253
349
 
254
350
  if (ux < px)
255
351
  {
@@ -262,7 +358,7 @@ namespace Eigen
262
358
  qx = std::pow(xx, alpha - 1);
263
359
  }
264
360
 
265
- if (ur_base::operator()() < qx)
361
+ if (expon.ur(rng) < qx)
266
362
  {
267
363
  return beta * xx;
268
364
  }
@@ -270,27 +366,27 @@ namespace Eigen
270
366
  }
271
367
  if (alpha == 1)
272
368
  {
273
- return beta * scalar_exp_dist_op<Scalar, Rng>::operator()();
369
+ return beta * expon(rng);
274
370
  }
275
371
  int count;
276
372
  if ((count = alpha) == alpha && count < 20)
277
373
  {
278
- Scalar yx;
279
- yx = this->nzur_scalar();
374
+ _Scalar yx;
375
+ yx = expon.ur.nzur_scalar(rng);
280
376
  while (--count)
281
377
  {
282
- yx *= this->nzur_scalar();
378
+ yx *= expon.ur.nzur_scalar(rng);
283
379
  }
284
380
  return -beta * std::log(yx);
285
381
  }
286
382
 
287
383
  while (1)
288
384
  {
289
- Scalar yx, xx;
290
- yx = std::tan(constant::pi * ur_base::operator()());
385
+ _Scalar yx, xx;
386
+ yx = std::tan(constant::pi * expon.ur(rng));
291
387
  xx = sqrt * yx + alpha - 1;
292
388
  if (xx <= 0) continue;
293
- if (ur_base::operator()() <= (1 + yx * yx)
389
+ if (expon.ur(rng) <= (1 + yx * yx)
294
390
  * std::exp((alpha - 1) * std::log(xx / (alpha - 1)) - sqrt * yx))
295
391
  {
296
392
  return beta * xx;
@@ -298,29 +394,20 @@ namespace Eigen
298
394
  }
299
395
  }
300
396
 
301
- template<typename Packet>
302
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp() const
397
+ template<typename Packet, typename Rng>
398
+ EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
303
399
  {
400
+ using namespace Eigen::internal;
304
401
  using RUtils = RandUtils<Packet, Rng>;
305
402
  auto& cm = Rand::detail::CompressMask<sizeof(Packet)>::get_inst();
306
403
 
307
404
  RUtils ru;
308
- thread_local Packet cache_rest;
309
- thread_local int cache_rest_cnt;
310
- thread_local const scalar_gamma_dist_op* cache_ptr = nullptr;
311
- if (cache_ptr != this)
312
- {
313
- cache_ptr = this;
314
- cache_rest = pset1<Packet>(0);
315
- cache_rest_cnt = 0;
316
- }
317
-
318
405
  if (alpha < 1)
319
406
  {
320
407
  while (1)
321
408
  {
322
- Packet ux = ru.uniform_real(this->rng);
323
- Packet vx = ru.nonzero_uniform_real(this->rng);
409
+ Packet ux = ru.uniform_real(rng);
410
+ Packet vx = ru.nonzero_uniform_real(rng);
324
411
 
325
412
  Packet xx = pexp(pmul(pset1<Packet>(1 / alpha), plog(vx)));
326
413
  Packet qx = pexp(pnegate(xx));
@@ -332,18 +419,18 @@ namespace Eigen
332
419
  xx = pblendv(c, xx, xx2);
333
420
  qx = pblendv(c, qx, qx2);
334
421
 
335
- ux = ru.uniform_real(this->rng);
422
+ ux = ru.uniform_real(rng);
336
423
  Packet cands = pmul(pset1<Packet>(beta), xx);
337
424
  bool full = false;
338
425
  cache_rest_cnt = cm.compress_append(cands, pcmplt(ux, qx),
339
- cache_rest, cache_rest_cnt, full);
426
+ OptCacheStore::template get<Packet>(), cache_rest_cnt, full);
340
427
  if (full) return cands;
341
428
  }
342
429
  }
343
430
  if (alpha == 1)
344
431
  {
345
432
  return pmul(pset1<Packet>(beta),
346
- scalar_exp_dist_op<Scalar, Rng>::template packetOp<Packet>()
433
+ expon.template packetOp<Packet>(rng)
347
434
  );
348
435
  }
349
436
  int count;
@@ -351,10 +438,10 @@ namespace Eigen
351
438
  {
352
439
  RUtils ru;
353
440
  Packet ux, yx;
354
- yx = ru.nonzero_uniform_real(this->rng);
441
+ yx = ru.nonzero_uniform_real(rng);
355
442
  while (--count)
356
443
  {
357
- yx = pmul(yx, ru.nonzero_uniform_real(this->rng));
444
+ yx = pmul(yx, ru.nonzero_uniform_real(rng));
358
445
  }
359
446
  return pnegate(pmul(pset1<Packet>(beta), plog(yx)));
360
447
  }
@@ -364,11 +451,11 @@ namespace Eigen
364
451
  {
365
452
  Packet alpha_1 = pset1<Packet>(alpha - 1);
366
453
  Packet ys, yc;
367
- psincos(pmul(pset1<Packet>(constant::pi), ru.uniform_real(this->rng)), ys, yc);
454
+ psincos(pmul(pset1<Packet>(constant::pi), ru.uniform_real(rng)), ys, yc);
368
455
  Packet yx = pdiv(ys, yc);
369
456
  Packet xx = padd(pmul(pset1<Packet>(sqrt), yx), alpha_1);
370
457
  auto c = pcmplt(pset1<Packet>(0), xx);
371
- Packet ux = ru.uniform_real(this->rng);
458
+ Packet ux = ru.uniform_real(rng);
372
459
  Packet ub = pmul(padd(pmul(yx, yx), pset1<Packet>(1)),
373
460
  pexp(psub(
374
461
  pmul(alpha_1, plog(pdiv(xx, alpha_1))),
@@ -379,124 +466,200 @@ namespace Eigen
379
466
  Packet cands = pmul(pset1<Packet>(beta), xx);
380
467
  bool full = false;
381
468
  cache_rest_cnt = cm.compress_append(cands, c,
382
- cache_rest, cache_rest_cnt, full);
469
+ OptCacheStore::template get<Packet>(), cache_rest_cnt, full);
383
470
  if (full) return cands;
384
471
  }
385
472
  }
386
473
  }
387
474
  };
388
475
 
389
- template<typename Scalar, typename Urng>
390
- struct functor_traits<scalar_gamma_dist_op<Scalar, Urng> >
391
- {
392
- enum { Cost = HugeCost, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = false };
393
- };
394
-
395
- template<typename Scalar, typename Rng>
396
- struct scalar_weibull_dist_op : public scalar_uniform_real_op<Scalar, Rng>
476
+ /**
477
+ * @brief Generator of reals on a Weibull distribution
478
+ *
479
+ * @tparam _Scalar
480
+ */
481
+ template<typename _Scalar>
482
+ class WeibullGen : public GenBase<WeibullGen<_Scalar>, _Scalar>
397
483
  {
398
- static_assert(std::is_floating_point<Scalar>::value, "weilbullDist needs floating point types.");
399
-
400
- Scalar a = 1, b = 1;
401
-
402
- scalar_weibull_dist_op(const Rng& _rng, Scalar _a = 1, Scalar _b = 1)
403
- : scalar_uniform_real_op<Scalar, Rng>{ _rng }, a{ _a }, b{ _b }
484
+ static_assert(std::is_floating_point<_Scalar>::value, "weilbullDist needs floating point types.");
485
+ UniformRealGen<_Scalar> ur;
486
+ _Scalar a = 1, b = 1;
487
+
488
+ public:
489
+ using Scalar = _Scalar;
490
+
491
+ /**
492
+ * @brief Construct a new Weibull generator
493
+ *
494
+ * @param _a shape parameter of the distribution
495
+ * @param _b scale parameter of the distribution
496
+ */
497
+ WeibullGen(_Scalar _a = 1, _Scalar _b = 1)
498
+ : a{ _a }, b{ _b }
404
499
  {
405
500
  }
501
+
502
+ WeibullGen(const WeibullGen&) = default;
503
+ WeibullGen(WeibullGen&&) = default;
504
+
505
+ WeibullGen& operator=(const WeibullGen&) = default;
506
+ WeibullGen& operator=(WeibullGen&&) = default;
406
507
 
407
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() () const
508
+ template<typename Rng>
509
+ EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
408
510
  {
409
- return std::pow(-std::log(1 - scalar_uniform_real_op<Scalar, Rng>::operator()()), 1 / a) * b;
511
+ using namespace Eigen::internal;
512
+ return std::pow(-std::log(1 - ur(std::forward<Rng>(rng))), 1 / a) * b;
410
513
  }
411
514
 
412
- template<typename Packet>
413
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp() const
515
+ template<typename Packet, typename Rng>
516
+ EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
414
517
  {
518
+ using namespace Eigen::internal;
415
519
  return pmul(pexp(pmul(plog(pnegate(plog(
416
- psub(pset1<Packet>(1), scalar_uniform_real_op<Scalar, Rng>::template packetOp<Packet>())
520
+ psub(pset1<Packet>(1), ur.template packetOp<Packet>(std::forward<Rng>(rng)))
417
521
  ))), pset1<Packet>(1 / a))), pset1<Packet>(b));
418
522
  }
419
523
  };
420
524
 
421
- template<typename Scalar, typename Urng>
422
- struct functor_traits<scalar_weibull_dist_op<Scalar, Urng> >
525
+ /**
526
+ * @brief Generator of reals on an extreme value distribution
527
+ *
528
+ * @tparam _Scalar
529
+ */
530
+ template<typename _Scalar>
531
+ class ExtremeValueGen : public GenBase<ExtremeValueGen<_Scalar>, _Scalar>
423
532
  {
424
- enum { Cost = HugeCost, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = false };
425
- };
426
-
427
- template<typename Scalar, typename Rng>
428
- struct scalar_extreme_value_dist_op : public scalar_uniform_real_op<Scalar, Rng>
429
- {
430
- static_assert(std::is_floating_point<Scalar>::value, "extremeValueDist needs floating point types.");
431
-
432
- Scalar a = 0, b = 1;
433
-
434
- scalar_extreme_value_dist_op(const Rng& _rng, Scalar _a = 0, Scalar _b = 1)
435
- : scalar_uniform_real_op<Scalar, Rng>{ _rng }, a{ _a }, b{ _b }
533
+ static_assert(std::is_floating_point<_Scalar>::value, "extremeValueDist needs floating point types.");
534
+ UniformRealGen<_Scalar> ur;
535
+ _Scalar a = 0, b = 1;
536
+
537
+ public:
538
+ using Scalar = _Scalar;
539
+
540
+ /**
541
+ * @brief Construct a new extreme value generator
542
+ *
543
+ * @param _a location parameter of the distribution
544
+ * @param _b scale parameter of the distribution
545
+ */
546
+ ExtremeValueGen(_Scalar _a = 0, _Scalar _b = 1)
547
+ : a{ _a }, b{ _b }
436
548
  {
437
549
  }
438
550
 
439
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() () const
551
+ ExtremeValueGen(const ExtremeValueGen&) = default;
552
+ ExtremeValueGen(ExtremeValueGen&&) = default;
553
+
554
+ ExtremeValueGen& operator=(const ExtremeValueGen&) = default;
555
+ ExtremeValueGen& operator=(ExtremeValueGen&&) = default;
556
+
557
+ template<typename Rng>
558
+ EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
440
559
  {
441
- return (a - b * std::log(-std::log(this->nzur_scalar())));
560
+ using namespace Eigen::internal;
561
+ return (a - b * std::log(-std::log(ur.nzur_scalar(std::forward<Rng>(rng)))));
442
562
  }
443
563
 
444
- template<typename Packet>
445
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp() const
564
+ template<typename Packet, typename Rng>
565
+ EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
446
566
  {
567
+ using namespace Eigen::internal;
447
568
  using RUtils = RandUtils<Packet, Rng>;
448
569
  return psub(pset1<Packet>(a),
449
- pmul(plog(pnegate(plog(RUtils{}.nonzero_uniform_real(this->rng)))), pset1<Packet>(b))
570
+ pmul(plog(pnegate(plog(RUtils{}.nonzero_uniform_real(std::forward<Rng>(rng))))), pset1<Packet>(b))
450
571
  );
451
572
  }
452
573
  };
453
574
 
454
- template<typename Scalar, typename Urng>
455
- struct functor_traits<scalar_extreme_value_dist_op<Scalar, Urng> >
575
+ /**
576
+ * @brief Generator of reals on a chi-squared distribution
577
+ *
578
+ * @tparam _Scalar
579
+ */
580
+ template<typename _Scalar>
581
+ class ChiSquaredGen : public GenBase<ChiSquaredGen<_Scalar>, _Scalar>
456
582
  {
457
- enum { Cost = HugeCost, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = false };
458
- };
583
+ static_assert(std::is_floating_point<_Scalar>::value, "chiSquaredDist needs floating point types.");
584
+ GammaGen<_Scalar> gamma;
585
+ public:
586
+ using Scalar = _Scalar;
587
+
588
+ /**
589
+ * @brief Construct a new chi-squared generator
590
+ *
591
+ * @param n degrees of freedom
592
+ */
593
+ ChiSquaredGen(_Scalar n = 1)
594
+ : gamma{ n * _Scalar(0.5), 2 }
595
+ {
596
+ }
459
597
 
460
- template<typename Scalar, typename Rng>
461
- struct scalar_chi_squared_dist_op : public scalar_gamma_dist_op<Scalar, Rng>
462
- {
463
- static_assert(std::is_floating_point<Scalar>::value, "chiSquaredDist needs floating point types.");
598
+ ChiSquaredGen(const ChiSquaredGen&) = default;
599
+ ChiSquaredGen(ChiSquaredGen&&) = default;
464
600
 
465
- scalar_chi_squared_dist_op(const Rng& _rng, Scalar n = 1)
466
- : scalar_gamma_dist_op<Scalar, Rng>{ _rng, n * Scalar(0.5), 2 }
601
+ ChiSquaredGen& operator=(const ChiSquaredGen&) = default;
602
+ ChiSquaredGen& operator=(ChiSquaredGen&&) = default;
603
+
604
+ template<typename Rng>
605
+ EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
467
606
  {
607
+ return gamma(rng);
468
608
  }
469
- };
470
609
 
471
- template<typename Scalar, typename Urng>
472
- struct functor_traits<scalar_chi_squared_dist_op<Scalar, Urng> >
473
- {
474
- enum { Cost = HugeCost, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = false };
610
+ template<typename Packet, typename Rng>
611
+ EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
612
+ {
613
+ return gamma.template packetOp<Packet>(rng);
614
+ }
475
615
  };
476
-
477
- template<typename Scalar, typename Rng>
478
- struct scalar_cauchy_dist_op : public scalar_uniform_real_op<Scalar, Rng>
616
+
617
+ /**
618
+ * @brief Generator of reals on a Cauchy distribution
619
+ *
620
+ * @tparam _Scalar
621
+ */
622
+ template<typename _Scalar>
623
+ class CauchyGen : public GenBase<CauchyGen<_Scalar>, _Scalar>
479
624
  {
480
- static_assert(std::is_floating_point<Scalar>::value, "cauchyDist needs floating point types.");
481
-
482
- Scalar a = 0, b = 1;
483
-
484
- scalar_cauchy_dist_op(const Rng& _rng, Scalar _a = 0, Scalar _b = 1)
485
- : scalar_uniform_real_op<Scalar, Rng>{ _rng }, a{ _a }, b{ _b }
625
+ static_assert(std::is_floating_point<_Scalar>::value, "cauchyDist needs floating point types.");
626
+ UniformRealGen<_Scalar> ur;
627
+ _Scalar a = 0, b = 1;
628
+
629
+ public:
630
+ using Scalar = _Scalar;
631
+
632
+ /**
633
+ * @brief Construct a new Cauchy generator
634
+ *
635
+ * @param _a location parameter of the distribution
636
+ * @param _b scale parameter of the distribution
637
+ */
638
+ CauchyGen(_Scalar _a = 0, _Scalar _b = 1)
639
+ : a{ _a }, b{ _b }
486
640
  {
487
641
  }
488
642
 
489
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() () const
643
+ CauchyGen(const CauchyGen&) = default;
644
+ CauchyGen(CauchyGen&&) = default;
645
+
646
+ CauchyGen& operator=(const CauchyGen&) = default;
647
+ CauchyGen& operator=(CauchyGen&&) = default;
648
+
649
+ template<typename Rng>
650
+ EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
490
651
  {
491
- return a + b * std::tan(constant::pi * (scalar_uniform_real_op<Scalar, Rng>::operator()() - 0.5));
652
+ using namespace Eigen::internal;
653
+ return a + b * std::tan(constant::pi * (ur(std::forward<Rng>(rng)) - 0.5));
492
654
  }
493
655
 
494
- template<typename Packet>
495
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp() const
656
+ template<typename Packet, typename Rng>
657
+ EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
496
658
  {
659
+ using namespace Eigen::internal;
497
660
  Packet s, c;
498
661
  psincos(pmul(pset1<Packet>(constant::pi),
499
- psub(scalar_uniform_real_op<Scalar, Rng>::template packetOp<Packet>(), pset1<Packet>(0.5))
662
+ psub(ur.template packetOp<Packet>(std::forward<Rng>(rng)), pset1<Packet>(0.5))
500
663
  ), s, c);
501
664
  return padd(pset1<Packet>(a),
502
665
  pmul(pset1<Packet>(b), pdiv(s, c))
@@ -504,36 +667,54 @@ namespace Eigen
504
667
  }
505
668
  };
506
669
 
507
- template<typename Scalar, typename Urng>
508
- struct functor_traits<scalar_cauchy_dist_op<Scalar, Urng> >
509
- {
510
- enum { Cost = HugeCost, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = false };
511
- };
670
+ template<typename> class FisherFGen;
512
671
 
513
- template<typename Scalar, typename Rng>
514
- struct scalar_beta_dist_op : public scalar_uniform_real_op<Scalar, Rng>
672
+ /**
673
+ * @brief Generator of reals on a beta distribution
674
+ *
675
+ * @tparam _Scalar
676
+ */
677
+ template<typename _Scalar>
678
+ class BetaGen : OptCacheStore, public GenBase<BetaGen<_Scalar>, _Scalar>
515
679
  {
516
- static_assert(std::is_floating_point<Scalar>::value, "betaDist needs floating point types.");
517
- using ur_base = scalar_uniform_real_op<Scalar, Rng>;
518
-
519
- Scalar a, b;
520
- scalar_gamma_dist_op<Scalar, Rng> gd1, gd2;
521
-
522
- scalar_beta_dist_op(const Rng& _rng, Scalar _a = 1, Scalar _b = 1)
523
- : ur_base{ _rng }, a{ _a }, b{ _b },
524
- gd1{ _rng, _a }, gd2{ _rng, _b }
680
+ friend FisherFGen<_Scalar>;
681
+ static_assert(std::is_floating_point<_Scalar>::value, "betaDist needs floating point types.");
682
+ int cache_rest_cnt = 0;
683
+ UniformRealGen<_Scalar> ur;
684
+ _Scalar a, b;
685
+ GammaGen<_Scalar> gd1, gd2;
686
+
687
+ public:
688
+ using Scalar = _Scalar;
689
+
690
+ /**
691
+ * @brief Construct a new beta generator
692
+ *
693
+ * @param _a, _b shape parameter
694
+ */
695
+ BetaGen(_Scalar _a = 1, _Scalar _b = 1)
696
+ : a{ _a }, b{ _b },
697
+ gd1{ _a }, gd2{ _b }
525
698
  {
526
699
  }
527
700
 
528
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() () const
701
+ BetaGen(const BetaGen&) = default;
702
+ BetaGen(BetaGen&&) = default;
703
+
704
+ BetaGen& operator=(const BetaGen&) = default;
705
+ BetaGen& operator=(BetaGen&&) = default;
706
+
707
+ template<typename Rng>
708
+ EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
529
709
  {
710
+ using namespace Eigen::internal;
530
711
  if (a < 1 && b < 1)
531
712
  {
532
- Scalar x, p1, p2;
533
- while(1)
713
+ _Scalar x, p1, p2;
714
+ while (1)
534
715
  {
535
- p1 = std::pow(ur_base::operator()(), 1 / a);
536
- p2 = std::pow(ur_base::operator()(), 1 / b);
716
+ p1 = std::pow(ur(rng), 1 / a);
717
+ p2 = std::pow(ur(rng), 1 / b);
537
718
  x = p1 + p2;
538
719
  if (x <= 1) break;
539
720
  }
@@ -541,85 +722,652 @@ namespace Eigen
541
722
  }
542
723
  else
543
724
  {
544
- Scalar p1 = gd1(), p2 = gd2();
725
+ _Scalar p1 = gd1(rng), p2 = gd2(rng);
545
726
  return p1 / (p1 + p2);
546
727
  }
547
728
  }
548
729
 
549
- template<typename Packet>
550
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp() const
730
+ template<typename Packet, typename Rng>
731
+ EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
551
732
  {
733
+ using namespace Eigen::internal;
552
734
  if (a < 1 && b < 1)
553
735
  {
554
736
  auto& cm = Rand::detail::CompressMask<sizeof(Packet)>::get_inst();
555
-
556
- thread_local Packet cache_rest;
557
- thread_local int cache_rest_cnt;
558
- thread_local const scalar_beta_dist_op* cache_ptr = nullptr;
559
- if (cache_ptr != this)
560
- {
561
- cache_ptr = this;
562
- cache_rest = pset1<Packet>(0);
563
- cache_rest_cnt = 0;
564
- }
565
-
566
737
  Packet x, p1, p2;
567
738
  while (1)
568
739
  {
569
- p1 = pexp(pmul(plog(ur_base::template packetOp<Packet>()), pset1<Packet>(1 / a)));
570
- p2 = pexp(pmul(plog(ur_base::template packetOp<Packet>()), pset1<Packet>(1 / b)));
740
+ p1 = pexp(pmul(plog(ur.template packetOp<Packet>(rng)), pset1<Packet>(1 / a)));
741
+ p2 = pexp(pmul(plog(ur.template packetOp<Packet>(rng)), pset1<Packet>(1 / b)));
571
742
  x = padd(p1, p2);
572
743
  Packet cands = pdiv(p1, x);
573
744
  bool full = false;
574
745
  cache_rest_cnt = cm.compress_append(cands, pcmple(x, pset1<Packet>(1)),
575
- cache_rest, cache_rest_cnt, full);
746
+ OptCacheStore::template get<Packet>(), cache_rest_cnt, full);
576
747
  if (full) return cands;
577
748
  }
578
749
  }
579
750
  else
580
751
  {
581
- auto p1 = gd1.template packetOp<Packet>(),
582
- p2 = gd2.template packetOp<Packet>();
752
+ auto p1 = gd1.template packetOp<Packet>(rng),
753
+ p2 = gd2.template packetOp<Packet>(rng);
583
754
  return pdiv(p1, padd(p1, p2));
584
755
  }
585
756
  }
586
757
  };
587
758
 
588
- template<typename Scalar, typename Urng>
589
- struct functor_traits<scalar_beta_dist_op<Scalar, Urng> >
590
- {
591
- enum { Cost = HugeCost, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = false };
592
- };
593
-
594
- template<typename Scalar, typename Rng>
595
- struct scalar_fisher_f_dist_op : public scalar_beta_dist_op<Scalar, Rng>
759
+ /**
760
+ * @brief Generator of reals on a Fisher's f distribution
761
+ *
762
+ * @tparam _Scalar
763
+ */
764
+ template<typename _Scalar>
765
+ class FisherFGen : public GenBase<FisherFGen<_Scalar>, _Scalar>
596
766
  {
597
- static_assert(std::is_floating_point<Scalar>::value, "chiSquaredDist needs floating point types.");
598
-
599
- scalar_fisher_f_dist_op(const Rng& _rng, Scalar m = 1, Scalar n = 1)
600
- : scalar_beta_dist_op<Scalar, Rng>{ _rng, m * Scalar(0.5), n * Scalar(0.5) }
767
+ static_assert(std::is_floating_point<_Scalar>::value, "fisherF needs floating point types.");
768
+ BetaGen<_Scalar> beta;
769
+ public:
770
+ using Scalar = _Scalar;
771
+
772
+ /**
773
+ * @brief Construct a new Fisher's f generator
774
+ *
775
+ * @param m, n degrees of freedom
776
+ */
777
+ FisherFGen(_Scalar m = 1, _Scalar n = 1)
778
+ : beta{ m * _Scalar(0.5), n * _Scalar(0.5) }
601
779
  {
602
780
  }
781
+
782
+ FisherFGen(const FisherFGen&) = default;
783
+ FisherFGen(FisherFGen&&) = default;
784
+
785
+ FisherFGen& operator=(const FisherFGen&) = default;
786
+ FisherFGen& operator=(FisherFGen&&) = default;
603
787
 
604
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() () const
788
+ template<typename Rng>
789
+ EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
605
790
  {
606
- auto x = scalar_beta_dist_op<Scalar, Rng>::operator()();
607
- return this->b / this->a * x / (1 - x);
791
+ using namespace Eigen::internal;
792
+ auto x = beta(std::forward<Rng>(rng));
793
+ return beta.b / beta.a * x / (1 - x);
608
794
  }
609
795
 
610
- template<typename Packet>
611
- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp() const
796
+ template<typename Packet, typename Rng>
797
+ EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
612
798
  {
613
- auto x = scalar_beta_dist_op<Scalar, Rng>::template packetOp<Packet>();
614
- return pdiv(pmul(pset1<Packet>(this->b / this->a), x), psub(pset1<Packet>(1), x));
799
+ using namespace Eigen::internal;
800
+ auto x = beta.template packetOp<Packet>(std::forward<Rng>(rng));
801
+ return pdiv(pmul(pset1<Packet>(beta.b / beta.a), x), psub(pset1<Packet>(1), x));
615
802
  }
616
803
  };
617
804
 
618
- template<typename Scalar, typename Urng>
619
- struct functor_traits<scalar_fisher_f_dist_op<Scalar, Urng> >
805
+
806
+ template<typename Derived, typename Urng>
807
+ using BetaType = CwiseNullaryOp<internal::scalar_rng_adaptor<BetaGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
808
+
809
+ /**
810
+ * @brief generates reals on the beta distribution.
811
+ *
812
+ * @tparam Derived
813
+ * @tparam Urng
814
+ * @param rows the number of rows being generated
815
+ * @param cols the number of columns being generated
816
+ * @param urng c++11-style random number generator
817
+ * @param a,b shape parameter
818
+ * @return a random matrix expression with a shape (`rows`, `cols`)
819
+ *
820
+ * @see Eigen::Rand::BetaGen
821
+ */
822
+ template<typename Derived, typename Urng>
823
+ inline const BetaType<Derived, Urng>
824
+ beta(Index rows, Index cols, Urng&& urng, typename Derived::Scalar a = 1, typename Derived::Scalar b = 1)
620
825
  {
621
- enum { Cost = HugeCost, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = false };
622
- };
826
+ return {
827
+ rows, cols, { std::forward<Urng>(urng), BetaGen<typename Derived::Scalar>{a, b} }
828
+ };
829
+ }
830
+
831
+ /**
832
+ * @brief generates reals on the beta distribution.
833
+ *
834
+ * @tparam Derived
835
+ * @tparam Urng
836
+ * @param o an instance of any type of Eigen::DenseBase
837
+ * @param urng c++11-style random number generator
838
+ * @param a,b shape parameter
839
+ * @return a random matrix expression of the same shape as `o`
840
+ *
841
+ * @see Eigen::Rand::BetaGen
842
+ */
843
+ template<typename Derived, typename Urng>
844
+ inline const BetaType<Derived, Urng>
845
+ betaLike(Derived& o, Urng&& urng, typename Derived::Scalar a = 1, typename Derived::Scalar b = 1)
846
+ {
847
+ return {
848
+ o.rows(), o.cols(), { std::forward<Urng>(urng), BetaGen<typename Derived::Scalar>{a, b} }
849
+ };
850
+ }
851
+
852
+ template<typename Derived, typename Urng>
853
+ using CauchyType = CwiseNullaryOp<internal::scalar_rng_adaptor<CauchyGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
854
+
855
+ /**
856
+ * @brief generates reals on the Cauchy distribution.
857
+ *
858
+ * @tparam Derived
859
+ * @tparam Urng
860
+ * @param rows the number of rows being generated
861
+ * @param cols the number of columns being generated
862
+ * @param urng c++11-style random number generator
863
+ * @param a a location parameter of the distribution
864
+ * @param b a scale parameter of the distribution
865
+ * @return a random matrix expression with a shape (`rows`, `cols`)
866
+ *
867
+ * @see Eigen::Rand::CauchyGen
868
+ */
869
+ template<typename Derived, typename Urng>
870
+ inline const CauchyType<Derived, Urng>
871
+ cauchy(Index rows, Index cols, Urng&& urng, typename Derived::Scalar a = 0, typename Derived::Scalar b = 1)
872
+ {
873
+ return {
874
+ rows, cols, { std::forward<Urng>(urng), CauchyGen<typename Derived::Scalar>{a, b} }
875
+ };
876
+ }
877
+
878
+ /**
879
+ * @brief generates reals on the Cauchy distribution.
880
+ *
881
+ * @tparam Derived
882
+ * @tparam Urng
883
+ * @param o an instance of any type of Eigen::DenseBase
884
+ * @param urng c++11-style random number generator
885
+ * @param a a location parameter of the distribution
886
+ * @param b a scale parameter of the distribution
887
+ * @return a random matrix expression of the same shape as `o`
888
+ *
889
+ * @see Eigen::Rand::CauchyGen
890
+ */
891
+ template<typename Derived, typename Urng>
892
+ inline const CauchyType<Derived, Urng>
893
+ cauchyLike(Derived& o, Urng&& urng, typename Derived::Scalar a = 0, typename Derived::Scalar b = 1)
894
+ {
895
+ return {
896
+ o.rows(), o.cols(), { std::forward<Urng>(urng), CauchyGen<typename Derived::Scalar>{a, b} }
897
+ };
898
+ }
899
+
900
+ template<typename Derived, typename Urng>
901
+ using NormalType = CwiseNullaryOp<internal::scalar_rng_adaptor<StdNormalGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
902
+
903
+ /**
904
+ * @brief generates reals on a standard normal distribution (`mean` = 0, `stdev`=1)
905
+ *
906
+ * @tparam Derived a type of Eigen::DenseBase
907
+ * @tparam Urng
908
+ * @param rows the number of rows being generated
909
+ * @param cols the number of columns being generated
910
+ * @param urng c++11-style random number generator
911
+ * @return a random matrix expression with a shape (`rows`, `cols`)
912
+ *
913
+ * @see Eigen::Rand::StdNormalGen
914
+ */
915
+ template<typename Derived, typename Urng>
916
+ inline const NormalType<Derived, Urng>
917
+ normal(Index rows, Index cols, Urng&& urng)
918
+ {
919
+ return {
920
+ rows, cols, { std::forward<Urng>(urng) }
921
+ };
922
+ }
923
+
924
+ /**
925
+ * @brief generates reals on a standard normal distribution (`mean` = 0, `stdev`=1)
926
+ *
927
+ * @tparam Derived
928
+ * @tparam Urng
929
+ * @param o an instance of any type of Eigen::DenseBase
930
+ * @param urng c++11-style random number generator
931
+ * @return a random matrix expression of the same shape as `o`
932
+ *
933
+ * @see Eigen::Rand::StdNormalGen
934
+ */
935
+ template<typename Derived, typename Urng>
936
+ inline const NormalType<Derived, Urng>
937
+ normalLike(Derived& o, Urng&& urng)
938
+ {
939
+ return {
940
+ o.rows(), o.cols(), { std::forward<Urng>(urng) }
941
+ };
942
+ }
943
+
944
+ template<typename Derived, typename Urng>
945
+ using Normal2Type = CwiseNullaryOp<internal::scalar_rng_adaptor<NormalGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
946
+
947
+ /**
948
+ * @brief generates reals on a normal distribution with arbitrary `mean` and `stdev`.
949
+ *
950
+ * @tparam Derived
951
+ * @tparam Urng
952
+ * @param rows the number of rows being generated
953
+ * @param cols the number of columns being generated
954
+ * @param urng c++11-style random number generator
955
+ * @param mean a mean value of the distribution
956
+ * @param stdev a standard deviation value of the distribution
957
+ * @return a random matrix expression with a shape (`rows`, `cols`)
958
+ *
959
+ * @see Eigen::Rand::NormalGen
960
+ */
961
+ template<typename Derived, typename Urng>
962
+ inline const Normal2Type<Derived, Urng>
963
+ normal(Index rows, Index cols, Urng&& urng, typename Derived::Scalar mean, typename Derived::Scalar stdev = 1)
964
+ {
965
+ return {
966
+ rows, cols, { std::forward<Urng>(urng), NormalGen<typename Derived::Scalar>{mean, stdev} }
967
+ };
968
+ }
969
+
970
+ /**
971
+ * @brief generates reals on a normal distribution with arbitrary `mean` and `stdev`.
972
+ *
973
+ * @tparam Derived
974
+ * @tparam Urng
975
+ * @param o an instance of any type of Eigen::DenseBase
976
+ * @param urng c++11-style random number generator
977
+ * @param mean a mean value of the distribution
978
+ * @param stdev a standard deviation value of the distribution
979
+ * @return a random matrix expression of the same shape as `o`
980
+ *
981
+ * @see Eigen::Rand::NormalGen
982
+ */
983
+ template<typename Derived, typename Urng>
984
+ inline const Normal2Type<Derived, Urng>
985
+ normalLike(Derived& o, Urng&& urng, typename Derived::Scalar mean, typename Derived::Scalar stdev = 1)
986
+ {
987
+ return {
988
+ o.rows(), o.cols(), { std::forward<Urng>(urng), NormalGen<typename Derived::Scalar>{mean, stdev} }
989
+ };
990
+ }
991
+
992
+ template<typename Derived, typename Urng>
993
+ using LognormalType = CwiseNullaryOp<internal::scalar_rng_adaptor<LognormalGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
994
+
995
+ /**
996
+ * @brief generates reals on a lognormal distribution with arbitrary `mean` and `stdev`.
997
+ *
998
+ * @tparam Derived
999
+ * @tparam Urng
1000
+ * @param rows the number of rows being generated
1001
+ * @param cols the number of columns being generated
1002
+ * @param urng c++11-style random number generator
1003
+ * @param mean a mean value of the distribution
1004
+ * @param stdev a standard deviation value of the distribution
1005
+ * @return a random matrix expression with a shape (`rows`, `cols`)
1006
+ *
1007
+ * @see Eigen::Rand::LognormalGen
1008
+ */
1009
+ template<typename Derived, typename Urng>
1010
+ inline const LognormalType<Derived, Urng>
1011
+ lognormal(Index rows, Index cols, Urng&& urng, typename Derived::Scalar mean = 0, typename Derived::Scalar stdev = 1)
1012
+ {
1013
+ return {
1014
+ rows, cols, { std::forward<Urng>(urng), LognormalGen<typename Derived::Scalar>{mean, stdev} }
1015
+ };
1016
+ }
1017
+
1018
+ /**
1019
+ * @brief generates reals on a lognormal distribution with arbitrary `mean` and `stdev`.
1020
+ *
1021
+ * @tparam Derived
1022
+ * @tparam Urng
1023
+ * @param o an instance of any type of Eigen::DenseBase
1024
+ * @param urng c++11-style random number generator
1025
+ * @param mean a mean value of the distribution
1026
+ * @param stdev a standard deviation value of the distribution
1027
+ * @return a random matrix expression of the same shape as `o`
1028
+ *
1029
+ * @see Eigen::Rand::LognormalGen
1030
+ */
1031
+ template<typename Derived, typename Urng>
1032
+ inline const LognormalType<Derived, Urng>
1033
+ lognormalLike(Derived& o, Urng&& urng, typename Derived::Scalar mean = 0, typename Derived::Scalar stdev = 1)
1034
+ {
1035
+ return {
1036
+ o.rows(), o.cols(), { std::forward<Urng>(urng), LognormalGen<typename Derived::Scalar>{mean, stdev} }
1037
+ };
1038
+ }
1039
+
1040
+ template<typename Derived, typename Urng>
1041
+ using StudentTType = CwiseNullaryOp<internal::scalar_rng_adaptor<StudentTGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
1042
+
1043
+ /**
1044
+ * @brief generates reals on the Student's t distribution with arbirtrary degress of freedom.
1045
+ *
1046
+ * @tparam Derived a type of Eigen::DenseBase
1047
+ * @tparam Urng
1048
+ * @param rows the number of rows being generated
1049
+ * @param cols the number of columns being generated
1050
+ * @param urng c++11-style random number generator
1051
+ * @param n degrees of freedom
1052
+ * @return a random matrix expression with a shape (`rows`, `cols`)
1053
+ *
1054
+ * @see Eigen::Rand::StudentTGen
1055
+ */
1056
+ template<typename Derived, typename Urng>
1057
+ inline const StudentTType<Derived, Urng>
1058
+ studentT(Index rows, Index cols, Urng&& urng, typename Derived::Scalar n = 1)
1059
+ {
1060
+ return {
1061
+ rows, cols, { std::forward<Urng>(urng), StudentTGen<typename Derived::Scalar>{n} }
1062
+ };
1063
+ }
1064
+
1065
+ /**
1066
+ * @brief generates reals on the Student's t distribution with arbirtrary degress of freedom.
1067
+ *
1068
+ * @tparam Derived
1069
+ * @tparam Urng
1070
+ * @param o an instance of any type of Eigen::DenseBase
1071
+ * @param urng c++11-style random number generator
1072
+ * @param n degrees of freedom
1073
+ * @return a random matrix expression of the same shape as `o`
1074
+ *
1075
+ * @see Eigen::Rand::StudentTGen
1076
+ */
1077
+ template<typename Derived, typename Urng>
1078
+ inline const StudentTType<Derived, Urng>
1079
+ studentTLike(Derived& o, Urng&& urng, typename Derived::Scalar n = 1)
1080
+ {
1081
+ return {
1082
+ o.rows(), o.cols(), { std::forward<Urng>(urng), StudentTGen<typename Derived::Scalar>{n} }
1083
+ };
1084
+ }
1085
+
1086
+ template<typename Derived, typename Urng>
1087
+ using ExponentialType = CwiseNullaryOp<internal::scalar_rng_adaptor<ExponentialGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
1088
+
1089
+ /**
1090
+ * @brief generates reals on an exponential distribution with arbitrary scale parameter.
1091
+ *
1092
+ * @tparam Derived
1093
+ * @tparam Urng
1094
+ * @param rows the number of rows being generated
1095
+ * @param cols the number of columns being generated
1096
+ * @param urng c++11-style random number generator
1097
+ * @param lambda a scale parameter of the distribution
1098
+ * @return a random matrix expression with a shape (`rows`, `cols`)
1099
+ *
1100
+ * @see Eigen::Rand::ExponentialGen
1101
+ */
1102
+ template<typename Derived, typename Urng>
1103
+ inline const ExponentialType<Derived, Urng>
1104
+ exponential(Index rows, Index cols, Urng&& urng, typename Derived::Scalar lambda = 1)
1105
+ {
1106
+ return {
1107
+ rows, cols, { std::forward<Urng>(urng), ExponentialGen<typename Derived::Scalar>{lambda} }
1108
+ };
1109
+ }
1110
+
1111
+ /**
1112
+ * @brief generates reals on an exponential distribution with arbitrary scale parameter.
1113
+ *
1114
+ * @tparam Derived
1115
+ * @tparam Urng
1116
+ * @param o an instance of any type of Eigen::DenseBase
1117
+ * @param urng c++11-style random number generator
1118
+ * @param lambda a scale parameter of the distribution
1119
+ * @return a random matrix expression of the same shape as `o`
1120
+ *
1121
+ * @see Eigen::Rand::ExponentialGen
1122
+ */
1123
+ template<typename Derived, typename Urng>
1124
+ inline const ExponentialType<Derived, Urng>
1125
+ exponentialLike(Derived& o, Urng&& urng, typename Derived::Scalar lambda = 1)
1126
+ {
1127
+ return {
1128
+ o.rows(), o.cols(), { std::forward<Urng>(urng), ExponentialGen<typename Derived::Scalar>{lambda} }
1129
+ };
1130
+ }
1131
+
1132
+ template<typename Derived, typename Urng>
1133
+ using GammaType = CwiseNullaryOp<internal::scalar_rng_adaptor<GammaGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
1134
+
1135
+ /**
1136
+ * @brief generates reals on a gamma distribution with arbitrary shape and scale parameter.
1137
+ *
1138
+ * @tparam Derived
1139
+ * @tparam Urng
1140
+ * @param rows the number of rows being generated
1141
+ * @param cols the number of columns being generated
1142
+ * @param urng c++11-style random number generator
1143
+ * @param alpha a shape parameter of the distribution
1144
+ * @param beta a scale parameter of the distribution
1145
+ * @return a random matrix expression with a shape (`rows`, `cols`)
1146
+ *
1147
+ * @see Eigen::Rand::GammaGen
1148
+ */
1149
+ template<typename Derived, typename Urng>
1150
+ inline const GammaType<Derived, Urng>
1151
+ gamma(Index rows, Index cols, Urng&& urng, typename Derived::Scalar alpha = 1, typename Derived::Scalar beta = 1)
1152
+ {
1153
+ return {
1154
+ rows, cols, { std::forward<Urng>(urng), GammaGen<typename Derived::Scalar>{alpha, beta} }
1155
+ };
1156
+ }
1157
+
1158
+ /**
1159
+ * @brief generates reals on a gamma distribution with arbitrary shape and scale parameter.
1160
+ *
1161
+ * @tparam Derived
1162
+ * @tparam Urng
1163
+ * @param o an instance of any type of Eigen::DenseBase
1164
+ * @param urng c++11-style random number generator
1165
+ * @param alpha a shape parameter of the distribution
1166
+ * @param beta a scale parameter of the distribution
1167
+ * @return a random matrix expression of the same shape as `o`
1168
+ *
1169
+ * @see Eigen::Rand::GammaGen
1170
+ */
1171
+ template<typename Derived, typename Urng>
1172
+ inline const GammaType<Derived, Urng>
1173
+ gammaLike(Derived& o, Urng&& urng, typename Derived::Scalar alpha = 1, typename Derived::Scalar beta = 1)
1174
+ {
1175
+ return {
1176
+ o.rows(), o.cols(), { std::forward<Urng>(urng), GammaGen<typename Derived::Scalar>{alpha, beta} }
1177
+ };
1178
+ }
1179
+
1180
+ template<typename Derived, typename Urng>
1181
+ using WeibullType = CwiseNullaryOp<internal::scalar_rng_adaptor<WeibullGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
1182
+
1183
+ /**
1184
+ * @brief generates reals on a Weibull distribution with arbitrary shape and scale parameter.
1185
+ *
1186
+ * @tparam Derived
1187
+ * @tparam Urng
1188
+ * @param rows the number of rows being generated
1189
+ * @param cols the number of columns being generated
1190
+ * @param urng c++11-style random number generator
1191
+ * @param a a shape parameter of the distribution
1192
+ * @param b a scale parameter of the distribution
1193
+ * @return a random matrix expression with a shape (`rows`, `cols`)
1194
+ *
1195
+ * @see Eigen::Rand::WeibullGen
1196
+ */
1197
+ template<typename Derived, typename Urng>
1198
+ inline const WeibullType<Derived, Urng>
1199
+ weibull(Index rows, Index cols, Urng&& urng, typename Derived::Scalar a = 1, typename Derived::Scalar b = 1)
1200
+ {
1201
+ return {
1202
+ rows, cols, { std::forward<Urng>(urng), WeibullGen<typename Derived::Scalar>{a, b} }
1203
+ };
1204
+ }
1205
+
1206
+ /**
1207
+ * @brief generates reals on a Weibull distribution with arbitrary shape and scale parameter.
1208
+ *
1209
+ * @tparam Derived
1210
+ * @tparam Urng
1211
+ * @param o an instance of any type of Eigen::DenseBase
1212
+ * @param urng c++11-style random number generator
1213
+ * @param a a shape parameter of the distribution
1214
+ * @param b a scale parameter of the distribution
1215
+ * @return a random matrix expression of the same shape as `o`
1216
+ *
1217
+ * @see Eigen::Rand::WeibullGen
1218
+ */
1219
+ template<typename Derived, typename Urng>
1220
+ inline const WeibullType<Derived, Urng>
1221
+ weibullLike(Derived& o, Urng&& urng, typename Derived::Scalar a = 1, typename Derived::Scalar b = 1)
1222
+ {
1223
+ return {
1224
+ o.rows(), o.cols(), { std::forward<Urng>(urng), WeibullGen<typename Derived::Scalar>{a, b} }
1225
+ };
1226
+ }
1227
+
1228
+ template<typename Derived, typename Urng>
1229
+ using ExtremeValueType = CwiseNullaryOp<internal::scalar_rng_adaptor<ExtremeValueGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
1230
+
1231
+ /**
1232
+ * @brief generates reals on an extreme value distribution
1233
+ * (a.k.a Gumbel Type I, log-Weibull, Fisher-Tippett Type I) with arbitrary shape and scale parameter.
1234
+ *
1235
+ * @tparam Derived
1236
+ * @tparam Urng
1237
+ * @param rows the number of rows being generated
1238
+ * @param cols the number of columns being generated
1239
+ * @param urng c++11-style random number generator
1240
+ * @param a a location parameter of the distribution
1241
+ * @param b a scale parameter of the distribution
1242
+ * @return a random matrix expression with a shape (`rows`, `cols`)
1243
+ *
1244
+ * @see Eigen::Rand::ExtremeValueGen
1245
+ */
1246
+ template<typename Derived, typename Urng>
1247
+ inline const ExtremeValueType<Derived, Urng>
1248
+ extremeValue(Index rows, Index cols, Urng&& urng, typename Derived::Scalar a = 0, typename Derived::Scalar b = 1)
1249
+ {
1250
+ return {
1251
+ rows, cols, { std::forward<Urng>(urng), ExtremeValueGen<typename Derived::Scalar>{a, b} }
1252
+ };
1253
+ }
1254
+
1255
+ /**
1256
+ * @brief generates reals on an extreme value distribution
1257
+ * (a.k.a Gumbel Type I, log-Weibull, Fisher-Tippett Type I) with arbitrary shape and scale parameter.
1258
+ *
1259
+ * @tparam Derived
1260
+ * @tparam Urng
1261
+ * @param o an instance of any type of Eigen::DenseBase
1262
+ * @param urng c++11-style random number generator
1263
+ * @param a a location parameter of the distribution
1264
+ * @param b a scale parameter of the distribution
1265
+ * @return a random matrix expression of the same shape as `o`
1266
+ *
1267
+ * @see Eigen::Rand::ExtremeValueGen
1268
+ */
1269
+ template<typename Derived, typename Urng>
1270
+ inline const ExtremeValueType<Derived, Urng>
1271
+ extremeValueLike(Derived& o, Urng&& urng, typename Derived::Scalar a = 0, typename Derived::Scalar b = 1)
1272
+ {
1273
+ return {
1274
+ o.rows(), o.cols(), { std::forward<Urng>(urng), ExtremeValueGen<typename Derived::Scalar>{a, b} }
1275
+ };
1276
+ }
1277
+
1278
+ template<typename Derived, typename Urng>
1279
+ using ChiSquaredType = CwiseNullaryOp<internal::scalar_rng_adaptor<ChiSquaredGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
1280
+
1281
+ /**
1282
+ * @brief generates reals on the Chi-squared distribution with arbitrary degrees of freedom.
1283
+ *
1284
+ * @tparam Derived
1285
+ * @tparam Urng
1286
+ * @param rows the number of rows being generated
1287
+ * @param cols the number of columns being generated
1288
+ * @param urng c++11-style random number generator
1289
+ * @param n the degrees of freedom of the distribution
1290
+ * @return a random matrix expression with a shape (`rows`, `cols`)
1291
+ *
1292
+ * @see Eigen::Rand::ChiSquaredGen
1293
+ */
1294
+ template<typename Derived, typename Urng>
1295
+ inline const ChiSquaredType<Derived, Urng>
1296
+ chiSquared(Index rows, Index cols, Urng&& urng, typename Derived::Scalar n = 1)
1297
+ {
1298
+ return {
1299
+ rows, cols, { std::forward<Urng>(urng), ChiSquaredGen<typename Derived::Scalar>{n} }
1300
+ };
1301
+ }
1302
+
1303
+ /**
1304
+ * @brief generates reals on the Chi-squared distribution with arbitrary degrees of freedom.
1305
+ *
1306
+ * @tparam Derived
1307
+ * @tparam Urng
1308
+ * @param o an instance of any type of Eigen::DenseBase
1309
+ * @param urng c++11-style random number generator
1310
+ * @param n the degrees of freedom of the distribution
1311
+ * @return a random matrix expression of the same shape as `o`
1312
+ *
1313
+ * @see Eigen::Rand::ChiSquaredGen
1314
+ */
1315
+ template<typename Derived, typename Urng>
1316
+ inline const ChiSquaredType<Derived, Urng>
1317
+ chiSquaredLike(Derived& o, Urng&& urng, typename Derived::Scalar n = 1)
1318
+ {
1319
+ return {
1320
+ o.rows(), o.cols(), { std::forward<Urng>(urng), ChiSquaredGen<typename Derived::Scalar>{n} }
1321
+ };
1322
+ }
1323
+
1324
+ template<typename Derived, typename Urng>
1325
+ using FisherFType = CwiseNullaryOp<internal::scalar_rng_adaptor<FisherFGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
1326
+
1327
+ /**
1328
+ * @brief generates reals on the Fisher's F distribution.
1329
+ *
1330
+ * @tparam Derived
1331
+ * @tparam Urng
1332
+ * @param rows the number of rows being generated
1333
+ * @param cols the number of columns being generated
1334
+ * @param urng c++11-style random number generator
1335
+ * @param m degrees of freedom
1336
+ * @param n degrees of freedom
1337
+ * @return a random matrix expression with a shape (`rows`, `cols`)
1338
+ *
1339
+ * @see Eigen::Rand::FisherFGen
1340
+ */
1341
+ template<typename Derived, typename Urng>
1342
+ inline const FisherFType<Derived, Urng>
1343
+ fisherF(Index rows, Index cols, Urng&& urng, typename Derived::Scalar m = 1, typename Derived::Scalar n = 1)
1344
+ {
1345
+ return {
1346
+ rows, cols, { std::forward<Urng>(urng), FisherFGen<typename Derived::Scalar>{m, n} }
1347
+ };
1348
+ }
1349
+
1350
+ /**
1351
+ * @brief generates reals on the Fisher's F distribution.
1352
+ *
1353
+ * @tparam Derived
1354
+ * @tparam Urng
1355
+ * @param o an instance of any type of Eigen::DenseBase
1356
+ * @param urng c++11-style random number generator
1357
+ * @param m degrees of freedom
1358
+ * @param n degrees of freedom
1359
+ * @return a random matrix expression of the same shape as `o`
1360
+ *
1361
+ * @see Eigen::Rand::FisherFGen
1362
+ */
1363
+ template<typename Derived, typename Urng>
1364
+ inline const FisherFType<Derived, Urng>
1365
+ fisherFLike(Derived& o, Urng&& urng, typename Derived::Scalar m = 1, typename Derived::Scalar n = 1)
1366
+ {
1367
+ return {
1368
+ o.rows(), o.cols(), { std::forward<Urng>(urng), FisherFGen<typename Derived::Scalar>{m, n} }
1369
+ };
1370
+ }
623
1371
  }
624
1372
  }
625
1373