LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
interp_grid.c
浏览该文件的文档.
2
3#include <math.h>
4
6 const lmmc_real_t* xs, size_t nx,
7 const lmmc_real_t* ys, size_t ny,
8 const lmmc_real_t* zs,
10 lmmc_real_t* out_z)
11{
12 size_t ix, iy;
13 const interp_grid_t grid = {xs, ys, zs, nx, ny, qx, qy};
14 lmmc_status_t status = interp_check_grid(&grid, 2, out_z);
15 lmmc_real_t tx, ty;
16 lmmc_real_t z00, z01, z10, z11, result;
17
18 if (status != LMMC_STATUS_OK) {
19 return status;
20 }
21
22 ix = interp_find_interval(xs, nx, qx);
23 iy = interp_find_interval(ys, ny, qy);
24 if (ix >= nx - 1) ix = nx - 2;
25 if (iy >= ny - 1) iy = ny - 2;
26
27 tx = interp_interval_fraction(xs[ix], xs[ix + 1], qx);
28 ty = interp_interval_fraction(ys[iy], ys[iy + 1], qy);
29 z00 = zs[ix * ny + iy];
30 z01 = zs[ix * ny + (iy + 1)];
31 z10 = zs[(ix + 1) * ny + iy];
32 z11 = zs[(ix + 1) * ny + (iy + 1)];
33 if (!isfinite(z00) || !isfinite(z01)) {
35 }
36 if (!isfinite(z10) || !isfinite(z11)) {
38 }
39
40 result = (1.0 - tx) * (1.0 - ty) * z00
41 + (1.0 - tx) * ty * z01
42 + tx * (1.0 - ty) * z10
43 + tx * ty * z11;
44 if (!isfinite(result)) {
46 }
47 *out_z = result;
48 return LMMC_STATUS_OK;
49}
50
52static size_t interp_grid_stencil(const lmmc_real_t* xs, size_t n, lmmc_real_t q)
53{
54 size_t interval = interp_find_interval(xs, n, q);
55 size_t start = interval > 0 ? interval - 1 : 0;
56 return start > n - 4 ? n - 4 : start;
57}
58
59static lmmc_status_t interp_grid_basis(const lmmc_real_t* nodes, lmmc_real_t q,
60 lmmc_real_t* basis)
61{
62 size_t i, j;
63 lmmc_real_t denominator = 0.0, largest = -INFINITY;
64 lmmc_real_t log_terms[4];
65 lmmc_status_t status;
66 for (i = 0; i < 4; ++i) {
67 if (q == nodes[i]) {
68 for (j = 0; j < 4; ++j) basis[j] = i == j ? 1.0 : 0.0;
69 return LMMC_STATUS_OK;
70 }
71 }
72 status = interp_barycentric_weights(nodes, 4, basis);
73 if (status != LMMC_STATUS_OK) {
74 return status;
75 }
76 for (i = 0; i < 4; ++i) {
77 lmmc_real_t difference = q - nodes[i];
78 lmmc_real_t log_distance = isfinite(difference) ?
79 log(fabs(difference)) :
80 log(fabs(q / 2.0 - nodes[i] / 2.0)) + log(2.0);
81 log_terms[i] = log(fabs(basis[i])) - log_distance;
82 if (log_terms[i] > largest) largest = log_terms[i];
83 }
84 for (i = 0; i < 4; ++i) {
85 lmmc_real_t difference = q - nodes[i];
86 basis[i] = copysign(exp(log_terms[i] - largest), basis[i]) *
87 (difference < 0.0 ? -1.0 : 1.0);
88 denominator += basis[i];
89 }
90 if (denominator == 0.0 || !isfinite(denominator)) {
92 }
93 for (i = 0; i < 4; ++i) basis[i] /= denominator;
94 return interp_check_finite_values(basis, 4) ?
96}
97
98static int interp_grid_values_finite(const interp_grid_t* grid,
99 size_t ix, size_t iy)
100{
101 size_t i;
102 for (i = 0; i < 4; ++i) {
103 if (!interp_check_finite_values(grid->zs + (ix + i) * grid->ny + iy, 4)) {
104 return 0;
105 }
106 }
107 return 1;
108}
109
110static lmmc_status_t interp_grid_tensor_product(const interp_grid_t* grid,
111 size_t ix, size_t iy, const lmmc_real_t* bx, const lmmc_real_t* by,
112 lmmc_real_t* out)
113{
114 size_t i, j;
115 lmmc_real_t result = 0.0;
116 for (i = 0; i < 4; ++i) {
117 lmmc_real_t row = 0.0;
118 for (j = 0; j < 4; ++j) {
119 row += by[j] * grid->zs[(ix + i) * grid->ny + iy + j];
120 if (!isfinite(row)) {
122 }
123 }
124 result += bx[i] * row;
125 if (!isfinite(result)) {
127 }
128 }
129 *out = result;
130 return LMMC_STATUS_OK;
131}
132
134 const lmmc_real_t* xs, size_t nx,
135 const lmmc_real_t* ys, size_t ny,
136 const lmmc_real_t* zs, lmmc_real_t qx, lmmc_real_t qy,
137 lmmc_real_t* out_z)
138{
139 const interp_grid_t grid = {xs, ys, zs, nx, ny, qx, qy};
140 size_t ix, iy;
141 lmmc_real_t bx[4], by[4];
142 lmmc_status_t status = interp_check_grid(&grid, 4, out_z);
143 if (status != LMMC_STATUS_OK) {
144 return status;
145 }
146 ix = interp_grid_stencil(xs, nx, qx);
147 iy = interp_grid_stencil(ys, ny, qy);
148 if (!interp_grid_values_finite(&grid, ix, iy)) {
150 }
151 status = interp_grid_basis(xs + ix, qx, bx);
152 if (status != LMMC_STATUS_OK) {
153 return status;
154 }
155 status = interp_grid_basis(ys + iy, qy, by);
156 if (status != LMMC_STATUS_OK) {
157 return status;
158 }
159 return interp_grid_tensor_product(&grid, ix, iy, bx, by, out_z);
160}
double lmmc_real_t
Public and internal LMMC real type.
lmmc_status_t lmmc_interp_bicubic(const lmmc_real_t *xs, size_t nx, const lmmc_real_t *ys, size_t ny, const lmmc_real_t *zs, lmmc_real_t qx, lmmc_real_t qy, lmmc_real_t *out_z)
双三次插值(矩形网格).
lmmc_status_t lmmc_interp_bilinear(const lmmc_real_t *xs, size_t nx, const lmmc_real_t *ys, size_t ny, const lmmc_real_t *zs, lmmc_real_t qx, lmmc_real_t qy, lmmc_real_t *out_z)
双线性插值(矩形网格).
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)
lmmc_real_t interp_interval_fraction(lmmc_real_t left, lmmc_real_t right, lmmc_real_t query)
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