17 if (!lmmc_mat_descriptor_is_valid(a) || !out_rows || !out_cols) {
30 if (!lmmc_std_vec_is_empty(out) || !lmmc_mat_descriptor_is_valid(a)) {
48 status = lmmc_std_require_finite_mat(&result);
63 status = lmmc_std_require_finite_vec(diagonal);
65 status = lmmc_std_vec_to_diag(diagonal, diagonal->
size, diagonal->
size, &result);
78 status = lmmc_std_require_finite_vec(a);
80 status = lmmc_std_require_finite_vec(b);
85 return lmmc_std_store_finite_real(value, out);
95 status = lmmc_std_require_finite_vec(a);
97 status = lmmc_std_require_finite_vec(b);
105 status = lmmc_std_require_finite_vec(&result);
120 status = lmmc_std_require_finite_vec(x);
124 return lmmc_std_store_finite_real(value, out);
158 status = lmmc_std_require_finite_mat(a);
160 status = lmmc_std_require_finite_mat(b);
167 status = lmmc_std_require_finite_mat(&result);
184 status = lmmc_std_require_finite_mat(a);
186 status = lmmc_std_require_finite_vec(x);
193 status = lmmc_std_require_finite_vec(&result);
209 status = lmmc_std_require_finite_mat(a);
215 status = lmmc_std_require_finite_mat(&result);
237 status = lmmc_std_require_finite_mat(a);
241 return lmmc_std_store_finite_real(value, out);
250 status = lmmc_std_require_finite_mat(a);
257 status = lmmc_std_require_finite_mat(&result);
267static size_t lmmc_std_echelon_rank(
272 for (col = 0; col < cols && rank < rows; ++col) {
275 (
lmmc_real_t)fabs((
double)work[pivot * cols + col]);
276 for (
size_t row = rank + 1; row < rows; ++row) {
279 if (candidate > pivot_abs) {
281 pivot_abs = candidate;
284 if (pivot_abs <= tol) {
continue; }
287 for (
size_t j = col; j < cols; ++j) {
289 work[rank * cols + j] = work[pivot * cols + j];
290 work[pivot * cols + j] = tmp;
294 for (
size_t row = rank + 1; row < rows; ++row) {
296 work[rank * cols + col];
298 for (
size_t j = col + 1; j < cols; ++j) {
299 work[row * cols + j] -= factor * work[rank * cols + j];
311 size_t rows, cols, count, rank;
329 for (
size_t i = 0; i < rows; ++i) {
330 for (
size_t j = 0; j < cols; ++j) {
332 work[i * cols + j] = value;
333 if (fabs((
double)value) > fabs((
double)scale)) {
345 (
double)(rows > cols ? rows : cols));
347 rank = lmmc_std_echelon_rank(work, rows, cols, tol);
360 status = lmmc_std_require_finite_mat(a);
364 return lmmc_std_store_finite_real(value, out);
372 for (
size_t col = 0; col < b->
cols; ++col) {
373 for (
size_t row = 0; row < b->
rows; ++row) {
380 for (
size_t row = 0; row < lu->
cols; ++row) {
395 size_t* pivots = NULL;
399 status = lmmc_std_require_finite_mat(a);
401 status = lmmc_std_require_finite_mat(b);
437 status = lmmc_std_solve_columns(&lu, pivots, b, &rhs, &sol, &result);
465 status = lmmc_std_require_finite_mat(a);
467 status = lmmc_std_require_finite_mat(b);
501 if (!out || !lmmc_std_vec_is_empty(&out->
real_parts) ||
507 status = lmmc_std_require_finite_mat(a);
512 status = lmmc_std_require_finite_eig_result(&result);
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)) {
532 status = lmmc_std_require_finite_mat(a);
536 status = lmmc_std_require_finite_svd_result(&result);
552 if (!out || !lmmc_std_mat_is_empty(&out->
values_real) ||
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; }
589 return table ? 4u : 0u;
595 static const char* keys[] = {
601 if (!table || index >=
sizeof(keys) /
sizeof(keys[0])) {
return NULL; }
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)) {
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; }
654 return table ? 3u : 0u;
660 static const char* keys[] = {
"U",
"S",
"Vt"};
661 if (!table || index >=
sizeof(keys) /
sizeof(keys[0])) {
return NULL; }
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_status_t lmmc_svd(const lmmc_mat_t *a, lmmc_svd_result_t *out_result)
计算奇异值分解:A = U * Σ * V^T.
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 输出结果.
一般实矩阵完整特征分解结果(特征值 + 特征向量).
稠密矩阵直接分解接口(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_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> 视图。