LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
quadrature_extrapolation.c
浏览该文件的文档.
2
12
13static int lmmc_quad_romberg_arguments(
14 lmmc_real_t a, lmmc_real_t b, lmmc_real_t abs_tol, size_t max_iter)
15{
16 if (!isfinite(a) || !isfinite(b) || a >= b) {
17 return 0;
18 }
19 if (!isfinite(abs_tol)) {
20 return 0;
21 }
22 if (abs_tol < 1e-15 || abs_tol > 1e-1) {
23 return 0;
24 }
25 return max_iter >= 1 && max_iter <= 30;
26}
27
28static int lmmc_quad_romberg_initial(
30{
31 lmmc_real_t fa, fb;
32 lmmc_quad_center_half_length(a, b, &state->center, &state->half_length);
33 if (!isfinite(state->center) || !isfinite(state->half_length)) {
34 return 0;
35 }
36 fa = state->func(a, state->user_data);
37 fb = state->func(b, state->user_data);
38 state->out->num_evals = 2;
39 if (!isfinite(fa) || !isfinite(fb)) {
40 return 0;
41 }
42 state->prev[0] = state->half_length * (fa + fb);
43 if (!isfinite(state->prev[0])) {
44 return 0;
45 }
46 state->out->value = state->prev[0];
47 return 1;
48}
49
50static int lmmc_quad_romberg_sample_row(
51 lmmc_quad_romberg_state_t* state, size_t row)
52{
53 const size_t n = (size_t)1 << row;
54 const lmmc_real_t normalized_h = 2.0 / (lmmc_real_t)n;
55 lmmc_real_t sum_new = 0.0;
56 for (size_t k = 1; k <= n / 2; ++k) {
57 const lmmc_real_t normalized_x =
58 -1.0 + (2.0 * (lmmc_real_t)k - 1.0) * normalized_h;
59 const lmmc_real_t x = fma(state->half_length, normalized_x, state->center);
60 const lmmc_real_t value = state->func(x, state->user_data);
61 ++state->out->num_evals;
62 if (!isfinite(value)) {
63 return 0;
64 }
65 sum_new += value;
66 if (!isfinite(sum_new)) {
67 return 0;
68 }
69 }
70 state->curr[0] = state->prev[0] / 2.0 +
71 state->half_length * normalized_h * sum_new;
72 return isfinite(state->curr[0]);
73}
74
75static int lmmc_quad_romberg_extrapolate(
76 lmmc_quad_romberg_state_t* state, size_t row)
77{
78 lmmc_real_t pow4 = 1.0;
79 for (size_t j = 1; j <= row; ++j) {
80 pow4 *= 4.0;
81 state->curr[j] = state->curr[j - 1] +
82 (state->curr[j - 1] - state->prev[j - 1]) / (pow4 - 1.0);
83 if (!isfinite(state->curr[j])) {
84 return 0;
85 }
86 }
87 state->out->value = state->curr[row];
88 state->out->error = lmmc_abs(state->curr[row] - state->prev[row - 1]);
89 return isfinite(state->out->error);
90}
91
94 lmmc_real_t abs_tol, size_t max_iter, lmmc_quad_result_t* out)
95{
96 lmmc_quad_romberg_state_t state = {0};
97 if (f == NULL || out == NULL) {
99 }
100 out->value = 0.0;
101 out->error = INFINITY;
102 out->num_evals = 0;
103 if (!lmmc_quad_romberg_arguments(a, b, abs_tol, max_iter)) {
105 }
106 state.func = f;
107 state.user_data = ud;
108 state.out = out;
109 if (!lmmc_quad_romberg_initial(&state, a, b)) {
111 }
112 for (size_t i = 1; i < max_iter; ++i) {
113 if (!lmmc_quad_romberg_sample_row(&state, i) ||
114 !lmmc_quad_romberg_extrapolate(&state, i)) {
116 }
117 if (out->error <= abs_tol) {
118 return LMMC_STATUS_OK;
119 }
120 for (size_t j = 0; j <= i; ++j) state.prev[j] = state.curr[j];
121 }
123}
double lmmc_real_t
Public and internal LMMC real type.
lmmc_status_t lmmc_quad_romberg(lmmc_quad_func_t f, void *ud, lmmc_real_t a, lmmc_real_t b, lmmc_real_t abs_tol, size_t max_iter, lmmc_quad_result_t *out)
Romberg 积分(Richardson 外推加速梯形法则)。
lmmc_real_t(*) lmmc_quad_func_t(lmmc_real_t x, void *user_data)
被积函数签名 。
自适应积分输出结果。
void lmmc_quad_center_half_length(lmmc_real_t a, lmmc_real_t b, lmmc_real_t *center, lmmc_real_t *half_length)
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_CONVERGENCE_FAILED
@ LMMC_STATUS_OK
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_INVALID_ARGUMENT