LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
stdlib_linalg_structural.c
浏览该文件的文档.
1#include "lmmc/stdlib.h"
2
3#include <math.h>
4#include <string.h>
5
6#include "lmmc/dense.h"
7#include "lmmc/eigen.h"
9#include "memory_bridge.h"
10
11#include "stdlib_internal.h"
12
14 size_t* out_rows,
15 size_t* out_cols)
16{
17 if (!lmmc_mat_descriptor_is_valid(a) || !out_rows || !out_cols) {
19 }
20 *out_rows = a->rows;
21 *out_cols = a->cols;
22 return LMMC_STATUS_OK;
23}
24
26 lmmc_vec_t* out)
27{
28 lmmc_status_t status;
29 lmmc_vec_t result = {0};
30 if (!lmmc_std_vec_is_empty(out) || !lmmc_mat_descriptor_is_valid(a)) {
32 }
33 status = lmmc_vec_create(2, &result);
34 if (status != LMMC_STATUS_OK) { return status; }
35 result.data[0] = (lmmc_real_t)a->rows;
36 result.data[1] = (lmmc_real_t)a->cols;
37 *out = result;
38 return LMMC_STATUS_OK;
39}
40
42{
43 lmmc_status_t status;
44 lmmc_mat_t result = {0};
45 if (!lmmc_std_mat_is_empty(out) || n == 0) { return LMMC_STATUS_INVALID_ARGUMENT; }
46 status = lmmc_mat_identity(n, &result);
47 if (status != LMMC_STATUS_OK) { return status; }
48 status = lmmc_std_require_finite_mat(&result);
49 if (status != LMMC_STATUS_OK) {
50 lmmc_mat_destroy(&result);
51 } else {
52 *out = result;
53 }
54 return status;
55}
56
58 lmmc_mat_t* out)
59{
60 lmmc_status_t status;
61 lmmc_mat_t result = {0};
62 if (!lmmc_std_mat_is_empty(out)) { return LMMC_STATUS_INVALID_ARGUMENT; }
63 status = lmmc_std_require_finite_vec(diagonal);
64 if (status != LMMC_STATUS_OK) { return status; }
65 status = lmmc_std_vec_to_diag(diagonal, diagonal->size, diagonal->size, &result);
66 if (status == LMMC_STATUS_OK) { *out = result; }
67 else { lmmc_mat_destroy(&result); }
68 return status;
69}
70
72 const lmmc_vec_t* b,
73 lmmc_real_t* out)
74{
75 lmmc_real_t value;
76 lmmc_status_t status;
77 if (!out) { return LMMC_STATUS_INVALID_ARGUMENT; }
78 status = lmmc_std_require_finite_vec(a);
79 if (status != LMMC_STATUS_OK) { return status; }
80 status = lmmc_std_require_finite_vec(b);
81 if (status != LMMC_STATUS_OK) { return status; }
82 if (a->size != b->size) { return LMMC_STATUS_DIMENSION_MISMATCH; }
83 status = lmmc_vec_dot(a, b, &value);
84 if (status != LMMC_STATUS_OK) { return status; }
85 return lmmc_std_store_finite_real(value, out);
86}
87
89 const lmmc_vec_t* b,
90 lmmc_vec_t* out)
91{
92 lmmc_status_t status;
93 lmmc_vec_t result = {0};
94 if (!lmmc_std_vec_is_empty(out)) { return LMMC_STATUS_INVALID_ARGUMENT; }
95 status = lmmc_std_require_finite_vec(a);
96 if (status != LMMC_STATUS_OK) { return status; }
97 status = lmmc_std_require_finite_vec(b);
98 if (status != LMMC_STATUS_OK) { return status; }
99 if (a->size != 3 || b->size != 3) { return LMMC_STATUS_DIMENSION_MISMATCH; }
100 status = lmmc_vec_create(3, &result);
101 if (status != LMMC_STATUS_OK) { return status; }
102 result.data[0] = a->data[1] * b->data[2] - a->data[2] * b->data[1];
103 result.data[1] = a->data[2] * b->data[0] - a->data[0] * b->data[2];
104 result.data[2] = a->data[0] * b->data[1] - a->data[1] * b->data[0];
105 status = lmmc_std_require_finite_vec(&result);
106 if (status != LMMC_STATUS_OK) {
107 lmmc_vec_destroy(&result);
108 } else {
109 *out = result;
110 }
111 return status;
112}
113
115 lmmc_real_t* out)
116{
117 lmmc_real_t value;
118 lmmc_status_t status;
119 if (!out) { return LMMC_STATUS_INVALID_ARGUMENT; }
120 status = lmmc_std_require_finite_vec(x);
121 if (status != LMMC_STATUS_OK) { return status; }
122 status = lmmc_vec_norm2(x, &value);
123 if (status != LMMC_STATUS_OK) { return status; }
124 return lmmc_std_store_finite_real(value, out);
125}
126
128{
129 if (!vec) return;
130 if (vec->owns_data && vec->data) {
132 }
133 vec->size = 0;
134 vec->data = NULL;
135 vec->owns_data = 0;
136}
137
139{
140 if (!mat) return;
141 if (mat->owns_data && mat->data) {
143 }
144 mat->rows = 0;
145 mat->cols = 0;
146 mat->stride = 0;
147 mat->data = NULL;
148 mat->owns_data = 0;
149}
150
152 const lmmc_mat_t* b,
153 lmmc_mat_t* out)
154{
155 lmmc_status_t status;
156 lmmc_mat_t result = {0};
157 if (!lmmc_std_mat_is_empty(out)) { return LMMC_STATUS_INVALID_ARGUMENT; }
158 status = lmmc_std_require_finite_mat(a);
159 if (status != LMMC_STATUS_OK) { return status; }
160 status = lmmc_std_require_finite_mat(b);
161 if (status != LMMC_STATUS_OK) { return status; }
162 if (a->cols != b->rows) { return LMMC_STATUS_DIMENSION_MISMATCH; }
163 status = lmmc_mat_create(a->rows, b->cols, &result);
164 if (status != LMMC_STATUS_OK) { return status; }
165 status = lmmc_mat_mul(a, b, &result);
166 if (status == LMMC_STATUS_OK) {
167 status = lmmc_std_require_finite_mat(&result);
168 }
169 if (status != LMMC_STATUS_OK) {
170 lmmc_mat_destroy(&result);
171 } else {
172 *out = result;
173 }
174 return status;
175}
176
178 const lmmc_vec_t* x,
179 lmmc_vec_t* out)
180{
181 lmmc_status_t status;
182 lmmc_vec_t result = {0};
183 if (!lmmc_std_vec_is_empty(out)) { return LMMC_STATUS_INVALID_ARGUMENT; }
184 status = lmmc_std_require_finite_mat(a);
185 if (status != LMMC_STATUS_OK) { return status; }
186 status = lmmc_std_require_finite_vec(x);
187 if (status != LMMC_STATUS_OK) { return status; }
188 if (a->cols != x->size) { return LMMC_STATUS_DIMENSION_MISMATCH; }
189 status = lmmc_vec_create(a->rows, &result);
190 if (status != LMMC_STATUS_OK) { return status; }
191 status = lmmc_mat_vec_mul(a, x, &result);
192 if (status == LMMC_STATUS_OK) {
193 status = lmmc_std_require_finite_vec(&result);
194 }
195 if (status != LMMC_STATUS_OK) {
196 lmmc_vec_destroy(&result);
197 } else {
198 *out = result;
199 }
200 return status;
201}
202
204 lmmc_mat_t* out)
205{
206 lmmc_status_t status;
207 lmmc_mat_t result = {0};
208 if (!lmmc_std_mat_is_empty(out)) { return LMMC_STATUS_INVALID_ARGUMENT; }
209 status = lmmc_std_require_finite_mat(a);
210 if (status != LMMC_STATUS_OK) { return status; }
211 status = lmmc_mat_create(a->cols, a->rows, &result);
212 if (status != LMMC_STATUS_OK) { return status; }
213 status = lmmc_mat_transpose_to(a, &result);
214 if (status == LMMC_STATUS_OK) {
215 status = lmmc_std_require_finite_mat(&result);
216 }
217 if (status != LMMC_STATUS_OK) {
218 lmmc_mat_destroy(&result);
219 } else {
220 *out = result;
221 }
222 return status;
223}
224
230
232 lmmc_real_t* out)
233{
234 lmmc_real_t value;
235 lmmc_status_t status;
236 if (!out) { return LMMC_STATUS_INVALID_ARGUMENT; }
237 status = lmmc_std_require_finite_mat(a);
238 if (status != LMMC_STATUS_OK) { return status; }
239 status = lmmc_mat_det(a, &value);
240 if (status != LMMC_STATUS_OK) { return status; }
241 return lmmc_std_store_finite_real(value, out);
242}
243
245 lmmc_mat_t* out)
246{
247 lmmc_status_t status;
248 lmmc_mat_t result = {0};
249 if (!lmmc_std_mat_is_empty(out)) { return LMMC_STATUS_INVALID_ARGUMENT; }
250 status = lmmc_std_require_finite_mat(a);
251 if (status != LMMC_STATUS_OK) { return status; }
252 if (a->rows != a->cols) { return LMMC_STATUS_INVALID_ARGUMENT; }
253 status = lmmc_mat_create(a->rows, a->cols, &result);
254 if (status != LMMC_STATUS_OK) { return status; }
255 status = lmmc_mat_inv(a, &result);
256 if (status == LMMC_STATUS_OK) {
257 status = lmmc_std_require_finite_mat(&result);
258 }
259 if (status != LMMC_STATUS_OK) {
260 lmmc_mat_destroy(&result);
261 } else {
262 *out = result;
263 }
264 return status;
265}
266
267static size_t lmmc_std_echelon_rank(
268 lmmc_real_t* work, size_t rows, size_t cols, lmmc_real_t tol)
269{
270 size_t rank, col;
271 rank = 0;
272 for (col = 0; col < cols && rank < rows; ++col) {
273 size_t pivot = rank;
274 lmmc_real_t pivot_abs =
275 (lmmc_real_t)fabs((double)work[pivot * cols + col]);
276 for (size_t row = rank + 1; row < rows; ++row) {
277 lmmc_real_t candidate =
278 (lmmc_real_t)fabs((double)work[row * cols + col]);
279 if (candidate > pivot_abs) {
280 pivot = row;
281 pivot_abs = candidate;
282 }
283 }
284 if (pivot_abs <= tol) { continue; }
285
286 if (pivot != rank) {
287 for (size_t j = col; j < cols; ++j) {
288 lmmc_real_t tmp = work[rank * cols + j];
289 work[rank * cols + j] = work[pivot * cols + j];
290 work[pivot * cols + j] = tmp;
291 }
292 }
293
294 for (size_t row = rank + 1; row < rows; ++row) {
295 lmmc_real_t factor = work[row * cols + col] /
296 work[rank * cols + col];
297 work[row * cols + col] = (lmmc_real_t)0;
298 for (size_t j = col + 1; j < cols; ++j) {
299 work[row * cols + j] -= factor * work[rank * cols + j];
300 }
301 }
302 ++rank;
303 }
304
305 return rank;
306}
307
309 size_t* out_rank)
310{
311 size_t rows, cols, count, rank;
312 lmmc_real_t* work;
313 lmmc_real_t scale = (lmmc_real_t)0;
314 lmmc_real_t tol;
315
316 if (!out_rank) { return LMMC_STATUS_INVALID_ARGUMENT; }
317 lmmc_status_t input_status = lmmc_std_require_finite_mat(a);
318 if (input_status != LMMC_STATUS_OK) { return input_status; }
319 if (a->rows != 0 && a->cols > ((size_t)-1) / a->rows) {
321 }
322
323 rows = a->rows;
324 cols = a->cols;
325 count = rows * cols;
326 work = (lmmc_real_t*)lmmc_memory_alloc_array(count, sizeof(lmmc_real_t));
327 if (!work) { return LMMC_STATUS_ALLOCATION_FAILED; }
328
329 for (size_t i = 0; i < rows; ++i) {
330 for (size_t j = 0; j < cols; ++j) {
331 lmmc_real_t value = a->data[i * a->stride + j];
332 work[i * cols + j] = value;
333 if (fabs((double)value) > fabs((double)scale)) {
334 scale = value;
335 }
336 }
337 }
338
339 if (scale == (lmmc_real_t)0) {
340 lmmc_memory_free(work);
341 *out_rank = 0;
342 return LMMC_STATUS_OK;
343 }
344 tol = (lmmc_real_t)(1e-12 * fabs((double)scale) *
345 (double)(rows > cols ? rows : cols));
346
347 rank = lmmc_std_echelon_rank(work, rows, cols, tol);
348
349 lmmc_memory_free(work);
350 *out_rank = rank;
351 return LMMC_STATUS_OK;
352}
353
355 lmmc_real_t* out)
356{
357 lmmc_real_t value;
358 lmmc_status_t status;
359 if (!out) { return LMMC_STATUS_INVALID_ARGUMENT; }
360 status = lmmc_std_require_finite_mat(a);
361 if (status != LMMC_STATUS_OK) { return status; }
362 status = lmmc_mat_trace(a, &value);
363 if (status != LMMC_STATUS_OK) { return status; }
364 return lmmc_std_store_finite_real(value, out);
365}
366
367static lmmc_status_t lmmc_std_solve_columns(
368 const lmmc_mat_t* lu, const size_t* pivots, const lmmc_mat_t* b,
369 lmmc_vec_t* rhs, lmmc_vec_t* sol, lmmc_mat_t* out)
370{
371 lmmc_status_t status;
372 for (size_t col = 0; col < b->cols; ++col) {
373 for (size_t row = 0; row < b->rows; ++row) {
374 rhs->data[row] = b->data[row * b->stride + col];
375 }
376 status = lmmc_lu_solve(lu, pivots, rhs, sol);
377 if (status != LMMC_STATUS_OK) {
378 return status;
379 }
380 for (size_t row = 0; row < lu->cols; ++row) {
381 out->data[row * out->stride + col] = sol->data[row];
382 }
383 }
384 return LMMC_STATUS_OK;
385}
386
388 const lmmc_mat_t* b,
389 lmmc_mat_t* out)
390{
391 lmmc_mat_t lu = {0};
392 lmmc_mat_t result = {0};
393 lmmc_vec_t rhs = {0};
394 lmmc_vec_t sol = {0};
395 size_t* pivots = NULL;
396 lmmc_status_t status;
397
398 if (!lmmc_std_mat_is_empty(out)) { return LMMC_STATUS_INVALID_ARGUMENT; }
399 status = lmmc_std_require_finite_mat(a);
400 if (status != LMMC_STATUS_OK) { return status; }
401 status = lmmc_std_require_finite_mat(b);
402 if (status != LMMC_STATUS_OK) { return status; }
403 if (a->rows != a->cols || b->rows != a->rows) {
405 }
406
407 status = lmmc_mat_create(a->rows, a->cols, &lu);
408 if (status != LMMC_STATUS_OK) { return status; }
409 status = lmmc_mat_copy(a, &lu);
410 if (status != LMMC_STATUS_OK) {
411 goto cleanup;
412 }
413
414 pivots = (size_t*)lmmc_memory_alloc_array(a->rows, sizeof(size_t));
415 if (!pivots) {
417 goto cleanup;
418 }
419 status = lmmc_lu_decompose_inplace(&lu, pivots, NULL);
420 if (status != LMMC_STATUS_OK) {
421 goto cleanup;
422 }
423
424 status = lmmc_mat_create(a->cols, b->cols, &result);
425 if (status != LMMC_STATUS_OK) {
426 goto cleanup;
427 }
428 status = lmmc_vec_create(b->rows, &rhs);
429 if (status != LMMC_STATUS_OK) {
430 goto cleanup;
431 }
432 status = lmmc_vec_create(a->cols, &sol);
433 if (status != LMMC_STATUS_OK) {
434 goto cleanup;
435 }
436
437 status = lmmc_std_solve_columns(&lu, pivots, b, &rhs, &sol, &result);
438 if (status != LMMC_STATUS_OK) {
439 goto cleanup;
440 }
441
442cleanup:
443 lmmc_vec_destroy(&sol);
444 lmmc_vec_destroy(&rhs);
445 if (pivots) {
446 lmmc_memory_free(pivots);
447 }
448 lmmc_mat_destroy(&lu);
449 if (status == LMMC_STATUS_OK) { *out = result; }
450 else { lmmc_mat_destroy(&result); }
451 return status;
452}
453
455 const lmmc_mat_t* a,
456 lmmc_mat_t* out)
457{
458 lmmc_mat_t at = {0};
459 lmmc_mat_t bt = {0};
460 lmmc_mat_t xt = {0};
461 lmmc_mat_t result = {0};
462 lmmc_status_t status;
463
464 if (!lmmc_std_mat_is_empty(out)) { return LMMC_STATUS_INVALID_ARGUMENT; }
465 status = lmmc_std_require_finite_mat(a);
466 if (status != LMMC_STATUS_OK) { return status; }
467 status = lmmc_std_require_finite_mat(b);
468 if (status != LMMC_STATUS_OK) { return status; }
469 if (a->rows != a->cols || b->cols != a->rows) {
471 }
472
473 status = lmmc_std_linalg_transpose(a, &at);
474 if (status != LMMC_STATUS_OK) {
475 goto cleanup;
476 }
477 status = lmmc_std_linalg_transpose(b, &bt);
478 if (status != LMMC_STATUS_OK) {
479 goto cleanup;
480 }
481 status = lmmc_std_linalg_solve_left(&at, &bt, &xt);
482 if (status != LMMC_STATUS_OK) {
483 goto cleanup;
484 }
485 status = lmmc_std_linalg_transpose(&xt, &result);
486
487cleanup:
488 lmmc_mat_destroy(&xt);
489 lmmc_mat_destroy(&bt);
490 lmmc_mat_destroy(&at);
491 if (status == LMMC_STATUS_OK) { *out = result; }
492 else { lmmc_mat_destroy(&result); }
493 return status;
494}
495
498{
499 lmmc_status_t status;
500 lmmc_eigen_gen_full_result_t result = {0};
501 if (!out || !lmmc_std_vec_is_empty(&out->real_parts) ||
502 !lmmc_std_vec_is_empty(&out->imag_parts) ||
503 !lmmc_std_mat_is_empty(&out->vectors_real) ||
504 !lmmc_std_mat_is_empty(&out->vectors_imag)) {
506 }
507 status = lmmc_std_require_finite_mat(a);
508 if (status != LMMC_STATUS_OK) { return status; }
509 if (a->rows != a->cols) { return LMMC_STATUS_INVALID_ARGUMENT; }
510 status = lmmc_eigen_general_full(a, &result);
511 if (status == LMMC_STATUS_OK) {
512 status = lmmc_std_require_finite_eig_result(&result);
513 }
514 if (status != LMMC_STATUS_OK) {
516 return status;
517 }
518 *out = result;
519 return LMMC_STATUS_OK;
520}
521
524{
525 lmmc_status_t status;
526 lmmc_svd_result_t result = {0};
527 if (!out || !lmmc_std_mat_is_empty(&out->U) ||
528 !lmmc_std_vec_is_empty(&out->sigma) ||
529 !lmmc_std_mat_is_empty(&out->Vt)) {
531 }
532 status = lmmc_std_require_finite_mat(a);
533 if (status != LMMC_STATUS_OK) { return status; }
534 status = lmmc_svd(a, &result);
535 if (status == LMMC_STATUS_OK) {
536 status = lmmc_std_require_finite_svd_result(&result);
537 }
538 if (status != LMMC_STATUS_OK) {
540 return status;
541 }
542 *out = result;
543 return LMMC_STATUS_OK;
544}
545
548{
549 lmmc_status_t status;
551 lmmc_std_eig_table_t result = {0};
552 if (!out || !lmmc_std_mat_is_empty(&out->values_real) ||
553 !lmmc_std_mat_is_empty(&out->values_imag) ||
554 !lmmc_std_mat_is_empty(&out->vectors_real) ||
555 !lmmc_std_mat_is_empty(&out->vectors_imag)) {
557 }
558 status = lmmc_std_linalg_eig(a, &raw);
559 if (status != LMMC_STATUS_OK) { return status; }
560
561 result.values_real = (lmmc_mat_t){
562 raw.real_parts.size, 1, 1, raw.real_parts.data, raw.real_parts.owns_data};
563 raw.real_parts = (lmmc_vec_t){0};
564 result.values_imag = (lmmc_mat_t){
565 raw.imag_parts.size, 1, 1, raw.imag_parts.data, raw.imag_parts.owns_data};
566 raw.imag_parts = (lmmc_vec_t){0};
567 result.vectors_real = raw.vectors_real;
568 raw.vectors_real = (lmmc_mat_t){0};
569 result.vectors_imag = raw.vectors_imag;
570 raw.vectors_imag = (lmmc_mat_t){0};
572 *out = result;
573 return LMMC_STATUS_OK;
574}
575
577 const char* key)
578{
579 if (!table || !key) { return NULL; }
580 if (strcmp(key, "values_real") == 0) { return &table->values_real; }
581 if (strcmp(key, "values_imag") == 0) { return &table->values_imag; }
582 if (strcmp(key, "vectors_real") == 0) { return &table->vectors_real; }
583 if (strcmp(key, "vectors_imag") == 0) { return &table->vectors_imag; }
584 return NULL;
585}
586
588{
589 return table ? 4u : 0u;
590}
591
593 size_t index)
594{
595 static const char* keys[] = {
596 "values_real",
597 "values_imag",
598 "vectors_real",
599 "vectors_imag",
600 };
601 if (!table || index >= sizeof(keys) / sizeof(keys[0])) { return NULL; }
602 return keys[index];
603}
604
606{
607 if (!table) return;
612}
613
616{
617 lmmc_status_t status;
618 lmmc_svd_result_t raw = {0};
619 lmmc_std_svd_table_t result = {0};
620 if (!out || !lmmc_std_mat_is_empty(&out->U) ||
621 !lmmc_std_mat_is_empty(&out->S) ||
622 !lmmc_std_mat_is_empty(&out->Vt)) {
624 }
625 status = lmmc_std_linalg_svd(a, &raw);
626 if (status != LMMC_STATUS_OK) { return status; }
627
628 status = lmmc_std_vec_to_diag(&raw.sigma, raw.U.cols, raw.Vt.rows, &result.S);
629 if (status == LMMC_STATUS_OK) {
630 result.U = raw.U;
631 raw.U = (lmmc_mat_t){0};
632 result.Vt = raw.Vt;
633 raw.Vt = (lmmc_mat_t){0};
634 *out = result;
635 } else {
637 }
639 return status;
640}
641
643 const char* key)
644{
645 if (!table || !key) { return NULL; }
646 if (strcmp(key, "U") == 0) { return &table->U; }
647 if (strcmp(key, "S") == 0) { return &table->S; }
648 if (strcmp(key, "Vt") == 0) { return &table->Vt; }
649 return NULL;
650}
651
653{
654 return table ? 3u : 0u;
655}
656
658 size_t index)
659{
660 static const char* keys[] = {"U", "S", "Vt"};
661 if (!table || index >= sizeof(keys) / sizeof(keys[0])) { return NULL; }
662 return keys[index];
663}
664
666{
667 if (!table) return;
668 lmmc_mat_destroy(&table->U);
669 lmmc_mat_destroy(&table->S);
670 lmmc_mat_destroy(&table->Vt);
671}
double lmmc_real_t
Public and internal LMMC real type.
lmmc_status_t lmmc_vec_dot(const lmmc_vec_t *a, const lmmc_vec_t *b, lmmc_real_t *out_dot)
计算两个等长向量的内积: 。
lmmc_status_t lmmc_mat_vec_mul(const lmmc_mat_t *a, const lmmc_vec_t *x, lmmc_vec_t *y)
计算矩阵与向量的乘积:y = A * x。
lmmc_status_t lmmc_mat_mul(const lmmc_mat_t *a, const lmmc_mat_t *b, lmmc_mat_t *c)
计算矩阵乘积:c = a * b。
lmmc_status_t lmmc_vec_norm2(const lmmc_vec_t *x, lmmc_real_t *out_norm)
计算向量的欧几里得(L2)范数: 。 采用缩放平方和累加;最终结果超出 binary64 范围时可为无穷。
lmmc_status_t lmmc_mat_trace(const lmmc_mat_t *a, lmmc_real_t *out_trace)
计算方阵的迹: 。
lmmc_status_t lmmc_mat_det(const lmmc_mat_t *a, lmmc_real_t *out_det)
通过 LU 分解计算方阵行列式。
lmmc_status_t lmmc_mat_inv(const lmmc_mat_t *A, lmmc_mat_t *A_inv)
计算方阵的逆矩阵。
lmmc_status_t lmmc_mat_copy(const lmmc_mat_t *src, lmmc_mat_t *dst)
逐元素复制矩阵内容:dst = src。
lmmc_status_t lmmc_mat_create(size_t rows, size_t cols, lmmc_mat_t *out_mat)
创建 rows x cols 的零矩阵。
lmmc_status_t lmmc_mat_transpose_to(const lmmc_mat_t *src, lmmc_mat_t *dst)
计算矩阵转置:dst = src^T。
lmmc_status_t lmmc_vec_create(size_t size, lmmc_vec_t *out_vec)
创建长度为 size 的零向量。
lmmc_status_t lmmc_mat_identity(size_t n, lmmc_mat_t *out_mat)
创建 nxn 单位矩阵,对角线为 1,其余元素为 0。
void lmmc_mat_destroy(lmmc_mat_t *mat)
销毁矩阵,释放其拥有的缓冲区并清零结构体字段。
void lmmc_vec_destroy(lmmc_vec_t *vec)
销毁向量,释放其拥有的缓冲区并清零字段。
lmmc_real_t * data
lmmc_real_t * data
行优先存储的稠密矩阵。
一维稠密向量。
特征值 / 奇异值分解,伪逆与条件数接口.
lmmc_status_t lmmc_svd(const lmmc_mat_t *a, lmmc_svd_result_t *out_result)
计算奇异值分解:A = U * Σ * V^T.
lmmc_vec_t sigma
定义 eigen.h:54
lmmc_status_t lmmc_eigen_general_full(const lmmc_mat_t *a, lmmc_eigen_gen_full_result_t *out_result)
计算一般实矩阵的特征值与特征向量.
void lmmc_svd_result_destroy(lmmc_svd_result_t *result)
释放 lmmc_svd 输出结果.
void lmmc_eigen_gen_full_result_destroy(lmmc_eigen_gen_full_result_t *result)
释放 lmmc_eigen_general_full 输出结果.
一般实矩阵完整特征分解结果(特征值 + 特征向量).
定义 eigen.h:42
奇异值分解结果: .
定义 eigen.h:52
稠密矩阵直接分解接口(LU、Cholesky、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_lu_decompose_inplace(lmmc_mat_t *a, size_t *pivots, size_t *out_swap_count)
就地 LU 分解(带部分主元选取):P*A = L*U。
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.
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_OK
@ LMMC_STATUS_DIMENSION_MISMATCH
@ LMMC_STATUS_ALLOCATION_FAILED
@ LMMC_STATUS_INVALID_ARGUMENT
lmmc_status_t lmmc_std_linalg_norm(const lmmc_vec_t *x, lmmc_real_t *out)
const lmmc_mat_t * lmmc_std_svd_table_get(const lmmc_std_svd_table_t *table, const char *key)
const char * lmmc_std_svd_table_key(const lmmc_std_svd_table_t *table, size_t index)
lmmc_status_t lmmc_std_linalg_svd_table(const lmmc_mat_t *a, lmmc_std_svd_table_t *out)
lmmc_status_t lmmc_std_linalg_eig_table(const lmmc_mat_t *a, lmmc_std_eig_table_t *out)
lmmc_status_t lmmc_std_linalg_inv(const lmmc_mat_t *a, lmmc_mat_t *out)
const char * lmmc_std_eig_table_key(const lmmc_std_eig_table_t *table, size_t index)
lmmc_status_t lmmc_std_linalg_adjoint(const lmmc_mat_t *a, lmmc_mat_t *out)
lmmc_status_t lmmc_std_linalg_matvec(const lmmc_mat_t *a, const lmmc_vec_t *x, lmmc_vec_t *out)
lmmc_status_t lmmc_std_linalg_solve_left(const lmmc_mat_t *a, const lmmc_mat_t *b, lmmc_mat_t *out)
lmmc_status_t lmmc_std_linalg_det(const lmmc_mat_t *a, lmmc_real_t *out)
const lmmc_mat_t * lmmc_std_eig_table_get(const lmmc_std_eig_table_t *table, const char *key)
lmmc_status_t lmmc_std_linalg_dot(const lmmc_vec_t *a, const lmmc_vec_t *b, lmmc_real_t *out)
lmmc_status_t lmmc_std_linalg_shape_vec(const lmmc_mat_t *a, lmmc_vec_t *out)
void lmmc_std_bool_vec_destroy(lmmc_std_bool_vec_t *vec)
lmmc_status_t lmmc_std_linalg_shape(const lmmc_mat_t *a, size_t *out_rows, size_t *out_cols)
lmmc_status_t lmmc_std_linalg_transpose(const lmmc_mat_t *a, lmmc_mat_t *out)
lmmc_status_t lmmc_std_linalg_trace(const lmmc_mat_t *a, lmmc_real_t *out)
lmmc_status_t lmmc_std_linalg_svd(const lmmc_mat_t *a, lmmc_svd_result_t *out)
void lmmc_std_bool_mat_destroy(lmmc_std_bool_mat_t *mat)
lmmc_status_t lmmc_std_linalg_matmul(const lmmc_mat_t *a, const lmmc_mat_t *b, lmmc_mat_t *out)
size_t lmmc_std_eig_table_count(const lmmc_std_eig_table_t *table)
lmmc_status_t lmmc_std_linalg_eig(const lmmc_mat_t *a, lmmc_eigen_gen_full_result_t *out)
void lmmc_std_eig_table_destroy(lmmc_std_eig_table_t *table)
lmmc_status_t lmmc_std_linalg_cross(const lmmc_vec_t *a, const lmmc_vec_t *b, lmmc_vec_t *out)
size_t lmmc_std_svd_table_count(const lmmc_std_svd_table_t *table)
lmmc_status_t lmmc_std_linalg_solve_right(const lmmc_mat_t *b, const lmmc_mat_t *a, lmmc_mat_t *out)
lmmc_status_t lmmc_std_linalg_rank(const lmmc_mat_t *a, size_t *out_rank)
void lmmc_std_svd_table_destroy(lmmc_std_svd_table_t *table)
lmmc_status_t lmmc_std_linalg_eye(size_t n, lmmc_mat_t *out)
lmmc_status_t lmmc_std_linalg_diag(const lmmc_vec_t *diagonal, lmmc_mat_t *out)
std.linalg.eig 使用的 LSR 标准 table<text, matrix> 视图。
std.linalg.svd 使用的 LSR 标准 table<text, matrix> 视图。