LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
quadrature_tanh_sinh.c
浏览该文件的文档.
2
14
15static int lmmc_quad_tanh_sinh_arguments(
16 lmmc_real_t a, lmmc_real_t b, lmmc_real_t abs_tol, size_t max_nodes)
17{
18 if (!isfinite(a) || !isfinite(b) || a >= b) {
19 return 0;
20 }
21 if (!isfinite(abs_tol)) {
22 return 0;
23 }
24 if (abs_tol < 1e-15 || abs_tol > 1e-1) {
25 return 0;
26 }
27 return max_nodes >= 1 && max_nodes <= 1000000;
28}
29
30static lmmc_real_t lmmc_quad_tanh_sinh_weight(lmmc_real_t t, lmmc_real_t u)
31{
32 const lmmc_real_t pi_half = LMMC_CONST_PI / 2.0;
33 if (u > 6.0) {
34 return pi_half * cosh(t) * 4.0 * exp(-2.0 * u);
35 }
36 const lmmc_real_t cosh_u = cosh(u);
37 return pi_half * cosh(t) / (cosh_u * cosh_u);
38}
39
40static lmmc_status_t lmmc_quad_tanh_sinh_pair(
42 lmmc_real_t weight, lmmc_real_t* sum)
43{
44 const lmmc_real_t tanh_u = u > 6.0 ? 1.0 - 2.0 * exp(-2.0 * u) : tanh(u);
45 const lmmc_real_t xp = fma(state->half_length, tanh_u, state->center);
46 const lmmc_real_t xn = fma(-state->half_length, tanh_u, state->center);
47 const size_t needed = (size_t)(xp != state->b) + (size_t)(xn != state->a);
48 if (state->max_nodes - state->num_evals < needed) {
50 }
51 lmmc_real_t fp = 0.0, fn = 0.0;
53 if (xp != state->b) {
54 fp = state->func(xp, state->user_data);
55 ++state->num_evals;
56 }
57 if (xn != state->a) {
58 fn = state->func(xn, state->user_data);
59 ++state->num_evals;
60 }
61 if (!isfinite(fp) || !isfinite(fn)) {
63 }
64 const lmmc_real_t next = *sum + (fp + fn) * weight;
65 if (!isfinite(next)) return LMMC_STATUS_NUMERICAL_FAILURE;
66 *sum = next;
67 return LMMC_STATUS_OK;
68}
69
70static lmmc_status_t lmmc_quad_tanh_sinh_level(
72{
73 const lmmc_real_t pi_half = LMMC_CONST_PI / 2.0;
74 if (state->num_evals == state->max_nodes) {
76 }
77 const lmmc_real_t fmid = state->func(state->center, state->user_data);
78 lmmc_real_t sum = fmid * pi_half;
79 ++state->num_evals;
80 if (!isfinite(fmid) || !isfinite(sum)) {
82 }
83 for (size_t j = 1; ; ++j) {
84 const lmmc_real_t t = (lmmc_real_t)j * h;
85 const lmmc_real_t u = pi_half * sinh(t);
86 lmmc_real_t weight;
87 if (u > 20.0) break;
88 weight = lmmc_quad_tanh_sinh_weight(t, u);
89 if (!isfinite(weight)) {
91 }
92 if (weight < 1e-50) break;
93 const lmmc_status_t status = lmmc_quad_tanh_sinh_pair(state, u, weight, &sum);
94 if (status != LMMC_STATUS_OK) return status;
95 }
96 const lmmc_real_t completed = state->half_length * h * sum;
97 if (!isfinite(completed)) return LMMC_STATUS_NUMERICAL_FAILURE;
98 *integral = completed;
99 return LMMC_STATUS_OK;
100}
101
102static lmmc_status_t lmmc_quad_tanh_sinh_integrate(
105{
106 int have_complete = 0;
107 lmmc_real_t last_complete = 0.0;
108 lmmc_real_t last_error = INFINITY;
109 lmmc_real_t h = 0.03125;
110 for (size_t level = 0; level < 10; ++level) {
111 lmmc_real_t integral;
112 const lmmc_status_t status = lmmc_quad_tanh_sinh_level(state, h, &integral);
113 out->num_evals = state->num_evals;
114 if (status != LMMC_STATUS_OK) {
115 out->value = last_complete;
116 out->error = INFINITY;
117 return status;
118 }
119 if (have_complete) {
120 last_error = lmmc_abs(integral - last_complete);
121 if (!isfinite(last_error)) {
122 out->error = INFINITY;
124 }
125 }
126 last_complete = integral;
127 out->value = last_complete;
128 out->error = last_error;
129 if (have_complete && last_error <= abs_tol) return LMMC_STATUS_OK;
130 have_complete = 1;
131 h /= 2.0;
132 }
134}
135
137 lmmc_quad_func_t f, void* ud, lmmc_real_t a, lmmc_real_t b,
138 lmmc_real_t abs_tol, size_t max_nodes, lmmc_quad_result_t* out)
139{
140 lmmc_quad_tanh_sinh_state_t state = {0};
141 if (f == NULL || out == NULL) {
143 }
144 out->value = 0.0;
145 out->error = INFINITY;
146 out->num_evals = 0;
147 if (!lmmc_quad_tanh_sinh_arguments(a, b, abs_tol, max_nodes)) {
149 }
150 state.func = f;
151 state.user_data = ud;
152 state.a = a;
153 state.b = b;
154 state.max_nodes = max_nodes;
155 lmmc_quad_center_half_length(a, b, &state.center, &state.half_length);
156 if (!isfinite(state.center) || !isfinite(state.half_length)) {
158 }
159 return lmmc_quad_tanh_sinh_integrate(&state, abs_tol, out);
160}
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_tanh_sinh(lmmc_quad_func_t f, void *ud, lmmc_real_t a, lmmc_real_t b, lmmc_real_t abs_tol, size_t max_nodes, lmmc_quad_result_t *out)
Tanh-Sinh(双指数)积分,适用于端点奇异性。
自适应积分输出结果。
void lmmc_quad_center_half_length(lmmc_real_t a, lmmc_real_t b, lmmc_real_t *center, lmmc_real_t *half_length)
双指数映射:x(t) = center + half_length*tanh(pi/2*sinh(t))。
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_CONVERGENCE_FAILED
@ LMMC_STATUS_OK
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_INVALID_ARGUMENT