24 const size_t* restrict col_idx = sparse->
col_idx;
25 const size_t* restrict row_ptr = sparse->
row_ptr;
36 for (i = 0; i < sparse->
rows; ++i) {
38 size_t start = row_ptr[i];
39 size_t end = row_ptr[i + 1];
42 for (; p + 3 < end; p += 4) {
47 LMMC_REAL_MUL(&tmp_mul, &vals[p + 1], &x_data[col_idx[p + 1]]);
51 LMMC_REAL_MUL(&tmp_mul, &vals[p + 2], &x_data[col_idx[p + 2]]);
55 LMMC_REAL_MUL(&tmp_mul, &vals[p + 3], &x_data[col_idx[p + 3]]);
59 for (; p < end; ++p) {
75 for (i = 0; i < sparse->
cols; ++i) {
76 size_t start = row_ptr[i];
77 size_t end = row_ptr[i + 1];
78 for (p = start; p < end; ++p) {
92static void lmmc_sparse_dense_row_add(
98 size_t j_limit = count & ~((size_t)3);
99 for (j = 0; j < j_limit; j += 4) {
116 for (; j < count; ++j) {
123static size_t lmmc_sparse_product_pattern(
125 size_t* marker,
size_t* c_row_ptr)
127 size_t i, j, k, p1, p2;
130 for (i = 0; i < pa->
rows; ++i) {
131 for (p1 = pa->
row_ptr[i]; p1 < pa->row_ptr[i + 1]; ++p1) {
133 for (p2 = pb->
row_ptr[k]; p2 < pb->row_ptr[k + 1]; ++p2) {
135 if (marker[j] != i) {
141 c_row_ptr[i + 1] = nnz_est;
146static int lmmc_sparse_index_compare(
const void* lhs,
const void* rhs) {
147 const size_t a = *(
const size_t*)lhs;
148 const size_t b = *(
const size_t*)rhs;
149 return (a > b) - (a < b);
152static void lmmc_sparse_product_values(
157 size_t i, j, k, p1, p2;
161 size_t current_nnz = 0;
162 for (i = 0; i < pa->
rows; ++i) {
163 size_t row_start = current_nnz;
164 for (p1 = pa->
row_ptr[i]; p1 < pa->row_ptr[i + 1]; ++p1) {
166 for (p2 = pb->
row_ptr[k]; p2 < pb->row_ptr[k + 1]; ++p2) {
168 if (marker[j] != i) {
170 c_col_idx[current_nnz++] = j;
177 if (current_nnz - row_start > 1) {
178 qsort(c_col_idx + row_start, current_nnz - row_start,
179 sizeof(
size_t), lmmc_sparse_index_compare);
181 for (p1 = row_start; p1 < current_nnz; ++p1) {
192static void lmmc_sparse_product_workspace_clear(
193 size_t* marker,
lmmc_real_t* accumulator,
size_t cols,
194 size_t* c_row_ptr,
size_t* c_col_idx,
lmmc_real_t* c_values,
size_t nnz_est)
200 for (
size_t act_i = 0; act_i < cols; act_i++) {
212 for (
size_t act_i = 0; act_i < nnz_est; act_i++) {
231 const size_t* restrict col_idx = sparse->
col_idx;
232 const size_t* restrict row_ptr = sparse->
row_ptr;
236 size_t b_stride = b->
stride;
237 size_t c_stride = c->
stride;
238 size_t b_cols = b->
cols;
254 for (i = 0; i < sparse->
rows; ++i) {
255 size_t start = row_ptr[i];
256 size_t end = row_ptr[i + 1];
257 for (p = start; p < end; ++p) {
258 size_t k = col_idx[p];
262 lmmc_sparse_dense_row_add(&val_p, &b_data[k * b_stride],
263 &c_data[i * c_stride], b_cols, &tmp_mul, &tmp_sum);
268 for (i = 0; i < sparse->
cols; ++i) {
269 size_t start = row_ptr[i];
270 size_t end = row_ptr[i + 1];
271 for (p = start; p < end; ++p) {
272 size_t row = col_idx[p];
276 lmmc_sparse_dense_row_add(&val_p, &b_data[i * b_stride],
277 &c_data[row * c_stride], b_cols, &tmp_mul, &tmp_sum);
290 size_t nnz,
size_t cols,
size_t* marker,
size_t** indices,
296 if ((nnz > 0 && (*indices == NULL || *values == NULL)) || *accumulator == NULL) {
299 memset(marker, 0xFF, cols *
sizeof(
size_t));
300 for (
size_t i = 0; i < cols; ++i) {
304 for (
size_t i = 0; i < nnz; ++i) {
316 size_t *marker = NULL;
318 size_t *c_row_ptr = NULL;
319 size_t *c_col_idx = NULL;
349 if (marker == NULL || c_row_ptr == NULL) {
353 memset(marker, 0xFF, pb->
cols *
sizeof(
size_t));
354 memset(c_row_ptr, 0, (pa->
rows + 1) *
sizeof(
size_t));
356 nnz_est = lmmc_sparse_product_pattern(pa, pb, marker, c_row_ptr);
358 st = lmmc_sparse_product_numeric_workspace(
359 nnz_est, pb->
cols, marker, &c_col_idx, &c_values, &accumulator);
364 lmmc_sparse_product_values(pa, pb, marker, accumulator, c_col_idx, c_values);
380 lmmc_sparse_product_workspace_clear(
381 marker, accumulator, pb->
cols, c_row_ptr, c_col_idx, c_values, nnz_est);
#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_status_t lmmc_vec_fill(lmmc_vec_t *vec, lmmc_real_t value)
就地将向量所有元素设为 value。
lmmc_status_t lmmc_mat_fill(lmmc_mat_t *mat, lmmc_real_t value)
就地将矩阵所有元素设为 value。
void * lmmc_memory_alloc_array(size_t count, size_t element_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_mat_mat_mul_sparse(const lmmc_sparse_mat_t *a, const lmmc_sparse_mat_t *b, lmmc_sparse_mat_t *c)
稀疏矩阵-稀疏矩阵乘法(SpGEMM):C = A * B。
lmmc_status_t lmmc_sparse_mat_vec_mul(const lmmc_sparse_mat_t *sparse, const lmmc_vec_t *x, lmmc_vec_t *y)
稀疏矩阵-稠密向量乘法:y = A * x。
lmmc_status_t lmmc_sparse_mat_mat_mul_dense(const lmmc_sparse_mat_t *sparse, const lmmc_mat_t *b, lmmc_mat_t *c)
稀疏矩阵 x 稠密矩阵:C = A * B(结果为稠密矩阵)。
lmmc_status_t lmmc_sparse_to_csr(const lmmc_sparse_mat_t *src, lmmc_sparse_mat_t *dst)
转换为 CSR,src 已为 CSR 时执行深拷贝。
void lmmc_sparse_destroy(lmmc_sparse_mat_t *sparse)
销毁稀疏矩阵,释放其拥有的缓冲区并清零全部字段。
lmmc_sparse_format_t format
通用稀疏矩阵(CSR / CSC 共用同一结构)。
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_DIMENSION_MISMATCH
@ LMMC_STATUS_ALLOCATION_FAILED
@ LMMC_STATUS_INVALID_ARGUMENT