LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
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
21static const double zig_xtab[ZIG_N + 1] = {
22#include "ziggurat_table.inc"
23};
24static inline double zig_pdf(double x) {
25 return exp(-0.5 * x * x);
26}
27
28
30static 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
50double 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
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) {
101 }
102 if (!isfinite(mean) || !isfinite(stddev) || stddev <= 0.0) {
104 }
105
106 *out_value = mean + stddev * lmmc_rng_standard_normal(rng->state);
107 return LMMC_STATUS_OK;
108}
double lmmc_real_t
Public and internal LMMC real type.
lmmc_status_t lmmc_rng_normal(lmmc_rng_t *rng, lmmc_real_t mean, lmmc_real_t stddev, lmmc_real_t *out_value)
生成正态分布 样本。
double lmmc_rng_standard_normal(uint64_t *state)
用 256 层 Ziggurat 采样标准正态:先采样 |x|,再随机赋予符号。
uint64_t state[4]
随机数发生器(不透明类型)。
#define ZIG_N
使用 256 个矩形的 Ziggurat 正态采样。
#define ZIG_R
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_OK
@ LMMC_STATUS_INVALID_ARGUMENT