LMMC
Lamina Mathematic core
Toggle main menu visibility
载入中...
搜索中...
未找到
random_normal.c
浏览该文件的文档.
1
#include <math.h>
2
#include "
random_internal.h
"
3
17
18
#define ZIG_N 256
19
#define ZIG_R 3.6541528853610088
20
21
static
const
double
zig_xtab[
ZIG_N
+ 1] = {
22
#include "ziggurat_table.inc"
23
};
24
static
inline
double
zig_pdf(
double
x) {
25
return
exp(-0.5 * x * x);
26
}
27
28
30
static
double
zig_sample_tail(uint64_t* state) {
31
double
x, y, u1, u2;
32
for
(;;) {
33
do
{
34
u1 = u64_to_double01(xoshiro256ss_next(state));
35
}
while
(u1 == 0.0);
36
do
{
37
u2 = u64_to_double01(xoshiro256ss_next(state));
38
}
while
(u2 == 0.0);
39
40
x = -log(u1) /
ZIG_R
;
41
y = -log(u2);
42
43
if
(2.0 * y >= x * x) {
44
return
x +
ZIG_R
;
45
}
46
}
47
}
48
50
double
lmmc_rng_standard_normal
(uint64_t* state) {
51
uint64_t u, u2;
52
int
i, sign;
53
double
x;
54
55
56
for
(;;) {
57
u = xoshiro256ss_next(state);
58
i = (int)(u & 0xFF);
59
sign = (u & 0x100) ? -1 : 1;
60
62
u2 = xoshiro256ss_next(state);
63
x = u64_to_double01(u2) * zig_xtab[i];
64
65
if
(x < zig_xtab[i + 1]) {
66
return
sign * x;
67
}
68
70
if
(i == 0) {
72
if
(x < zig_xtab[1]) {
73
return
sign * x;
74
}
75
double
tail = zig_sample_tail(state);
76
return
sign * tail;
77
}
78
80
{
81
double
f_x = zig_pdf(x);
82
double
f_outer = zig_pdf(zig_xtab[i]);
83
double
f_inner = zig_pdf(zig_xtab[i + 1]);
84
double
u_wedge = u64_to_double01(xoshiro256ss_next(state));
85
86
if
(u_wedge * (f_inner - f_outer) < (f_x - f_outer)) {
87
return
sign * x;
88
}
89
}
90
}
91
}
92
93
lmmc_status_t
lmmc_rng_normal
(
94
lmmc_rng_t
* rng,
95
lmmc_real_t
mean,
96
lmmc_real_t
stddev,
97
lmmc_real_t
* out_value)
98
{
99
if
(rng == NULL || out_value == NULL) {
100
return
LMMC_STATUS_INVALID_ARGUMENT
;
101
}
102
if
(!isfinite(mean) || !isfinite(stddev) || stddev <= 0.0) {
103
return
LMMC_STATUS_INVALID_ARGUMENT
;
104
}
105
106
*out_value = mean + stddev *
lmmc_rng_standard_normal
(rng->
state
);
107
return
LMMC_STATUS_OK
;
108
}
lmmc_real_t
double lmmc_real_t
Public and internal LMMC real type.
定义
config.h:28
lmmc_rng_normal
lmmc_status_t lmmc_rng_normal(lmmc_rng_t *rng, lmmc_real_t mean, lmmc_real_t stddev, lmmc_real_t *out_value)
生成正态分布 样本。
定义
random_normal.c:93
random_internal.h
lmmc_rng_standard_normal
double lmmc_rng_standard_normal(uint64_t *state)
用 256 层 Ziggurat 采样标准正态:先采样 |x|,再随机赋予符号。
定义
random_normal.c:50
lmmc_rng_t::state
uint64_t state[4]
定义
random_internal.h:8
lmmc_rng_t
随机数发生器(不透明类型)。
定义
random_internal.h:7
ZIG_N
#define ZIG_N
使用 256 个矩形的 Ziggurat 正态采样。
定义
random_normal.c:18
ZIG_R
#define ZIG_R
定义
random_normal.c:19
lmmc_status_t
lmmc_status_t
LMMC 库统一返回的状态码.
定义
status.h:22
LMMC_STATUS_OK
@ LMMC_STATUS_OK
定义
status.h:23
LMMC_STATUS_INVALID_ARGUMENT
@ LMMC_STATUS_INVALID_ARGUMENT
定义
status.h:24
src
random_normal.c
生成于
, 为 LMMC使用
1.18.0