LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
interp.c
浏览该文件的文档.
1#include "internal.h"
3
4#include <math.h>
5
6size_t interp_find_interval(const lmmc_real_t* xs, size_t n,
7 lmmc_real_t query_x)
8{
9 size_t lo = 0, hi = n - 1, mid;
10 while (hi - lo > 1) {
11 mid = lo + (hi - lo) / 2;
12 if (xs[mid] <= query_x) lo = mid;
13 else hi = mid;
14 }
15 return lo;
16}
17
19 const lmmc_real_t* xs, size_t n)
20{
21 size_t i;
22 if (!xs || n == 0 || !isfinite(xs[0])) {
23 return 0;
24 }
25 for (i = 1; i < n; ++i) {
26 if (!isfinite(xs[i]) || !(xs[i] > xs[i - 1])) {
27 return 0;
28 }
29 }
30 return 1;
31}
32
34 const lmmc_real_t* values, size_t n)
35{
36 size_t i;
37 if (!values && n != 0) {
38 return 0;
39 }
40 for (i = 0; i < n; ++i) {
41 if (!isfinite(values[i])) {
42 return 0;
43 }
44 }
45 return 1;
46}
47
49 lmmc_real_t* weights)
50{
51 size_t i, j;
52 lmmc_real_t largest = -INFINITY;
53 for (j = 0; j < n; j++) {
54 lmmc_real_t log_weight = 0.0;
55 for (i = 0; i < n; i++) {
56 if (i != j) {
57 lmmc_real_t difference = nodes[j] - nodes[i];
58 if (difference == 0.0) {
60 }
61 if (!isfinite(difference)) {
62 log_weight -= log(fabs(nodes[j] / 2.0 - nodes[i] / 2.0)) + log(2.0);
63 } else {
64 log_weight -= log(fabs(difference));
65 }
66 }
67 }
68 weights[j] = log_weight;
69 if (log_weight > largest) largest = log_weight;
70 }
71 for (j = 0; j < n; j++) {
72 weights[j] = exp(weights[j] - largest);
73 if (weights[j] == 0.0 || !isfinite(weights[j])) {
75 }
76 for (i = 0; i < n; i++) {
77 if (nodes[j] < nodes[i]) weights[j] = -weights[j];
78 }
79 }
80 return LMMC_STATUS_OK;
81}
82
84 size_t n, size_t minimum)
85{
86 return xs && ys && n >= minimum &&
89}
90
91static int interp_grid_coordinates_valid(const interp_grid_t* grid)
92{
93 size_t grid_size;
94 if (!isfinite(grid->qx) || !isfinite(grid->qy)) {
95 return 0;
96 }
97 if (!interp_check_strictly_increasing(grid->xs, grid->nx)) {
98 return 0;
99 }
100 if (!interp_check_strictly_increasing(grid->ys, grid->ny)) {
101 return 0;
102 }
103 return lmmc_safe_mul_size(grid->nx, grid->ny, &grid_size);
104}
105
107 const lmmc_real_t* out)
108{
109 if (!grid->xs || !grid->ys || !grid->zs || !out) {
111 }
112 if (grid->nx < minimum || grid->ny < minimum) {
114 }
115 if (!interp_grid_coordinates_valid(grid)) {
117 }
118 if (grid->qx < grid->xs[0] || grid->qx > grid->xs[grid->nx - 1] ||
119 grid->qy < grid->ys[0] || grid->qy > grid->ys[grid->ny - 1]) {
121 }
122 return LMMC_STATUS_OK;
123}
124
126 lmmc_real_t right,
127 lmmc_real_t query)
128{
129 const lmmc_real_t span = right - left;
130 lmmc_real_t scale, scaled_left, scaled_right;
131 if (isfinite(span)) {
132 return (query - left) / span;
133 }
134 scale = fmax(fabs(left), fabs(right));
135 scaled_left = left / scale;
136 scaled_right = right / scale;
137 return (query / scale - scaled_left) / (scaled_right - scaled_left);
138}
139
140static lmmc_real_t interp_linear_value(lmmc_real_t left,
141 lmmc_real_t right, lmmc_real_t t)
142{
143 if (t == 0.0) {
144 return left;
145 }
146 if (t == 1.0) {
147 return right;
148 }
149 if ((left <= 0.0 && right >= 0.0) || (left >= 0.0 && right <= 0.0)) {
150 return (1.0 - t) * left + t * right;
151 }
152 return left + t * (right - left);
153}
154
156 const lmmc_real_t* xs, const lmmc_real_t* ys, size_t n,
157 lmmc_real_t query_x, lmmc_real_t* out_y)
158{
159 size_t lo;
160 lmmc_real_t t, result;
161 if (!out_y || !isfinite(query_x) || !interp_check_samples(xs, ys, n, 2)) {
163 }
164 if (query_x < xs[0] || query_x > xs[n - 1]) {
166 }
167 if (query_x == xs[n - 1]) {
168 *out_y = ys[n - 1];
169 return LMMC_STATUS_OK;
170 }
171 lo = interp_find_interval(xs, n, query_x);
172 t = interp_interval_fraction(xs[lo], xs[lo + 1], query_x);
173 result = interp_linear_value(ys[lo], ys[lo + 1], t);
174 if (!isfinite(t) || !isfinite(result)) {
176 }
177 *out_y = result;
178 return LMMC_STATUS_OK;
179}
double lmmc_real_t
Public and internal LMMC real type.
LMMC 内部使用的公共工具(仅源文件可见).
lmmc_status_t lmmc_interp_linear(const lmmc_real_t *xs, const lmmc_real_t *ys, size_t n, lmmc_real_t query_x, lmmc_real_t *out_y)
在节点 (xs[i], ys[i]) 间做分段线性插值.
lmmc_status_t interp_check_grid(const interp_grid_t *grid, size_t minimum, const lmmc_real_t *out)
const lmmc_real_t * zs
size_t interp_find_interval(const lmmc_real_t *xs, size_t n, lmmc_real_t query_x)
定义 interp.c:6
int interp_check_finite_values(const lmmc_real_t *values, size_t n)
int interp_check_samples(const lmmc_real_t *xs, const lmmc_real_t *ys, size_t n, size_t minimum)
const lmmc_real_t * ys
const lmmc_real_t * xs
lmmc_real_t interp_interval_fraction(lmmc_real_t left, lmmc_real_t right, lmmc_real_t query)
int interp_check_strictly_increasing(const lmmc_real_t *xs, size_t n)
lmmc_status_t interp_barycentric_weights(const lmmc_real_t *nodes, size_t n, lmmc_real_t *weights)
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_OK
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_INVALID_ARGUMENT
@ LMMC_STATUS_OUT_OF_RANGE