LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
linear_algebra.c
浏览该文件的文档.
1
5#include <math.h>
6#include <string.h>
7#include "memory_bridge.h"
8#include "lmmc/config.h"
9#include "lmmc/numeric.h"
10#include "lmmc/linear_algebra.h"
11
12static void lmmc_abs_to(lmmc_real_t* res, const lmmc_real_t* x) {
13 lmmc_real_t zero;
14 LMMC_REAL_INIT(&zero);
15 LMMC_REAL_SET_D(&zero, 0.0);
16 if (LMMC_REAL_CMP(x, &zero) < 0) {
17 LMMC_REAL_NEG(res, x);
18 } else {
19 LMMC_REAL_SET(res, x);
20 }
21 LMMC_REAL_CLEAR(&zero);
22}
23
24static void lmmc_swap_rows(lmmc_mat_t* a, size_t r0, size_t r1) {
25 size_t j = 0;
26 if (r0 == r1) {
27 return;
28 }
29 for (j = 0; j < a->cols; ++j) {
30 lmmc_real_t tmp;
31 LMMC_REAL_INIT(&tmp);
32 LMMC_REAL_SET(&tmp, &a->data[r0 * a->stride + j]);
33 LMMC_REAL_SET(&a->data[r0 * a->stride + j], &a->data[r1 * a->stride + j]);
34 LMMC_REAL_SET(&a->data[r1 * a->stride + j], &tmp);
35 LMMC_REAL_CLEAR(&tmp);
36 }
37}
38
39lmmc_status_t lmmc_lu_decompose_inplace(lmmc_mat_t* a, size_t* pivots, size_t* out_swap_count) {
40 size_t n = 0;
41 size_t k = 0;
42 size_t swap_count = 0;
43
44 if (a == NULL || pivots == NULL || a->data == NULL) {
46 }
47 if (a->rows != a->cols) {
49 }
50
51 n = a->rows;
52 for (k = 0; k < n; ++k) {
53 size_t i = 0;
54 size_t p = k;
55 lmmc_real_t maxv;
56 LMMC_REAL_INIT(&maxv);
57 if (!LMMC_REAL_IS_FINITE(&a->data[k * a->stride + k])) {
58 LMMC_REAL_CLEAR(&maxv);
60 }
61 lmmc_abs_to(&maxv, &a->data[k * a->stride + k]);
62
63 for (i = k + 1; i < n; ++i) {
66 if (!LMMC_REAL_IS_FINITE(&a->data[i * a->stride + k])) {
68 LMMC_REAL_CLEAR(&maxv);
70 }
71 lmmc_abs_to(&v, &a->data[i * a->stride + k]);
72 if (LMMC_REAL_CMP(&v, &maxv) > 0) {
73 LMMC_REAL_SET(&maxv, &v);
74 p = i;
75 }
77 }
78
79 if (maxv == 0.0) {
80 LMMC_REAL_CLEAR(&maxv);
82 }
83 LMMC_REAL_CLEAR(&maxv);
84
85 pivots[k] = p;
86 if (p != k) {
87 lmmc_swap_rows(a, p, k);
88 ++swap_count;
89 }
90
91 {
92 lmmc_real_t akk;
93 LMMC_REAL_INIT(&akk);
94 LMMC_REAL_SET(&akk, &a->data[k * a->stride + k]);
95 for (i = k + 1; i < n; ++i) {
96 size_t j = 0;
97 LMMC_REAL_DIV(&a->data[i * a->stride + k], &a->data[i * a->stride + k], &akk);
98 if (!LMMC_REAL_IS_FINITE(&a->data[i * a->stride + k])) {
99 LMMC_REAL_CLEAR(&akk);
101 }
102 for (j = k + 1; j < n; ++j) {
103 lmmc_real_t tmp;
104 LMMC_REAL_INIT(&tmp);
105 LMMC_REAL_MUL(&tmp, &a->data[i * a->stride + k], &a->data[k * a->stride + j]);
106 LMMC_REAL_SUB(&a->data[i * a->stride + j], &a->data[i * a->stride + j], &tmp);
107 if (!LMMC_REAL_IS_FINITE(&tmp) ||
108 !LMMC_REAL_IS_FINITE(&a->data[i * a->stride + j])) {
109 LMMC_REAL_CLEAR(&tmp);
110 LMMC_REAL_CLEAR(&akk);
112 }
113 LMMC_REAL_CLEAR(&tmp);
114 }
115 }
116 LMMC_REAL_CLEAR(&akk);
117 }
118 }
119
120 if (out_swap_count != NULL) {
121 *out_swap_count = swap_count;
122 }
123 return LMMC_STATUS_OK;
124}
125
126static lmmc_status_t lmmc_lu_forward(const lmmc_mat_t* lu, const size_t* pivots,
127 const lmmc_vec_t* b, lmmc_vec_t* x) {
128 size_t n = lu->rows;
129 size_t i;
130 for (i = 0; i < n; ++i) {
131 if (!LMMC_REAL_IS_FINITE(&b->data[i])) {
133 }
134 LMMC_REAL_SET(&x->data[i], &b->data[i]);
135 }
136
137 for (i = 0; i < n; ++i) {
138 size_t p = pivots[i];
139 if (p != i) {
140 lmmc_real_t tmp;
141 LMMC_REAL_INIT(&tmp);
142 LMMC_REAL_SET(&tmp, &x->data[i]);
143 LMMC_REAL_SET(&x->data[i], &x->data[p]);
144 LMMC_REAL_SET(&x->data[p], &tmp);
145 LMMC_REAL_CLEAR(&tmp);
146 }
147 }
148
149 for (i = 0; i < n; ++i) {
150 size_t j = 0;
151 for (j = 0; j < i; ++j) {
152 lmmc_real_t tmp;
153 LMMC_REAL_INIT(&tmp);
154 LMMC_REAL_MUL(&tmp, &lu->data[i * lu->stride + j], &x->data[j]);
155 LMMC_REAL_SUB(&x->data[i], &x->data[i], &tmp);
156 if (!LMMC_REAL_IS_FINITE(&tmp) || !LMMC_REAL_IS_FINITE(&x->data[i])) {
157 LMMC_REAL_CLEAR(&tmp);
159 }
160 LMMC_REAL_CLEAR(&tmp);
161 }
162 }
163 return LMMC_STATUS_OK;
164}
165
166lmmc_status_t lmmc_lu_solve(const lmmc_mat_t* lu, const size_t* pivots, const lmmc_vec_t* b, lmmc_vec_t* x) {
167 size_t n = 0;
168 size_t i = 0;
169
170 if (lu == NULL || pivots == NULL || b == NULL || x == NULL || lu->data == NULL || b->data == NULL || x->data == NULL) {
172 }
173 if (lu->rows != lu->cols || b->size != lu->rows || x->size != lu->rows) {
175 }
176
177 n = lu->rows;
178 lmmc_status_t status = lmmc_lu_forward(lu, pivots, b, x);
179 if (status != LMMC_STATUS_OK) {
180 return status;
181 }
182
183 for (i = n; i-- > 0;) {
184 size_t j = 0;
185 for (j = i + 1; j < n; ++j) {
186 lmmc_real_t tmp;
187 LMMC_REAL_INIT(&tmp);
188 LMMC_REAL_MUL(&tmp, &lu->data[i * lu->stride + j], &x->data[j]);
189 LMMC_REAL_SUB(&x->data[i], &x->data[i], &tmp);
190 if (!LMMC_REAL_IS_FINITE(&tmp) || !LMMC_REAL_IS_FINITE(&x->data[i])) {
191 LMMC_REAL_CLEAR(&tmp);
193 }
194 LMMC_REAL_CLEAR(&tmp);
195 }
196
197 if (!LMMC_REAL_IS_FINITE(&lu->data[i * lu->stride + i])) {
199 }
200 if (lu->data[i * lu->stride + i] == 0.0) {
202 }
203
204 LMMC_REAL_DIV(&x->data[i], &x->data[i], &lu->data[i * lu->stride + i]);
205 if (!LMMC_REAL_IS_FINITE(&x->data[i])) {
207 }
208 }
209
210 return LMMC_STATUS_OK;
211}
212
214 size_t n = 0;
215 size_t i = 0;
216 size_t j = 0;
217 size_t k = 0;
218 lmmc_real_t maxDiag;
219
220 if (a == NULL || a->data == NULL) {
222 }
223 if (a->rows != a->cols) {
225 }
226
227 n = a->rows;
228 LMMC_REAL_INIT(&maxDiag);
229 LMMC_REAL_SET_D(&maxDiag, 0.0);
230
231 for (i = 0; i < n; ++i) {
232 for (j = 0; j <= i; ++j) {
233 lmmc_real_t sum;
234 LMMC_REAL_INIT(&sum);
235 LMMC_REAL_SET(&sum, &a->data[i * a->stride + j]);
236 for (k = 0; k < j; ++k) {
237 lmmc_real_t tmp;
238 LMMC_REAL_INIT(&tmp);
239 LMMC_REAL_MUL(&tmp, &a->data[i * a->stride + k], &a->data[j * a->stride + k]);
240 LMMC_REAL_SUB(&sum, &sum, &tmp);
241 LMMC_REAL_CLEAR(&tmp);
242 }
243
244 if (i == j) {
245 /* Relative SPD threshold: reject when d_i <= LMMC_DEFAULT_REL_TOL * maxDiag */
246 lmmc_real_t threshold;
247 LMMC_REAL_INIT(&threshold);
249 LMMC_REAL_MUL(&threshold, &threshold, &maxDiag);
250 if (LMMC_REAL_CMP(&sum, &threshold) <= 0) {
251 LMMC_REAL_CLEAR(&threshold);
252 LMMC_REAL_CLEAR(&sum);
253 LMMC_REAL_CLEAR(&maxDiag);
255 }
256 LMMC_REAL_CLEAR(&threshold);
257 /* Update maxDiag with the current diagonal entry */
258 if (LMMC_REAL_CMP(&sum, &maxDiag) > 0) {
259 LMMC_REAL_SET(&maxDiag, &sum);
260 }
261 LMMC_REAL_SQRT(&a->data[i * a->stride + i], &sum);
262 } else {
263 LMMC_REAL_DIV(&a->data[i * a->stride + j], &sum, &a->data[j * a->stride + j]);
264 }
265 LMMC_REAL_CLEAR(&sum);
266 }
267 for (j = i + 1; j < n; ++j) {
268 lmmc_real_t zero;
269 LMMC_REAL_INIT(&zero);
270 LMMC_REAL_SET_D(&zero, 0.0);
271 LMMC_REAL_SET(&a->data[i * a->stride + j], &zero);
272 LMMC_REAL_CLEAR(&zero);
273 }
274 }
275
276 LMMC_REAL_CLEAR(&maxDiag);
277 return LMMC_STATUS_OK;
278}
279
281 size_t n = 0;
282 size_t i = 0;
283 size_t j = 0;
284
285 if (l == NULL || b == NULL || x == NULL || l->data == NULL || b->data == NULL || x->data == NULL) {
287 }
288 if (l->rows != l->cols || b->size != l->rows || x->size != l->rows) {
290 }
291
292 n = l->rows;
293
294 for (i = 0; i < n; ++i) {
295 lmmc_real_t sum;
296 LMMC_REAL_INIT(&sum);
297 LMMC_REAL_SET(&sum, &b->data[i]);
298 for (j = 0; j < i; ++j) {
299 lmmc_real_t tmp;
300 LMMC_REAL_INIT(&tmp);
301 LMMC_REAL_MUL(&tmp, &l->data[i * l->stride + j], &x->data[j]);
302 LMMC_REAL_SUB(&sum, &sum, &tmp);
303 LMMC_REAL_CLEAR(&tmp);
304 }
305 LMMC_REAL_DIV(&x->data[i], &sum, &l->data[i * l->stride + i]);
306 LMMC_REAL_CLEAR(&sum);
307 }
308
309 for (i = n; i-- > 0;) {
310 lmmc_real_t sum;
311 LMMC_REAL_INIT(&sum);
312 LMMC_REAL_SET(&sum, &x->data[i]);
313 for (j = i + 1; j < n; ++j) {
314 lmmc_real_t tmp;
315 LMMC_REAL_INIT(&tmp);
316 LMMC_REAL_MUL(&tmp, &l->data[j * l->stride + i], &x->data[j]);
317 LMMC_REAL_SUB(&sum, &sum, &tmp);
318 LMMC_REAL_CLEAR(&tmp);
319 }
320 LMMC_REAL_DIV(&x->data[i], &sum, &l->data[i * l->stride + i]);
321 LMMC_REAL_CLEAR(&sum);
322 }
323
324 return LMMC_STATUS_OK;
325}
326
327static void lmmc_qr_update_trailing(lmmc_mat_t* a,
328 const lmmc_real_t* tau, size_t k) {
329 size_t m = a->rows;
330 size_t n = a->cols;
331 size_t i, j;
332 for (j = k + 1; j < n; ++j) {
333 lmmc_real_t dot;
334 LMMC_REAL_INIT(&dot);
335 LMMC_REAL_SET(&dot, &a->data[k * a->stride + j]);
336 for (i = k + 1; i < m; ++i) {
337 lmmc_real_t tmp;
338 LMMC_REAL_INIT(&tmp);
339 LMMC_REAL_MUL(&tmp, &a->data[i * a->stride + k], &a->data[i * a->stride + j]);
340 LMMC_REAL_ADD(&dot, &dot, &tmp);
341 LMMC_REAL_CLEAR(&tmp);
342 }
343 LMMC_REAL_MUL(&dot, &dot, &tau[k]);
344
345 LMMC_REAL_SUB(&a->data[k * a->stride + j], &a->data[k * a->stride + j], &dot);
346 for (i = k + 1; i < m; ++i) {
347 lmmc_real_t tmp;
348 LMMC_REAL_INIT(&tmp);
349 LMMC_REAL_MUL(&tmp, &a->data[i * a->stride + k], &dot);
350 LMMC_REAL_SUB(&a->data[i * a->stride + j], &a->data[i * a->stride + j], &tmp);
351 LMMC_REAL_CLEAR(&tmp);
352 }
353 LMMC_REAL_CLEAR(&dot);
354 }
355}
356
357static void lmmc_qr_reflector(lmmc_mat_t* a, lmmc_real_t* tau,
358 size_t k, lmmc_real_t alpha, lmmc_real_t sigma) {
359 size_t m = a->rows;
360 size_t i;
361 lmmc_real_t zero = 0.0;
362 lmmc_real_t norm;
363 lmmc_real_t beta;
364 lmmc_real_t v0;
365 lmmc_real_t alpha_sq;
366 lmmc_real_t sum;
367
368 LMMC_REAL_INIT(&norm);
369 LMMC_REAL_INIT(&beta);
370 LMMC_REAL_INIT(&v0);
371 LMMC_REAL_INIT(&alpha_sq);
372 LMMC_REAL_INIT(&sum);
373
374 LMMC_REAL_MUL(&alpha_sq, &alpha, &alpha);
375 LMMC_REAL_ADD(&sum, &alpha_sq, &sigma);
376 LMMC_REAL_SQRT(&norm, &sum);
377
378 if (LMMC_REAL_CMP(&alpha, &zero) <= 0) {
379 LMMC_REAL_SET(&beta, &norm);
380 } else {
381 LMMC_REAL_NEG(&beta, &norm);
382 }
383
384 LMMC_REAL_SUB(&v0, &alpha, &beta);
385 LMMC_REAL_SET(&a->data[k * a->stride + k], &beta);
386
387 for (i = k + 1; i < m; ++i) {
388 LMMC_REAL_DIV(&a->data[i * a->stride + k], &a->data[i * a->stride + k], &v0);
389 }
390
391 LMMC_REAL_SUB(&tau[k], &beta, &alpha);
392 LMMC_REAL_DIV(&tau[k], &tau[k], &beta);
393
394 lmmc_qr_update_trailing(a, tau, k);
395
396 LMMC_REAL_CLEAR(&sum);
397 LMMC_REAL_CLEAR(&alpha_sq);
398 LMMC_REAL_CLEAR(&v0);
399 LMMC_REAL_CLEAR(&beta);
400 LMMC_REAL_CLEAR(&norm);
401}
402
404 size_t m = 0;
405 size_t n = 0;
406 size_t k = 0;
407
408 if (a == NULL || tau == NULL || a->data == NULL) {
410 }
411
412 m = a->rows;
413 n = a->cols;
414 if (m == 0 || n == 0) {
416 }
417 if (tau_size < (m < n ? m : n)) {
419 }
420
421 for (k = 0; k < (m < n ? m : n); ++k) {
422 size_t i = 0;
423 lmmc_real_t sigma;
424 lmmc_real_t alpha;
425 lmmc_real_t zero;
426
427 LMMC_REAL_INIT(&sigma);
428 LMMC_REAL_SET_D(&sigma, 0.0);
429 LMMC_REAL_INIT(&alpha);
430 LMMC_REAL_SET(&alpha, &a->data[k * a->stride + k]);
431
432 for (i = k + 1; i < m; ++i) {
433 lmmc_real_t v;
434 lmmc_real_t v_sq;
435 LMMC_REAL_INIT(&v);
436 LMMC_REAL_SET(&v, &a->data[i * a->stride + k]);
437 LMMC_REAL_INIT(&v_sq);
438 LMMC_REAL_MUL(&v_sq, &v, &v);
439 LMMC_REAL_ADD(&sigma, &sigma, &v_sq);
440 LMMC_REAL_CLEAR(&v_sq);
441 LMMC_REAL_CLEAR(&v);
442 }
443
444 LMMC_REAL_INIT(&zero);
445 LMMC_REAL_SET_D(&zero, 0.0);
446 if (LMMC_REAL_CMP(&sigma, &zero) == 0) {
447 LMMC_REAL_SET(&tau[k], &zero);
448 LMMC_REAL_CLEAR(&zero);
449 LMMC_REAL_CLEAR(&alpha);
450 LMMC_REAL_CLEAR(&sigma);
451 continue;
452 }
453
454 lmmc_qr_reflector(a, tau, k, alpha, sigma);
455 LMMC_REAL_CLEAR(&zero);
456 LMMC_REAL_CLEAR(&alpha);
457 LMMC_REAL_CLEAR(&sigma);
458 }
459
460 return LMMC_STATUS_OK;
461}
462
463static lmmc_status_t lmmc_qr_apply_transpose(const lmmc_mat_t* qr,
464 const lmmc_real_t* tau, lmmc_real_t* y) {
465 size_t m = qr->rows;
466 size_t n = qr->cols;
467 size_t k;
468 for (k = 0; k < m; ++k) {
469 if (!LMMC_REAL_IS_FINITE(&y[k])) {
471 }
472 }
473 for (k = 0; k < n; ++k) {
474 if (!LMMC_REAL_IS_FINITE(&tau[k])) {
476 }
477 if (tau[k] == 0.0) {
478 continue;
479 }
480 size_t i = 0;
481 lmmc_real_t dot;
482 LMMC_REAL_INIT(&dot);
483 LMMC_REAL_SET(&dot, &y[k]);
484 for (i = k + 1; i < m; ++i) {
485 lmmc_real_t tmp;
486 LMMC_REAL_INIT(&tmp);
487 LMMC_REAL_MUL(&tmp, &qr->data[i * qr->stride + k], &y[i]);
488 LMMC_REAL_ADD(&dot, &dot, &tmp);
489 if (!LMMC_REAL_IS_FINITE(&tmp) || !LMMC_REAL_IS_FINITE(&dot)) {
490 LMMC_REAL_CLEAR(&tmp);
491 LMMC_REAL_CLEAR(&dot);
493 }
494 LMMC_REAL_CLEAR(&tmp);
495 }
496 LMMC_REAL_MUL(&dot, &dot, &tau[k]);
497 LMMC_REAL_SUB(&y[k], &y[k], &dot);
498 if (!LMMC_REAL_IS_FINITE(&dot) || !LMMC_REAL_IS_FINITE(&y[k])) {
499 LMMC_REAL_CLEAR(&dot);
501 }
502 for (i = k + 1; i < m; ++i) {
503 lmmc_real_t tmp;
504 LMMC_REAL_INIT(&tmp);
505 LMMC_REAL_MUL(&tmp, &qr->data[i * qr->stride + k], &dot);
506 LMMC_REAL_SUB(&y[i], &y[i], &tmp);
507 if (!LMMC_REAL_IS_FINITE(&tmp) || !LMMC_REAL_IS_FINITE(&y[i])) {
508 LMMC_REAL_CLEAR(&tmp);
509 LMMC_REAL_CLEAR(&dot);
511 }
512 LMMC_REAL_CLEAR(&tmp);
513 }
514 LMMC_REAL_CLEAR(&dot);
515 }
516 return LMMC_STATUS_OK;
517}
518
519static lmmc_status_t lmmc_qr_back_substitute(const lmmc_mat_t* qr,
520 const lmmc_real_t* y, lmmc_vec_t* x) {
521 size_t n = qr->cols;
522 size_t k;
523
524 for (k = n; k-- > 0;) {
525 size_t j = 0;
526 lmmc_real_t rhs;
527
528 LMMC_REAL_INIT(&rhs);
529 LMMC_REAL_SET(&rhs, &y[k]);
530 for (j = k + 1; j < n; ++j) {
531 lmmc_real_t tmp;
532 LMMC_REAL_INIT(&tmp);
533 LMMC_REAL_MUL(&tmp, &qr->data[k * qr->stride + j], &x->data[j]);
534 LMMC_REAL_SUB(&rhs, &rhs, &tmp);
535 if (!LMMC_REAL_IS_FINITE(&tmp) || !LMMC_REAL_IS_FINITE(&rhs)) {
536 LMMC_REAL_CLEAR(&tmp);
537 LMMC_REAL_CLEAR(&rhs);
539 }
540 LMMC_REAL_CLEAR(&tmp);
541 }
542
543 if (!LMMC_REAL_IS_FINITE(&qr->data[k * qr->stride + k])) {
544 LMMC_REAL_CLEAR(&rhs);
546 }
547 if (qr->data[k * qr->stride + k] == 0.0) {
548 LMMC_REAL_CLEAR(&rhs);
550 }
551
552 LMMC_REAL_DIV(&x->data[k], &rhs, &qr->data[k * qr->stride + k]);
553 LMMC_REAL_CLEAR(&rhs);
554 if (!LMMC_REAL_IS_FINITE(&x->data[k])) {
556 }
557 }
558
559 return LMMC_STATUS_OK;
560}
561
563 size_t m = 0;
564 size_t n = 0;
565 size_t k = 0;
566 lmmc_real_t* y = NULL;
567
568 if (qr == NULL || tau == NULL || b == NULL || x == NULL || qr->data == NULL || b->data == NULL || x->data == NULL) {
570 }
571 m = qr->rows;
572 n = qr->cols;
573 if (m < n || b->size != m || x->size != n) {
575 }
576
578 if (y == NULL) {
580 }
581
582 for (k = 0; k < m; ++k) {
583 LMMC_REAL_INIT(&y[k]);
584 LMMC_REAL_SET(&y[k], &b->data[k]);
585 }
586 lmmc_status_t status = lmmc_qr_apply_transpose(qr, tau, y);
587 if (status == LMMC_STATUS_OK) {
588 status = lmmc_qr_back_substitute(qr, y, x);
589 }
590 for (k = 0; k < m; ++k) {
591 LMMC_REAL_CLEAR(&y[k]);
592 }
594 return status;
595}
LMMC binary real type and arithmetic spelling.
#define LMMC_REAL_CLEAR(x)
释放一个 lmmc_real_t 变量(POD 类型为空操作)。
#define LMMC_REAL_INIT(x)
初始化一个 lmmc_real_t 变量(POD 类型为空操作)。
#define LMMC_REAL_ADD(res, a, b)
计算 *res = *a + *b 。
#define LMMC_REAL_DIV(res, a, b)
计算 *res = *a / *b 。
#define LMMC_REAL_SUB(res, a, b)
计算 *res = *a - *b 。
double lmmc_real_t
Public and internal LMMC real type.
#define LMMC_REAL_SET(dst, src)
将一个 lmmc_real_t 赋值到另一个:*dst = *src 。
#define LMMC_REAL_MUL(res, a, b)
计算 *res = *a * *b 。
#define LMMC_REAL_SQRT(res, a)
计算平方根,*res = sqrt(*a) 。
#define LMMC_REAL_CMP(a, b)
比较 *a 与 *b ,返回 -1/0/1 。
#define LMMC_REAL_NEG(res, a)
取相反数,*res = -*a 。
#define LMMC_REAL_SET_D(dst, dbl)
将一个 double 字面量赋值到 lmmc_real_t 。
#define LMMC_REAL_IS_FINITE(x)
判断 *x 是否为有限数。
lmmc_real_t * data
lmmc_real_t * data
行优先存储的稠密矩阵。
一维稠密向量。
稠密矩阵直接分解接口(LU、Cholesky、QR)。
lmmc_status_t lmmc_qr_solve(const lmmc_mat_t *qr, const lmmc_real_t *tau, const lmmc_vec_t *b, lmmc_vec_t *x)
利用 QR 分解结果求解线性系统或最小二乘问题。
lmmc_status_t lmmc_qr_decompose_inplace(lmmc_mat_t *a, lmmc_real_t *tau, size_t tau_size)
就地 Householder QR 分解。
lmmc_status_t lmmc_lu_solve(const lmmc_mat_t *lu, const size_t *pivots, const lmmc_vec_t *b, lmmc_vec_t *x)
利用 LU 分解结果求解线性系统 A*x = b。
lmmc_status_t lmmc_cholesky_decompose_inplace(lmmc_mat_t *a)
就地 Cholesky 分解:A = L*L^T,要求 A 对称正定。
lmmc_status_t lmmc_lu_decompose_inplace(lmmc_mat_t *a, size_t *pivots, size_t *out_swap_count)
就地 LU 分解(带部分主元选取):P*A = L*U。
lmmc_status_t lmmc_cholesky_solve(const lmmc_mat_t *l, const lmmc_vec_t *b, lmmc_vec_t *x)
利用 Cholesky 因子求解 A*x = b(A = L*L^T)。
void * lmmc_memory_alloc_array(size_t count, size_t element_size)
void lmmc_memory_free(void *pointer)
Private recoverable allocator for persistent LMMC ownership.
数值标量、特殊函数和 FFT 公共接口。
#define LMMC_DEFAULT_REL_TOL
库默认的相对容差.
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_OK
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_NOT_POSITIVE_DEFINITE
@ LMMC_STATUS_DIMENSION_MISMATCH
@ LMMC_STATUS_ALLOCATION_FAILED
@ LMMC_STATUS_SINGULAR_MATRIX
@ LMMC_STATUS_INVALID_ARGUMENT