37 if (fabs(acc->
sum) >= fabs(value)) {
38 residual = (acc->
sum - sum) + value;
40 residual = (value - sum) + acc->
sum;
47static int lmmc_quad_sample(
50 if (!isfinite(x) || work->
num_evals == SIZE_MAX) {
55 return isfinite(*value);
63 leaf->
x[first], leaf->
x[first + 2 * step], ¢er, &half_length);
64 return (half_length / 3.0) *
65 (leaf->
f[first] + 4.0 * leaf->
f[first + step] +
66 leaf->
f[first + 2 * step]);
71 const lmmc_real_t whole = lmmc_quad_simpson_panel(leaf, 0, 2);
72 const lmmc_real_t left = lmmc_quad_simpson_panel(leaf, 0, 1);
73 const lmmc_real_t right = lmmc_quad_simpson_panel(leaf, 2, 1);
76 leaf->
value = combined + delta / 15.0;
77 leaf->
error = fabs(delta) / 15.0;
78 return isfinite(whole) && isfinite(left) && isfinite(right) &&
79 isfinite(combined) && isfinite(leaf->
value) && isfinite(leaf->
error);
86 return leaf->
x[0] < leaf->
x[1] && leaf->
x[1] < leaf->
x[2] &&
87 leaf->
x[2] < leaf->
x[3] && leaf->
x[3] < leaf->
x[4];
90static int lmmc_quad_leaf_finish(
93 if (!lmmc_quad_sample(work, leaf->
x[1], &leaf->
f[1])) {
96 if (!lmmc_quad_sample(work, leaf->
x[3], &leaf->
f[3])) {
99 return lmmc_quad_leaf_estimate(leaf);
102static int lmmc_quad_leaf_initial(
110 if (!lmmc_quad_leaf_midpoints(leaf)) {
113 if (!lmmc_quad_sample(work, a, &leaf->
f[0])) {
116 if (!lmmc_quad_sample(work, b, &leaf->
f[4])) {
119 if (!lmmc_quad_sample(work, leaf->
x[2], &leaf->
f[2])) {
122 return lmmc_quad_leaf_finish(work, leaf);
125static int lmmc_quad_leaf_can_split(
128 if (leaf->
depth >= max_depth) {
132 for (
size_t i = 0; i < 4; ++i) {
134 if (mid <= leaf->x[i] || mid >= leaf->
x[i + 1]) {
141static int lmmc_quad_leaf_child(
146 for (
size_t i = 0; i < 3; ++i) {
147 child->
x[2 * i] = parent->
x[first + i];
148 child->
f[2 * i] = parent->
f[first + i];
150 if (!lmmc_quad_leaf_midpoints(child)) {
153 return lmmc_quad_leaf_finish(work, child);
156static int lmmc_quad_leaf_precedes(
162 return left->
x[0] < right->
x[0];
167 size_t needed, capacity, bytes;
169 if (!lmmc_safe_add_size(work->
size, extra, &needed)) {
172 if (needed <= work->capacity) {
176 while (capacity < needed) {
177 if (capacity > SIZE_MAX / 2) {
183 if (!lmmc_safe_mul_size(capacity,
sizeof(*heap), &bytes)) {
195static void lmmc_quad_heap_push(
198 size_t pos = work->
size++;
200 const size_t parent = (pos - 1) / 2;
201 if (!lmmc_quad_leaf_precedes(leaf, &work->
heap[parent]))
break;
202 work->
heap[pos] = work->
heap[parent];
205 work->
heap[pos] = *leaf;
214 while (pos < work->size / 2) {
215 size_t child = 2 * pos + 1;
216 if (child + 1 < work->
size &&
217 lmmc_quad_leaf_precedes(&work->
heap[child + 1], &work->
heap[child])) {
220 if (!lmmc_quad_leaf_precedes(&work->
heap[child], &last))
break;
221 work->
heap[pos] = work->
heap[child];
224 if (work->
size != 0) work->
heap[pos] = last;
228static int lmmc_quad_totals_add(
232 return lmmc_quad_sum_add(&work->
value, sign * leaf->
value) &&
233 lmmc_quad_sum_add(&work->
error, sign * leaf->
error);
240 int split_left, split_right;
244 if (!lmmc_quad_leaf_child(work, &parent, 0, &left) ||
245 !lmmc_quad_leaf_child(work, &parent, 2, &right)) {
248 split_left = lmmc_quad_leaf_can_split(&left, work->
max_depth);
249 split_right = lmmc_quad_leaf_can_split(&right, work->
max_depth);
250 if (!lmmc_quad_heap_reserve(work, (
size_t)split_left + (
size_t)split_right)) {
253 if (!lmmc_quad_totals_add(work, &parent, -1.0) ||
254 !lmmc_quad_totals_add(work, &left, 1.0) ||
255 !lmmc_quad_totals_add(work, &right, 1.0)) {
260 lmmc_quad_heap_push(work, &left);
263 lmmc_quad_heap_push(work, &right);
279 tolerance = lmmc_max(abs_tol, rel_tol * fabs(result->
value));
280 if (!isfinite(result->
value) || !isfinite(result->
error) ||
281 result->
error < 0.0 || !isfinite(tolerance)) {
284 if (result->
error <= tolerance) {
288 if (lmmc_quad_leaf_can_split(root, work->
max_depth)) {
289 if (!lmmc_quad_heap_reserve(work, 1)) {
292 lmmc_quad_heap_push(work, root);
296 if (work->
size == 0) {
299 status = lmmc_quad_refine(work);
306static int lmmc_quad_adaptive_arguments(
309 if (!isfinite(a) || !isfinite(b) || a >= b) {
312 if (!isfinite(abs_tol) || !isfinite(rel_tol)) {
315 return abs_tol >= 0.0 && rel_tol >= 0.0;
328 if (func == NULL || out_result == NULL ||
329 !lmmc_quad_adaptive_arguments(a, b, abs_tol, rel_tol)) {
335 if (!lmmc_quad_leaf_initial(&work, &root, a, b) ||
336 !lmmc_quad_totals_add(&work, &root, 1.0)) {
339 status = lmmc_quad_global_integral(&work, &root, abs_tol, rel_tol, &result);
342 *out_result = result;
double lmmc_real_t
Public and internal LMMC real type.
void * lmmc_memory_realloc(void *pointer, size_t size)
void lmmc_memory_free(void *pointer)
Private recoverable allocator for persistent LMMC ownership.
lmmc_real_t(*) lmmc_quad_func_t(lmmc_real_t x, void *user_data)
被积函数签名 。
lmmc_status_t lmmc_quad_adaptive(lmmc_quad_func_t func, void *user_data, lmmc_real_t a, lmmc_real_t b, lmmc_real_t abs_tol, lmmc_real_t rel_tol, size_t max_depth, lmmc_quad_result_t *out_result)
自适应 Simpson 积分,使用最大误差堆控制全局误差。
void lmmc_quad_center_half_length(lmmc_real_t a, lmmc_real_t b, lmmc_real_t *center, lmmc_real_t *half_length)
lmmc_real_t lmmc_quad_midpoint(lmmc_real_t a, lmmc_real_t b)
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_ALLOCATION_FAILED
@ LMMC_STATUS_INVALID_ARGUMENT
@ LMMC_STATUS_WARNING_MAX_DEPTH