LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
random_continuous.c
浏览该文件的文档.
1#include <math.h>
2#include "random_internal.h"
3
5 lmmc_rng_t* rng,
6 lmmc_real_t shape,
7 lmmc_real_t scale,
8 lmmc_real_t* out)
9{
10 double d, c, x, v, u;
11
12 if (rng == NULL || out == NULL) {
14 }
15 if (!isfinite(shape) || !isfinite(scale) ||
16 shape <= 0.0 || scale <= 0.0) {
18 }
19
21 if (shape < 1.0) {
23 lmmc_status_t st = lmmc_rng_gamma(rng, shape + 1.0, 1.0, &g);
24 if (st != LMMC_STATUS_OK) {
25 return st;
26 }
27
28 u = u64_to_double01(xoshiro256ss_next(rng->state));
29 while (u == 0.0) {
30 u = u64_to_double01(xoshiro256ss_next(rng->state));
31 }
32 *out = scale * g * pow(u, 1.0 / shape);
33 return LMMC_STATUS_OK;
34 }
35
37 d = shape - 1.0 / 3.0;
38 c = 1.0 / sqrt(9.0 * d);
39
40 for (;;) {
41 do {
43 v = 1.0 + c * x;
44 } while (v <= 0.0);
45
46 v = v * v * v;
47 u = u64_to_double01(xoshiro256ss_next(rng->state));
48
50 if (u < 1.0 - 0.0331 * (x * x) * (x * x)) {
51 *out = scale * d * v;
52 return LMMC_STATUS_OK;
53 }
54
56 if (log(u) < 0.5 * x * x + d * (1.0 - v + log(v))) {
57 *out = scale * d * v;
58 return LMMC_STATUS_OK;
59 }
60 }
61}
62
64static lmmc_status_t beta_log_gamma_parts(
65 lmmc_rng_t* rng, lmmc_real_t shape,
66 lmmc_real_t* log_base, lmmc_real_t* log_u)
67{
69 lmmc_status_t st = lmmc_rng_gamma(rng, shape < 1.0 ? shape + 1.0 : shape, 1.0, &g);
70 if (st != LMMC_STATUS_OK) { return st; }
71 if (!isfinite(g) || g <= 0.0) { return LMMC_STATUS_NUMERICAL_FAILURE; }
72 *log_base = log(g);
73 *log_u = 0.0;
74 if (shape < 1.0) {
75 unsigned attempt;
76 for (attempt = 0; attempt < 64; ++attempt) {
77 const double u = u64_to_double01(xoshiro256ss_next(rng->state));
78 if (u != 0.0) {
79 *log_u = log(u);
80 return LMMC_STATUS_OK;
81 }
82 }
84 }
85 return LMMC_STATUS_OK;
86}
87
88static lmmc_status_t beta_ratio_from_log_parts(
89 lmmc_real_t alpha, lmmc_real_t beta_param,
91 lmmc_real_t* out)
92{
93 lmmc_real_t m, ta, tb, difference, q, value;
94 m = fmin(1.0, fmin(alpha, beta_param));
95 ta = alpha < 1.0 ? (m / alpha) * ua : 0.0;
96 tb = beta_param < 1.0 ? (m / beta_param) * ub : 0.0;
101 difference = (tb - ta) / m + (b - a);
102 if (isnan(difference)) { return LMMC_STATUS_NUMERICAL_FAILURE; }
103 if (difference >= 0.0) {
104 q = exp(-difference);
105 value = q / (1.0 + q);
106 } else {
107 q = exp(difference);
108 value = 1.0 / (1.0 + q);
109 }
110 if (!isfinite(value) || value < 0.0 || value > 1.0) {
112 }
113 *out = value;
114 return LMMC_STATUS_OK;
115}
116
118 lmmc_rng_t* rng,
119 lmmc_real_t alpha,
120 lmmc_real_t beta_param,
121 lmmc_real_t* out)
122{
123 lmmc_real_t a, b, ua, ub;
124 lmmc_status_t st;
125
126 if (rng == NULL || out == NULL) {
128 }
129 if (!isfinite(alpha) || !isfinite(beta_param) ||
130 alpha <= 0.0 || beta_param <= 0.0) {
132 }
133
134 st = beta_log_gamma_parts(rng, alpha, &a, &ua);
135 if (st != LMMC_STATUS_OK) {
136 return st;
137 }
138
139 st = beta_log_gamma_parts(rng, beta_param, &b, &ub);
140 if (st != LMMC_STATUS_OK) {
141 return st;
142 }
143
144 return beta_ratio_from_log_parts(alpha, beta_param, a, b, ua, ub, out);
145}
146
148 lmmc_rng_t* rng,
149 lmmc_real_t df,
150 lmmc_real_t* out)
151{
152 if (rng == NULL || out == NULL) {
154 }
155 if (!isfinite(df) || df <= 0.0) {
157 }
158
159 if (df / 2.0 == 0.0) {
160 lmmc_real_t g;
161 lmmc_status_t st = lmmc_rng_gamma(rng, 1.0, 2.0, &g);
162 double u;
163 if (st != LMMC_STATUS_OK) {
164 return st;
165 }
166 do {
167 u = u64_to_double01(xoshiro256ss_next(rng->state));
168 } while (u == 0.0);
169 /* Keep the unrepresentable shape df/2 in the Gamma power exponent. */
170 *out = g * exp(2.0 * log(u) / df);
171 return LMMC_STATUS_OK;
172 }
173
174 return lmmc_rng_gamma(rng, df / 2.0, 2.0, out);
175}
176
178 lmmc_rng_t* rng,
179 lmmc_real_t df,
180 lmmc_real_t* out)
181{
182 lmmc_real_t z, chi2, denom, value;
183 lmmc_status_t st;
184
185 if (rng == NULL || out == NULL) {
187 }
188 if (!isfinite(df) || df <= 0.0) {
190 }
191
193
194 st = lmmc_rng_chi_squared(rng, df, &chi2);
195 if (st != LMMC_STATUS_OK) {
196 return st;
197 }
198
199 denom = sqrt(chi2 / df);
200 if (denom == 0.0) {
202 }
203 value = z / denom;
204 if (!isfinite(value)) {
206 }
207 *out = value;
208 return LMMC_STATUS_OK;
209}
210
212 lmmc_rng_t* rng,
213 lmmc_real_t df1,
214 lmmc_real_t df2,
215 lmmc_real_t* out)
216{
217 lmmc_real_t chi1, chi2, denominator, value;
218 lmmc_status_t st;
219
220 if (rng == NULL || out == NULL) {
222 }
223 if (!isfinite(df1) || !isfinite(df2) ||
224 df1 <= 0.0 || df2 <= 0.0) {
226 }
227
228 st = lmmc_rng_chi_squared(rng, df1, &chi1);
229 if (st != LMMC_STATUS_OK) {
230 return st;
231 }
232
233 st = lmmc_rng_chi_squared(rng, df2, &chi2);
234 if (st != LMMC_STATUS_OK) {
235 return st;
236 }
237
238 denominator = chi2 / df2;
239 if (denominator == 0.0) {
241 }
242 value = (chi1 / df1) / denominator;
243 if (!isfinite(value)) {
245 }
246 *out = value;
247 return LMMC_STATUS_OK;
248}
double lmmc_real_t
Public and internal LMMC real type.
lmmc_status_t lmmc_rng_student_t(lmmc_rng_t *rng, lmmc_real_t df, lmmc_real_t *out)
生成 Student-t 分布样本 t(df)。
lmmc_status_t lmmc_rng_chi_squared(lmmc_rng_t *rng, lmmc_real_t df, lmmc_real_t *out)
生成卡方分布样本 Chi-squared(df)。
lmmc_status_t lmmc_rng_f(lmmc_rng_t *rng, lmmc_real_t df1, lmmc_real_t df2, lmmc_real_t *out)
生成 F 分布样本 F(df1, df2)。
lmmc_status_t lmmc_rng_gamma(lmmc_rng_t *rng, lmmc_real_t shape, lmmc_real_t scale, lmmc_real_t *out)
生成 Gamma 分布样本 。
lmmc_status_t lmmc_rng_beta(lmmc_rng_t *rng, lmmc_real_t alpha, lmmc_real_t beta_param, lmmc_real_t *out)
生成 Beta 分布样本 Beta(alpha, beta)。
double lmmc_rng_standard_normal(uint64_t *state)
用 256 层 Ziggurat 采样标准正态:先采样 |x|,再随机赋予符号。
uint64_t state[4]
随机数发生器(不透明类型)。
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_CONVERGENCE_FAILED
@ LMMC_STATUS_OK
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_INVALID_ARGUMENT