1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
#pragma once
#include <utility>
#include <util/generic/typetraits.h>
// common engine for lcg-based RNG's
// http://en.wikipedia.org/wiki/Linear_congruential_generator
namespace NPrivate {
template <typename T>
T LcgAdvance(T seed, T lcgBase, T lcgAddend, T delta) noexcept;
}
template <typename T, T A, T C>
struct TFastLcgIterator {
static_assert(C % 2 == 1, "C must be odd");
static constexpr T Iterate(T x) noexcept {
return x * A + C;
}
static inline T IterateMultiple(T x, T delta) noexcept {
return ::NPrivate::LcgAdvance(x, A, C, delta);
}
};
template <typename T, T A>
struct TLcgIterator {
inline TLcgIterator(T seq) noexcept
: C((seq << 1u) | (T)1) // C must be odd
{
}
inline T Iterate(T x) noexcept {
return x * A + C;
}
inline T IterateMultiple(T x, T delta) noexcept {
return ::NPrivate::LcgAdvance(x, A, C, delta);
}
const T C;
};
template <class TIterator, class TMixer>
struct TLcgRngBase: public TIterator, public TMixer {
using TStateType = decltype(std::declval<TIterator>().Iterate(0));
using TResultType = decltype(std::declval<TMixer>().Mix(TStateType()));
template <typename... Args>
inline TLcgRngBase(TStateType seed, Args&&... args)
: TIterator(std::forward<Args>(args)...)
, X(seed)
{
}
inline TResultType GenRand() noexcept {
return this->Mix(X = this->Iterate(X));
}
inline void Advance(TStateType delta) noexcept {
X = this->IterateMultiple(X, delta);
}
TStateType X;
};
|