void ccv_slice(ccv_matrix_t* a, ccv_matrix_t** b, int btype, int y, int x, int rows, int cols) { int type = *(int*)a; if (type & CCV_MATRIX_DENSE) { ccv_dense_matrix_t* da = ccv_get_dense_matrix(a); ccv_declare_derived_signature(sig, da->sig != 0, ccv_sign_with_format(128, "ccv_slice(%d,%d,%d,%d)", y, x, rows, cols), da->sig, CCV_EOF_SIGN); btype = (btype == 0) ? CCV_GET_DATA_TYPE(da->type) | CCV_GET_CHANNEL(da->type) : CCV_GET_DATA_TYPE(btype) | CCV_GET_CHANNEL(da->type); ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, rows, cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(da->type), btype, sig); ccv_object_return_if_cached(, db); int i, j, ch = CCV_GET_CHANNEL(da->type); int dx = 0, dy = 0; if (!(y >= 0 && y + rows <= da->rows && x >= 0 && x + cols <= da->cols)) { ccv_zero(db); if (y < 0) { rows += y; dy = -y; y = 0; } if (y + rows > da->rows) rows = da->rows - y; if (x < 0) { cols += x; dx = -x; x = 0; } if (x + cols > da->cols) cols = da->cols - x; } unsigned char* a_ptr = da->data.u8 + x * ch * CCV_GET_DATA_TYPE_SIZE(da->type) + y * da->step; unsigned char* b_ptr = db->data.u8 + dx * ch * CCV_GET_DATA_TYPE_SIZE(db->type) + dy * db->step; #define for_block(_for_set, _for_get) \ for (i = 0; i < rows; i++) \ { \ for (j = 0; j < cols * ch; j++) \ { \ _for_set(b_ptr, j, _for_get(a_ptr, j, 0), 0); \ } \ a_ptr += da->step; \ b_ptr += db->step; \ } ccv_matrix_setter(db->type, ccv_matrix_getter, da->type, for_block); #undef for_block } else if (type & CCV_MATRIX_SPARSE) {
void ccv_sample_up(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int src_x, int src_y) { assert(src_x >= 0 && src_y >= 0); ccv_declare_matrix_signature(sig, a->sig != 0, ccv_sign_with_format(64, "ccv_sample_up(%d,%d)", src_x, src_y), a->sig, 0); type = (type == 0) ? CCV_GET_DATA_TYPE(a->type) | CCV_GET_CHANNEL(a->type) : CCV_GET_DATA_TYPE(type) | CCV_GET_CHANNEL(a->type); ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, a->rows * 2, a->cols * 2, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(a->type), type, sig); ccv_matrix_return_if_cached(, db); int ch = CCV_GET_CHANNEL(a->type); int cols0 = a->cols - 1 - src_x; int y, x, sy = -1 + src_y, sx = src_x * ch, k; int* tab = (int*)alloca((a->cols + src_x + 2) * ch * sizeof(int)); for (x = 0; x < a->cols + src_x + 2; x++) for (k = 0; k < ch; k++) tab[x * ch + k] = ((x >= a->cols) ? a->cols * 2 - 1 - x : x) * ch + k; unsigned char* buf = (unsigned char*)alloca(3 * db->cols * ch * ccv_max(CCV_GET_DATA_TYPE_SIZE(db->type), sizeof(int))); int bufstep = db->cols * ch * ccv_max(CCV_GET_DATA_TYPE_SIZE(db->type), sizeof(int)); unsigned char* b_ptr = db->data.u8; /* why src_y * 2: the same argument as in ccv_sample_down */ #define for_block(_for_get_a, _for_set, _for_get, _for_set_b) \ for (y = 0; y < a->rows; y++) \ { \ for (; sy <= y + 1 + src_y; sy++) \ { \ unsigned char* row = buf + ((sy + src_y * 2 + 1) % 3) * bufstep; \ int _sy = (sy < 0) ? -1 - sy : (sy >= a->rows) ? a->rows * 2 - 1 - sy : sy; \ unsigned char* a_ptr = a->data.u8 + a->step * _sy; \ if (a->cols == 1) \ { \ for (k = 0; k < ch; k++) \ { \ _for_set(row, k, _for_get_a(a_ptr, k, 0) * (G025 + G075 + G125), 0); \ _for_set(row, k + ch, _for_get_a(a_ptr, k, 0) * (G025 + G075 + G125), 0); \ } \ continue; \ } \ if (sx == 0) \ { \ for (k = 0; k < ch; k++) \ { \ _for_set(row, k, _for_get_a(a_ptr, k + sx, 0) * (G025 + G075) + _for_get_a(a_ptr, k + sx + ch, 0) * G125, 0); \ _for_set(row, k + ch, _for_get_a(a_ptr, k + sx, 0) * (G125 + G025) + _for_get_a(a_ptr, k + sx + ch, 0) * G075, 0); \ } \ } \ /* some serious flaw in computing Gaussian weighting in previous version * specially, we are doing perfect upsampling (2x) so, it concerns a grid like: * XXYY * XXYY * in this case, to upsampling, the weight should be from distance 0.25 and 1.25, and 0.25 and 0.75 * previously, it was mistakingly be 0.0 1.0, 0.5 0.5 (imperfect upsampling (2x - 1)) */ \ for (x = (sx == 0) ? ch : 0; x < cols0 * ch; x += ch) \ { \ for (k = 0; k < ch; k++) \ { \ _for_set(row, x * 2 + k, _for_get_a(a_ptr, x + sx - ch + k, 0) * G075 + _for_get_a(a_ptr, x + sx + k, 0) * G025 + _for_get_a(a_ptr, x + sx + ch + k, 0) * G125, 0); \ _for_set(row, x * 2 + ch + k, _for_get_a(a_ptr, x + sx - ch + k, 0) * G125 + _for_get_a(a_ptr, x + sx + k, 0) * G025 + _for_get_a(a_ptr, x + sx + ch + k, 0) * G075, 0); \ } \ } \ x_block(_for_get_a, _for_set, _for_get, _for_set_b); \ } \
void ccv_decompress_sparse_matrix(ccv_compressed_sparse_matrix_t* csm, ccv_sparse_matrix_t** smt) { ccv_sparse_matrix_t* mat = *smt = ccv_sparse_matrix_new(csm->rows, csm->cols, csm->type & ~CCV_MATRIX_CSR & ~CCV_MATRIX_CSC, (csm->type & CCV_MATRIX_CSR) ? CCV_SPARSE_ROW_MAJOR : CCV_SPARSE_COL_MAJOR, 0); int i, j; for (i = 0; i < ((mat->major == CCV_SPARSE_COL_MAJOR) ? mat->cols : mat->rows); i++) for (j = csm->offset[i]; j < csm->offset[i + 1]; j++) if (mat->major == CCV_SPARSE_COL_MAJOR) ccv_set_sparse_matrix_cell(mat, csm->index[j], i, csm->data.u8 + CCV_GET_DATA_TYPE_SIZE(csm->type) * j); else ccv_set_sparse_matrix_cell(mat, i, csm->index[j], csm->data.u8 + CCV_GET_DATA_TYPE_SIZE(csm->type) * j); }
ccv_dense_matrix_t* ccv_dense_matrix_new(int rows, int cols, int type, void* data, uint64_t sig) { ccv_dense_matrix_t* mat; if (ccv_cache_opt && sig != 0 && !data && !(type & CCV_NO_DATA_ALLOC)) { uint8_t type; mat = (ccv_dense_matrix_t*)ccv_cache_out(&ccv_cache, sig, &type); if (mat) { assert(type == 0); mat->type |= CCV_GARBAGE; // set the flag so the upper level function knows this is from recycle-bin mat->refcount = 1; return mat; } } if (type & CCV_NO_DATA_ALLOC) { mat = (ccv_dense_matrix_t*)ccmalloc(sizeof(ccv_dense_matrix_t)); mat->type = (CCV_GET_CHANNEL(type) | CCV_GET_DATA_TYPE(type) | CCV_MATRIX_DENSE | CCV_NO_DATA_ALLOC) & ~CCV_GARBAGE; mat->data.u8 = data; } else { mat = (ccv_dense_matrix_t*)(data ? data : ccmalloc(ccv_compute_dense_matrix_size(rows, cols, type))); mat->type = (CCV_GET_CHANNEL(type) | CCV_GET_DATA_TYPE(type) | CCV_MATRIX_DENSE) & ~CCV_GARBAGE; mat->type |= data ? CCV_UNMANAGED : CCV_REUSABLE; // it still could be reusable because the signature could be derived one. mat->data.u8 = (unsigned char*)(mat + 1); } mat->sig = sig; mat->rows = rows; mat->cols = cols; mat->step = (cols * CCV_GET_DATA_TYPE_SIZE(type) * CCV_GET_CHANNEL(type) + 3) & -4; mat->refcount = 1; return mat; }
static void _ccv_dense_vector_expand(ccv_sparse_matrix_t* mat, ccv_dense_vector_t* vector) { if (vector->prime == -1) return; vector->prime++; int new_length = CCV_GET_SPARSE_PRIME(vector->prime); int cell_width = CCV_GET_DATA_TYPE_SIZE(mat->type) * CCV_GET_CHANNEL(mat->type); int new_step = (new_length * cell_width + 3) & -4; ccv_matrix_cell_t new_data; new_data.u8 = (unsigned char*)ccmalloc(new_step + sizeof(int) * new_length); int* new_indice = (int*)(new_data.u8 + new_step); int i; for (i = 0; i < new_length; i++) new_indice[i] = -1; for (i = 0; i < vector->length; i++) if (vector->indice[i] != -1) { int index = vector->indice[i]; int h = (index * 33) % new_length, j = 0; while (new_indice[(h + j * j) % new_length] != index && new_indice[(h + j * j) % new_length] != -1) j++; j = (h + j * j) % new_length; new_indice[j] = index; memcpy(new_data.u8 + j * cell_width, vector->data.u8 + i * cell_width, cell_width); } vector->length = new_length; ccfree(vector->data.u8); vector->data = new_data; vector->indice = new_indice; }
static void _ccv_resample_cubic_integer_only(ccv_dense_matrix_t* a, ccv_dense_matrix_t* b) { assert(CCV_GET_DATA_TYPE(b->type) == CCV_8U || CCV_GET_DATA_TYPE(b->type) == CCV_32S || CCV_GET_DATA_TYPE(b->type) == CCV_64S); int i, j, k, ch = CCV_GET_CHANNEL(a->type); int no_8u_type = (b->type & CCV_8U) ? CCV_32S : b->type; assert(b->cols > 0); ccv_cubic_integer_coeffs_t* xofs = (ccv_cubic_integer_coeffs_t*)alloca(sizeof(ccv_cubic_integer_coeffs_t) * b->cols); float scale_x = (float)a->cols / b->cols; for (i = 0; i < b->cols; i++) { float sx = (i + 0.5) * scale_x - 0.5; _ccv_init_cubic_integer_coeffs((int)sx, a->cols, sx, xofs + i); } float scale_y = (float)a->rows / b->rows; int bufstep = b->cols * ch * CCV_GET_DATA_TYPE_SIZE(no_8u_type); unsigned char* buf = (unsigned char*)alloca(bufstep * 4); #ifdef __clang_analyzer__ memset(buf, 0, bufstep * 4); #endif unsigned char* a_ptr = a->data.u8; unsigned char* b_ptr = b->data.u8; int psi = -1, siy = 0; #define for_block(_for_get_a, _for_set, _for_get, _for_set_b) \ for (i = 0; i < b->rows; i++) \ { \ ccv_cubic_integer_coeffs_t yofs; \ float sy = (i + 0.5) * scale_y - 0.5; \ _ccv_init_cubic_integer_coeffs((int)sy, a->rows, sy, &yofs); \ if (yofs.si[3] > psi) \ { \ for (; siy <= yofs.si[3]; siy++) \ { \ unsigned char* row = buf + (siy & 0x3) * bufstep; \ for (j = 0; j < b->cols; j++) \ for (k = 0; k < ch; k++) \ _for_set(row, j * ch + k, _for_get_a(a_ptr, xofs[j].si[0] * ch + k, 0) * xofs[j].coeffs[0] + \ _for_get_a(a_ptr, xofs[j].si[1] * ch + k, 0) * xofs[j].coeffs[1] + \ _for_get_a(a_ptr, xofs[j].si[2] * ch + k, 0) * xofs[j].coeffs[2] + \ _for_get_a(a_ptr, xofs[j].si[3] * ch + k, 0) * xofs[j].coeffs[3], 0); \ a_ptr += a->step; \ } \ psi = yofs.si[3]; \ } \ unsigned char* row[4] = { \ buf + (yofs.si[0] & 0x3) * bufstep, \ buf + (yofs.si[1] & 0x3) * bufstep, \ buf + (yofs.si[2] & 0x3) * bufstep, \ buf + (yofs.si[3] & 0x3) * bufstep, \ }; \ for (j = 0; j < b->cols * ch; j++) \ _for_set_b(b_ptr, j, ccv_descale(_for_get(row[0], j, 0) * yofs.coeffs[0] + _for_get(row[1], j, 0) * yofs.coeffs[1] + \ _for_get(row[2], j, 0) * yofs.coeffs[2] + _for_get(row[3], j, 0) * yofs.coeffs[3], 12), 0); \ b_ptr += b->step; \ } ccv_matrix_getter(a->type, ccv_matrix_setter_getter_integer_only, no_8u_type, ccv_matrix_setter_integer_only, b->type, for_block); #undef for_block }
ccv_dense_matrix_t ccv_dense_matrix(int rows, int cols, int type, void* data, uint64_t sig) { ccv_dense_matrix_t mat; mat.sig = sig; mat.type = (CCV_GET_CHANNEL(type) | CCV_GET_DATA_TYPE(type) | CCV_MATRIX_DENSE | CCV_UNMANAGED) & ~CCV_GARBAGE; mat.rows = rows; mat.cols = cols; mat.step = (cols * CCV_GET_DATA_TYPE_SIZE(type) * CCV_GET_CHANNEL(type) + 3) & -4; mat.refcount = 1; mat.data.u8 = (unsigned char*)data; return mat; }
void _ccv_flip_x_self(ccv_dense_matrix_t* a) { int i, j; int len = CCV_GET_DATA_TYPE_SIZE(a->type) * CCV_GET_CHANNEL(a->type); unsigned char* buffer = (unsigned char*)alloca(len); unsigned char* a_ptr = a->data.u8; for (i = 0; i < a->rows; i++) { for (j = 0; j < a->cols / 2; j++) { memcpy(buffer, a_ptr + j * len, len); memcpy(a_ptr + j * len, a_ptr + (a->cols - 1 - j) * len, len); memcpy(a_ptr + (a->cols - 1 - j) * len, buffer, len); } a_ptr += a->step; } }
ccv_matrix_cell_t ccv_get_sparse_matrix_cell(ccv_sparse_matrix_t* mat, int row, int col) { ccv_dense_vector_t* vector = ccv_get_sparse_matrix_vector(mat, (mat->major == CCV_SPARSE_COL_MAJOR) ? col : row); ccv_matrix_cell_t cell; cell.u8 = 0; if (vector != 0 && vector->length > 0) { int cell_width = CCV_GET_DATA_TYPE_SIZE(mat->type) * CCV_GET_CHANNEL(mat->type); int vidx = (mat->major == CCV_SPARSE_COL_MAJOR) ? row : col; if (mat->type & CCV_DENSE_VECTOR) { cell.u8 = vector->data.u8 + cell_width * vidx; } else { int h = (vidx * 33) % vector->length, i = 0; while (vector->indice[(h + i * i) % vector->length] != vidx && vector->indice[(h + i * i) % vector->length] != -1) i++; i = (h + i * i) % vector->length; if (vector->indice[i] != -1) cell.u8 = vector->data.u8 + i * cell_width; } } return cell; }
/* the following code is adopted from OpenCV cvPyrDown */ void ccv_sample_down(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int src_x, int src_y) { assert(src_x >= 0 && src_y >= 0); ccv_declare_derived_signature(sig, a->sig != 0, ccv_sign_with_format(64, "ccv_sample_down(%d,%d)", src_x, src_y), a->sig, CCV_EOF_SIGN); type = (type == 0) ? CCV_GET_DATA_TYPE(a->type) | CCV_GET_CHANNEL(a->type) : CCV_GET_DATA_TYPE(type) | CCV_GET_CHANNEL(a->type); ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, a->rows / 2, a->cols / 2, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(a->type), type, sig); ccv_object_return_if_cached(, db); int ch = CCV_GET_CHANNEL(a->type); int cols0 = db->cols - 1 - src_x; int dy, sy = -2 + src_y, sx = src_x * ch, dx, k; int* tab = (int*)alloca((a->cols + src_x + 2) * ch * sizeof(int)); for (dx = 0; dx < a->cols + src_x + 2; dx++) for (k = 0; k < ch; k++) tab[dx * ch + k] = ((dx >= a->cols) ? a->cols * 2 - 1 - dx : dx) * ch + k; unsigned char* buf = (unsigned char*)alloca(5 * db->cols * ch * ccv_max(CCV_GET_DATA_TYPE_SIZE(db->type), sizeof(int))); int bufstep = db->cols * ch * ccv_max(CCV_GET_DATA_TYPE_SIZE(db->type), sizeof(int)); #ifdef __clang_analyzer__ memset(buf, 0, 5 * bufstep); #endif unsigned char* b_ptr = db->data.u8; /* why is src_y * 4 in computing the offset of row? * Essentially, it means sy - src_y but in a manner that doesn't result negative number. * notice that we added src_y before when computing sy in the first place, however, * it is not desirable to have that offset when we try to wrap it into our 5-row buffer ( * because in later rearrangement, we have no src_y to backup the arrangement). In * such micro scope, we managed to stripe 5 addition into one shift and addition. */ #define for_block(_for_get_a, _for_set, _for_get, _for_set_b) \ for (dy = 0; dy < db->rows; dy++) \ { \ for(; sy <= dy * 2 + 2 + src_y; sy++) \ { \ unsigned char* row = buf + ((sy + src_y * 4 + 2) % 5) * bufstep; \ int _sy = (sy < 0) ? -1 - sy : (sy >= a->rows) ? a->rows * 2 - 1 - sy : sy; \ unsigned char* a_ptr = a->data.u8 + a->step * _sy; \ for (k = 0; k < ch; k++) \ _for_set(row, k, _for_get_a(a_ptr, sx + k, 0) * 10 + _for_get_a(a_ptr, ch + sx + k, 0) * 5 + _for_get_a(a_ptr, 2 * ch + sx + k, 0), 0); \ for(dx = ch; dx < cols0 * ch; dx += ch) \ for (k = 0; k < ch; k++) \ _for_set(row, dx + k, _for_get_a(a_ptr, dx * 2 + sx + k, 0) * 6 + (_for_get_a(a_ptr, dx * 2 + sx + k - ch, 0) + _for_get_a(a_ptr, dx * 2 + sx + k + ch, 0)) * 4 + _for_get_a(a_ptr, dx * 2 + sx + k - ch * 2, 0) + _for_get_a(a_ptr, dx * 2 + sx + k + ch * 2, 0), 0); \ x_block(_for_get_a, _for_set, _for_get, _for_set_b); \ } \ unsigned char* rows[5]; \ for(k = 0; k < 5; k++) \ rows[k] = buf + ((dy * 2 + k) % 5) * bufstep; \ for(dx = 0; dx < db->cols * ch; dx++) \ _for_set_b(b_ptr, dx, (_for_get(rows[2], dx, 0) * 6 + (_for_get(rows[1], dx, 0) + _for_get(rows[3], dx, 0)) * 4 + _for_get(rows[0], dx, 0) + _for_get(rows[4], dx, 0)) / 256, 0); \ b_ptr += db->step; \ } int no_8u_type = (a->type & CCV_8U) ? CCV_32S : a->type; if (src_x > 0) { #define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \ for (dx = cols0 * ch; dx < db->cols * ch; dx += ch) \ for (k = 0; k < ch; k++) \ _for_set(row, dx + k, _for_get_a(a_ptr, tab[dx * 2 + sx + k], 0) * 6 + (_for_get_a(a_ptr, tab[dx * 2 + sx + k - ch], 0) + _for_get_a(a_ptr, tab[dx * 2 + sx + k + ch], 0)) * 4 + _for_get_a(a_ptr, tab[dx * 2 + sx + k - ch * 2], 0) + _for_get_a(a_ptr, tab[dx * 2 + sx + k + ch * 2], 0), 0); ccv_matrix_getter_a(a->type, ccv_matrix_setter_getter, no_8u_type, ccv_matrix_setter_b, db->type, for_block); #undef x_block } else { #define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \ for (k = 0; k < ch; k++) \ _for_set(row, (db->cols - 1) * ch + k, _for_get_a(a_ptr, a->cols * ch + sx - ch + k, 0) * 10 + _for_get_a(a_ptr, (a->cols - 2) * ch + sx + k, 0) * 5 + _for_get_a(a_ptr, (a->cols - 3) * ch + sx + k, 0), 0); ccv_matrix_getter_a(a->type, ccv_matrix_setter_getter, no_8u_type, ccv_matrix_setter_b, db->type, for_block); #undef x_block } #undef for_block }
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); } } } }
void ccv_set_sparse_matrix_cell(ccv_sparse_matrix_t* mat, int row, int col, void* data) { int i; int index = (mat->major == CCV_SPARSE_COL_MAJOR) ? col : row; int vidx = (mat->major == CCV_SPARSE_COL_MAJOR) ? row : col; int length = CCV_GET_SPARSE_PRIME(mat->prime); ccv_dense_vector_t* vector = ccv_get_sparse_matrix_vector(mat, index); if (vector == 0) { mat->load_factor++; if (mat->load_factor * 4 > CCV_GET_SPARSE_PRIME(mat->prime) * 3) { _ccv_sparse_matrix_expand(mat); length = CCV_GET_SPARSE_PRIME(mat->prime); } vector = &mat->vector[(index * 33) % length]; if (vector->index != -1) { vector = (ccv_dense_vector_t*)ccmalloc(sizeof(ccv_dense_vector_t)); vector->index = -1; vector->length = 0; vector->next = mat->vector[(index * 33) % length].next; mat->vector[(index * 33) % length].next = vector; } } int cell_width = CCV_GET_DATA_TYPE_SIZE(mat->type) * CCV_GET_CHANNEL(mat->type); if (mat->type & CCV_DENSE_VECTOR) { if (vector->index == -1) { vector->prime = -1; vector->length = (mat->major == CCV_SPARSE_COL_MAJOR) ? mat->rows : mat->cols; vector->index = index; vector->step = (vector->length * cell_width + 3) & -4; vector->data.u8 = (unsigned char*)calloc(vector->step, 1); } if (data != 0) memcpy(vector->data.u8 + vidx * cell_width, data, cell_width); } else { if (vector->index == -1) { vector->prime = 0; vector->load_factor = 0; vector->length = CCV_GET_SPARSE_PRIME(vector->prime); vector->index = index; vector->step = (vector->length * cell_width + 3) & -4; vector->data.u8 = (unsigned char*)ccmalloc(vector->step + sizeof(int) * vector->length); vector->indice = (int*)(vector->data.u8 + vector->step); for (i = 0; i < vector->length; i++) vector->indice[i] = -1; } vector->load_factor++; if (vector->load_factor * 2 > vector->length) { _ccv_dense_vector_expand(mat, vector); } i = 0; int h = (vidx * 33) % vector->length; while (vector->indice[(h + i * i) % vector->length] != vidx && vector->indice[(h + i * i) % vector->length] != -1) i++; i = (h + i * i) % vector->length; vector->indice[i] = vidx; if (data != 0) memcpy(vector->data.u8 + i * cell_width, data, cell_width); } }