LMMC
Lamina Mathematic core
Toggle main menu visibility
载入中...
搜索中...
未找到
nonlinear_bisection.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
left
;
9
lmmc_real_t
right
;
10
lmmc_real_t
f_left
;
11
lmmc_real_t
f_right
;
12
size_t
iter
;
13
}
bisection_state_t
;
14
15
static
lmmc_status_t
bisection_endpoints(
bisection_state_t
* s) {
16
s->
f_left
= s->
func
(s->
left
, s->
user_data
);
17
s->
f_right
= s->
func
(s->
right
, s->
user_data
);
18
19
if
(!lmmc_is_finite(&s->
f_left
) || !lmmc_is_finite(&s->
f_right
)) {
20
s->
out_result
->
failure_reason
=
LMMC_NONLINEAR_FAILURE_NUMERICAL_ISSUE
;
21
return
LMMC_STATUS_NUMERICAL_FAILURE
;
22
}
23
24
s->
out_result
->
root
= s->
left
;
25
s->
out_result
->
function_value
= s->
f_left
;
26
s->
out_result
->
residual_norm
= lmmc_abs(s->
f_left
);
27
28
lmmc_nonlinear_do_log
(&s->
local_cfg
, 0, s->
out_result
->
root
, s->
out_result
->
function_value
);
29
30
if
(lmmc_abs(s->
f_left
) <= s->
local_cfg
.
abs_tol
) {
31
s->
out_result
->
converged
= 1;
32
return
LMMC_STATUS_OK
;
33
}
34
35
if
(lmmc_abs(s->
f_right
) <= s->
local_cfg
.
abs_tol
) {
36
s->
out_result
->
converged
= 1;
37
s->
out_result
->
root
= s->
right
;
38
s->
out_result
->
function_value
= s->
f_right
;
39
s->
out_result
->
residual_norm
= lmmc_abs(s->
f_right
);
40
lmmc_nonlinear_do_log
(&s->
local_cfg
, 0, s->
out_result
->
root
, s->
out_result
->
function_value
);
41
return
LMMC_STATUS_OK
;
42
}
43
44
if
((s->
f_left
> 0.0 && s->
f_right
> 0.0) || (s->
f_left
< 0.0 && s->
f_right
< 0.0)) {
45
s->
out_result
->
failure_reason
=
LMMC_NONLINEAR_FAILURE_INVALID_BRACKET
;
46
return
LMMC_STATUS_INVALID_ARGUMENT
;
47
}
48
return
LMMC_STATUS_OK
;
49
}
50
51
static
lmmc_status_t
bisection_iteration(
bisection_state_t
* s) {
52
lmmc_real_t
mid;
53
lmmc_real_t
f_mid;
54
lmmc_real_t
x_tol;
55
lmmc_real_t
half_width;
56
lmmc_status_t
tolerance_status;
57
58
mid =
lmmc_nonlinear_midpoint
(s->
left
, s->
right
);
59
half_width =
lmmc_nonlinear_half_width
(s->
left
, s->
right
);
60
f_mid = s->
func
(mid, s->
user_data
);
61
tolerance_status =
lmmc_nonlinear_x_tolerance
(
62
mid, &s->
local_cfg
, &x_tol);
63
64
if
(!lmmc_is_finite(&mid) || !lmmc_is_finite(&f_mid) ||
65
!lmmc_is_finite(&half_width) || tolerance_status !=
LMMC_STATUS_OK
) {
66
s->
out_result
->
num_iter
= s->
iter
;
67
s->
out_result
->
failure_reason
=
LMMC_NONLINEAR_FAILURE_NUMERICAL_ISSUE
;
68
return
LMMC_STATUS_NUMERICAL_FAILURE
;
69
}
70
71
s->
out_result
->
num_iter
= s->
iter
;
72
s->
out_result
->
root
= mid;
73
s->
out_result
->
function_value
= f_mid;
74
s->
out_result
->
residual_norm
= lmmc_abs(f_mid);
75
76
lmmc_nonlinear_do_log
(
77
&s->
local_cfg
, s->
iter
,
78
s->
out_result
->
root
, s->
out_result
->
function_value
);
79
80
if
(lmmc_abs(f_mid) <= s->
local_cfg
.
abs_tol
|| half_width <= x_tol) {
81
s->
out_result
->
converged
= 1;
82
s->
out_result
->
failure_reason
=
LMMC_NONLINEAR_FAILURE_NONE
;
83
return
LMMC_STATUS_OK
;
84
}
85
86
if
((s->
f_left
< 0.0) != (f_mid < 0.0)) {
87
s->
right
= mid;
88
s->
f_right
= f_mid;
89
}
else
{
90
s->
left
= mid;
91
s->
f_left
= f_mid;
92
}
93
return
LMMC_STATUS_OK
;
94
}
95
96
static
lmmc_status_t
bisection_initialize(
97
bisection_state_t
* s,
const
lmmc_nonlinear_config_t
* cfg
98
) {
99
if
(s->
func
== NULL || s->
out_result
== NULL) {
100
return
LMMC_STATUS_INVALID_ARGUMENT
;
101
}
102
lmmc_nonlinear_reset_result
(s->
out_result
);
103
if
(!lmmc_is_finite(&s->
left
) || !lmmc_is_finite(&s->
right
)) {
104
return
LMMC_STATUS_INVALID_ARGUMENT
;
105
}
106
if
(!(s->
left
< s->
right
)) {
107
return
LMMC_STATUS_INVALID_ARGUMENT
;
108
}
109
if
(cfg != NULL) {
110
s->
local_cfg
= *cfg;
111
}
else
{
112
lmmc_status_t
st =
lmmc_nonlinear_default_config
(&s->
local_cfg
);
113
if
(st !=
LMMC_STATUS_OK
) {
114
return
st;
115
}
116
}
117
if
(!lmmc_is_finite(&s->
local_cfg
.
abs_tol
) || !lmmc_is_finite(&s->
local_cfg
.
rel_tol
)) {
118
return
LMMC_STATUS_INVALID_ARGUMENT
;
119
}
120
if
(s->
local_cfg
.
abs_tol
< 0.0 || s->
local_cfg
.
rel_tol
< 0.0 || s->
local_cfg
.
max_iter
== 0) {
121
return
LMMC_STATUS_INVALID_ARGUMENT
;
122
}
123
return
LMMC_STATUS_OK
;
124
}
125
126
lmmc_status_t
lmmc_bisection_solve
(
127
lmmc_scalar_func_t
func,
128
void
* user_data,
129
lmmc_real_t
left,
130
lmmc_real_t
right,
131
const
lmmc_nonlinear_config_t
* cfg,
132
lmmc_nonlinear_result_t
* out_result
133
) {
134
bisection_state_t
state = {0};
135
bisection_state_t
* s = &state;
136
s->
func
= func;
137
s->
user_data
= user_data;
138
s->
out_result
= out_result;
139
s->
left
= left;
140
s->
right
= right;
141
lmmc_status_t
st = bisection_initialize(s, cfg);
142
if
(st !=
LMMC_STATUS_OK
) {
143
return
st;
144
}
145
st = bisection_endpoints(s);
146
if
(st !=
LMMC_STATUS_OK
|| out_result->
converged
) {
return
st; }
147
for
(s->
iter
= 1; s->
iter
<= s->
local_cfg
.
max_iter
; ++s->
iter
) {
148
st = bisection_iteration(s);
149
if
(st !=
LMMC_STATUS_OK
|| out_result->
converged
) {
return
st; }
150
}
151
s->
out_result
->
converged
= 0;
152
s->
out_result
->
failure_reason
=
LMMC_NONLINEAR_FAILURE_MAX_ITER
;
153
return
LMMC_STATUS_NUMERICAL_FAILURE
;
154
}
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_config_t::rel_tol
lmmc_real_t rel_tol
定义
nonlinear.h:59
LMMC_NONLINEAR_FAILURE_INVALID_BRACKET
@ LMMC_NONLINEAR_FAILURE_INVALID_BRACKET
定义
nonlinear.h:35
LMMC_NONLINEAR_FAILURE_NONE
@ LMMC_NONLINEAR_FAILURE_NONE
定义
nonlinear.h:34
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_default_config
lmmc_status_t lmmc_nonlinear_default_config(lmmc_nonlinear_config_t *out_cfg)
生成默认配置.
定义
nonlinear.c:130
lmmc_bisection_solve
lmmc_status_t lmmc_bisection_solve(lmmc_scalar_func_t func, void *user_data, lmmc_real_t left, lmmc_real_t right, const lmmc_nonlinear_config_t *cfg, lmmc_nonlinear_result_t *out_result)
二分法求根.
定义
nonlinear_bisection.c:126
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_nonlinear_config_t
求根算法配置.
定义
nonlinear.h:57
lmmc_nonlinear_result_t
求根结果统计.
定义
nonlinear.h:45
bisection_state_t::iter
size_t iter
定义
nonlinear_bisection.c:12
bisection_state_t::func
lmmc_scalar_func_t func
定义
nonlinear_bisection.c:4
bisection_state_t::f_right
lmmc_real_t f_right
定义
nonlinear_bisection.c:11
bisection_state_t::local_cfg
lmmc_nonlinear_config_t local_cfg
定义
nonlinear_bisection.c:6
bisection_state_t::left
lmmc_real_t left
定义
nonlinear_bisection.c:8
bisection_state_t::f_left
lmmc_real_t f_left
定义
nonlinear_bisection.c:10
bisection_state_t::user_data
void * user_data
定义
nonlinear_bisection.c:5
bisection_state_t::out_result
lmmc_nonlinear_result_t * out_result
定义
nonlinear_bisection.c:7
bisection_state_t::right
lmmc_real_t right
定义
nonlinear_bisection.c:9
bisection_state_t
定义
nonlinear_bisection.c:3
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_half_width
lmmc_real_t lmmc_nonlinear_half_width(lmmc_real_t left, lmmc_real_t right)
定义
nonlinear.c:24
lmmc_nonlinear_midpoint
lmmc_real_t lmmc_nonlinear_midpoint(lmmc_real_t left, lmmc_real_t right)
定义
nonlinear.c:19
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_bisection.c
生成于
, 为 LMMC使用
1.18.0