LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
mt19937.h
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2012-2026, QORE Lab, Imperial College London
3
* All rights reserved.
4
*/
5
#ifndef LINE_OPT_DE_MT19937_H
6
#define LINE_OPT_DE_MT19937_H
7
8
/**
9
* @file
10
* @ingroup line_opt
11
* Bit-exact port of `matlab/src/opt/+opt/+de/MT19937.m`.
12
*
13
* This is NumPy's legacy MT19937 core, including its scalar seeding rule. It
14
* intentionally does not use `std::mt19937`: the standard fixes the generator
15
* recurrence but not NumPy RandomState's seed expansion and draw adapters, and
16
* line-opt requires the same word stream in every language so Differential
17
* Evolution follows the same trajectory for a fixed seed.
18
*/
19
20
#include <array>
21
#include <cstddef>
22
#include <cstdint>
23
#include <vector>
24
25
#include "
line/util/error.h
"
26
27
namespace
line
{
28
namespace
opt
{
29
namespace
de
{
30
31
class
MT19937
{
32
public
:
33
static
constexpr
std::size_t
state_size
= 624;
34
35
explicit
MT19937
(std::uint64_t seed_value) {
seed
(seed_value); }
36
37
/** NumPy legacy scalar seeding (`init_genrand`, or little-endian words). */
38
void
seed
(std::uint64_t value) {
39
if
(value <= UINT64_C(0xffffffff)) {
40
init_genrand
(
static_cast<
std::uint32_t
>
(value));
41
return
;
42
}
43
std::vector<std::uint32_t> key;
44
while
(value != 0) {
45
key.push_back(
static_cast<
std::uint32_t
>
(value & UINT64_C(0xffffffff)));
46
value >>= 32;
47
}
48
init_by_array
(key);
49
}
50
51
void
init_genrand
(std::uint32_t value) {
52
mt_[0] = value;
53
for
(std::size_t i = 1; i <
state_size
; ++i) {
54
const
std::uint32_t prev = mt_[i - 1];
55
mt_[i] = UINT32_C(1812433253) * (prev ^ (prev >> 30)) +
56
static_cast<
std::uint32_t
>
(i);
57
}
58
pos_ =
state_size
;
59
}
60
61
void
init_by_array
(
const
std::vector<std::uint32_t>& key) {
62
if
(key.empty())
throw
InputError
(
"MT19937::init_by_array: the seed key is empty"
);
63
init_genrand
(UINT32_C(19650218));
64
std::size_t i = 1, j = 0;
65
std::size_t k =
state_size
> key.size() ?
state_size
: key.size();
66
for
(; k != 0; --k) {
67
const
std::uint32_t prev = mt_[i - 1];
68
mt_[i] = (mt_[i] ^ ((prev ^ (prev >> 30)) * UINT32_C(1664525))) + key[j] +
69
static_cast<
std::uint32_t
>
(j);
70
++i;
71
++j;
72
if
(i >=
state_size
) {
73
mt_[0] = mt_[
state_size
- 1];
74
i = 1;
75
}
76
if
(j >= key.size()) j = 0;
77
}
78
for
(k =
state_size
- 1; k != 0; --k) {
79
const
std::uint32_t prev = mt_[i - 1];
80
mt_[i] = (mt_[i] ^ ((prev ^ (prev >> 30)) * UINT32_C(1566083941))) -
81
static_cast<
std::uint32_t
>
(i);
82
++i;
83
if
(i >=
state_size
) {
84
mt_[0] = mt_[
state_size
- 1];
85
i = 1;
86
}
87
}
88
mt_[0] = UINT32_C(0x80000000);
89
pos_ =
state_size
;
90
}
91
92
/** Next tempered word, exactly `MT19937.nextUint32` in the MATLAB port. */
93
std::uint32_t
next_uint32
() {
94
constexpr
std::size_t M = 397;
95
constexpr
std::uint32_t matrix_a = UINT32_C(0x9908b0df);
96
constexpr
std::uint32_t upper = UINT32_C(0x80000000);
97
constexpr
std::uint32_t lower = UINT32_C(0x7fffffff);
98
if
(pos_ >=
state_size
) {
99
std::size_t k = 0;
100
for
(; k <
state_size
- M; ++k) {
101
const
std::uint32_t y = (mt_[k] & upper) | (mt_[k + 1] & lower);
102
mt_[k] = mt_[k + M] ^ (y >> 1) ^ ((y & 1U) ? matrix_a : 0U);
103
}
104
for
(; k <
state_size
- 1; ++k) {
105
const
std::uint32_t y = (mt_[k] & upper) | (mt_[k + 1] & lower);
106
mt_[k] = mt_[k + (M -
state_size
)] ^ (y >> 1) ^
107
((y & 1U) ? matrix_a : 0U);
108
}
109
const
std::uint32_t y = (mt_[
state_size
- 1] & upper) | (mt_[0] & lower);
110
mt_[
state_size
- 1] = mt_[M - 1] ^ (y >> 1) ^ ((y & 1U) ? matrix_a : 0U);
111
pos_ = 0;
112
}
113
114
std::uint32_t y = mt_[pos_++];
115
y ^= y >> 11;
116
y ^= (y << 7) & UINT32_C(0x9d2c5680);
117
y ^= (y << 15) & UINT32_C(0xefc60000);
118
y ^= y >> 18;
119
return
y;
120
}
121
122
const
std::array<std::uint32_t, state_size>&
state_key
()
const
{
return
mt_; }
123
std::size_t
position
()
const
{
return
pos_; }
124
125
private
:
126
std::array<std::uint32_t, state_size> mt_{};
127
std::size_t pos_ =
state_size
;
128
};
129
130
}
// namespace de
131
}
// namespace opt
132
}
// namespace line
133
134
#endif
line::InputError::InputError
InputError(const std::string &what)
Definition
error.h:39
line::opt::de::MT19937::MT19937
MT19937(std::uint64_t seed_value)
Definition
mt19937.h:35
line::opt::de::MT19937::state_key
const std::array< std::uint32_t, state_size > & state_key() const
Definition
mt19937.h:122
line::opt::de::MT19937::seed
void seed(std::uint64_t value)
NumPy legacy scalar seeding (init_genrand, or little-endian words).
Definition
mt19937.h:38
line::opt::de::MT19937::position
std::size_t position() const
Definition
mt19937.h:123
line::opt::de::MT19937::state_size
static constexpr std::size_t state_size
Definition
mt19937.h:33
line::opt::de::MT19937::init_genrand
void init_genrand(std::uint32_t value)
Definition
mt19937.h:51
line::opt::de::MT19937::init_by_array
void init_by_array(const std::vector< std::uint32_t > &key)
Definition
mt19937.h:61
line::opt::de::MT19937::next_uint32
std::uint32_t next_uint32()
Next tempered word, exactly MT19937.nextUint32 in the MATLAB port.
Definition
mt19937.h:93
error.h
The exception types the port throws.
line::opt::de
Definition
differential_evolution.h:37
line::opt
Definition
bisection_solver.h:31
line
Definition
aoi_dist2ph.h:52
include
line
opt
de
mt19937.h
Generated by
1.18.0