12#define LMMC_GH_MAX_ORDER 20
14static size_t lmmc_quad_tridiag_block_end(
18 while (last < n - 1) {
19 const lmmc_real_t dd = lmmc_abs(diag[last]) + lmmc_abs(diag[last + 1]);
20 if (lmmc_abs(subdiag[last]) + dd == dd)
break;
26static void lmmc_quad_tridiag_sweep(
28 size_t first,
size_t last)
30 lmmc_real_t g = (diag[first + 1] - diag[first]) / (2.0 * subdiag[first]);
34 g = diag[last] - diag[first] + subdiag[first] / (g + sign_g * r);
35 for (
size_t i = last; i > first; --i) {
39 if (lmmc_abs(fi) >= lmmc_abs(g)) {
41 r = sqrt(c * c + 1.0);
47 r = sqrt(s * s + 1.0);
53 r = (diag[i - 1] - g) * s + 2.0 * c * bi;
57 z[i] = s * z[i - 1] + c * zi;
58 z[i - 1] = c * z[i - 1] - s * zi;
67 size_t iteration_limit)
70 for (
size_t i = 0; i < n; i++) z[i] = (i == 0) ? 1.0 : 0.0;
72 for (
size_t l = 0; l < n; l++) {
73 size_t iterations = 0;
76 lmmc_quad_tridiag_block_end(diag, subdiag, l, n);
78 if (iterations++ >= iteration_limit) {
81 lmmc_quad_tridiag_sweep(diag, subdiag, z, l, m);
82 if (m < n - 1) subdiag[m] = 0.0;
86 for (
size_t i = 0; i < n; i++) {
87 weights[i] = mu0 * z[i] * z[i];
92#ifdef LMMC_BUILD_TESTS
93lmmc_status_t lmmc_quad_gauss_hermite_with_iteration_limit_for_test(
107 if (f == NULL || out == NULL) {
115 for (
size_t i = 0; i < order; i++) {
118 for (
size_t i = 0; i < order - 1; i++) {
122 const lmmc_status_t eigensolver_status = tridiag_eigvals_weights(
126 return eigensolver_status;
130 for (
size_t i = 0; i < order; i++) {
132 if (!isfinite(value)) {
135 sum += weights[i] * value;
136 if (!isfinite(sum)) {
145#ifdef LMMC_BUILD_TESTS
146lmmc_status_t lmmc_quad_gauss_hermite_with_iteration_limit_for_test(
150 return lmmc_quad_gauss_hermite_impl(
151 f, ud, order, iteration_limit, out);
159 return lmmc_quad_gauss_hermite_impl(f, ud, order, 100, out);
172#define LMMC_GL_LAG_MAX_ORDER 20
183 if (f == NULL || out == NULL) {
191 for (
size_t i = 0; i < order; i++) {
194 for (
size_t i = 0; i < order - 1; i++) {
198 const lmmc_status_t eigensolver_status = tridiag_eigvals_weights(
199 diag, subdiag, weights, order, 1.0, 100);
201 return eigensolver_status;
204 for (
size_t i = 0; i < order; i++) {
206 if (!isfinite(value)) {
209 sum += weights[i] * value;
210 if (!isfinite(sum)) {
double lmmc_real_t
Public and internal LMMC real type.
#define LMMC_CONST_PI
圆周率常数 。
lmmc_real_t(*) lmmc_quad_func_t(lmmc_real_t x, void *user_data)
被积函数签名 。
lmmc_status_t lmmc_quad_gauss_hermite(lmmc_quad_func_t f, void *ud, size_t order, lmmc_real_t *out)
Gauss-Hermite 求积:权函数 ,积分域 。
lmmc_status_t lmmc_quad_gauss_laguerre(lmmc_quad_func_t f, void *ud, size_t order, lmmc_real_t *out)
Gauss-Laguerre 求积:权函数 ,积分域 。
#define LMMC_GH_MAX_ORDER
Gauss-Hermite 求积,权函数 exp(-x^2),积分域 (-inf, +inf)。
#define LMMC_GL_LAG_MAX_ORDER
Gauss-Laguerre 求积,权函数 exp(-x),积分域 [0, +inf)。
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_CONVERGENCE_FAILED
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_INVALID_ARGUMENT