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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/ext/tomoto/ct.cpp +8 -4
- data/ext/tomoto/dmr.cpp +10 -4
- data/ext/tomoto/dt.cpp +13 -4
- data/ext/tomoto/extconf.rb +1 -1
- data/ext/tomoto/gdmr.cpp +14 -6
- data/ext/tomoto/hdp.cpp +9 -4
- data/ext/tomoto/hlda.cpp +9 -4
- data/ext/tomoto/hpa.cpp +9 -4
- data/ext/tomoto/lda.cpp +8 -4
- data/ext/tomoto/llda.cpp +8 -4
- data/ext/tomoto/mglda.cpp +11 -1
- data/ext/tomoto/pa.cpp +9 -4
- data/ext/tomoto/plda.cpp +8 -4
- data/ext/tomoto/slda.cpp +13 -5
- data/lib/tomoto/gdmr.rb +2 -2
- data/lib/tomoto/version.rb +1 -1
- data/vendor/EigenRand/EigenRand/Core.h +6 -1107
- data/vendor/EigenRand/EigenRand/Dists/Basic.h +490 -43
- data/vendor/EigenRand/EigenRand/Dists/Discrete.h +916 -285
- data/vendor/EigenRand/EigenRand/Dists/GammaPoisson.h +85 -36
- data/vendor/EigenRand/EigenRand/Dists/NormalExp.h +1038 -290
- data/vendor/EigenRand/EigenRand/EigenRand +2 -2
- data/vendor/EigenRand/EigenRand/Macro.h +4 -4
- data/vendor/EigenRand/EigenRand/MorePacketMath.h +54 -22
- data/vendor/EigenRand/EigenRand/MvDists/Multinomial.h +222 -0
- data/vendor/EigenRand/EigenRand/MvDists/MvNormal.h +492 -0
- data/vendor/EigenRand/EigenRand/PacketFilter.h +2 -2
- data/vendor/EigenRand/EigenRand/PacketRandomEngine.h +2 -2
- data/vendor/EigenRand/EigenRand/RandUtils.h +65 -11
- data/vendor/EigenRand/EigenRand/doc.h +142 -25
- data/vendor/EigenRand/LICENSE +1 -1
- data/vendor/EigenRand/README.md +109 -24
- data/vendor/tomotopy/README.kr.rst +27 -6
- data/vendor/tomotopy/README.rst +29 -8
- data/vendor/tomotopy/src/Labeling/FoRelevance.cpp +60 -12
- data/vendor/tomotopy/src/Labeling/FoRelevance.h +2 -2
- data/vendor/tomotopy/src/Labeling/Phraser.hpp +33 -21
- data/vendor/tomotopy/src/TopicModel/CT.h +8 -5
- data/vendor/tomotopy/src/TopicModel/CTModel.cpp +2 -6
- data/vendor/tomotopy/src/TopicModel/CTModel.hpp +29 -23
- data/vendor/tomotopy/src/TopicModel/DMR.h +33 -4
- data/vendor/tomotopy/src/TopicModel/DMRModel.cpp +2 -6
- data/vendor/tomotopy/src/TopicModel/DMRModel.hpp +231 -57
- data/vendor/tomotopy/src/TopicModel/DT.h +24 -5
- data/vendor/tomotopy/src/TopicModel/DTModel.cpp +2 -8
- data/vendor/tomotopy/src/TopicModel/DTModel.hpp +41 -28
- data/vendor/tomotopy/src/TopicModel/GDMR.h +31 -5
- data/vendor/tomotopy/src/TopicModel/GDMRModel.cpp +2 -7
- data/vendor/tomotopy/src/TopicModel/GDMRModel.hpp +211 -104
- data/vendor/tomotopy/src/TopicModel/HDP.h +11 -2
- data/vendor/tomotopy/src/TopicModel/HDPModel.cpp +2 -6
- data/vendor/tomotopy/src/TopicModel/HDPModel.hpp +52 -45
- data/vendor/tomotopy/src/TopicModel/HLDA.h +11 -2
- data/vendor/tomotopy/src/TopicModel/HLDAModel.cpp +2 -6
- data/vendor/tomotopy/src/TopicModel/HLDAModel.hpp +13 -16
- data/vendor/tomotopy/src/TopicModel/HPA.h +5 -2
- data/vendor/tomotopy/src/TopicModel/HPAModel.cpp +2 -6
- data/vendor/tomotopy/src/TopicModel/HPAModel.hpp +51 -21
- data/vendor/tomotopy/src/TopicModel/LDA.h +9 -2
- data/vendor/tomotopy/src/TopicModel/LDACVB0Model.hpp +8 -8
- data/vendor/tomotopy/src/TopicModel/LDAModel.cpp +2 -6
- data/vendor/tomotopy/src/TopicModel/LDAModel.hpp +70 -28
- data/vendor/tomotopy/src/TopicModel/LLDA.h +1 -2
- data/vendor/tomotopy/src/TopicModel/LLDAModel.cpp +2 -6
- data/vendor/tomotopy/src/TopicModel/LLDAModel.hpp +22 -12
- data/vendor/tomotopy/src/TopicModel/MGLDA.h +12 -3
- data/vendor/tomotopy/src/TopicModel/MGLDAModel.cpp +2 -10
- data/vendor/tomotopy/src/TopicModel/MGLDAModel.hpp +42 -19
- data/vendor/tomotopy/src/TopicModel/PA.h +9 -4
- data/vendor/tomotopy/src/TopicModel/PAModel.cpp +2 -6
- data/vendor/tomotopy/src/TopicModel/PAModel.hpp +48 -25
- data/vendor/tomotopy/src/TopicModel/PLDA.h +13 -2
- data/vendor/tomotopy/src/TopicModel/PLDAModel.cpp +2 -6
- data/vendor/tomotopy/src/TopicModel/PLDAModel.hpp +27 -19
- data/vendor/tomotopy/src/TopicModel/PT.h +12 -5
- data/vendor/tomotopy/src/TopicModel/PTModel.cpp +2 -3
- data/vendor/tomotopy/src/TopicModel/PTModel.hpp +29 -14
- data/vendor/tomotopy/src/TopicModel/SLDA.h +18 -6
- data/vendor/tomotopy/src/TopicModel/SLDAModel.cpp +2 -10
- data/vendor/tomotopy/src/TopicModel/SLDAModel.hpp +93 -43
- data/vendor/tomotopy/src/TopicModel/TopicModel.hpp +58 -23
- data/vendor/tomotopy/src/Utils/AliasMethod.hpp +6 -6
- data/vendor/tomotopy/src/Utils/Dictionary.h +11 -0
- data/vendor/tomotopy/src/Utils/SharedString.hpp +26 -1
- data/vendor/tomotopy/src/Utils/Trie.hpp +46 -21
- data/vendor/tomotopy/src/Utils/Utils.hpp +99 -14
- data/vendor/tomotopy/src/Utils/exception.h +1 -1
- data/vendor/tomotopy/src/Utils/math.h +5 -7
- data/vendor/tomotopy/src/Utils/serializer.hpp +329 -201
- data/vendor/tomotopy/src/Utils/text.hpp +8 -0
- data/vendor/tomotopy/src/Utils/tvector.hpp +49 -7
- metadata +9 -7
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* @file Discrete.h
|
|
3
3
|
* @author bab2min (bab2min@gmail.com)
|
|
4
4
|
* @brief
|
|
5
|
-
* @version 0.
|
|
6
|
-
* @date 2020-
|
|
7
|
-
*
|
|
5
|
+
* @version 0.3.0
|
|
6
|
+
* @date 2020-10-07
|
|
7
|
+
*
|
|
8
8
|
* @copyright Copyright (c) 2020
|
|
9
9
|
*
|
|
10
10
|
*/
|
|
@@ -18,113 +18,8 @@
|
|
|
18
18
|
|
|
19
19
|
namespace Eigen
|
|
20
20
|
{
|
|
21
|
-
namespace
|
|
21
|
+
namespace Rand
|
|
22
22
|
{
|
|
23
|
-
template<typename Scalar, typename Rng>
|
|
24
|
-
struct scalar_uniform_int_op : public scalar_randbits_op<Scalar, Rng>
|
|
25
|
-
{
|
|
26
|
-
static_assert(std::is_same<Scalar, int32_t>::value, "uniformInt needs integral types.");
|
|
27
|
-
using ur_base = scalar_randbits_op<Scalar, Rng>;
|
|
28
|
-
|
|
29
|
-
Scalar pmin;
|
|
30
|
-
size_t pdiff, bitsize, bitmask;
|
|
31
|
-
|
|
32
|
-
scalar_uniform_int_op(const Rng& _rng, Scalar _min, Scalar _max)
|
|
33
|
-
: ur_base{ _rng }, pmin{ _min }, pdiff{ (size_t)(_max - _min) }
|
|
34
|
-
{
|
|
35
|
-
if ((pdiff + 1) > pdiff)
|
|
36
|
-
{
|
|
37
|
-
bitsize = (size_t)std::ceil(std::log2(pdiff + 1));
|
|
38
|
-
}
|
|
39
|
-
else
|
|
40
|
-
{
|
|
41
|
-
bitsize = (size_t)std::ceil(std::log2(pdiff));
|
|
42
|
-
}
|
|
43
|
-
bitmask = (Scalar)(((size_t)-1) >> (sizeof(size_t) * 8 - bitsize));
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() () const
|
|
47
|
-
{
|
|
48
|
-
auto rx = ur_base::operator()();
|
|
49
|
-
if (pdiff == bitmask)
|
|
50
|
-
{
|
|
51
|
-
return (Scalar)(rx & bitmask) + pmin;
|
|
52
|
-
}
|
|
53
|
-
else
|
|
54
|
-
{
|
|
55
|
-
size_t bitcnt = bitsize;
|
|
56
|
-
while (1)
|
|
57
|
-
{
|
|
58
|
-
Scalar cands = (Scalar)(rx & bitmask);
|
|
59
|
-
if (cands <= pdiff) return cands;
|
|
60
|
-
if (bitcnt + bitsize < 32)
|
|
61
|
-
{
|
|
62
|
-
rx >>= bitsize;
|
|
63
|
-
bitcnt += bitsize;
|
|
64
|
-
}
|
|
65
|
-
else
|
|
66
|
-
{
|
|
67
|
-
rx = ur_base::operator()();
|
|
68
|
-
bitcnt = bitsize;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
template<typename Packet>
|
|
75
|
-
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp() const
|
|
76
|
-
{
|
|
77
|
-
auto rx = ur_base::template packetOp<Packet>();
|
|
78
|
-
auto pbitmask = pset1<Packet>(bitmask);
|
|
79
|
-
if (pdiff == bitmask)
|
|
80
|
-
{
|
|
81
|
-
return padd(pand(rx, pbitmask), pset1<Packet>(pmin));
|
|
82
|
-
}
|
|
83
|
-
else
|
|
84
|
-
{
|
|
85
|
-
auto& cm = Rand::detail::CompressMask<sizeof(Packet)>::get_inst();
|
|
86
|
-
thread_local Packet cache_rest;
|
|
87
|
-
thread_local int cache_rest_cnt;
|
|
88
|
-
thread_local const scalar_uniform_int_op* cache_ptr = nullptr;
|
|
89
|
-
if (cache_ptr != this)
|
|
90
|
-
{
|
|
91
|
-
cache_ptr = this;
|
|
92
|
-
cache_rest = pset1<Packet>(0);
|
|
93
|
-
cache_rest_cnt = 0;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
auto plen = pset1<Packet>(pdiff + 1);
|
|
97
|
-
size_t bitcnt = bitsize;
|
|
98
|
-
while (1)
|
|
99
|
-
{
|
|
100
|
-
// accept cands that only < plen
|
|
101
|
-
auto cands = pand(rx, pbitmask);
|
|
102
|
-
bool full = false;
|
|
103
|
-
cache_rest_cnt = cm.compress_append(cands, pcmplt(cands, plen),
|
|
104
|
-
cache_rest, cache_rest_cnt, full);
|
|
105
|
-
if (full) return padd(cands, pset1<Packet>(pmin));
|
|
106
|
-
|
|
107
|
-
if (bitcnt + bitsize < 32)
|
|
108
|
-
{
|
|
109
|
-
rx = psrl(rx, bitsize);
|
|
110
|
-
bitcnt += bitsize;
|
|
111
|
-
}
|
|
112
|
-
else
|
|
113
|
-
{
|
|
114
|
-
rx = ur_base::template packetOp<Packet>();
|
|
115
|
-
bitcnt = bitsize;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
template<typename Scalar, typename Urng>
|
|
123
|
-
struct functor_traits<scalar_uniform_int_op<Scalar, Urng> >
|
|
124
|
-
{
|
|
125
|
-
enum { Cost = HugeCost, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = false };
|
|
126
|
-
};
|
|
127
|
-
|
|
128
23
|
template<typename _Precision = uint32_t, typename _Size = uint32_t>
|
|
129
24
|
class AliasMethod
|
|
130
25
|
{
|
|
@@ -310,22 +205,156 @@ namespace Eigen
|
|
|
310
205
|
return alias.get();
|
|
311
206
|
}
|
|
312
207
|
};
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* @brief Generator of integers with a given range `[min, max]`
|
|
211
|
+
*
|
|
212
|
+
* @tparam _Scalar any integral type
|
|
213
|
+
*/
|
|
214
|
+
template<typename _Scalar>
|
|
215
|
+
class UniformIntGen : OptCacheStore, public GenBase<UniformIntGen<_Scalar>, _Scalar>
|
|
216
|
+
{
|
|
217
|
+
static_assert(std::is_same<_Scalar, int32_t>::value, "uniformInt needs integral types.");
|
|
218
|
+
int cache_rest_cnt = 0;
|
|
219
|
+
RandbitsGen<_Scalar> randbits;
|
|
220
|
+
_Scalar pmin;
|
|
221
|
+
size_t pdiff, bitsize, bitmask;
|
|
222
|
+
|
|
223
|
+
public:
|
|
224
|
+
using Scalar = _Scalar;
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* @brief Construct a new UniformInt Generator
|
|
228
|
+
*
|
|
229
|
+
* @param _min, _max the range of integers being generated
|
|
230
|
+
*/
|
|
231
|
+
UniformIntGen(_Scalar _min = 0, _Scalar _max = 0)
|
|
232
|
+
: pmin{ _min }, pdiff{ (size_t)(_max - _min) }
|
|
233
|
+
{
|
|
234
|
+
if ((pdiff + 1) > pdiff)
|
|
235
|
+
{
|
|
236
|
+
bitsize = (size_t)std::ceil(std::log2(pdiff + 1));
|
|
237
|
+
}
|
|
238
|
+
else
|
|
239
|
+
{
|
|
240
|
+
bitsize = (size_t)std::ceil(std::log2(pdiff));
|
|
241
|
+
}
|
|
242
|
+
bitmask = (_Scalar)(((size_t)-1) >> (sizeof(size_t) * 8 - bitsize));
|
|
243
|
+
}
|
|
313
244
|
|
|
314
|
-
|
|
315
|
-
|
|
245
|
+
UniformIntGen(const UniformIntGen&) = default;
|
|
246
|
+
UniformIntGen(UniformIntGen&&) = default;
|
|
316
247
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
{
|
|
320
|
-
static_assert(std::is_same<Scalar, int32_t>::value, "discreteDist needs integral types.");
|
|
321
|
-
using ur_base = scalar_randbits_op<Scalar, Rng>;
|
|
248
|
+
UniformIntGen& operator=(const UniformIntGen&) = default;
|
|
249
|
+
UniformIntGen& operator=(UniformIntGen&&) = default;
|
|
322
250
|
|
|
251
|
+
template<typename Rng>
|
|
252
|
+
EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
|
|
253
|
+
{
|
|
254
|
+
using namespace Eigen::internal;
|
|
255
|
+
auto rx = randbits(rng);
|
|
256
|
+
if (pdiff == bitmask)
|
|
257
|
+
{
|
|
258
|
+
return (_Scalar)(rx & bitmask) + pmin;
|
|
259
|
+
}
|
|
260
|
+
else
|
|
261
|
+
{
|
|
262
|
+
size_t bitcnt = bitsize;
|
|
263
|
+
while (1)
|
|
264
|
+
{
|
|
265
|
+
_Scalar cands = (_Scalar)(rx & bitmask);
|
|
266
|
+
if (cands <= pdiff) return cands;
|
|
267
|
+
if (bitcnt + bitsize < 32)
|
|
268
|
+
{
|
|
269
|
+
rx >>= bitsize;
|
|
270
|
+
bitcnt += bitsize;
|
|
271
|
+
}
|
|
272
|
+
else
|
|
273
|
+
{
|
|
274
|
+
rx = randbits(rng);
|
|
275
|
+
bitcnt = bitsize;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
template<typename Packet, typename Rng>
|
|
282
|
+
EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
|
|
283
|
+
{
|
|
284
|
+
using namespace Eigen::internal;
|
|
285
|
+
auto rx = randbits.template packetOp<Packet>(rng);
|
|
286
|
+
auto pbitmask = pset1<Packet>(bitmask);
|
|
287
|
+
if (pdiff == bitmask)
|
|
288
|
+
{
|
|
289
|
+
return padd(pand(rx, pbitmask), pset1<Packet>(pmin));
|
|
290
|
+
}
|
|
291
|
+
else
|
|
292
|
+
{
|
|
293
|
+
auto& cm = Rand::detail::CompressMask<sizeof(Packet)>::get_inst();
|
|
294
|
+
auto plen = pset1<Packet>(pdiff + 1);
|
|
295
|
+
size_t bitcnt = bitsize;
|
|
296
|
+
while (1)
|
|
297
|
+
{
|
|
298
|
+
// accept cands that only < plen
|
|
299
|
+
auto cands = pand(rx, pbitmask);
|
|
300
|
+
bool full = false;
|
|
301
|
+
cache_rest_cnt = cm.compress_append(cands, pcmplt(cands, plen),
|
|
302
|
+
OptCacheStore::template get<Packet>(), cache_rest_cnt, full);
|
|
303
|
+
if (full) return padd(cands, pset1<Packet>(pmin));
|
|
304
|
+
|
|
305
|
+
if (bitcnt + bitsize < 32)
|
|
306
|
+
{
|
|
307
|
+
rx = psrl(rx, bitsize);
|
|
308
|
+
bitcnt += bitsize;
|
|
309
|
+
}
|
|
310
|
+
else
|
|
311
|
+
{
|
|
312
|
+
rx = randbits.template packetOp<Packet>(rng);
|
|
313
|
+
bitcnt = bitsize;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* @brief Generator of integers on the interval `[0, n)`, where the probability of each individual integer `i` is proportional to `w(i)`
|
|
322
|
+
*
|
|
323
|
+
* @tparam _Scalar any integral type
|
|
324
|
+
* @tparam Precision internal precision type
|
|
325
|
+
*/
|
|
326
|
+
template<typename _Scalar, typename Precision = float>
|
|
327
|
+
class DiscreteGen;
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* @brief `DiscreteGen` with `int32_t` precision
|
|
331
|
+
*
|
|
332
|
+
* @tparam _Scalar any intergral type
|
|
333
|
+
*/
|
|
334
|
+
template<typename _Scalar>
|
|
335
|
+
class DiscreteGen<_Scalar, int32_t> : public GenBase<DiscreteGen<_Scalar, int32_t>, _Scalar>
|
|
336
|
+
{
|
|
337
|
+
static_assert(std::is_same<_Scalar, int32_t>::value, "discreteDist needs integral types.");
|
|
338
|
+
#ifdef EIGEN_VECTORIZE_AVX2
|
|
339
|
+
OptCacheStore cache;
|
|
340
|
+
bool valid = false;
|
|
341
|
+
#endif
|
|
342
|
+
RandbitsGen<int32_t> randbits;
|
|
323
343
|
std::vector<uint32_t> cdf;
|
|
324
|
-
AliasMethod<int32_t,
|
|
344
|
+
AliasMethod<int32_t, _Scalar> alias_table;
|
|
325
345
|
|
|
346
|
+
public:
|
|
347
|
+
using Scalar = _Scalar;
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* @brief Construct a new Discrete Generator
|
|
351
|
+
*
|
|
352
|
+
* @tparam RealIter
|
|
353
|
+
* @param first, last the range of elements defining the numbers to use as weights.
|
|
354
|
+
* The type of the elements referred by it must be convertible to `double`.
|
|
355
|
+
*/
|
|
326
356
|
template<typename RealIter>
|
|
327
|
-
|
|
328
|
-
: ur_base{ _rng }
|
|
357
|
+
DiscreteGen(RealIter first, RealIter last)
|
|
329
358
|
{
|
|
330
359
|
if (std::distance(first, last) < 16)
|
|
331
360
|
{
|
|
@@ -345,20 +374,47 @@ namespace Eigen
|
|
|
345
374
|
else
|
|
346
375
|
{
|
|
347
376
|
// use alias table
|
|
348
|
-
alias_table = AliasMethod<int32_t,
|
|
377
|
+
alias_table = AliasMethod<int32_t, _Scalar>{ first, last };
|
|
349
378
|
}
|
|
350
379
|
}
|
|
351
380
|
|
|
352
|
-
|
|
381
|
+
/**
|
|
382
|
+
* @brief Construct a new Discrete Generator
|
|
383
|
+
*
|
|
384
|
+
* @tparam Real
|
|
385
|
+
* @param il an instance of initializer_list containing the numbers to use as weights.
|
|
386
|
+
* The type of the elements referred by it must be convertible to `double`.
|
|
387
|
+
*/
|
|
388
|
+
template<typename Real,
|
|
389
|
+
typename std::enable_if<std::is_arithmetic<Real>::value, int>::type = 0>
|
|
390
|
+
DiscreteGen(const std::initializer_list<Real>& il)
|
|
391
|
+
: DiscreteGen(il.begin(), il.end())
|
|
392
|
+
{
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
DiscreteGen()
|
|
396
|
+
: DiscreteGen({ 1 })
|
|
353
397
|
{
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
DiscreteGen(const DiscreteGen&) = default;
|
|
401
|
+
DiscreteGen(DiscreteGen&&) = default;
|
|
402
|
+
|
|
403
|
+
DiscreteGen& operator=(const DiscreteGen&) = default;
|
|
404
|
+
DiscreteGen& operator=(DiscreteGen&&) = default;
|
|
405
|
+
|
|
406
|
+
template<typename Rng>
|
|
407
|
+
EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
|
|
408
|
+
{
|
|
409
|
+
using namespace Eigen::internal;
|
|
354
410
|
if (!cdf.empty())
|
|
355
411
|
{
|
|
356
|
-
auto rx =
|
|
357
|
-
return (
|
|
412
|
+
auto rx = randbits(std::forward<Rng>(rng)) & 0x7FFFFFFF;
|
|
413
|
+
return (_Scalar)(std::lower_bound(cdf.begin(), cdf.end() - 1, rx) - cdf.begin());
|
|
358
414
|
}
|
|
359
415
|
else
|
|
360
416
|
{
|
|
361
|
-
auto rx =
|
|
417
|
+
auto rx = randbits(std::forward<Rng>(rng));
|
|
362
418
|
auto albit = rx & alias_table.get_bitmask();
|
|
363
419
|
uint32_t alx = (uint32_t)(rx >> (sizeof(rx) * 8 - 31));
|
|
364
420
|
if (alx < alias_table.get_prob()[albit]) return albit;
|
|
@@ -366,18 +422,16 @@ namespace Eigen
|
|
|
366
422
|
}
|
|
367
423
|
}
|
|
368
424
|
|
|
369
|
-
template<typename Packet>
|
|
370
|
-
|
|
425
|
+
template<typename Packet, typename Rng>
|
|
426
|
+
EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
|
|
371
427
|
{
|
|
428
|
+
using namespace Eigen::internal;
|
|
372
429
|
#ifdef EIGEN_VECTORIZE_AVX2
|
|
373
|
-
|
|
374
|
-
thread_local const scalar_discrete_dist_op* cache_ptr = nullptr;
|
|
375
|
-
if (cache_ptr == this)
|
|
430
|
+
if (valid)
|
|
376
431
|
{
|
|
377
|
-
|
|
378
|
-
return cache;
|
|
432
|
+
valid = false;
|
|
433
|
+
return cache.template get<Packet>();
|
|
379
434
|
}
|
|
380
|
-
|
|
381
435
|
using PacketType = Packet8i;
|
|
382
436
|
#else
|
|
383
437
|
using PacketType = Packet;
|
|
@@ -387,7 +441,7 @@ namespace Eigen
|
|
|
387
441
|
if (!cdf.empty())
|
|
388
442
|
{
|
|
389
443
|
ret = pset1<PacketType>(cdf.size() - 1);
|
|
390
|
-
auto rx = pand(
|
|
444
|
+
auto rx = pand(randbits.template packetOp<PacketType>(std::forward<Rng>(rng)), pset1<PacketType>(0x7FFFFFFF));
|
|
391
445
|
for (size_t i = 0; i < cdf.size() - 1; ++i)
|
|
392
446
|
{
|
|
393
447
|
ret = padd(ret, pcmplt(rx, pset1<PacketType>(cdf[i])));
|
|
@@ -395,15 +449,15 @@ namespace Eigen
|
|
|
395
449
|
}
|
|
396
450
|
else
|
|
397
451
|
{
|
|
398
|
-
auto rx =
|
|
452
|
+
auto rx = randbits.template packetOp<PacketType>(std::forward<Rng>(rng));
|
|
399
453
|
auto albit = pand(rx, pset1<PacketType>(alias_table.get_bitmask()));
|
|
400
454
|
auto c = pcmplt(psrl(rx, 1), pgather(alias_table.get_prob(), albit));
|
|
401
455
|
ret = pblendv(c, albit, pgather(alias_table.get_alias(), albit));
|
|
402
456
|
}
|
|
403
457
|
|
|
404
458
|
#ifdef EIGEN_VECTORIZE_AVX2
|
|
405
|
-
|
|
406
|
-
|
|
459
|
+
valid = true;
|
|
460
|
+
cache.template get<Packet>() = _mm256_extractf128_si256(ret, 1);
|
|
407
461
|
return _mm256_extractf128_si256(ret, 0);
|
|
408
462
|
#else
|
|
409
463
|
return ret;
|
|
@@ -411,18 +465,31 @@ namespace Eigen
|
|
|
411
465
|
}
|
|
412
466
|
};
|
|
413
467
|
|
|
414
|
-
|
|
415
|
-
|
|
468
|
+
/**
|
|
469
|
+
* @brief `DiscreteGen` with `float` precision
|
|
470
|
+
*
|
|
471
|
+
* @tparam _Scalar any intergral type
|
|
472
|
+
*/
|
|
473
|
+
template<typename _Scalar>
|
|
474
|
+
class DiscreteGen<_Scalar, float> : public GenBase<DiscreteGen<_Scalar, float>, _Scalar>
|
|
416
475
|
{
|
|
417
|
-
static_assert(std::is_same<
|
|
418
|
-
|
|
419
|
-
|
|
476
|
+
static_assert(std::is_same<_Scalar, int32_t>::value, "discreteDist needs integral types.");
|
|
477
|
+
UniformRealGen<float> ur;
|
|
420
478
|
std::vector<float> cdf;
|
|
421
|
-
AliasMethod<float,
|
|
479
|
+
AliasMethod<float, _Scalar> alias_table;
|
|
422
480
|
|
|
481
|
+
public:
|
|
482
|
+
using Scalar = _Scalar;
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* @brief Construct a new Discrete Generator
|
|
486
|
+
*
|
|
487
|
+
* @tparam RealIter
|
|
488
|
+
* @param first, last the range of elements defining the numbers to use as weights.
|
|
489
|
+
* The type of the elements referred by it must be convertible to `double`.
|
|
490
|
+
*/
|
|
423
491
|
template<typename RealIter>
|
|
424
|
-
|
|
425
|
-
: ur_base{ _rng }
|
|
492
|
+
DiscreteGen(RealIter first, RealIter last)
|
|
426
493
|
{
|
|
427
494
|
if (std::distance(first, last) < 16)
|
|
428
495
|
{
|
|
@@ -442,35 +509,63 @@ namespace Eigen
|
|
|
442
509
|
else
|
|
443
510
|
{
|
|
444
511
|
// use alias table
|
|
445
|
-
alias_table = AliasMethod<float,
|
|
512
|
+
alias_table = AliasMethod<float, _Scalar>{ first, last };
|
|
446
513
|
}
|
|
447
514
|
}
|
|
448
515
|
|
|
449
|
-
|
|
516
|
+
/**
|
|
517
|
+
* @brief Construct a new Discrete Generator
|
|
518
|
+
*
|
|
519
|
+
* @tparam Real
|
|
520
|
+
* @param il an instance of initializer_list containing the numbers to use as weights.
|
|
521
|
+
* The type of the elements referred by it must be convertible to `double`.
|
|
522
|
+
*/
|
|
523
|
+
template<typename Real,
|
|
524
|
+
typename std::enable_if<std::is_arithmetic<Real>::value, int>::type = 0>
|
|
525
|
+
DiscreteGen(const std::initializer_list<Real>& il)
|
|
526
|
+
: DiscreteGen(il.begin(), il.end())
|
|
527
|
+
{
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
DiscreteGen()
|
|
531
|
+
: DiscreteGen({ 1 })
|
|
532
|
+
{
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
DiscreteGen(const DiscreteGen&) = default;
|
|
536
|
+
DiscreteGen(DiscreteGen&&) = default;
|
|
537
|
+
|
|
538
|
+
DiscreteGen& operator=(const DiscreteGen&) = default;
|
|
539
|
+
DiscreteGen& operator=(DiscreteGen&&) = default;
|
|
540
|
+
|
|
541
|
+
template<typename Rng>
|
|
542
|
+
EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
|
|
450
543
|
{
|
|
544
|
+
using namespace Eigen::internal;
|
|
451
545
|
if (!cdf.empty())
|
|
452
546
|
{
|
|
453
|
-
auto rx =
|
|
454
|
-
return (
|
|
547
|
+
auto rx = ur(std::forward<Rng>(rng));
|
|
548
|
+
return (_Scalar)(std::lower_bound(cdf.begin(), cdf.end() - 1, rx) - cdf.begin());
|
|
455
549
|
}
|
|
456
550
|
else
|
|
457
551
|
{
|
|
458
|
-
auto albit = pfirst(
|
|
459
|
-
auto alx =
|
|
552
|
+
auto albit = pfirst(rng()) & alias_table.get_bitmask();
|
|
553
|
+
auto alx = ur(rng);
|
|
460
554
|
if (alx < alias_table.get_prob()[albit]) return albit;
|
|
461
555
|
return alias_table.get_alias()[albit];
|
|
462
556
|
}
|
|
463
557
|
}
|
|
464
558
|
|
|
465
|
-
template<typename Packet>
|
|
466
|
-
|
|
559
|
+
template<typename Packet, typename Rng>
|
|
560
|
+
EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
|
|
467
561
|
{
|
|
562
|
+
using namespace Eigen::internal;
|
|
468
563
|
using PacketType = decltype(reinterpret_to_float(std::declval<Packet>()));
|
|
469
564
|
|
|
470
565
|
if (!cdf.empty())
|
|
471
566
|
{
|
|
472
567
|
auto ret = pset1<Packet>(cdf.size());
|
|
473
|
-
auto rx =
|
|
568
|
+
auto rx = ur.template packetOp<PacketType>(std::forward<Rng>(rng));
|
|
474
569
|
for (auto& p : cdf)
|
|
475
570
|
{
|
|
476
571
|
ret = padd(ret, reinterpret_to_int(pcmplt(rx, pset1<PacketType>(p))));
|
|
@@ -480,25 +575,38 @@ namespace Eigen
|
|
|
480
575
|
else
|
|
481
576
|
{
|
|
482
577
|
using RUtils = RawbitsMaker<Packet, Rng>;
|
|
483
|
-
auto albit = pand(RUtils{}.rawbits(
|
|
484
|
-
auto c = reinterpret_to_int(pcmplt(
|
|
578
|
+
auto albit = pand(RUtils{}.rawbits(rng), pset1<Packet>(alias_table.get_bitmask()));
|
|
579
|
+
auto c = reinterpret_to_int(pcmplt(ur.template packetOp<PacketType>(rng), pgather(alias_table.get_prob(), albit)));
|
|
485
580
|
return pblendv(c, albit, pgather(alias_table.get_alias(), albit));
|
|
486
581
|
}
|
|
487
582
|
}
|
|
488
583
|
};
|
|
489
584
|
|
|
490
|
-
|
|
491
|
-
|
|
585
|
+
/**
|
|
586
|
+
* @brief `DiscreteGen` with `double` precision
|
|
587
|
+
*
|
|
588
|
+
* @tparam _Scalar any intergral type
|
|
589
|
+
*/
|
|
590
|
+
template<typename _Scalar>
|
|
591
|
+
class DiscreteGen<_Scalar, double> : public GenBase<DiscreteGen<_Scalar, double>, _Scalar>
|
|
492
592
|
{
|
|
493
|
-
static_assert(std::is_same<
|
|
494
|
-
|
|
495
|
-
|
|
593
|
+
static_assert(std::is_same<_Scalar, int32_t>::value, "discreteDist needs integral types.");
|
|
594
|
+
UniformRealGen<double> ur;
|
|
496
595
|
std::vector<double> cdf;
|
|
497
|
-
AliasMethod<double,
|
|
596
|
+
AliasMethod<double, _Scalar> alias_table;
|
|
498
597
|
|
|
598
|
+
public:
|
|
599
|
+
using Scalar = _Scalar;
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* @brief Construct a new Discrete Generator
|
|
603
|
+
*
|
|
604
|
+
* @tparam RealIter
|
|
605
|
+
* @param first, last the range of elements defining the numbers to use as weights.
|
|
606
|
+
* The type of the elements referred by it must be convertible to `double`.
|
|
607
|
+
*/
|
|
499
608
|
template<typename RealIter>
|
|
500
|
-
|
|
501
|
-
: ur_base{ _rng }
|
|
609
|
+
DiscreteGen(RealIter first, RealIter last)
|
|
502
610
|
{
|
|
503
611
|
if (std::distance(first, last) < 16)
|
|
504
612
|
{
|
|
@@ -518,35 +626,63 @@ namespace Eigen
|
|
|
518
626
|
else
|
|
519
627
|
{
|
|
520
628
|
// use alias table
|
|
521
|
-
alias_table = AliasMethod<double,
|
|
629
|
+
alias_table = AliasMethod<double, _Scalar>{ first, last };
|
|
522
630
|
}
|
|
523
631
|
}
|
|
524
632
|
|
|
525
|
-
|
|
633
|
+
/**
|
|
634
|
+
* @brief Construct a new Discrete Generator
|
|
635
|
+
*
|
|
636
|
+
* @tparam Real
|
|
637
|
+
* @param il an instance of initializer_list containing the numbers to use as weights.
|
|
638
|
+
* The type of the elements referred by it must be convertible to `double`.
|
|
639
|
+
*/
|
|
640
|
+
template<typename Real,
|
|
641
|
+
typename std::enable_if<std::is_arithmetic<Real>::value, int>::type = 0>
|
|
642
|
+
DiscreteGen(const std::initializer_list<Real>& il)
|
|
643
|
+
: DiscreteGen(il.begin(), il.end())
|
|
644
|
+
{
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
DiscreteGen()
|
|
648
|
+
: DiscreteGen({ 1 })
|
|
526
649
|
{
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
DiscreteGen(const DiscreteGen&) = default;
|
|
653
|
+
DiscreteGen(DiscreteGen&&) = default;
|
|
654
|
+
|
|
655
|
+
DiscreteGen& operator=(const DiscreteGen&) = default;
|
|
656
|
+
DiscreteGen& operator=(DiscreteGen&&) = default;
|
|
657
|
+
|
|
658
|
+
template<typename Rng>
|
|
659
|
+
EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
|
|
660
|
+
{
|
|
661
|
+
using namespace Eigen::internal;
|
|
527
662
|
if (!cdf.empty())
|
|
528
663
|
{
|
|
529
|
-
auto rx =
|
|
530
|
-
return (
|
|
664
|
+
auto rx = ur(std::forward<Rng>(rng));
|
|
665
|
+
return (_Scalar)(std::lower_bound(cdf.begin(), cdf.end() - 1, rx) - cdf.begin());
|
|
531
666
|
}
|
|
532
667
|
else
|
|
533
668
|
{
|
|
534
|
-
auto albit = pfirst(
|
|
535
|
-
auto alx =
|
|
669
|
+
auto albit = pfirst(rng()) & alias_table.get_bitmask();
|
|
670
|
+
auto alx = ur(rng);
|
|
536
671
|
if (alx < alias_table.get_prob()[albit]) return albit;
|
|
537
672
|
return alias_table.get_alias()[albit];
|
|
538
673
|
}
|
|
539
674
|
}
|
|
540
675
|
|
|
541
|
-
template<typename Packet>
|
|
542
|
-
|
|
676
|
+
template<typename Packet, typename Rng>
|
|
677
|
+
EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
|
|
543
678
|
{
|
|
679
|
+
using namespace Eigen::internal;
|
|
544
680
|
using DPacket = decltype(reinterpret_to_double(std::declval<Packet>()));
|
|
545
681
|
if (!cdf.empty())
|
|
546
682
|
{
|
|
547
683
|
auto ret = pset1<Packet>(cdf.size());
|
|
548
684
|
#ifdef EIGEN_VECTORIZE_AVX
|
|
549
|
-
auto rx =
|
|
685
|
+
auto rx = ur.template packetOp<Packet4d>(std::forward<Rng>(rng));
|
|
550
686
|
for (auto& p : cdf)
|
|
551
687
|
{
|
|
552
688
|
auto c = reinterpret_to_int(pcmplt(rx, pset1<decltype(rx)>(p)));
|
|
@@ -554,8 +690,8 @@ namespace Eigen
|
|
|
554
690
|
ret = padd(ret, r);
|
|
555
691
|
}
|
|
556
692
|
#else
|
|
557
|
-
auto rx1 =
|
|
558
|
-
rx2 =
|
|
693
|
+
auto rx1 = ur.template packetOp<DPacket>(rng),
|
|
694
|
+
rx2 = ur.template packetOp<DPacket>(rng);
|
|
559
695
|
for (auto& p : cdf)
|
|
560
696
|
{
|
|
561
697
|
auto pp = pset1<decltype(rx1)>(p);
|
|
@@ -568,64 +704,84 @@ namespace Eigen
|
|
|
568
704
|
{
|
|
569
705
|
#ifdef EIGEN_VECTORIZE_AVX
|
|
570
706
|
using RUtils = RawbitsMaker<Packet, Rng>;
|
|
571
|
-
auto albit = pand(RUtils{}.rawbits(
|
|
572
|
-
auto c = reinterpret_to_int(pcmplt(
|
|
707
|
+
auto albit = pand(RUtils{}.rawbits(rng), pset1<Packet>(alias_table.get_bitmask()));
|
|
708
|
+
auto c = reinterpret_to_int(pcmplt(ur.template packetOp<Packet4d>(rng), pgather(alias_table.get_prob(), _mm256_castsi128_si256(albit))));
|
|
573
709
|
return pblendv(combine_low32(c), albit, pgather(alias_table.get_alias(), albit));
|
|
574
710
|
#else
|
|
575
711
|
using RUtils = RawbitsMaker<Packet, Rng>;
|
|
576
|
-
auto albit = pand(RUtils{}.rawbits(
|
|
577
|
-
auto c1 = reinterpret_to_int(pcmplt(
|
|
578
|
-
auto c2 = reinterpret_to_int(pcmplt(
|
|
712
|
+
auto albit = pand(RUtils{}.rawbits(rng), pset1<Packet>(alias_table.get_bitmask()));
|
|
713
|
+
auto c1 = reinterpret_to_int(pcmplt(ur.template packetOp<DPacket>(rng), pgather(alias_table.get_prob(), albit)));
|
|
714
|
+
auto c2 = reinterpret_to_int(pcmplt(ur.template packetOp<DPacket>(rng), pgather(alias_table.get_prob(), albit, true)));
|
|
579
715
|
return pblendv(combine_low32(c1, c2), albit, pgather(alias_table.get_alias(), albit));
|
|
580
716
|
#endif
|
|
581
717
|
}
|
|
582
718
|
}
|
|
583
719
|
};
|
|
584
720
|
|
|
585
|
-
template<typename
|
|
586
|
-
struct functor_traits<scalar_discrete_dist_op<Scalar, Urng, Precision> >
|
|
587
|
-
{
|
|
588
|
-
enum { Cost = HugeCost, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = false };
|
|
589
|
-
};
|
|
721
|
+
template<typename> class BinomialGen;
|
|
590
722
|
|
|
591
|
-
|
|
592
|
-
|
|
723
|
+
/**
|
|
724
|
+
* @brief Generator of integers on a Poisson distribution
|
|
725
|
+
*
|
|
726
|
+
* @tparam _Scalar
|
|
727
|
+
*/
|
|
728
|
+
template<typename _Scalar>
|
|
729
|
+
class PoissonGen : OptCacheStore, public GenBase<PoissonGen<_Scalar>, _Scalar>
|
|
593
730
|
{
|
|
594
|
-
|
|
595
|
-
|
|
731
|
+
friend BinomialGen<_Scalar>;
|
|
732
|
+
static_assert(std::is_same<_Scalar, int32_t>::value, "poisson needs integral types.");
|
|
733
|
+
int cache_rest_cnt = 0;
|
|
734
|
+
UniformRealGen<float> ur;
|
|
596
735
|
|
|
736
|
+
protected:
|
|
597
737
|
double mean, ne_mean, sqrt_tmean, log_mean, g1;
|
|
598
738
|
|
|
599
|
-
|
|
600
|
-
|
|
739
|
+
public:
|
|
740
|
+
using Scalar = _Scalar;
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* @brief Construct a new Poisson Generator
|
|
744
|
+
*
|
|
745
|
+
* @param _mean mean of the distribution
|
|
746
|
+
*/
|
|
747
|
+
PoissonGen(double _mean = 1)
|
|
748
|
+
: mean{ _mean }, ne_mean{ std::exp(-_mean) }
|
|
601
749
|
{
|
|
602
750
|
sqrt_tmean = std::sqrt(2 * mean);
|
|
603
751
|
log_mean = std::log(mean);
|
|
604
752
|
g1 = mean * log_mean - std::lgamma(mean + 1);
|
|
605
753
|
}
|
|
606
754
|
|
|
607
|
-
|
|
755
|
+
PoissonGen(const PoissonGen&) = default;
|
|
756
|
+
PoissonGen(PoissonGen&&) = default;
|
|
757
|
+
|
|
758
|
+
PoissonGen& operator=(const PoissonGen&) = default;
|
|
759
|
+
PoissonGen& operator=(PoissonGen&&) = default;
|
|
760
|
+
|
|
761
|
+
template<typename Rng>
|
|
762
|
+
EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
|
|
608
763
|
{
|
|
764
|
+
using namespace Eigen::internal;
|
|
609
765
|
if (mean < 12)
|
|
610
766
|
{
|
|
611
|
-
|
|
767
|
+
_Scalar res = 0;
|
|
612
768
|
double val = 1;
|
|
613
769
|
for (; ; ++res)
|
|
614
770
|
{
|
|
615
|
-
val *=
|
|
771
|
+
val *= ur(rng);
|
|
616
772
|
if (val <= ne_mean) break;
|
|
617
773
|
}
|
|
618
774
|
return res;
|
|
619
775
|
}
|
|
620
776
|
else
|
|
621
777
|
{
|
|
622
|
-
|
|
778
|
+
_Scalar res;
|
|
623
779
|
double yx;
|
|
624
|
-
while(1)
|
|
780
|
+
while (1)
|
|
625
781
|
{
|
|
626
|
-
yx = std::tan(constant::pi *
|
|
627
|
-
res = (
|
|
628
|
-
if (res >= 0 &&
|
|
782
|
+
yx = std::tan(constant::pi * ur(rng));
|
|
783
|
+
res = (_Scalar)(sqrt_tmean * yx + mean);
|
|
784
|
+
if (res >= 0 && ur(rng) <= 0.9 * (1.0 + yx * yx)
|
|
629
785
|
* std::exp(res * log_mean - std::lgamma(res + 1.0) - g1))
|
|
630
786
|
{
|
|
631
787
|
return res;
|
|
@@ -634,9 +790,10 @@ namespace Eigen
|
|
|
634
790
|
}
|
|
635
791
|
}
|
|
636
792
|
|
|
637
|
-
template<typename Packet>
|
|
638
|
-
|
|
793
|
+
template<typename Packet, typename Rng>
|
|
794
|
+
EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
|
|
639
795
|
{
|
|
796
|
+
using namespace Eigen::internal;
|
|
640
797
|
using PacketType = decltype(reinterpret_to_float(std::declval<Packet>()));
|
|
641
798
|
|
|
642
799
|
if (mean < 12)
|
|
@@ -645,7 +802,7 @@ namespace Eigen
|
|
|
645
802
|
PacketType val = pset1<PacketType>(1), pne_mean = pset1<PacketType>(ne_mean);
|
|
646
803
|
while (1)
|
|
647
804
|
{
|
|
648
|
-
val = pmul(val,
|
|
805
|
+
val = pmul(val, ur.template packetOp<PacketType>(rng));
|
|
649
806
|
auto c = reinterpret_to_int(pcmplt(pne_mean, val));
|
|
650
807
|
if (pmovemask(c) == 0) break;
|
|
651
808
|
res = padd(res, pnegate(c));
|
|
@@ -655,16 +812,6 @@ namespace Eigen
|
|
|
655
812
|
else
|
|
656
813
|
{
|
|
657
814
|
auto& cm = Rand::detail::CompressMask<sizeof(Packet)>::get_inst();
|
|
658
|
-
thread_local PacketType cache_rest;
|
|
659
|
-
thread_local int cache_rest_cnt;
|
|
660
|
-
thread_local const scalar_poisson_dist_op* cache_ptr = nullptr;
|
|
661
|
-
if (cache_ptr != this)
|
|
662
|
-
{
|
|
663
|
-
cache_ptr = this;
|
|
664
|
-
cache_rest = pset1<PacketType>(0);
|
|
665
|
-
cache_rest_cnt = 0;
|
|
666
|
-
}
|
|
667
|
-
|
|
668
815
|
const PacketType ppi = pset1<PacketType>(constant::pi),
|
|
669
816
|
psqrt_tmean = pset1<PacketType>(sqrt_tmean),
|
|
670
817
|
pmean = pset1<PacketType>(mean),
|
|
@@ -673,7 +820,7 @@ namespace Eigen
|
|
|
673
820
|
while (1)
|
|
674
821
|
{
|
|
675
822
|
PacketType fres, yx, psin, pcos;
|
|
676
|
-
psincos(pmul(ppi,
|
|
823
|
+
psincos(pmul(ppi, ur.template packetOp<PacketType>(rng)), psin, pcos);
|
|
677
824
|
yx = pdiv(psin, pcos);
|
|
678
825
|
fres = ptruncate(padd(pmul(psqrt_tmean, yx), pmean));
|
|
679
826
|
|
|
@@ -681,68 +828,87 @@ namespace Eigen
|
|
|
681
828
|
auto p2 = pexp(psub(psub(pmul(fres, plog_mean), plgamma(padd(fres, pset1<PacketType>(1)))), pg1));
|
|
682
829
|
|
|
683
830
|
auto c1 = pcmple(pset1<PacketType>(0), fres);
|
|
684
|
-
auto c2 = pcmple(
|
|
831
|
+
auto c2 = pcmple(ur.template packetOp<PacketType>(rng), pmul(p1, p2));
|
|
685
832
|
|
|
686
833
|
auto cands = fres;
|
|
687
834
|
bool full = false;
|
|
688
835
|
cache_rest_cnt = cm.compress_append(cands, pand(c1, c2),
|
|
689
|
-
|
|
836
|
+
OptCacheStore::template get<PacketType>(), cache_rest_cnt, full);
|
|
690
837
|
if (full) return pcast<PacketType, Packet>(cands);
|
|
691
838
|
}
|
|
692
839
|
}
|
|
693
840
|
}
|
|
694
841
|
};
|
|
695
842
|
|
|
696
|
-
|
|
697
|
-
|
|
843
|
+
/**
|
|
844
|
+
* @brief Generator of integers on a binomial distribution
|
|
845
|
+
*
|
|
846
|
+
* @tparam _Scalar
|
|
847
|
+
*/
|
|
848
|
+
template<typename _Scalar>
|
|
849
|
+
class BinomialGen : public GenBase<BinomialGen<_Scalar>, _Scalar>
|
|
698
850
|
{
|
|
699
|
-
|
|
700
|
-
};
|
|
851
|
+
static_assert(std::is_same<_Scalar, int32_t>::value, "binomial needs integral types.");
|
|
701
852
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
{
|
|
705
|
-
static_assert(std::is_same<Scalar, int32_t>::value, "binomial needs integral types.");
|
|
706
|
-
using ur_base = scalar_uniform_real_op<float, Rng>;
|
|
707
|
-
|
|
708
|
-
Scalar trials;
|
|
853
|
+
PoissonGen<_Scalar> poisson;
|
|
854
|
+
_Scalar trials;
|
|
709
855
|
double p, small_p, g1, sqrt_v, log_small_p, log_small_q;
|
|
710
856
|
|
|
711
|
-
|
|
712
|
-
|
|
857
|
+
public:
|
|
858
|
+
using Scalar = _Scalar;
|
|
859
|
+
|
|
860
|
+
/**
|
|
861
|
+
* @brief Construct a new Binomial Generator
|
|
862
|
+
*
|
|
863
|
+
* @param _trials the number of trials
|
|
864
|
+
* @param _p probability of a trial generating true
|
|
865
|
+
*/
|
|
866
|
+
BinomialGen(_Scalar _trials = 1, double _p = 0.5)
|
|
867
|
+
: poisson{ _trials * std::min(_p, 1 - _p) },
|
|
713
868
|
trials{ _trials }, p{ _p }, small_p{ std::min(p, 1 - p) }
|
|
714
|
-
|
|
869
|
+
|
|
715
870
|
{
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
871
|
+
if (!(trials < 25 || poisson.mean < 1.0))
|
|
872
|
+
{
|
|
873
|
+
g1 = std::lgamma(trials + 1);
|
|
874
|
+
sqrt_v = std::sqrt(2 * poisson.mean * (1 - small_p));
|
|
875
|
+
log_small_p = std::log(small_p);
|
|
876
|
+
log_small_q = std::log(1 - small_p);
|
|
877
|
+
}
|
|
720
878
|
}
|
|
721
879
|
|
|
722
|
-
|
|
880
|
+
BinomialGen(const BinomialGen&) = default;
|
|
881
|
+
BinomialGen(BinomialGen&&) = default;
|
|
882
|
+
|
|
883
|
+
BinomialGen& operator=(const BinomialGen&) = default;
|
|
884
|
+
BinomialGen& operator=(BinomialGen&&) = default;
|
|
885
|
+
|
|
886
|
+
template<typename Rng>
|
|
887
|
+
EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
|
|
723
888
|
{
|
|
724
|
-
|
|
889
|
+
using namespace Eigen::internal;
|
|
890
|
+
_Scalar res;
|
|
725
891
|
if (trials < 25)
|
|
726
892
|
{
|
|
727
893
|
res = 0;
|
|
728
894
|
for (int i = 0; i < trials; ++i)
|
|
729
895
|
{
|
|
730
|
-
if (
|
|
896
|
+
if (poisson.ur(rng) < p) ++res;
|
|
731
897
|
}
|
|
732
898
|
return res;
|
|
733
899
|
}
|
|
734
|
-
else if (
|
|
900
|
+
else if (poisson.mean < 1.0)
|
|
735
901
|
{
|
|
736
|
-
res =
|
|
902
|
+
res = poisson(rng);
|
|
737
903
|
}
|
|
738
904
|
else
|
|
739
905
|
{
|
|
740
|
-
while(1)
|
|
906
|
+
while (1)
|
|
741
907
|
{
|
|
742
908
|
double ys;
|
|
743
|
-
ys = std::tan(constant::pi *
|
|
744
|
-
res = (
|
|
745
|
-
if (0 <= res && res <= trials &&
|
|
909
|
+
ys = std::tan(constant::pi * poisson.ur(rng));
|
|
910
|
+
res = (_Scalar)(sqrt_v * ys + poisson.mean);
|
|
911
|
+
if (0 <= res && res <= trials && poisson.ur(rng) <= 1.2 * sqrt_v
|
|
746
912
|
* (1.0 + ys * ys)
|
|
747
913
|
* std::exp(g1 - std::lgamma(res + 1)
|
|
748
914
|
- std::lgamma(trials - res + 1.0)
|
|
@@ -757,9 +923,10 @@ namespace Eigen
|
|
|
757
923
|
return p == small_p ? res : trials - res;
|
|
758
924
|
}
|
|
759
925
|
|
|
760
|
-
template<typename Packet>
|
|
761
|
-
|
|
926
|
+
template<typename Packet, typename Rng>
|
|
927
|
+
EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
|
|
762
928
|
{
|
|
929
|
+
using namespace Eigen::internal;
|
|
763
930
|
using PacketType = decltype(reinterpret_to_float(std::declval<Packet>()));
|
|
764
931
|
Packet res;
|
|
765
932
|
if (trials < 25)
|
|
@@ -768,42 +935,32 @@ namespace Eigen
|
|
|
768
935
|
res = pset1<Packet>(trials);
|
|
769
936
|
for (int i = 0; i < trials; ++i)
|
|
770
937
|
{
|
|
771
|
-
auto c = reinterpret_to_int(pcmple(pp,
|
|
938
|
+
auto c = reinterpret_to_int(pcmple(pp, poisson.ur.template packetOp<PacketType>(rng)));
|
|
772
939
|
res = padd(res, c);
|
|
773
940
|
}
|
|
774
941
|
return res;
|
|
775
942
|
}
|
|
776
|
-
else if (
|
|
943
|
+
else if (poisson.mean < 1.0)
|
|
777
944
|
{
|
|
778
|
-
res =
|
|
945
|
+
res = poisson.template packetOp<Packet>(rng);
|
|
779
946
|
}
|
|
780
947
|
else
|
|
781
948
|
{
|
|
782
949
|
auto& cm = Rand::detail::CompressMask<sizeof(Packet)>::get_inst();
|
|
783
|
-
thread_local PacketType cache_rest;
|
|
784
|
-
thread_local int cache_rest_cnt;
|
|
785
|
-
thread_local const scalar_binomial_dist_op* cache_ptr = nullptr;
|
|
786
|
-
if (cache_ptr != this)
|
|
787
|
-
{
|
|
788
|
-
cache_ptr = this;
|
|
789
|
-
cache_rest = pset1<PacketType>(0);
|
|
790
|
-
cache_rest_cnt = 0;
|
|
791
|
-
}
|
|
792
|
-
|
|
793
950
|
const PacketType ppi = pset1<PacketType>(constant::pi),
|
|
794
951
|
ptrials = pset1<PacketType>(trials),
|
|
795
952
|
psqrt_v = pset1<PacketType>(sqrt_v),
|
|
796
|
-
pmean = pset1<PacketType>(
|
|
953
|
+
pmean = pset1<PacketType>(poisson.mean),
|
|
797
954
|
plog_small_p = pset1<PacketType>(log_small_p),
|
|
798
955
|
plog_small_q = pset1<PacketType>(log_small_q),
|
|
799
956
|
pg1 = pset1<PacketType>(g1);
|
|
800
957
|
while (1)
|
|
801
958
|
{
|
|
802
959
|
PacketType fres, ys, psin, pcos;
|
|
803
|
-
psincos(pmul(ppi,
|
|
960
|
+
psincos(pmul(ppi, poisson.ur.template packetOp<PacketType>(rng)), psin, pcos);
|
|
804
961
|
ys = pdiv(psin, pcos);
|
|
805
962
|
fres = ptruncate(padd(pmul(psqrt_v, ys), pmean));
|
|
806
|
-
|
|
963
|
+
|
|
807
964
|
auto p1 = pmul(pmul(pset1<PacketType>(1.2), psqrt_v), padd(pset1<PacketType>(1), pmul(ys, ys)));
|
|
808
965
|
auto p2 = pexp(
|
|
809
966
|
padd(padd(psub(
|
|
@@ -813,12 +970,12 @@ namespace Eigen
|
|
|
813
970
|
);
|
|
814
971
|
|
|
815
972
|
auto c1 = pand(pcmple(pset1<PacketType>(0), fres), pcmple(fres, ptrials));
|
|
816
|
-
auto c2 = pcmple(
|
|
973
|
+
auto c2 = pcmple(poisson.ur.template packetOp<PacketType>(rng), pmul(p1, p2));
|
|
817
974
|
|
|
818
975
|
auto cands = fres;
|
|
819
976
|
bool full = false;
|
|
820
|
-
cache_rest_cnt = cm.compress_append(cands, pand(c1, c2),
|
|
821
|
-
|
|
977
|
+
poisson.cache_rest_cnt = cm.compress_append(cands, pand(c1, c2),
|
|
978
|
+
poisson.template get<PacketType>(), poisson.cache_rest_cnt, full);
|
|
822
979
|
if (full)
|
|
823
980
|
{
|
|
824
981
|
res = pcast<PacketType, Packet>(cands);
|
|
@@ -830,47 +987,521 @@ namespace Eigen
|
|
|
830
987
|
}
|
|
831
988
|
};
|
|
832
989
|
|
|
833
|
-
|
|
834
|
-
|
|
990
|
+
/**
|
|
991
|
+
* @brief Generator of integers on a geometric distribution
|
|
992
|
+
*
|
|
993
|
+
* @tparam _Scalar
|
|
994
|
+
*/
|
|
995
|
+
template<typename _Scalar>
|
|
996
|
+
class GeometricGen : public GenBase<GeometricGen<_Scalar>, _Scalar>
|
|
835
997
|
{
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
template<typename Scalar, typename Rng>
|
|
840
|
-
struct scalar_geometric_dist_op : public scalar_uniform_real_op<float, Rng>
|
|
841
|
-
{
|
|
842
|
-
static_assert(std::is_same<Scalar, int32_t>::value, "geomtric needs integral types.");
|
|
843
|
-
using ur_base = scalar_uniform_real_op<float, Rng>;
|
|
844
|
-
|
|
998
|
+
static_assert(std::is_same<_Scalar, int32_t>::value, "geomtric needs integral types.");
|
|
999
|
+
UniformRealGen<float> ur;
|
|
845
1000
|
double p, rlog_q;
|
|
846
1001
|
|
|
847
|
-
|
|
848
|
-
|
|
1002
|
+
public:
|
|
1003
|
+
using Scalar = _Scalar;
|
|
1004
|
+
|
|
1005
|
+
/**
|
|
1006
|
+
* @brief Construct a new Geometric Generator
|
|
1007
|
+
*
|
|
1008
|
+
* @param _p probability of a trial generating true
|
|
1009
|
+
*/
|
|
1010
|
+
GeometricGen(double _p = 0.5)
|
|
1011
|
+
: p{ _p }, rlog_q{ 1 / std::log(1 - p) }
|
|
849
1012
|
{
|
|
850
1013
|
}
|
|
851
1014
|
|
|
852
|
-
|
|
1015
|
+
GeometricGen(const GeometricGen&) = default;
|
|
1016
|
+
GeometricGen(GeometricGen&&) = default;
|
|
1017
|
+
|
|
1018
|
+
GeometricGen& operator=(const GeometricGen&) = default;
|
|
1019
|
+
GeometricGen& operator=(GeometricGen&&) = default;
|
|
1020
|
+
|
|
1021
|
+
template<typename Rng>
|
|
1022
|
+
EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
|
|
853
1023
|
{
|
|
854
|
-
|
|
1024
|
+
using namespace Eigen::internal;
|
|
1025
|
+
return (_Scalar)(std::log(1 - ur(std::forward<Rng>(rng))) * rlog_q);
|
|
855
1026
|
}
|
|
856
1027
|
|
|
857
|
-
template<typename Packet>
|
|
858
|
-
|
|
1028
|
+
template<typename Packet, typename Rng>
|
|
1029
|
+
EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
|
|
859
1030
|
{
|
|
1031
|
+
using namespace Eigen::internal;
|
|
860
1032
|
using PacketType = decltype(reinterpret_to_float(std::declval<Packet>()));
|
|
861
1033
|
|
|
862
1034
|
return pcast<PacketType, Packet>(ptruncate(pmul(plog(
|
|
863
|
-
psub(pset1<PacketType>(1),
|
|
1035
|
+
psub(pset1<PacketType>(1), ur.template packetOp<PacketType>(std::forward<Rng>(rng)))
|
|
864
1036
|
), pset1<PacketType>(rlog_q))));
|
|
865
1037
|
}
|
|
866
1038
|
};
|
|
867
1039
|
|
|
868
|
-
template<typename Scalar, typename Urng>
|
|
869
|
-
struct functor_traits<scalar_geometric_dist_op<Scalar, Urng> >
|
|
870
|
-
{
|
|
871
|
-
enum { Cost = HugeCost, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = false };
|
|
872
|
-
};
|
|
873
1040
|
|
|
1041
|
+
template<typename Derived, typename Urng>
|
|
1042
|
+
using UniformIntType = CwiseNullaryOp<internal::scalar_rng_adaptor<UniformIntGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
|
|
1043
|
+
|
|
1044
|
+
/**
|
|
1045
|
+
* @brief generates integers with a given range `[min, max]`
|
|
1046
|
+
*
|
|
1047
|
+
* @tparam Derived a type of Eigen::DenseBase
|
|
1048
|
+
* @tparam Urng
|
|
1049
|
+
* @param rows the number of rows being generated
|
|
1050
|
+
* @param cols the number of columns being generated
|
|
1051
|
+
* @param urng c++11-style random number generator
|
|
1052
|
+
* @param min, max the range of integers being generated
|
|
1053
|
+
* @return a random matrix expression with a shape (`rows`, `cols`)
|
|
1054
|
+
*
|
|
1055
|
+
* @see Eigen::Rand::UniformIntGen
|
|
1056
|
+
*/
|
|
1057
|
+
template<typename Derived, typename Urng>
|
|
1058
|
+
inline const UniformIntType<Derived, Urng>
|
|
1059
|
+
uniformInt(Index rows, Index cols, Urng&& urng, typename Derived::Scalar min, typename Derived::Scalar max)
|
|
1060
|
+
{
|
|
1061
|
+
return {
|
|
1062
|
+
rows, cols, { std::forward<Urng>(urng), UniformIntGen<typename Derived::Scalar>{ min, max } }
|
|
1063
|
+
};
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
/**
|
|
1067
|
+
* @brief generates integers with a given range `[min, max]`
|
|
1068
|
+
*
|
|
1069
|
+
* @tparam Derived
|
|
1070
|
+
* @tparam Urng
|
|
1071
|
+
* @param o an instance of any type of Eigen::DenseBase
|
|
1072
|
+
* @param urng c++11-style random number generator
|
|
1073
|
+
* @param min, max the range of integers being generated
|
|
1074
|
+
* @return a random matrix expression of the same shape as `o`
|
|
1075
|
+
*
|
|
1076
|
+
* @see Eigen::Rand::UniformIntGen
|
|
1077
|
+
*/
|
|
1078
|
+
template<typename Derived, typename Urng>
|
|
1079
|
+
inline const UniformIntType<Derived, Urng>
|
|
1080
|
+
uniformIntLike(Derived& o, Urng&& urng, typename Derived::Scalar min, typename Derived::Scalar max)
|
|
1081
|
+
{
|
|
1082
|
+
return {
|
|
1083
|
+
o.rows(), o.cols(), { std::forward<Urng>(urng), UniformIntGen<typename Derived::Scalar>{ min, max } }
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
template<typename Derived, typename Urng>
|
|
1088
|
+
using DiscreteFType = CwiseNullaryOp<internal::scalar_rng_adaptor<DiscreteGen<typename Derived::Scalar, float>, typename Derived::Scalar, Urng, true>, const Derived>;
|
|
1089
|
+
|
|
1090
|
+
/**
|
|
1091
|
+
* @brief generates random integers on the interval `[0, n)`, where the probability of each individual integer `i` is proportional to `w(i)`.
|
|
1092
|
+
* The data type used for calculation of probabilities is float(23bit precision).
|
|
1093
|
+
*
|
|
1094
|
+
* @tparam Derived
|
|
1095
|
+
* @tparam Urng
|
|
1096
|
+
* @param rows the number of rows being generated
|
|
1097
|
+
* @param cols the number of columns being generated
|
|
1098
|
+
* @param urng c++11-style random number generator
|
|
1099
|
+
* @param first, last the range of elements defining the numbers to use as weights. The type of the elements referred by `RealIter` must be convertible to `double`.
|
|
1100
|
+
* @return a random matrix expression with a shape (`rows`, `cols`)
|
|
1101
|
+
*
|
|
1102
|
+
* @see Eigen::Rand::DiscreteGen
|
|
1103
|
+
*/
|
|
1104
|
+
template<typename Derived, typename Urng, typename RealIter>
|
|
1105
|
+
inline const DiscreteFType<Derived, Urng>
|
|
1106
|
+
discreteF(Index rows, Index cols, Urng&& urng, RealIter first, RealIter last)
|
|
1107
|
+
{
|
|
1108
|
+
return {
|
|
1109
|
+
rows, cols, { std::forward<Urng>(urng), DiscreteGen<typename Derived::Scalar, float>{first, last} }
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
/**
|
|
1114
|
+
* @brief generates random integers on the interval `[0, n)`, where the probability of each individual integer `i` is proportional to `w(i)`.
|
|
1115
|
+
* The data type used for calculation of probabilities is float(23bit precision).
|
|
1116
|
+
*
|
|
1117
|
+
* @tparam Derived
|
|
1118
|
+
* @tparam Urng
|
|
1119
|
+
* @param o an instance of any type of Eigen::DenseBase
|
|
1120
|
+
* @param urng c++11-style random number generator
|
|
1121
|
+
* @param first, last the range of elements defining the numbers to use as weights. The type of the elements referred by `RealIter` must be convertible to `double`.
|
|
1122
|
+
* @return a random matrix expression of the same shape as `o`
|
|
1123
|
+
*
|
|
1124
|
+
* @see Eigen::Rand::DiscreteGen
|
|
1125
|
+
*/
|
|
1126
|
+
template<typename Derived, typename Urng, typename RealIter>
|
|
1127
|
+
inline const DiscreteFType<Derived, Urng>
|
|
1128
|
+
discreteFLike(Derived& o, Urng&& urng, RealIter first, RealIter last)
|
|
1129
|
+
{
|
|
1130
|
+
return {
|
|
1131
|
+
o.rows(), o.cols(), { std::forward<Urng>(urng), DiscreteGen<typename Derived::Scalar, float>(first, last) }
|
|
1132
|
+
};
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
/**
|
|
1136
|
+
* @brief generates random integers on the interval `[0, n)`, where the probability of each individual integer `i` is proportional to `w(i)`.
|
|
1137
|
+
* The data type used for calculation of probabilities is float(23bit precision).
|
|
1138
|
+
*
|
|
1139
|
+
* @tparam Derived
|
|
1140
|
+
* @tparam Urng
|
|
1141
|
+
* @param rows the number of rows being generated
|
|
1142
|
+
* @param cols the number of columns being generated
|
|
1143
|
+
* @param urng c++11-style random number generator
|
|
1144
|
+
* @param il an instance of `initializer_list` containing the numbers to use as weights. The type of the elements referred by it must be convertible to `double`.
|
|
1145
|
+
* @return a random matrix expression with a shape (`rows`, `cols`)
|
|
1146
|
+
*
|
|
1147
|
+
* @see Eigen::Rand::DiscreteGen
|
|
1148
|
+
*/
|
|
1149
|
+
template<typename Derived, typename Urng, typename Real>
|
|
1150
|
+
inline const DiscreteFType<Derived, Urng>
|
|
1151
|
+
discreteF(Index rows, Index cols, Urng&& urng, const std::initializer_list<Real>& il)
|
|
1152
|
+
{
|
|
1153
|
+
return {
|
|
1154
|
+
rows, cols, { std::forward<Urng>(urng), DiscreteGen<typename Derived::Scalar, float>{il.begin(), il.end()} }
|
|
1155
|
+
};
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
/**
|
|
1159
|
+
* @brief generates random integers on the interval `[0, n)`, where the probability of each individual integer `i` is proportional to `w(i)`.
|
|
1160
|
+
* The data type used for calculation of probabilities is float(23bit precision).
|
|
1161
|
+
*
|
|
1162
|
+
* @tparam Derived
|
|
1163
|
+
* @tparam Urng
|
|
1164
|
+
* @param o an instance of any type of Eigen::DenseBase
|
|
1165
|
+
* @param urng c++11-style random number generator
|
|
1166
|
+
* @param il an instance of `initializer_list` containing the numbers to use as weights. The type of the elements referred by it must be convertible to `double`.
|
|
1167
|
+
* @return a random matrix expression of the same shape as `o`
|
|
1168
|
+
*
|
|
1169
|
+
* @see Eigen::Rand::DiscreteGen
|
|
1170
|
+
*/
|
|
1171
|
+
template<typename Derived, typename Urng, typename Real>
|
|
1172
|
+
inline const DiscreteFType<Derived, Urng>
|
|
1173
|
+
discreteFLike(Derived& o, Urng&& urng, const std::initializer_list<Real>& il)
|
|
1174
|
+
{
|
|
1175
|
+
return {
|
|
1176
|
+
o.rows(), o.cols(), { std::forward<Urng>(urng), DiscreteGen<typename Derived::Scalar, float>(il.begin(), il.end()) }
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
template<typename Derived, typename Urng>
|
|
1181
|
+
using DiscreteDType = CwiseNullaryOp<internal::scalar_rng_adaptor<DiscreteGen<typename Derived::Scalar, double>, typename Derived::Scalar, Urng, true>, const Derived>;
|
|
1182
|
+
|
|
1183
|
+
/**
|
|
1184
|
+
* @brief generates random integers on the interval `[0, n)`, where the probability of each individual integer `i` is proportional to `w(i)`.
|
|
1185
|
+
* The data type used for calculation of probabilities is double(52bit precision).
|
|
1186
|
+
*
|
|
1187
|
+
* @tparam Derived
|
|
1188
|
+
* @tparam Urng
|
|
1189
|
+
* @param rows the number of rows being generated
|
|
1190
|
+
* @param cols the number of columns being generated
|
|
1191
|
+
* @param urng c++11-style random number generator
|
|
1192
|
+
* @param first, last the range of elements defining the numbers to use as weights. The type of the elements referred by `RealIter` must be convertible to `double`.
|
|
1193
|
+
* @return a random matrix expression with a shape (`rows`, `cols`)
|
|
1194
|
+
*
|
|
1195
|
+
* @see Eigen::Rand::DiscreteGen
|
|
1196
|
+
*/
|
|
1197
|
+
template<typename Derived, typename Urng, typename RealIter>
|
|
1198
|
+
inline const DiscreteDType<Derived, Urng>
|
|
1199
|
+
discreteD(Index rows, Index cols, Urng&& urng, RealIter first, RealIter last)
|
|
1200
|
+
{
|
|
1201
|
+
return {
|
|
1202
|
+
rows, cols, { std::forward<Urng>(urng), DiscreteGen<typename Derived::Scalar, double>{first, last} }
|
|
1203
|
+
};
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
/**
|
|
1207
|
+
* @brief generates random integers on the interval `[0, n)`, where the probability of each individual integer `i` is proportional to `w(i)`.
|
|
1208
|
+
* The data type used for calculation of probabilities is double(52bit precision).
|
|
1209
|
+
*
|
|
1210
|
+
* @tparam Derived
|
|
1211
|
+
* @tparam Urng
|
|
1212
|
+
* @param o an instance of any type of Eigen::DenseBase
|
|
1213
|
+
* @param urng c++11-style random number generator
|
|
1214
|
+
* @param first, last the range of elements defining the numbers to use as weights. The type of the elements referred by `RealIter` must be convertible to `double`.
|
|
1215
|
+
* @return a random matrix expression of the same shape as `o`
|
|
1216
|
+
*
|
|
1217
|
+
* @see Eigen::Rand::DiscreteGen
|
|
1218
|
+
*/
|
|
1219
|
+
template<typename Derived, typename Urng, typename RealIter>
|
|
1220
|
+
inline const DiscreteDType<Derived, Urng>
|
|
1221
|
+
discreteDLike(Derived& o, Urng&& urng, RealIter first, RealIter last)
|
|
1222
|
+
{
|
|
1223
|
+
return {
|
|
1224
|
+
o.rows(), o.cols(), { std::forward<Urng>(urng), DiscreteGen<typename Derived::Scalar, double>{first, last} }
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
/**
|
|
1229
|
+
* @brief generates random integers on the interval `[0, n)`, where the probability of each individual integer `i` is proportional to `w(i)`.
|
|
1230
|
+
* The data type used for calculation of probabilities is double(52bit precision).
|
|
1231
|
+
*
|
|
1232
|
+
* @tparam Derived
|
|
1233
|
+
* @tparam Urng
|
|
1234
|
+
* @param rows the number of rows being generated
|
|
1235
|
+
* @param cols the number of columns being generated
|
|
1236
|
+
* @param urng c++11-style random number generator
|
|
1237
|
+
* @param il an instance of `initializer_list` containing the numbers to use as weights. The type of the elements referred by it must be convertible to `double`.
|
|
1238
|
+
* @return a random matrix expression with a shape (`rows`, `cols`)
|
|
1239
|
+
*
|
|
1240
|
+
* @see Eigen::Rand::DiscreteGen
|
|
1241
|
+
*/
|
|
1242
|
+
template<typename Derived, typename Urng, typename Real>
|
|
1243
|
+
inline const DiscreteDType<Derived, Urng>
|
|
1244
|
+
discreteD(Index rows, Index cols, Urng&& urng, const std::initializer_list<Real>& il)
|
|
1245
|
+
{
|
|
1246
|
+
return {
|
|
1247
|
+
rows, cols, { std::forward<Urng>(urng), DiscreteGen<typename Derived::Scalar, double>{il.begin(), il.end()} }
|
|
1248
|
+
};
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
/**
|
|
1252
|
+
* @brief generates random integers on the interval `[0, n)`, where the probability of each individual integer `i` is proportional to `w(i)`.
|
|
1253
|
+
* The data type used for calculation of probabilities is double(52bit precision).
|
|
1254
|
+
*
|
|
1255
|
+
* @tparam Derived
|
|
1256
|
+
* @tparam Urng
|
|
1257
|
+
* @param o an instance of any type of Eigen::DenseBase
|
|
1258
|
+
* @param urng c++11-style random number generator
|
|
1259
|
+
* @param il an instance of `initializer_list` containing the numbers to use as weights. The type of the elements referred by it must be convertible to `double`.
|
|
1260
|
+
* @return a random matrix expression of the same shape as `o`
|
|
1261
|
+
*
|
|
1262
|
+
* @see Eigen::Rand::DiscreteGen
|
|
1263
|
+
*/
|
|
1264
|
+
template<typename Derived, typename Urng, typename Real>
|
|
1265
|
+
inline const DiscreteDType<Derived, Urng>
|
|
1266
|
+
discreteDLike(Derived& o, Urng&& urng, const std::initializer_list<Real>& il)
|
|
1267
|
+
{
|
|
1268
|
+
return {
|
|
1269
|
+
o.rows(), o.cols(), { std::forward<Urng>(urng), DiscreteGen<typename Derived::Scalar, double>{il.begin(), il.end()} }
|
|
1270
|
+
};
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
template<typename Derived, typename Urng>
|
|
1274
|
+
using DiscreteType = CwiseNullaryOp<internal::scalar_rng_adaptor<DiscreteGen<typename Derived::Scalar, int32_t>, typename Derived::Scalar, Urng, true>, const Derived>;
|
|
1275
|
+
|
|
1276
|
+
/**
|
|
1277
|
+
* @brief generates random integers on the interval `[0, n)`, where the probability of each individual integer `i` is proportional to `w(i)`.
|
|
1278
|
+
* The data type used for calculation of probabilities is int32(32bit precision).
|
|
1279
|
+
*
|
|
1280
|
+
* @tparam Derived
|
|
1281
|
+
* @tparam Urng
|
|
1282
|
+
* @param rows the number of rows being generated
|
|
1283
|
+
* @param cols the number of columns being generated
|
|
1284
|
+
* @param urng c++11-style random number generator
|
|
1285
|
+
* @param first, last the range of elements defining the numbers to use as weights. The type of the elements referred by `RealIter` must be convertible to `double`.
|
|
1286
|
+
* @return a random matrix expression with a shape (`rows`, `cols`)
|
|
1287
|
+
*
|
|
1288
|
+
* @see Eigen::Rand::DiscreteGen
|
|
1289
|
+
*/
|
|
1290
|
+
template<typename Derived, typename Urng, typename RealIter>
|
|
1291
|
+
inline const DiscreteType<Derived, Urng>
|
|
1292
|
+
discrete(Index rows, Index cols, Urng&& urng, RealIter first, RealIter last)
|
|
1293
|
+
{
|
|
1294
|
+
return {
|
|
1295
|
+
rows, cols, { std::forward<Urng>(urng), DiscreteGen<typename Derived::Scalar, int32_t>{first, last} }
|
|
1296
|
+
};
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
/**
|
|
1300
|
+
* @brief generates random integers on the interval `[0, n)`, where the probability of each individual integer `i` is proportional to `w(i)`.
|
|
1301
|
+
* The data type used for calculation of probabilities is int32(32bit precision).
|
|
1302
|
+
*
|
|
1303
|
+
* @tparam Derived
|
|
1304
|
+
* @tparam Urng
|
|
1305
|
+
* @param o an instance of any type of Eigen::DenseBase
|
|
1306
|
+
* @param urng c++11-style random number generator
|
|
1307
|
+
* @param first, last the range of elements defining the numbers to use as weights. The type of the elements referred by `RealIter` must be convertible to `double`.
|
|
1308
|
+
* @return a random matrix expression of the same shape as `o`
|
|
1309
|
+
*
|
|
1310
|
+
* @see Eigen::Rand::DiscreteGen
|
|
1311
|
+
*/
|
|
1312
|
+
template<typename Derived, typename Urng, typename RealIter>
|
|
1313
|
+
inline const DiscreteType<Derived, Urng>
|
|
1314
|
+
discreteLike(Derived& o, Urng&& urng, RealIter first, RealIter last)
|
|
1315
|
+
{
|
|
1316
|
+
return {
|
|
1317
|
+
o.rows(), o.cols(), { std::forward<Urng>(urng), DiscreteGen<typename Derived::Scalar, int32_t>{first, last} }
|
|
1318
|
+
};
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
/**
|
|
1322
|
+
* @brief generates random integers on the interval `[0, n)`, where the probability of each individual integer `i` is proportional to `w(i)`.
|
|
1323
|
+
* The data type used for calculation of probabilities is int32(32bit precision).
|
|
1324
|
+
*
|
|
1325
|
+
* @tparam Derived
|
|
1326
|
+
* @tparam Urng
|
|
1327
|
+
* @param rows the number of rows being generated
|
|
1328
|
+
* @param cols the number of columns being generated
|
|
1329
|
+
* @param urng c++11-style random number generator
|
|
1330
|
+
* @param il an instance of `initializer_list` containing the numbers to use as weights. The type of the elements referred by it must be convertible to `double`.
|
|
1331
|
+
* @return a random matrix expression with a shape (`rows`, `cols`)
|
|
1332
|
+
*
|
|
1333
|
+
* @see Eigen::Rand::DiscreteGen
|
|
1334
|
+
*/
|
|
1335
|
+
template<typename Derived, typename Urng, typename Real>
|
|
1336
|
+
inline const DiscreteType<Derived, Urng>
|
|
1337
|
+
discrete(Index rows, Index cols, Urng&& urng, const std::initializer_list<Real>& il)
|
|
1338
|
+
{
|
|
1339
|
+
return {
|
|
1340
|
+
rows, cols, { std::forward<Urng>(urng), DiscreteGen<typename Derived::Scalar, int32_t>{il.begin(), il.end()} }
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
/**
|
|
1345
|
+
* @brief generates random integers on the interval `[0, n)`, where the probability of each individual integer `i` is proportional to `w(i)`.
|
|
1346
|
+
* The data type used for calculation of probabilities is int32(32bit precision).
|
|
1347
|
+
*
|
|
1348
|
+
* @tparam Derived
|
|
1349
|
+
* @tparam Urng
|
|
1350
|
+
* @param o an instance of any type of Eigen::DenseBase
|
|
1351
|
+
* @param urng c++11-style random number generator
|
|
1352
|
+
* @param il an instance of `initializer_list` containing the numbers to use as weights. The type of the elements referred by it must be convertible to `double`.
|
|
1353
|
+
* @return a random matrix expression of the same shape as `o`
|
|
1354
|
+
*
|
|
1355
|
+
* @see Eigen::Rand::DiscreteGen
|
|
1356
|
+
*/
|
|
1357
|
+
template<typename Derived, typename Urng, typename Real>
|
|
1358
|
+
inline const DiscreteType<Derived, Urng>
|
|
1359
|
+
discreteLike(Derived& o, Urng&& urng, const std::initializer_list<Real>& il)
|
|
1360
|
+
{
|
|
1361
|
+
return {
|
|
1362
|
+
o.rows(), o.cols(), { std::forward<Urng>(urng), DiscreteGen<typename Derived::Scalar, int32_t>{il.begin(), il.end()} }
|
|
1363
|
+
};
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
template<typename Derived, typename Urng>
|
|
1367
|
+
using PoissonType = CwiseNullaryOp<internal::scalar_rng_adaptor<PoissonGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
|
|
1368
|
+
|
|
1369
|
+
/**
|
|
1370
|
+
* @brief generates reals on the Poisson distribution.
|
|
1371
|
+
*
|
|
1372
|
+
* @tparam Derived
|
|
1373
|
+
* @tparam Urng
|
|
1374
|
+
* @param rows the number of rows being generated
|
|
1375
|
+
* @param cols the number of columns being generated
|
|
1376
|
+
* @param urng c++11-style random number generator
|
|
1377
|
+
* @param mean rate parameter
|
|
1378
|
+
* @return a random matrix expression with a shape (`rows`, `cols`)
|
|
1379
|
+
*
|
|
1380
|
+
* @see Eigen::Rand::PoissonGen
|
|
1381
|
+
*/
|
|
1382
|
+
template<typename Derived, typename Urng>
|
|
1383
|
+
inline const PoissonType<Derived, Urng>
|
|
1384
|
+
poisson(Index rows, Index cols, Urng&& urng, double mean = 1)
|
|
1385
|
+
{
|
|
1386
|
+
return {
|
|
1387
|
+
rows, cols, { std::forward<Urng>(urng), PoissonGen<typename Derived::Scalar>{mean} }
|
|
1388
|
+
};
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
/**
|
|
1392
|
+
* @brief generates reals on the Poisson distribution.
|
|
1393
|
+
*
|
|
1394
|
+
* @tparam Derived
|
|
1395
|
+
* @tparam Urng
|
|
1396
|
+
* @param o an instance of any type of Eigen::DenseBase
|
|
1397
|
+
* @param urng c++11-style random number generator
|
|
1398
|
+
* @param mean rate parameter
|
|
1399
|
+
* @return a random matrix expression of the same shape as `o`
|
|
1400
|
+
*
|
|
1401
|
+
* @see Eigen::Rand::PoissonGen
|
|
1402
|
+
*/
|
|
1403
|
+
template<typename Derived, typename Urng>
|
|
1404
|
+
inline const PoissonType<Derived, Urng>
|
|
1405
|
+
poissonLike(Derived& o, Urng&& urng, double mean = 1)
|
|
1406
|
+
{
|
|
1407
|
+
return {
|
|
1408
|
+
o.rows(), o.cols(), { std::forward<Urng>(urng), PoissonGen<typename Derived::Scalar>{mean} }
|
|
1409
|
+
};
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
template<typename Derived, typename Urng>
|
|
1413
|
+
using BinomialType = CwiseNullaryOp<internal::scalar_rng_adaptor<BinomialGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
|
|
1414
|
+
|
|
1415
|
+
/**
|
|
1416
|
+
* @brief generates reals on the binomial distribution.
|
|
1417
|
+
*
|
|
1418
|
+
* @tparam Derived
|
|
1419
|
+
* @tparam Urng
|
|
1420
|
+
* @param rows the number of rows being generated
|
|
1421
|
+
* @param cols the number of columns being generated
|
|
1422
|
+
* @param urng c++11-style random number generator
|
|
1423
|
+
* @param trials the number of trials
|
|
1424
|
+
* @param p probability of a trial generating true
|
|
1425
|
+
* @return a random matrix expression with a shape (`rows`, `cols`)
|
|
1426
|
+
*
|
|
1427
|
+
* @see Eigen::Rand::BinomialGen
|
|
1428
|
+
*/
|
|
1429
|
+
template<typename Derived, typename Urng>
|
|
1430
|
+
inline const BinomialType<Derived, Urng>
|
|
1431
|
+
binomial(Index rows, Index cols, Urng&& urng, typename Derived::Scalar trials = 1, double p = 0.5)
|
|
1432
|
+
{
|
|
1433
|
+
return {
|
|
1434
|
+
rows, cols, { std::forward<Urng>(urng), BinomialGen<typename Derived::Scalar>{trials, p} }
|
|
1435
|
+
};
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
/**
|
|
1439
|
+
* @brief generates reals on the binomial distribution.
|
|
1440
|
+
*
|
|
1441
|
+
* @tparam Derived
|
|
1442
|
+
* @tparam Urng
|
|
1443
|
+
* @param o an instance of any type of Eigen::DenseBase
|
|
1444
|
+
* @param urng c++11-style random number generator
|
|
1445
|
+
* @param trials the number of trials
|
|
1446
|
+
* @param p probability of a trial generating true
|
|
1447
|
+
* @return a random matrix expression of the same shape as `o`
|
|
1448
|
+
*
|
|
1449
|
+
* @see Eigen::Rand::BinomialGen
|
|
1450
|
+
*/
|
|
1451
|
+
template<typename Derived, typename Urng>
|
|
1452
|
+
inline const BinomialType<Derived, Urng>
|
|
1453
|
+
binomialLike(Derived& o, Urng&& urng, typename Derived::Scalar trials = 1, double p = 0.5)
|
|
1454
|
+
{
|
|
1455
|
+
return {
|
|
1456
|
+
o.rows(), o.cols(), { std::forward<Urng>(urng), BinomialGen<typename Derived::Scalar>{trials, p} }
|
|
1457
|
+
};
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1460
|
+
template<typename Derived, typename Urng>
|
|
1461
|
+
using GeometricType = CwiseNullaryOp<internal::scalar_rng_adaptor<GeometricGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
|
|
1462
|
+
|
|
1463
|
+
/**
|
|
1464
|
+
* @brief generates reals on the geometric distribution.
|
|
1465
|
+
*
|
|
1466
|
+
* @tparam Derived
|
|
1467
|
+
* @tparam Urng
|
|
1468
|
+
* @param rows the number of rows being generated
|
|
1469
|
+
* @param cols the number of columns being generated
|
|
1470
|
+
* @param urng c++11-style random number generator
|
|
1471
|
+
* @param p probability of a trial generating true
|
|
1472
|
+
* @return a random matrix expression with a shape (`rows`, `cols`)
|
|
1473
|
+
*
|
|
1474
|
+
* @see Eigen::Rand::GeometricGen
|
|
1475
|
+
*/
|
|
1476
|
+
template<typename Derived, typename Urng>
|
|
1477
|
+
inline const GeometricType<Derived, Urng>
|
|
1478
|
+
geometric(Index rows, Index cols, Urng&& urng, double p = 0.5)
|
|
1479
|
+
{
|
|
1480
|
+
return {
|
|
1481
|
+
rows, cols, { std::forward<Urng>(urng), GeometricGen<typename Derived::Scalar>{p} }
|
|
1482
|
+
};
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
/**
|
|
1486
|
+
* @brief generates reals on the geometric distribution.
|
|
1487
|
+
*
|
|
1488
|
+
* @tparam Derived
|
|
1489
|
+
* @tparam Urng
|
|
1490
|
+
* @param o an instance of any type of Eigen::DenseBase
|
|
1491
|
+
* @param urng c++11-style random number generator
|
|
1492
|
+
* @param p probability of a trial generating true
|
|
1493
|
+
* @return a random matrix expression of the same shape as `o`
|
|
1494
|
+
*
|
|
1495
|
+
* @see Eigen::Rand::GeometricGen
|
|
1496
|
+
*/
|
|
1497
|
+
template<typename Derived, typename Urng>
|
|
1498
|
+
inline const GeometricType<Derived, Urng>
|
|
1499
|
+
geometricLike(Derived& o, Urng&& urng, double p = 0.5)
|
|
1500
|
+
{
|
|
1501
|
+
return {
|
|
1502
|
+
o.rows(), o.cols(), { std::forward<Urng>(urng), GeometricGen<typename Derived::Scalar>{p} }
|
|
1503
|
+
};
|
|
1504
|
+
}
|
|
874
1505
|
}
|
|
875
1506
|
}
|
|
876
1507
|
|