LMMC
Lamina Mathematic core
Toggle main menu visibility
载入中...
搜索中...
未找到
interp.c
浏览该文件的文档.
1
#include "
internal.h
"
2
#include "
internal/interp_internal.h
"
3
4
#include <math.h>
5
6
size_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
18
int
interp_check_strictly_increasing
(
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
33
int
interp_check_finite_values
(
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
48
lmmc_status_t
interp_barycentric_weights
(
const
lmmc_real_t
* nodes,
size_t
n,
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) {
59
return
LMMC_STATUS_INVALID_ARGUMENT
;
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])) {
74
return
LMMC_STATUS_NUMERICAL_FAILURE
;
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
83
int
interp_check_samples
(
const
lmmc_real_t
* xs,
const
lmmc_real_t
* ys,
84
size_t
n,
size_t
minimum)
85
{
86
return
xs && ys && n >= minimum &&
87
interp_check_strictly_increasing
(xs, n) &&
88
interp_check_finite_values
(ys, n);
89
}
90
91
static
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
106
lmmc_status_t
interp_check_grid
(
const
interp_grid_t
* grid,
size_t
minimum,
107
const
lmmc_real_t
* out)
108
{
109
if
(!grid->
xs
|| !grid->
ys
|| !grid->
zs
|| !out) {
110
return
LMMC_STATUS_INVALID_ARGUMENT
;
111
}
112
if
(grid->
nx
< minimum || grid->
ny
< minimum) {
113
return
LMMC_STATUS_INVALID_ARGUMENT
;
114
}
115
if
(!interp_grid_coordinates_valid(grid)) {
116
return
LMMC_STATUS_INVALID_ARGUMENT
;
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]) {
120
return
LMMC_STATUS_OUT_OF_RANGE
;
121
}
122
return
LMMC_STATUS_OK
;
123
}
124
125
lmmc_real_t
interp_interval_fraction
(
lmmc_real_t
left,
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
140
static
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
155
lmmc_status_t
lmmc_interp_linear
(
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)) {
162
return
LMMC_STATUS_INVALID_ARGUMENT
;
163
}
164
if
(query_x < xs[0] || query_x > xs[n - 1]) {
165
return
LMMC_STATUS_OUT_OF_RANGE
;
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)) {
175
return
LMMC_STATUS_NUMERICAL_FAILURE
;
176
}
177
*out_y = result;
178
return
LMMC_STATUS_OK
;
179
}
lmmc_real_t
double lmmc_real_t
Public and internal LMMC real type.
定义
config.h:28
internal.h
LMMC 内部使用的公共工具(仅源文件可见).
lmmc_interp_linear
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]) 间做分段线性插值.
定义
interp.c:155
interp_internal.h
interp_grid_t::ny
size_t ny
定义
interp_internal.h:21
interp_check_grid
lmmc_status_t interp_check_grid(const interp_grid_t *grid, size_t minimum, const lmmc_real_t *out)
定义
interp.c:106
interp_grid_t::zs
const lmmc_real_t * zs
定义
interp_internal.h:19
interp_find_interval
size_t interp_find_interval(const lmmc_real_t *xs, size_t n, lmmc_real_t query_x)
定义
interp.c:6
interp_check_finite_values
int interp_check_finite_values(const lmmc_real_t *values, size_t n)
定义
interp.c:33
interp_check_samples
int interp_check_samples(const lmmc_real_t *xs, const lmmc_real_t *ys, size_t n, size_t minimum)
定义
interp.c:83
interp_grid_t::qx
lmmc_real_t qx
定义
interp_internal.h:22
interp_grid_t::ys
const lmmc_real_t * ys
定义
interp_internal.h:18
interp_grid_t::nx
size_t nx
定义
interp_internal.h:20
interp_grid_t::xs
const lmmc_real_t * xs
定义
interp_internal.h:17
interp_interval_fraction
lmmc_real_t interp_interval_fraction(lmmc_real_t left, lmmc_real_t right, lmmc_real_t query)
定义
interp.c:125
interp_grid_t::qy
lmmc_real_t qy
定义
interp_internal.h:23
interp_check_strictly_increasing
int interp_check_strictly_increasing(const lmmc_real_t *xs, size_t n)
定义
interp.c:18
interp_barycentric_weights
lmmc_status_t interp_barycentric_weights(const lmmc_real_t *nodes, size_t n, lmmc_real_t *weights)
定义
interp.c:48
interp_grid_t
定义
interp_internal.h:16
lmmc_status_t
lmmc_status_t
LMMC 库统一返回的状态码.
定义
status.h:22
LMMC_STATUS_OK
@ LMMC_STATUS_OK
定义
status.h:23
LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_NUMERICAL_FAILURE
定义
status.h:29
LMMC_STATUS_INVALID_ARGUMENT
@ LMMC_STATUS_INVALID_ARGUMENT
定义
status.h:24
LMMC_STATUS_OUT_OF_RANGE
@ LMMC_STATUS_OUT_OF_RANGE
定义
status.h:32
src
interp.c
生成于
, 为 LMMC使用
1.18.0