11 size_t initial_capacity = (nnz > 64) ? nnz : 64;
13 if (initial_capacity < n) {
41 memset(lu->
L_col_ptr, 0, (n + 1) *
sizeof(
size_t));
42 memset(lu->
U_col_ptr, 0, (n + 1) *
sizeof(
size_t));
45 for (
size_t i = 0; i < n; i++) lu->
row_perm[i] = i;
55 int csc_needs_free = 0;
59 if (a == NULL || out_lu == NULL) {
85status = lu_allocate_indices(lu);
90 status = lu_allocate_factors(lu, a->
nnz);
102 if (csc_needs_free) {
113 size_t col_start = csc->
row_ptr[orig_col];
114 size_t col_end = csc->
row_ptr[orig_col + 1];
115 for (
size_t p = col_start; p < col_end; p++) {
117 size_t prow = piv_inv[row];
118 col_dense[prow] += csc->
values[p];
126 for (
size_t k = 0; k < j; k++) {
127 if (col_dense[k] == 0.0) {
136 for (
size_t p = L_start; p < L_end; p++) {
139 col_dense[row] = old_val - lu->
L_values[p] * ukj;
148 for (
size_t k = 0; k < j; k++) {
151 size_t idx_j = (size_t)-1;
152 size_t idx_p = (size_t)-1;
153 for (
size_t p = L_start; p < L_end; p++) {
161 if (idx_j != (
size_t)-1 && idx_p != (
size_t)-1) {
165 }
else if (idx_j != (
size_t)-1) {
167 }
else if (idx_p != (
size_t)-1) {
177 size_t pivot_row = j;
180 for (
size_t i = j + 1; i < n; i++) {
188 if (max_val == 0.0) {
192 if (pivot_row != j) {
194 col_dense[j] = col_dense[pivot_row];
195 col_dense[pivot_row] = tmp;
198 size_t orig_p = lu->
row_perm[pivot_row];
202 piv_inv[orig_j] = pivot_row;
204lu_swap_previous_rows(lu, j, pivot_row);
215 for (
size_t i = 0; i <= j; i++) {
216 if (col_dense[i] != 0.0) {
231 for (
size_t i = j + 1; i < n; i++) {
232 if (col_dense[i] != 0.0) {
257 for (
size_t i = 0; i < n; i++) {
262 for (
size_t i = 0; i < n; i++) {
265 for (
size_t j = 0; j < n; j++) {
268 lu_scatter_column(csc, lu->
col_perm[j], piv_inv, col_dense);
269 lu_update_column(lu, j, col_dense);
270 lmmc_status_t status = lu_pivot_column(lu, j, piv_inv, col_dense);
274 status = lu_store_column(lu, j, col_dense);
289 int csc_needs_free = 0;
293 size_t* piv_inv = NULL;
295 if (a == NULL || lu == NULL) {
301 if (a->
rows != lu->
n) {
316 if (!col_dense || !piv_inv) {
321 status = lu_factor_columns(&csc, lu, col_dense, piv_inv);
330 if (csc_needs_free) {
341 for (
size_t j = 0; j < n; j++) {
344 for (
size_t p = L_start; p < L_end; p++) {
346 work[i] -= lu->
L_values[p] * work[j];
350 for (
size_t jj = 0; jj < n; jj++) {
351 size_t j = n - 1 - jj;
355 for (
size_t p = U_start; p < U_end; p++) {
364 work[j] = work[j] / diag;
365 for (
size_t p = U_start; p < U_end; p++) {
368 work[i] -= lu->
U_values[p] * work[j];
388 if (lu == NULL || b == NULL || x == NULL) {
391 if (b->
data == NULL || x->
data == NULL) {
406 for (
size_t i = 0; i < n; i++) {
418 for (
size_t k = 0; k < n; k++) {
double lmmc_real_t
Public and internal LMMC real type.
void * lmmc_memory_alloc_array(size_t count, size_t element_size)
void * lmmc_memory_alloc(size_t size)
void * lmmc_memory_alloc_array_plus(size_t count, size_t extra, size_t element_size)
void lmmc_memory_free(void *pointer)
Private recoverable allocator for persistent LMMC ownership.
lmmc_status_t lmmc_sparse_factor_capacity(size_t **idx, lmmc_real_t **vals, size_t *capacity, size_t needed)
lmmc_status_t lmmc_sparse_direct_csc(const lmmc_sparse_mat_t *a, lmmc_sparse_mat_t *csc_out, int *needs_free)
lmmc_status_t lmmc_sparse_residual_reorder(const lmmc_sparse_mat_t *csc, size_t *perm)
lmmc_status_t lmmc_sparse_lu_solve(const lmmc_sparse_lu_t *lu, const lmmc_vec_t *b, lmmc_vec_t *x)
使用已分解的稀疏 LU 因子求解 A*x = b。
void lmmc_sparse_lu_destroy(lmmc_sparse_lu_t *lu)
销毁稀疏 LU 上下文。
lmmc_status_t lmmc_sparse_lu_numeric(const lmmc_sparse_mat_t *a, lmmc_sparse_lu_t *lu)
稀疏 LU 数值分解:稠密列工作区左看算法与部分主元法。
lmmc_status_t lmmc_sparse_lu_symbolic(const lmmc_sparse_mat_t *a, lmmc_sparse_lu_t **out_lu)
稀疏 LU 符号分析:去重简单图与贪心残余度重排序。
void lmmc_sparse_destroy(lmmc_sparse_mat_t *sparse)
销毁稀疏矩阵,释放其拥有的缓冲区并清零全部字段。
通用稀疏矩阵(CSR / CSC 共用同一结构)。
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_DIMENSION_MISMATCH
@ LMMC_STATUS_ALLOCATION_FAILED
@ LMMC_STATUS_SINGULAR_MATRIX
@ LMMC_STATUS_INVALID_ARGUMENT