nk
1.0.0
C++ Numerical Computing Runtime
Toggle main menu visibility
Loading...
Searching...
No Matches
rng_context.hpp
1
// ops/include/nk/ops/rng_context.hpp
2
//
3
// RngContext — the seedable random-number session state. Owns one MATLAB-style
4
// MT19937 stream and the rng() control surface (seed / shuffle / state save +
5
// restore). The Engine owns one RngContext (engine.rng()); every RNG-using
6
// function (rand/randn/randi/randperm + the toolbox *rnd samplers, comm noise,
7
// …) takes `RngContext &` and draws from it — so a single session shares ONE
8
// reproducible stream (MATLAB `rng(seed)` semantics) WITHOUT a process-global
9
// singleton or a mutex. Two Engines have independent streams.
10
//
11
// It models UniformRandomBitGenerator (forwards operator()/min/max/result_type
12
// to the owned MT19937), so the std distributions draw from it directly:
13
// std::normal_distribution<double> d; double x = d(rng);
14
// An L0.5 ops type (Value + MatlabMT19937 only, no Engine).
15
16
#pragma once
17
18
#include <nk/ops/matlab_mt19937.hpp>
19
#include <nk/value/value.hpp>
20
21
#include <cmath>
// v4Normal: std::sqrt / std::log
22
#include <cstdint>
23
#include <memory_resource>
24
#include <random>
// RngContext models a URBG — callers draw via std::*_distribution(rng)
25
26
namespace
nk::ops {
27
28
class
RngContext
29
{
30
public
:
31
// ── UniformRandomBitGenerator surface (forwarded to the owned stream) ──
32
// Lets std::*_distribution and the value generators draw via `dist(rng)`.
33
using
result_type = MatlabMT19937::result_type;
34
static
constexpr
result_type min() {
return
MatlabMT19937::min(); }
35
static
constexpr
result_type max() {
return
MatlabMT19937::max(); }
36
result_type operator()() {
return
gen_(); }
37
39
double
genRes53
() {
return
gen_.genRes53(); }
40
41
// ── MATLAB rng() control ──────────────────────────────────────────
43
void
seed
(std::uint64_t
seed
)
44
{
45
legacyV4_ =
false
;
46
gen_.seed(
static_cast<
std::uint32_t
>
(
seed
));
47
}
48
49
void
shuffle
();
51
Value
state
(std::pmr::memory_resource *mr =
nullptr
)
const
;
53
void
restore
(
const
Value
&s);
54
55
// ── Legacy v4 generator (rand/randn('seed', S)) ───────────────────
56
// MATLAB's pre-v5 generator, bit-identical (derived + verified vs
57
// R2025b, see bugs/closed/stats/randn-legacy-seed-syntax.md):
58
// x <- 16807*x mod (2^31-1); u = x/(2^31-1)
59
// seed S -> state S*2^16 (S==0 -> the constant 1144108930)
60
// randn: Marsaglia polar on that stream, FIRST of each accepted
61
// pair emitted (the second is discarded — probed; MATLAB's v4
62
// randn wastes half the pairs). ONE shared stream for rand+randn.
63
void
setLegacyV4(std::uint64_t
seed
)
64
{
65
legacyV4_ =
true
;
66
v4seed_ =
seed
;
67
v4state_ =
seed
?
seed
* 65536ull : 1144108930ull;
68
}
70
std::uint64_t
legacySeed
() const noexcept {
return
v4seed_; }
71
bool
legacyV4() const noexcept {
return
legacyV4_; }
72
double
v4Uniform()
73
{
74
v4state_ = 16807ull * v4state_ % 2147483647ull;
75
return
static_cast<
double
>
(v4state_) / 2147483647.0;
76
}
77
double
v4Normal()
78
{
79
for
(;;) {
80
const
double
v1 = 2.0 * v4Uniform() - 1.0;
81
const
double
v2 = 2.0 * v4Uniform() - 1.0;
82
const
double
s = v1 * v1 + v2 * v2;
83
if
(s > 0.0 && s < 1.0)
84
return
v1 * std::sqrt(-2.0 * std::log(s) / s);
85
}
86
}
87
89
MatlabMT19937 &
engine
() noexcept {
return
gen_; }
90
const
MatlabMT19937 &
engine
() const noexcept {
return
gen_; }
91
92
private
:
93
MatlabMT19937 gen_;
// default-constructed = rng('default')
94
bool
legacyV4_ =
false
;
95
std::uint64_t v4seed_ = 0;
96
std::uint64_t v4state_ = 1;
97
};
98
99
}
// namespace nk::ops
nk::Value
Core MATLAB-compatible multidimensional array and scalar value type.
Definition
value.hpp:61
nk::ops::RngContext
Definition
rng_context.hpp:29
nk::ops::RngContext::restore
void restore(const Value &s)
rng(s) — restore a state struct captured by state().
nk::ops::RngContext::genRes53
double genRes53()
MATLAB-canonical 53-bit double in [0, 1) — what rand uses.
Definition
rng_context.hpp:39
nk::ops::RngContext::legacySeed
std::uint64_t legacySeed() const noexcept
rand('seed') / randn('seed') — query the last legacy seed.
Definition
rng_context.hpp:70
nk::ops::RngContext::shuffle
void shuffle()
rng('shuffle') — seed from a nondeterministic source.
nk::ops::RngContext::seed
void seed(std::uint64_t seed)
Seed the stream. seed == 0 ≡ rng('default').
Definition
rng_context.hpp:43
nk::ops::RngContext::state
Value state(std::pmr::memory_resource *mr=nullptr) const
s = rng() — capture the stream state as a struct (.Type / .State).
nk::ops::RngContext::engine
MatlabMT19937 & engine() noexcept
Escape hatch: the underlying MT19937 (e.g. for getState/setState).
Definition
rng_context.hpp:89
src
ops
include
nk
ops
rng_context.hpp
Generated by
1.17.0