LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
nonlinear_bisection.c
浏览该文件的文档.
2
14
15static 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)) {
22 }
23
24 s->out_result->root = s->left;
26 s->out_result->residual_norm = lmmc_abs(s->f_left);
27
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;
39 s->out_result->residual_norm = lmmc_abs(s->f_right);
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)) {
47 }
48 return LMMC_STATUS_OK;
49}
50
51static 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
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;
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
77 &s->local_cfg, s->iter,
79
80 if (lmmc_abs(f_mid) <= s->local_cfg.abs_tol || half_width <= x_tol) {
81 s->out_result->converged = 1;
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
96static lmmc_status_t bisection_initialize(
98) {
99 if (s->func == NULL || s->out_result == NULL) {
101 }
103 if (!lmmc_is_finite(&s->left) || !lmmc_is_finite(&s->right)) {
105 }
106 if (!(s->left < s->right)) {
108 }
109 if (cfg != NULL) {
110 s->local_cfg = *cfg;
111 } else {
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)) {
119 }
120 if (s->local_cfg.abs_tol < 0.0 || s->local_cfg.rel_tol < 0.0 || s->local_cfg.max_iter == 0) {
122 }
123 return LMMC_STATUS_OK;
124}
125
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;
154}
double lmmc_real_t
Public and internal LMMC real type.
@ LMMC_NONLINEAR_FAILURE_INVALID_BRACKET
@ LMMC_NONLINEAR_FAILURE_NONE
@ LMMC_NONLINEAR_FAILURE_MAX_ITER
@ LMMC_NONLINEAR_FAILURE_NUMERICAL_ISSUE
lmmc_nonlinear_failure_t failure_reason
lmmc_status_t lmmc_nonlinear_default_config(lmmc_nonlinear_config_t *out_cfg)
生成默认配置.
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)
二分法求根.
lmmc_real_t(*) lmmc_scalar_func_t(lmmc_real_t x, void *user_data)
标量函数签名: .
求根算法配置.
求根结果统计.
lmmc_nonlinear_config_t local_cfg
lmmc_nonlinear_result_t * out_result
void lmmc_nonlinear_do_log(const lmmc_nonlinear_config_t *cfg, size_t iter, lmmc_real_t x, lmmc_real_t f_x)
lmmc_status_t lmmc_nonlinear_x_tolerance(lmmc_real_t x, const lmmc_nonlinear_config_t *cfg, lmmc_real_t *out_x_tol)
void lmmc_nonlinear_reset_result(lmmc_nonlinear_result_t *out_result)
lmmc_real_t lmmc_nonlinear_half_width(lmmc_real_t left, lmmc_real_t right)
lmmc_real_t lmmc_nonlinear_midpoint(lmmc_real_t left, lmmc_real_t right)
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_OK
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_INVALID_ARGUMENT