Skip to content

Commit cf27c10

Browse files
committed
shift to the Total-Random fork of the PCG PRNG
1 parent 292b1ea commit cf27c10

File tree

3 files changed

+36
-30
lines changed

3 files changed

+36
-30
lines changed

VERSIONS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ development head (in the master branch):
3636
CI workflow for calculating code coverage with Codecov, thanks to Andy Kern, https://github.com/MesserLab/SLiM/pull/601
3737
fix #594, the pedigreeID and haplosomePedigreeID properties should be accessible (without other predigree-tracking features) in tree-seq models, even without pedigree tracking being enabled
3838
fix #584, a way to generate a random 64-bit integer is needed; added new rdunif64(integer$ n) function for this purpose
39+
shift over to Release 1 of the Total-Random fork of the PCG random number generator (better maintained), found at https://github.com/Total-Random/pcg-cpp/releases/tag/v1.0
3940

4041

4142
version 5.1 (Eidos version 4.1):

eidos/pcg_extras.hpp

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@
5555

5656
#ifdef __GNUC__
5757
#define PCG_NOINLINE __attribute__((noinline))
58+
#elif defined(_MSC_VER)
59+
#define PCG_NOINLINE __declspec(noinline)
60+
#pragma warning(disable:4127) // conditional expression is constant
5861
#else
5962
#define PCG_NOINLINE
6063
#endif
@@ -263,21 +266,11 @@ inline std::istream& operator>>(std::istream& in, uint8_t& value)
263266
template <typename itype>
264267
inline itype unxorshift(itype x, bitcount_t bits, bitcount_t shift)
265268
{
266-
if (2*shift >= bits) {
267-
return x ^ (x >> shift);
268-
}
269-
itype lowmask1 = (itype(1U) << (bits - shift*2)) - 1;
270-
itype highmask1 = ~lowmask1;
271-
itype top1 = x;
272-
itype bottom1 = x & lowmask1;
273-
top1 ^= top1 >> shift;
274-
top1 &= highmask1;
275-
x = top1 | bottom1;
276-
itype lowmask2 = (itype(1U) << (bits - shift)) - 1;
277-
itype bottom2 = x & lowmask2;
278-
bottom2 = unxorshift(bottom2, bits - shift, shift);
279-
bottom2 &= lowmask1;
280-
return top1 | bottom2;
269+
do {
270+
x ^= x >> shift;
271+
shift *= 2u;
272+
} while(shift < bits);
273+
return x;
281274
}
282275

283276
/*
@@ -411,10 +404,10 @@ SrcIter uneven_copy_impl(
411404
typedef typename std::iterator_traits<SrcIter>::value_type src_t;
412405
typedef typename std::iterator_traits<DestIter>::value_type dest_t;
413406

414-
constexpr bitcount_t SRC_SIZE = sizeof(src_t);
415-
constexpr bitcount_t DEST_SIZE = sizeof(dest_t);
416-
constexpr bitcount_t DEST_BITS = DEST_SIZE * 8;
417-
constexpr bitcount_t SCALE = SRC_SIZE / DEST_SIZE;
407+
constexpr size_t SRC_SIZE = sizeof(src_t);
408+
constexpr size_t DEST_SIZE = sizeof(dest_t);
409+
constexpr bitcount_t DEST_BITS = bitcount_t(DEST_SIZE * 8);
410+
constexpr size_t SCALE = SRC_SIZE / DEST_SIZE;
418411

419412
size_t count = 0;
420413
src_t value = 0;
@@ -447,10 +440,10 @@ SrcIter uneven_copy_impl(
447440

448441
while (dest_first != dest_last) {
449442
dest_t value(0UL);
450-
unsigned int shift = 0;
443+
size_t shift = 0;
451444

452445
for (size_t i = 0; i < SCALE; ++i) {
453-
value |= dest_t(*src_first++) << shift;
446+
value |= dest_t(*src_first++) << bitcount_t(shift);
454447
shift += SRC_BITS;
455448
}
456449

@@ -583,9 +576,9 @@ class seed_seq_from {
583576
private:
584577
RngType rng_;
585578

579+
public:
586580
typedef uint_least32_t result_type;
587581

588-
public:
589582
template<typename... Args>
590583
seed_seq_from(Args&&... args) :
591584
rng_(std::forward<Args>(args)...)
@@ -628,6 +621,9 @@ struct static_arbitrary_seed {
628621
public:
629622
static constexpr IntType value = fnv(IntType(2166136261U ^ sizeof(IntType)),
630623
__DATE__ __TIME__ __FILE__);
624+
625+
//Prevent creation, while keeping GCC from giving a warning
626+
static_arbitrary_seed() = delete;
631627
};
632628

633629
// Sometimes, when debugging or testing, it's handy to be able print the name

eidos/pcg_random.hpp

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,23 @@
9090

9191
#ifdef _MSC_VER
9292
#pragma warning(disable:4146)
93+
#pragma warning(disable:4127) // conditional expression is constant
9394
#endif
9495

9596
#ifdef _MSC_VER
9697
#define PCG_ALWAYS_INLINE __forceinline
98+
#if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190024210
99+
// available since VS 2015 Update 2/3
100+
#define PCG_EBO __declspec(empty_bases)
101+
#else
102+
#define PCG_EBO
103+
#endif
97104
#elif __GNUC__
98105
#define PCG_ALWAYS_INLINE __attribute__((always_inline))
106+
#define PCG_EBO
99107
#else
100108
#define PCG_ALWAYS_INLINE inline
109+
#define PCG_EBO
101110
#endif
102111

103112
/*
@@ -333,7 +342,7 @@ class specific_stream {
333342

334343
void set_stream(itype specific_seq)
335344
{
336-
inc_ = (specific_seq << 1) | 1;
345+
inc_ = (specific_seq << 1) | itype(1U);
337346
}
338347

339348
static constexpr bool can_specify_stream = true;
@@ -375,7 +384,7 @@ template <typename xtype, typename itype,
375384
bool output_previous = true,
376385
typename stream_mixin = oneseq_stream<itype>,
377386
typename multiplier_mixin = default_multiplier<itype> >
378-
class engine : protected output_mixin,
387+
class PCG_EBO engine : protected output_mixin,
379388
public stream_mixin,
380389
protected multiplier_mixin {
381390
protected:
@@ -618,7 +627,7 @@ operator>>(std::basic_istream<CharT,Traits>& in,
618627

619628
if (!in.fail()) {
620629
bool good = true;
621-
if (multiplier != rng.multiplier()) {
630+
if (multiplier != itype(rng.multiplier())) {
622631
good = false;
623632
} else if (rng.can_specify_stream) {
624633
rng.set_stream(increment >> 1);
@@ -676,8 +685,8 @@ itype engine<xtype,itype,output_mixin,output_previous,stream_mixin,
676685
itype cur_state, itype newstate, itype cur_mult, itype cur_plus, itype mask)
677686
{
678687
constexpr itype ONE = 1u; // itype could be weird, so use constant
679-
bool is_mcg = cur_plus == itype(0);
680-
itype the_bit = is_mcg ? itype(4u) : itype(1u);
688+
bool is_mcg_internal = cur_plus == itype(0);
689+
itype the_bit = is_mcg_internal ? itype(4u) : itype(1u);
681690
itype distance = 0u;
682691
while ((cur_state & mask) != (newstate & mask)) {
683692
if ((cur_state & the_bit) != (newstate & the_bit)) {
@@ -689,7 +698,7 @@ itype engine<xtype,itype,output_mixin,output_previous,stream_mixin,
689698
cur_plus = (cur_mult+ONE)*cur_plus;
690699
cur_mult *= cur_mult;
691700
}
692-
return is_mcg ? distance >> 2 : distance;
701+
return is_mcg_internal ? distance >> 2 : distance;
693702
}
694703

695704
template <typename xtype, typename itype,
@@ -1187,7 +1196,7 @@ struct xsl_mixin {
11871196

11881197

11891198
template <typename baseclass>
1190-
struct inside_out : private baseclass {
1199+
struct PCG_EBO inside_out : private baseclass {
11911200
inside_out() = delete;
11921201

11931202
typedef typename baseclass::result_type result_type;
@@ -1229,7 +1238,7 @@ struct inside_out : private baseclass {
12291238

12301239

12311240
template <bitcount_t table_pow2, bitcount_t advance_pow2, typename baseclass, typename extvalclass, bool kdd = true>
1232-
class extended : public baseclass {
1241+
class PCG_EBO extended : public baseclass {
12331242
public:
12341243
typedef typename baseclass::state_type state_type;
12351244
typedef typename baseclass::result_type result_type;

0 commit comments

Comments
 (0)