void ccv_sat(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int padding_pattern) { ccv_declare_derived_signature(sig, a->sig != 0, ccv_sign_with_format(20, "ccv_sat(%d)", padding_pattern), a->sig, CCV_EOF_SIGN); int safe_type = (a->type & CCV_8U) ? ((a->rows * a->cols >= 0x808080) ? CCV_64S : CCV_32S) : ((a->type & CCV_32S) ? CCV_64S : a->type); type = (type == 0) ? CCV_GET_DATA_TYPE(safe_type) | CCV_GET_CHANNEL(a->type) : CCV_GET_DATA_TYPE(type) | CCV_GET_CHANNEL(a->type); int ch = CCV_GET_CHANNEL(a->type); int i, j; unsigned char* a_ptr = a->data.u8; ccv_dense_matrix_t* db; unsigned char* b_ptr; switch (padding_pattern) { case CCV_NO_PADDING: db = *b = ccv_dense_matrix_renew(*b, a->rows, a->cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(a->type), type, sig); ccv_object_return_if_cached(, db); b_ptr = db->data.u8; #define for_block(_for_set_b, _for_get_b, _for_get) \ for (j = 0; j < ch; j++) \ _for_set_b(b_ptr, j, _for_get(a_ptr, j, 0), 0); \ for (j = ch; j < a->cols * ch; j++) \ _for_set_b(b_ptr, j, _for_get_b(b_ptr, j - ch, 0) + _for_get(a_ptr, j, 0), 0); \ a_ptr += a->step; \ b_ptr += db->step; \ for (i = 1; i < a->rows; i++) \ { \ for (j = 0; j < ch; j++) \ _for_set_b(b_ptr, j, _for_get_b(b_ptr - db->step, j, 0) + _for_get(a_ptr, j, 0), 0); \ for (j = ch; j < a->cols * ch; j++) \ _for_set_b(b_ptr, j, _for_get_b(b_ptr, j - ch, 0) - _for_get_b(b_ptr - db->step, j - ch, 0) + _for_get_b(b_ptr - db->step, j, 0) + _for_get(a_ptr, j, 0), 0); \ a_ptr += a->step; \ b_ptr += db->step; \ } ccv_matrix_setter_getter(db->type, ccv_matrix_getter, a->type, for_block); #undef for_block break; case CCV_PADDING_ZERO: db = *b = ccv_dense_matrix_renew(*b, a->rows + 1, a->cols + 1, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(a->type), type, sig); ccv_object_return_if_cached(, db); b_ptr = db->data.u8; #define for_block(_for_set_b, _for_get_b, _for_get) \ for (j = 0; j < db->cols * ch; j++) \ _for_set_b(b_ptr, j, 0, 0); \ b_ptr += db->step; \ for (i = 0; i < a->rows; i++) \ { \ for (j = 0; j < ch; j++) \ _for_set_b(b_ptr, j, 0, 0); \ for (j = ch; j < db->cols * ch; j++) \ _for_set_b(b_ptr, j, _for_get_b(b_ptr, j - ch, 0) - _for_get_b(b_ptr - db->step, j - ch, 0) + _for_get_b(b_ptr - db->step, j, 0) + _for_get(a_ptr, j - ch, 0), 0); \ a_ptr += a->step; \ b_ptr += db->step; \ } ccv_matrix_setter_getter(db->type, ccv_matrix_getter, a->type, for_block); #undef for_block break; } }
void ccv_compress_sparse_matrix(ccv_sparse_matrix_t* mat, ccv_compressed_sparse_matrix_t** csm) { int i, j; int nnz = 0; int length = CCV_GET_SPARSE_PRIME(mat->prime); for (i = 0; i < length; i++) { ccv_dense_vector_t* vector = &mat->vector[i]; #define while_block(_, _while_get) \ while (vector != 0) \ { \ if (vector->index != -1) \ { \ if (mat->type & CCV_DENSE_VECTOR) \ { \ for (j = 0; j < vector->length; j++) \ if (_while_get(vector->data.u8, j, 0) != 0) \ nnz++; \ } else { \ nnz += vector->load_factor; \ } \ } \ vector = vector->next; \ } ccv_matrix_getter(mat->type, while_block); #undef while_block } ccv_compressed_sparse_matrix_t* cm = *csm = (ccv_compressed_sparse_matrix_t*)ccmalloc(sizeof(ccv_compressed_sparse_matrix_t) + nnz * sizeof(int) + nnz * CCV_GET_DATA_TYPE_SIZE(mat->type) + (((mat->major == CCV_SPARSE_COL_MAJOR) ? mat->cols : mat->rows) + 1) * sizeof(int)); cm->type = (mat->type & ~CCV_MATRIX_SPARSE & ~CCV_SPARSE_VECTOR & ~CCV_DENSE_VECTOR) | ((mat->major == CCV_SPARSE_COL_MAJOR) ? CCV_MATRIX_CSC : CCV_MATRIX_CSR); cm->nnz = nnz; cm->rows = mat->rows; cm->cols = mat->cols; cm->index = (int*)(cm + 1); cm->offset = cm->index + nnz; cm->data.i32 = cm->offset + ((mat->major == CCV_SPARSE_COL_MAJOR) ? mat->cols : mat->rows) + 1; unsigned char* m_ptr = cm->data.u8; int* idx = cm->index; cm->offset[0] = 0; for (i = 0; i < ((mat->major == CCV_SPARSE_COL_MAJOR) ? mat->cols : mat->rows); i++) { ccv_dense_vector_t* vector = ccv_get_sparse_matrix_vector(mat, i); if (vector == 0) cm->offset[i + 1] = cm->offset[i]; else { if (mat->type & CCV_DENSE_VECTOR) { int k = 0; #define for_block(_, _for_set, _for_get) \ for (j = 0; j < vector->length; j++) \ if (_for_get(vector->data.u8, j, 0) != 0) \ { \ _for_set(m_ptr, k, _for_get(vector->data.u8, j, 0), 0); \ idx[k] = j; \ k++; \ } ccv_matrix_setter_getter(mat->type, for_block); #undef for_block cm->offset[i + 1] = cm->offset[i] + k; idx += k; m_ptr += k * CCV_GET_DATA_TYPE_SIZE(mat->type); } else { int k = 0; #define for_block(_, _for_set, _for_get) \ for (j = 0; j < vector->length; j++) \ if (vector->indice[j] != -1) \ { \ _for_set(m_ptr, k, _for_get(vector->data.u8, j, 0), 0); \ idx[k] = vector->indice[j]; \ k++; \ } ccv_matrix_setter_getter(mat->type, for_block); #undef for_block switch (CCV_GET_DATA_TYPE(mat->type)) { case CCV_8U: _ccv_indice_uchar_sort(idx, vector->load_factor, (unsigned char*)m_ptr); break; case CCV_32S: _ccv_indice_int_sort(idx, vector->load_factor, (int*)m_ptr); break; case CCV_32F: _ccv_indice_float_sort(idx, vector->load_factor, (float*)m_ptr); break; case CCV_64F: _ccv_indice_double_sort(idx, vector->load_factor, (double*)m_ptr); break; } cm->offset[i + 1] = cm->offset[i] + vector->load_factor; idx += vector->load_factor; m_ptr += vector->load_factor * CCV_GET_DATA_TYPE_SIZE(mat->type); } } } }