14 size_t row_ptr_bytes = 0;
15 size_t col_idx_bytes = 0;
19 if (out == NULL || rows == 0 || cols == 0 || block_size == 0) {
24 if (!lmmc_safe_mul_size(rows + 1,
sizeof(
size_t), &row_ptr_bytes)) {
27 if (!lmmc_safe_mul_size(nnz_blocks,
sizeof(
size_t), &col_idx_bytes)) {
30 if (!lmmc_safe_mul_size(block_size, block_size, &val_count)) {
33 if (!lmmc_safe_mul_size(val_count, nnz_blocks, &val_count)) {
36 if (!lmmc_safe_mul_size(val_count,
sizeof(
lmmc_real_t), &val_bytes)) {
44 memset(out->
row_ptr, 0, row_ptr_bytes);
56 memset(out->
col_idx, 0, col_idx_bytes);
66 memset(out->
values, 0, val_bytes);
77static void lmmc_sparse_bsr_scatter(
81 for (bi = 0; bi < bsr->
rows; ++bi) {
82 for (p = bsr->
row_ptr[bi]; p < bsr->row_ptr[bi + 1]; ++p) {
90 size_t dense_idx = (row_base + li) * out->
stride + (col_base + lj);
91 size_t block_idx = block_offset + li * bsr->
block_size + lj;
99static int lmmc_sparse_dense_block_nonzero(
100 const lmmc_mat_t* dense,
size_t block_size,
size_t bi,
size_t bj,
103 for (
size_t li = 0; li < block_size; ++li) {
104 for (
size_t lj = 0; lj < block_size; ++lj) {
105 size_t row = bi * block_size + li;
106 size_t col = bj * block_size + lj;
116static void lmmc_sparse_dense_block_copy(
118 size_t bi,
size_t bj,
size_t nz_idx)
121 size_t block_offset = nz_idx * block_size * block_size;
123 for (
size_t li = 0; li < block_size; ++li) {
124 for (
size_t lj = 0; lj < block_size; ++lj) {
125 size_t row = bi * block_size + li;
126 size_t col = bj * block_size + lj;
127 size_t blk_idx = block_offset + li * block_size + lj;
134static void lmmc_sparse_bsr_gather(
140 for (
size_t bi = 0; bi < out->
rows; ++bi) {
141 for (
size_t bj = 0; bj < out->
cols; ++bj) {
142 if (lmmc_sparse_dense_block_nonzero(
143 dense, out->
block_size, bi, bj, eps, abs_v)) {
144 lmmc_sparse_dense_block_copy(dense, out, bi, bj, nz_idx);
154 size_t dense_rows, dense_cols;
158 if (bsr == NULL || out == NULL || out->
data == NULL) {
174 if (out->
rows != dense_rows || out->
cols != dense_cols) {
187 lmmc_sparse_bsr_scatter(bsr, out);
194 size_t block_rows, block_cols;
196 size_t nnz_blocks = 0;
201 if (dense == NULL || out == NULL || dense->
data == NULL) {
204 if (block_size == 0) {
207 if (dense->
rows % block_size != 0 || dense->
cols % block_size != 0) {
221 block_rows = dense->
rows / block_size;
222 block_cols = dense->
cols / block_size;
225 for (bi = 0; bi < block_rows; ++bi) {
226 for (bj = 0; bj < block_cols; ++bj) {
227 if (lmmc_sparse_dense_block_nonzero(
228 dense, block_size, bi, bj, &eps, &abs_v)) {
241 if (nnz_blocks == 0) {
248 lmmc_sparse_bsr_gather(dense, &eps, &abs_v, out);
266 if (bsr->
values != NULL) {
#define LMMC_REAL_CLEAR(x)
释放一个 lmmc_real_t 变量(POD 类型为空操作)。
#define LMMC_REAL_INIT(x)
初始化一个 lmmc_real_t 变量(POD 类型为空操作)。
double lmmc_real_t
Public and internal LMMC real type.
#define LMMC_REAL_SET(dst, src)
将一个 lmmc_real_t 赋值到另一个:*dst = *src 。
#define LMMC_REAL_ABS(res, a)
计算绝对值,*res = |*a| 。
#define LMMC_REAL_CMP(a, b)
比较 *a 与 *b ,返回 -1/0/1 。
#define LMMC_REAL_SET_D(dst, dbl)
将一个 double 字面量赋值到 lmmc_real_t 。
lmmc_status_t lmmc_mat_fill(lmmc_mat_t *mat, lmmc_real_t value)
就地将矩阵所有元素设为 value。
void * lmmc_memory_alloc(size_t size)
void lmmc_memory_free(void *pointer)
Private recoverable allocator for persistent LMMC ownership.
void lmmc_sparse_bsr_destroy(lmmc_sparse_bsr_t *bsr)
销毁 BSR 矩阵,按所有权释放底层缓冲区。
lmmc_status_t lmmc_sparse_bsr_create(size_t rows, size_t cols, size_t block_size, size_t nnz_blocks, lmmc_sparse_bsr_t *out)
创建 BSR 矩阵,数组内容未初始化。
lmmc_status_t lmmc_sparse_bsr_to_dense(const lmmc_sparse_bsr_t *bsr, lmmc_mat_t *out)
将 BSR 矩阵展开为稠密矩阵。
lmmc_status_t lmmc_sparse_dense_to_bsr(const lmmc_mat_t *dense, size_t block_size, lmmc_real_t eps, lmmc_sparse_bsr_t *out)
将稠密矩阵转换为 BSR 格式。
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_DIMENSION_MISMATCH
@ LMMC_STATUS_ALLOCATION_FAILED
@ LMMC_STATUS_INVALID_ARGUMENT