LMMC
Lamina Mathematic core
Toggle main menu visibility
载入中...
搜索中...
未找到
nonlinear_secant.c
浏览该文件的文档.
1
#include "
internal/nonlinear_internal.h
"
2
3
typedef
struct
{
4
lmmc_scalar_func_t
func
;
5
void
*
user_data
;
6
lmmc_nonlinear_config_t
local_cfg
;
7
lmmc_nonlinear_result_t
*
out_result
;
8
lmmc_real_t
x0
;
9
lmmc_real_t
x1
;
10
lmmc_real_t
f0
;
11
lmmc_real_t
f1
;
12
size_t
iter
;
13
}
secant_state_t
;
14
15
static
lmmc_status_t
secant_prediction(
secant_state_t
* s,
lmmc_real_t
* candidate,
lmmc_real_t
* distance) {
16
lmmc_real_t
scaled_f0;
17
lmmc_real_t
scaled_f1;
18
lmmc_real_t
scaled_denom;
19
lmmc_real_t
function_scale;
20
lmmc_real_t
step_magnitude;
21
lmmc_real_t
x2 = 0.0;
22
function_scale = lmmc_max(lmmc_abs(s->
f0
), lmmc_abs(s->
f1
));
23
scaled_f0 = s->
f0
/ function_scale;
24
scaled_f1 = s->
f1
/ function_scale;
25
scaled_denom = scaled_f1 - scaled_f0;
26
if
(!lmmc_is_finite(&scaled_denom)) {
27
s->
out_result
->
num_iter
= s->
iter
;
28
s->
out_result
->
failure_reason
=
LMMC_NONLINEAR_FAILURE_NUMERICAL_ISSUE
;
29
return
LMMC_STATUS_NUMERICAL_FAILURE
;
30
}
31
if
(lmmc_abs(scaled_denom) <= DBL_EPSILON * 64.0) {
32
s->
out_result
->
num_iter
= s->
iter
;
33
s->
out_result
->
failure_reason
=
LMMC_NONLINEAR_FAILURE_SINGULAR_STEP
;
34
return
LMMC_STATUS_NUMERICAL_FAILURE
;
35
}
36
37
if
((s->
f0
< 0.0) != (s->
f1
< 0.0)) {
38
const
lmmc_real_t
weight_sum =
39
lmmc_abs(scaled_f0) + lmmc_abs(scaled_f1);
40
const
lmmc_real_t
weight0 = lmmc_abs(scaled_f1) / weight_sum;
41
const
lmmc_real_t
weight1 = lmmc_abs(scaled_f0) / weight_sum;
42
x2 = fma(weight0, s->
x0
, weight1 * s->
x1
);
43
}
else
{
44
const
lmmc_real_t
numerator =
45
fma(s->
x0
, scaled_f1, -s->
x1
* scaled_f0);
46
x2 = numerator / scaled_denom;
47
}
48
step_magnitude =
lmmc_nonlinear_distance
(x2, s->
x1
);
49
50
if
(!lmmc_is_finite(&x2)) {
51
s->
out_result
->
num_iter
= s->
iter
;
52
s->
out_result
->
failure_reason
=
LMMC_NONLINEAR_FAILURE_SINGULAR_STEP
;
53
return
LMMC_STATUS_NUMERICAL_FAILURE
;
54
}
55
*candidate = x2;
56
*distance = step_magnitude;
57
return
LMMC_STATUS_OK
;
58
}
59
60
static
lmmc_status_t
secant_iteration(
secant_state_t
* s) {
61
lmmc_real_t
x2, step_magnitude;
62
lmmc_real_t
f2 = 0.0, x_tol = 0.0;
63
lmmc_status_t
st = secant_prediction(s, &x2, &step_magnitude);
64
if
(st !=
LMMC_STATUS_OK
) {
return
st; }
65
f2 = s->
func
(x2, s->
user_data
);
66
if
(!lmmc_is_finite(&f2)) {
67
s->
out_result
->
num_iter
= s->
iter
;
68
s->
out_result
->
failure_reason
=
LMMC_NONLINEAR_FAILURE_NUMERICAL_ISSUE
;
69
return
LMMC_STATUS_NUMERICAL_FAILURE
;
70
}
71
72
if
(
lmmc_nonlinear_x_tolerance
(x2, &s->
local_cfg
, &x_tol) !=
LMMC_STATUS_OK
) {
73
s->
out_result
->
num_iter
= s->
iter
;
74
s->
out_result
->
failure_reason
=
LMMC_NONLINEAR_FAILURE_NUMERICAL_ISSUE
;
75
return
LMMC_STATUS_NUMERICAL_FAILURE
;
76
}
77
78
s->
out_result
->
num_iter
= s->
iter
;
79
s->
out_result
->
root
= x2;
80
s->
out_result
->
function_value
= f2;
81
s->
out_result
->
residual_norm
= lmmc_abs(f2);
82
83
lmmc_nonlinear_do_log
(&s->
local_cfg
, s->
iter
, s->
out_result
->
root
, s->
out_result
->
function_value
);
84
85
{
86
if
(s->
out_result
->
residual_norm
<= s->
local_cfg
.
abs_tol
||
87
step_magnitude <= x_tol) {
88
s->
out_result
->
converged
= 1;
89
s->
out_result
->
failure_reason
=
LMMC_NONLINEAR_FAILURE_NONE
;
90
return
LMMC_STATUS_OK
;
91
}
92
93
if
(step_magnitude < s->local_cfg.min_step) {
94
s->
out_result
->
failure_reason
=
LMMC_NONLINEAR_FAILURE_SINGULAR_STEP
;
95
return
LMMC_STATUS_NUMERICAL_FAILURE
;
96
}
97
}
98
99
s->
x0
= s->
x1
;
100
s->
f0
= s->
f1
;
101
s->
x1
= x2;
102
s->
f1
= f2;
103
return
LMMC_STATUS_OK
;
104
}
105
106
lmmc_status_t
lmmc_secant_solve
(
107
lmmc_scalar_func_t
func,
108
void
* user_data,
109
lmmc_real_t
x0,
110
lmmc_real_t
x1,
111
const
lmmc_nonlinear_config_t
* cfg,
112
lmmc_nonlinear_result_t
* out_result
113
) {
114
secant_state_t
state = {0};
115
secant_state_t
* s = &state;
116
s->
func
= func;
117
s->
user_data
= user_data;
118
s->
out_result
= out_result;
119
s->
x0
= x0;
120
s->
x1
= x1;
121
if
(s->
func
== NULL || s->
out_result
== NULL || !lmmc_is_finite(&s->
x0
) || !lmmc_is_finite(&s->
x1
) || s->
x0
== s->
x1
) {
122
return
LMMC_STATUS_INVALID_ARGUMENT
;
123
}
124
125
lmmc_nonlinear_reset_result
(s->
out_result
);
126
127
{
128
lmmc_status_t
st_cfg =
lmmc_nonlinear_load_and_validate_config
(cfg, &s->
local_cfg
);
129
if
(st_cfg !=
LMMC_STATUS_OK
) {
130
return
st_cfg;
131
}
132
}
133
134
s->
f0
= s->
func
(s->
x0
, s->
user_data
);
135
s->
f1
= s->
func
(s->
x1
, s->
user_data
);
136
137
if
(!lmmc_is_finite(&s->
f0
) || !lmmc_is_finite(&s->
f1
)) {
138
s->
out_result
->
failure_reason
=
LMMC_NONLINEAR_FAILURE_NUMERICAL_ISSUE
;
139
return
LMMC_STATUS_NUMERICAL_FAILURE
;
140
}
141
142
if
(lmmc_abs(s->
f0
) <= s->
local_cfg
.
abs_tol
) {
143
s->
out_result
->
converged
= 1;
144
s->
out_result
->
root
= s->
x0
;
145
s->
out_result
->
function_value
= s->
f0
;
146
s->
out_result
->
residual_norm
= lmmc_abs(s->
f0
);
147
s->
out_result
->
failure_reason
=
LMMC_NONLINEAR_FAILURE_NONE
;
148
lmmc_nonlinear_do_log
(&s->
local_cfg
, 0, s->
out_result
->
root
, s->
out_result
->
function_value
);
149
return
LMMC_STATUS_OK
;
150
}
151
152
s->
out_result
->
root
= s->
x1
;
153
s->
out_result
->
function_value
= s->
f1
;
154
s->
out_result
->
residual_norm
= lmmc_abs(s->
f1
);
155
156
lmmc_nonlinear_do_log
(&s->
local_cfg
, 0, s->
out_result
->
root
, s->
out_result
->
function_value
);
157
158
if
(lmmc_abs(s->
f1
) <= s->
local_cfg
.
abs_tol
) {
159
s->
out_result
->
converged
= 1;
160
s->
out_result
->
failure_reason
=
LMMC_NONLINEAR_FAILURE_NONE
;
161
return
LMMC_STATUS_OK
;
162
}
163
for
(s->
iter
= 1; s->
iter
<= s->
local_cfg
.
max_iter
; ++s->
iter
) {
164
lmmc_status_t
st = secant_iteration(s);
165
if
(st !=
LMMC_STATUS_OK
|| out_result->
converged
) {
return
st; }
166
}
167
s->
out_result
->
converged
= 0;
168
s->
out_result
->
failure_reason
=
LMMC_NONLINEAR_FAILURE_MAX_ITER
;
169
return
LMMC_STATUS_NUMERICAL_FAILURE
;
170
}
lmmc_real_t
double lmmc_real_t
Public and internal LMMC real type.
定义
config.h:28
lmmc_nonlinear_result_t::num_iter
size_t num_iter
定义
nonlinear.h:47
lmmc_nonlinear_result_t::residual_norm
lmmc_real_t residual_norm
定义
nonlinear.h:50
lmmc_nonlinear_config_t::abs_tol
lmmc_real_t abs_tol
定义
nonlinear.h:58
lmmc_nonlinear_result_t::converged
int converged
定义
nonlinear.h:46
LMMC_NONLINEAR_FAILURE_NONE
@ LMMC_NONLINEAR_FAILURE_NONE
定义
nonlinear.h:34
LMMC_NONLINEAR_FAILURE_SINGULAR_STEP
@ LMMC_NONLINEAR_FAILURE_SINGULAR_STEP
定义
nonlinear.h:39
LMMC_NONLINEAR_FAILURE_MAX_ITER
@ LMMC_NONLINEAR_FAILURE_MAX_ITER
定义
nonlinear.h:36
LMMC_NONLINEAR_FAILURE_NUMERICAL_ISSUE
@ LMMC_NONLINEAR_FAILURE_NUMERICAL_ISSUE
定义
nonlinear.h:38
lmmc_nonlinear_result_t::failure_reason
lmmc_nonlinear_failure_t failure_reason
定义
nonlinear.h:51
lmmc_nonlinear_result_t::function_value
lmmc_real_t function_value
定义
nonlinear.h:49
lmmc_nonlinear_config_t::max_iter
size_t max_iter
定义
nonlinear.h:60
lmmc_scalar_func_t
lmmc_real_t(*) lmmc_scalar_func_t(lmmc_real_t x, void *user_data)
标量函数签名: .
定义
nonlinear.h:23
lmmc_nonlinear_result_t::root
lmmc_real_t root
定义
nonlinear.h:48
lmmc_secant_solve
lmmc_status_t lmmc_secant_solve(lmmc_scalar_func_t func, void *user_data, lmmc_real_t x0, lmmc_real_t x1, const lmmc_nonlinear_config_t *cfg, lmmc_nonlinear_result_t *out_result)
割线法求根.
定义
nonlinear_secant.c:106
lmmc_nonlinear_config_t
求根算法配置.
定义
nonlinear.h:57
lmmc_nonlinear_result_t
求根结果统计.
定义
nonlinear.h:45
nonlinear_internal.h
lmmc_nonlinear_do_log
void lmmc_nonlinear_do_log(const lmmc_nonlinear_config_t *cfg, size_t iter, lmmc_real_t x, lmmc_real_t f_x)
定义
nonlinear.c:10
lmmc_nonlinear_x_tolerance
lmmc_status_t lmmc_nonlinear_x_tolerance(lmmc_real_t x, const lmmc_nonlinear_config_t *cfg, lmmc_real_t *out_x_tol)
定义
nonlinear.c:70
lmmc_nonlinear_reset_result
void lmmc_nonlinear_reset_result(lmmc_nonlinear_result_t *out_result)
定义
nonlinear.c:98
lmmc_nonlinear_distance
lmmc_real_t lmmc_nonlinear_distance(lmmc_real_t left, lmmc_real_t right)
定义
nonlinear.c:32
lmmc_nonlinear_load_and_validate_config
lmmc_status_t lmmc_nonlinear_load_and_validate_config(const lmmc_nonlinear_config_t *cfg, lmmc_nonlinear_config_t *out_cfg)
定义
nonlinear.c:39
secant_state_t::f0
lmmc_real_t f0
定义
nonlinear_secant.c:10
secant_state_t::x0
lmmc_real_t x0
定义
nonlinear_secant.c:8
secant_state_t::out_result
lmmc_nonlinear_result_t * out_result
定义
nonlinear_secant.c:7
secant_state_t::iter
size_t iter
定义
nonlinear_secant.c:12
secant_state_t::func
lmmc_scalar_func_t func
定义
nonlinear_secant.c:4
secant_state_t::local_cfg
lmmc_nonlinear_config_t local_cfg
定义
nonlinear_secant.c:6
secant_state_t::f1
lmmc_real_t f1
定义
nonlinear_secant.c:11
secant_state_t::x1
lmmc_real_t x1
定义
nonlinear_secant.c:9
secant_state_t::user_data
void * user_data
定义
nonlinear_secant.c:5
secant_state_t
定义
nonlinear_secant.c:3
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
src
nonlinear_secant.c
生成于
, 为 LMMC使用
1.18.0