LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
sparse_symmetric.c
浏览该文件的文档.
1
5#include "memory_bridge.h"
6#include "internal.h"
7#include "sparse_internal.h"
8#include "lmmc/sparse.h"
9
10static size_t lmmc_sparse_sym_count(
12{
13 size_t i, p, n = full->rows, nnz_half = 0;
14 for (i = 0; i < n; ++i) {
15 for (p = full->row_ptr[i]; p < full->row_ptr[i + 1]; ++p) {
16 size_t j = full->col_idx[p];
17 if (half == LMMC_SPARSE_SYM_UPPER) {
18 if (j >= i) ++nnz_half;
19 } else {
20 if (j <= i) ++nnz_half;
21 }
22 }
23 }
24 return nnz_half;
25}
26
27static void lmmc_sparse_sym_copy(
30{
31 size_t i, p, n = full->rows, nz_idx;
32 nz_idx = 0;
33 out->row_ptr[0] = 0;
34 for (i = 0; i < n; ++i) {
35 for (p = full->row_ptr[i]; p < full->row_ptr[i + 1]; ++p) {
36 size_t j = full->col_idx[p];
37 int keep = 0;
38 if (half == LMMC_SPARSE_SYM_UPPER) {
39 keep = (j >= i);
40 } else {
41 keep = (j <= i);
42 }
43 if (keep) {
44 out->col_idx[nz_idx] = j;
45 LMMC_REAL_SET(&out->values[nz_idx], &full->values[p]);
46 ++nz_idx;
47 }
48 }
49 out->row_ptr[i + 1] = nz_idx;
50 }
51}
52
53static void lmmc_sparse_sym_accumulate(
54 const lmmc_sparse_sym_csr_t* A, const lmmc_vec_t* x,
55 lmmc_vec_t* y, lmmc_real_t* prod)
56{
57 size_t i, p;
58 for (i = 0; i < A->n; ++i) {
59 for (p = A->row_ptr[i]; p < A->row_ptr[i + 1]; ++p) {
60 size_t j = A->col_idx[p];
61 LMMC_REAL_MUL(prod, &A->values[p], &x->data[j]);
62
64 {
65 lmmc_real_t tmp;
66 LMMC_REAL_INIT(&tmp);
67 LMMC_REAL_ADD(&tmp, &y->data[i], prod);
68 LMMC_REAL_SET(&y->data[i], &tmp);
69 LMMC_REAL_CLEAR(&tmp);
70 }
71
73 if (i != j) {
74 lmmc_real_t prod2;
75 lmmc_real_t tmp2;
76 LMMC_REAL_INIT(&prod2);
77 LMMC_REAL_INIT(&tmp2);
78 LMMC_REAL_MUL(&prod2, &A->values[p], &x->data[i]);
79 LMMC_REAL_ADD(&tmp2, &y->data[j], &prod2);
80 LMMC_REAL_SET(&y->data[j], &tmp2);
81 LMMC_REAL_CLEAR(&prod2);
82 LMMC_REAL_CLEAR(&tmp2);
83 }
84 }
85 }
86}
87
88
91 size_t i;
92 size_t n;
93 size_t nnz_half = 0;
94 size_t row_ptr_bytes, col_idx_bytes, val_bytes;
96
97 if (full == NULL || out == NULL) {
99 }
100
101 st = lmmc_sparse_validate(full);
102 if (st != LMMC_STATUS_OK) {
104 }
105
106 if (full->rows != full->cols) {
108 }
109 if (full->format != LMMC_SPARSE_CSR) {
111 }
112
113 n = full->rows;
114
115 /* 第一遍:计算半三角中的非零元数量 */
116 nnz_half = lmmc_sparse_sym_count(full, half);
117
118 /* 分配内存 */
119 if (!lmmc_safe_mul_size(n + 1, sizeof(size_t), &row_ptr_bytes) ||
120 !lmmc_safe_mul_size(nnz_half, sizeof(size_t), &col_idx_bytes) ||
121 !lmmc_safe_mul_size(nnz_half, sizeof(lmmc_real_t), &val_bytes)) {
123 }
124
125 out->row_ptr = (size_t*)lmmc_memory_alloc(row_ptr_bytes);
126 if (out->row_ptr == NULL) {
128 }
129
130 out->col_idx = NULL;
131 out->values = NULL;
132
133 if (nnz_half > 0) {
134 out->col_idx = (size_t*)lmmc_memory_alloc(col_idx_bytes);
135 if (out->col_idx == NULL) {
137 out->row_ptr = NULL;
139 }
140
141 out->values = (lmmc_real_t*)lmmc_memory_alloc(val_bytes);
142 if (out->values == NULL) {
145 out->col_idx = NULL;
146 out->row_ptr = NULL;
148 }
149 }
150 if (nnz_half == 0) {
151 for (i = 0; i < n; ++i) {
152 out->row_ptr[i] = 0;
153 }
154 out->row_ptr[n] = 0;
155 out->n = n;
156 out->nnz = 0;
157 out->half = half;
158 out->owns_data = 1;
159 return LMMC_STATUS_OK;
160 }
161
162 /* 第二遍:填充数据 */
163 lmmc_sparse_sym_copy(full, half, out);
164
165 out->n = n;
166 out->nnz = nnz_half;
167 out->half = half;
168 out->owns_data = 1;
169 return LMMC_STATUS_OK;
170}
171
173 const lmmc_vec_t* x, lmmc_vec_t* y) {
174 size_t i;
175 lmmc_real_t zero;
176 lmmc_real_t prod;
177
178 if (A == NULL || x == NULL || y == NULL) {
180 }
181 if (x->data == NULL || y->data == NULL) {
183 }
184 if (A->row_ptr == NULL) {
186 }
187 if (A->nnz > 0 && (A->col_idx == NULL || A->values == NULL)) {
189 }
190 if (x->size != A->n || y->size != A->n) {
192 }
193
194 /* 清零输出向量 */
195 LMMC_REAL_INIT(&zero);
196 LMMC_REAL_INIT(&prod);
197 LMMC_REAL_SET_D(&zero, 0.0);
198
199 for (i = 0; i < A->n; ++i) {
200 LMMC_REAL_SET_D(&y->data[i], 0.0);
201 }
202
203 /* 对称 SpMV:利用对称性,每个非对角元贡献两次 */
204 lmmc_sparse_sym_accumulate(A, x, y, &prod);
205
206 LMMC_REAL_CLEAR(&zero);
207 LMMC_REAL_CLEAR(&prod);
208 return LMMC_STATUS_OK;
209}
210
212 if (s == NULL) {
213 return;
214 }
215 if (s->owns_data) {
216 if (s->row_ptr != NULL) {
218 }
219 if (s->col_idx != NULL) {
221 }
222 if (s->values != NULL) {
224 }
225 }
226 s->row_ptr = NULL;
227 s->col_idx = NULL;
228 s->values = NULL;
229 s->n = 0;
230 s->nnz = 0;
231 s->owns_data = 0;
232}
#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 。
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_SET_D(dst, dbl)
将一个 double 字面量赋值到 lmmc_real_t 。
lmmc_real_t * data
一维稠密向量。
LMMC 内部使用的公共工具(仅源文件可见).
void * lmmc_memory_alloc(size_t size)
void lmmc_memory_free(void *pointer)
Private recoverable allocator for persistent LMMC ownership.
lmmc_status_t lmmc_sparse_sym_spmv(const lmmc_sparse_sym_csr_t *A, const lmmc_vec_t *x, lmmc_vec_t *y)
对称半存储 SpMV:y = A * x 。
稀疏矩阵模块内部共享辅助函数(仅源文件可见)。
lmmc_status_t lmmc_sparse_sym_csr_from_csr(const lmmc_sparse_mat_t *full, lmmc_sparse_sym_half_t half, lmmc_sparse_sym_csr_t *out)
从完整 CSR 矩阵提取对称半存储。
void lmmc_sparse_sym_csr_destroy(lmmc_sparse_sym_csr_t *s)
销毁对称半存储 CSR 矩阵,按所有权释放底层缓冲区。
lmmc_sparse_sym_half_t half
@ LMMC_SPARSE_CSR
lmmc_sparse_sym_half_t
对称半存储选择:上三角或下三角。
@ LMMC_SPARSE_SYM_UPPER
lmmc_sparse_format_t format
通用稀疏矩阵(CSR / CSC 共用同一结构)。
对称半存储 CSR 格式矩阵。
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_OK
@ LMMC_STATUS_DIMENSION_MISMATCH
@ LMMC_STATUS_ALLOCATION_FAILED
@ LMMC_STATUS_INVALID_ARGUMENT