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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
/* SPDX-License-Identifier: BSD-3-Clause */
/* SPDX-FileCopyrightText: Olivier Lapicque */
/* SPDX-FileCopyrightText: OpenMPT Project Developers and Contributors */
#pragma once
#include "openmpt/all/BuildSettings.hpp"
#include "mpt/base/bit.hpp"
#include "mpt/random/random.hpp"
#include "openmpt/base/Types.hpp"
#include <limits>
#include <type_traits>
OPENMPT_NAMESPACE_BEGIN
namespace mpt
{
namespace rng
{
template <typename Tstate, typename Tvalue, Tstate x1, Tstate x2, Tstate x3, Tstate x4, int rol1, int rol2>
class modplug
{
public:
typedef Tstate state_type;
typedef Tvalue result_type;
private:
state_type state1;
state_type state2;
public:
template <typename Trng>
explicit inline modplug(Trng &rd)
: state1(mpt::random<state_type>(rd))
, state2(mpt::random<state_type>(rd))
{
}
explicit inline modplug(state_type seed1, state_type seed2)
: state1(seed1)
, state2(seed2)
{
}
public:
static MPT_CONSTEXPRINLINE result_type min()
{
return static_cast<result_type>(0);
}
static MPT_CONSTEXPRINLINE result_type max()
{
return std::numeric_limits<result_type>::max();
}
static MPT_CONSTEXPRINLINE int result_bits()
{
static_assert(std::is_integral<result_type>::value);
static_assert(std::is_unsigned<result_type>::value);
return std::numeric_limits<result_type>::digits;
}
inline result_type operator()()
{
state_type a = state1;
state_type b = state2;
a = mpt::rotl(a, rol1);
a ^= x1;
a += x2 + (b * x3);
b += mpt::rotl(a, rol2) * x4;
state1 = a;
state2 = b;
result_type result = static_cast<result_type>(b);
return result;
}
};
typedef modplug<uint32, uint32, 0x10204080u, 0x78649E7Du, 4, 5, 1, 16> modplug_dither;
} // namespace rng
} // namespace mpt
OPENMPT_NAMESPACE_END
|