LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
interp_lagrange.c
浏览该文件的文档.
1#include "memory_bridge.h"
2#include "internal.h"
4
5#include <math.h>
6#include <string.h>
7
14
16 const lmmc_real_t* xs, const lmmc_real_t* ys, size_t n,
17 lmmc_interp_lagrange_t** out_lagrange)
18{
19 lmmc_interp_lagrange_t* lag = NULL;
20 size_t alloc_size;
21 lmmc_status_t status;
22
23 if (!out_lagrange) {
25 }
26 *out_lagrange = NULL;
27 if (!xs || !ys || n < 1 ||
31 }
32
33 lag = (lmmc_interp_lagrange_t*)lmmc_memory_alloc(sizeof(*lag));
34 if (!lag) {
36 }
37 lag->n = n; lag->xs = NULL; lag->ys = NULL; lag->weights = NULL;
38
39 if (!lmmc_safe_mul_size(n, sizeof(lmmc_real_t), &alloc_size)) {
42 }
43
44 lag->xs = (lmmc_real_t*)lmmc_memory_alloc(alloc_size);
45 lag->ys = (lmmc_real_t*)lmmc_memory_alloc(alloc_size);
46 lag->weights = (lmmc_real_t*)lmmc_memory_alloc(alloc_size);
47 if (!lag->xs || !lag->ys || !lag->weights) {
50 }
51 memcpy(lag->xs, xs, alloc_size);
52 memcpy(lag->ys, ys, alloc_size);
53
54 status = interp_barycentric_weights(lag->xs, lag->n, lag->weights);
55 if (status != LMMC_STATUS_OK) {
57 return status;
58 }
59
60 *out_lagrange = lag;
61 return LMMC_STATUS_OK;
62}
63
65 const lmmc_interp_lagrange_t* lagrange,
66 lmmc_real_t query_x, lmmc_real_t* out_y)
67{
68 size_t j;
69 lmmc_real_t numer = 0.0, denom = 0.0, largest = -INFINITY;
70 lmmc_real_t value_scale = 0.0, result;
71 if (!lagrange || !out_y || !isfinite(query_x)) {
73 }
74
75 for (j = 0; j < lagrange->n; j++) {
76 if (query_x == lagrange->xs[j]) {
77 *out_y = lagrange->ys[j];
78 return LMMC_STATUS_OK;
79 }
80 if (fabs(lagrange->ys[j]) > value_scale) {
81 value_scale = fabs(lagrange->ys[j]);
82 }
83 }
84
85 for (j = 0; j < lagrange->n; j++) {
86 lmmc_real_t diff = query_x - lagrange->xs[j];
87 lmmc_real_t log_distance = isfinite(diff) ? log(fabs(diff)) :
88 log(fabs(query_x / 2.0 - lagrange->xs[j] / 2.0)) + log(2.0);
89 lmmc_real_t log_term = log(fabs(lagrange->weights[j])) - log_distance;
90 lmmc_real_t term;
91 if (log_term > largest) {
92 lmmc_real_t factor = exp(largest - log_term);
93 numer *= factor;
94 denom *= factor;
95 largest = log_term;
96 }
97 term = copysign(exp(log_term - largest), lagrange->weights[j]) *
98 (diff < 0.0 ? -1.0 : 1.0);
99 numer += term * (value_scale == 0.0 ? 0.0 : lagrange->ys[j] / value_scale);
100 denom += term;
101 }
102 if (denom == 0.0 || !isfinite(denom)) {
104 }
105 result = (numer / denom) * value_scale;
106 if (!isfinite(result)) {
108 }
109 *out_y = result;
110 return LMMC_STATUS_OK;
111}
112
114{
115 if (!lagrange) {
116 return;
117 }
118 lmmc_memory_free(lagrange->weights);
119 lmmc_memory_free(lagrange->ys);
120 lmmc_memory_free(lagrange->xs);
121 lmmc_memory_free(lagrange);
122}
double lmmc_real_t
Public and internal LMMC real type.
LMMC 内部使用的公共工具(仅源文件可见).
lmmc_status_t lmmc_interp_lagrange_eval(const lmmc_interp_lagrange_t *lagrange, lmmc_real_t query_x, lmmc_real_t *out_y)
在 Lagrange 插值多项式上求值.
void lmmc_interp_lagrange_destroy(lmmc_interp_lagrange_t *lagrange)
销毁 Lagrange 插值上下文.
lmmc_status_t lmmc_interp_lagrange_create(const lmmc_real_t *xs, const lmmc_real_t *ys, size_t n, lmmc_interp_lagrange_t **out_lagrange)
由节点构造 Lagrange 插值多项式(基于重心权重).
int interp_check_finite_values(const lmmc_real_t *values, size_t n)
lmmc_status_t interp_barycentric_weights(const lmmc_real_t *nodes, size_t n, lmmc_real_t *weights)
Lagrange 多项式插值上下文(不透明类型).
void * lmmc_memory_alloc(size_t size)
void lmmc_memory_free(void *pointer)
Private recoverable allocator for persistent LMMC ownership.
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_OK
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_ALLOCATION_FAILED
@ LMMC_STATUS_INVALID_ARGUMENT