LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
nonlinear_secant.c
浏览该文件的文档.
2
14
15static 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;
30 }
31 if (lmmc_abs(scaled_denom) <= DBL_EPSILON * 64.0) {
32 s->out_result->num_iter = s->iter;
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;
54 }
55 *candidate = x2;
56 *distance = step_magnitude;
57 return LMMC_STATUS_OK;
58}
59
60static 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;
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;
76 }
77
78 s->out_result->num_iter = s->iter;
79 s->out_result->root = x2;
81 s->out_result->residual_norm = lmmc_abs(f2);
82
84
85 {
87 step_magnitude <= x_tol) {
88 s->out_result->converged = 1;
90 return LMMC_STATUS_OK;
91 }
92
93 if (step_magnitude < s->local_cfg.min_step) {
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
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) {
123 }
124
126
127 {
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)) {
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;
146 s->out_result->residual_norm = lmmc_abs(s->f0);
149 return LMMC_STATUS_OK;
150 }
151
152 s->out_result->root = s->x1;
154 s->out_result->residual_norm = lmmc_abs(s->f1);
155
157
158 if (lmmc_abs(s->f1) <= s->local_cfg.abs_tol) {
159 s->out_result->converged = 1;
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;
170}
double lmmc_real_t
Public and internal LMMC real type.
@ LMMC_NONLINEAR_FAILURE_NONE
@ LMMC_NONLINEAR_FAILURE_SINGULAR_STEP
@ LMMC_NONLINEAR_FAILURE_MAX_ITER
@ LMMC_NONLINEAR_FAILURE_NUMERICAL_ISSUE
lmmc_nonlinear_failure_t failure_reason
lmmc_real_t(*) lmmc_scalar_func_t(lmmc_real_t x, void *user_data)
标量函数签名: .
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)
割线法求根.
求根算法配置.
求根结果统计.
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_distance(lmmc_real_t left, lmmc_real_t right)
lmmc_status_t lmmc_nonlinear_load_and_validate_config(const lmmc_nonlinear_config_t *cfg, lmmc_nonlinear_config_t *out_cfg)
lmmc_nonlinear_result_t * out_result
lmmc_scalar_func_t func
lmmc_nonlinear_config_t local_cfg
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_OK
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_INVALID_ARGUMENT