void ccv_subtract(ccv_matrix_t* a, ccv_matrix_t* b, ccv_matrix_t** c, int type) { ccv_dense_matrix_t* da = ccv_get_dense_matrix(a); ccv_dense_matrix_t* db = ccv_get_dense_matrix(b); assert(da->rows == db->rows && da->cols == db->cols && CCV_GET_DATA_TYPE(da->type) == CCV_GET_DATA_TYPE(db->type) && CCV_GET_CHANNEL(da->type) == CCV_GET_CHANNEL(db->type)); ccv_declare_derived_signature(sig, da->sig != 0 && db->sig != 0, ccv_sign_with_literal("ccv_subtract"), da->sig, db->sig, CCV_EOF_SIGN); int no_8u_type = (da->type & CCV_8U) ? CCV_32S : da->type; type = (type == 0) ? CCV_GET_DATA_TYPE(no_8u_type) | CCV_GET_CHANNEL(da->type) : CCV_GET_DATA_TYPE(type) | CCV_GET_CHANNEL(da->type); ccv_dense_matrix_t* dc = *c = ccv_dense_matrix_renew(*c, da->rows, da->cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(da->type), type, sig); ccv_object_return_if_cached(, dc); int i, j, ch = CCV_GET_CHANNEL(da->type); unsigned char* aptr = da->data.u8; unsigned char* bptr = db->data.u8; unsigned char* cptr = dc->data.u8; #define for_block(_for_get, _for_set) \ for (i = 0; i < da->rows; i++) \ { \ for (j = 0; j < da->cols * ch; j++) \ _for_set(cptr, j, _for_get(aptr, j, 0) - _for_get(bptr, j, 0), 0); \ aptr += da->step; \ bptr += db->step; \ cptr += dc->step; \ } ccv_matrix_getter(da->type, ccv_matrix_setter, dc->type, for_block); #undef for_block }
void ccv_gemm(ccv_matrix_t* a, ccv_matrix_t* b, double alpha, ccv_matrix_t* c, double beta, int transpose, ccv_matrix_t** d, int type) { ccv_dense_matrix_t* da = ccv_get_dense_matrix(a); ccv_dense_matrix_t* db = ccv_get_dense_matrix(b); ccv_dense_matrix_t* dc = (c == 0) ? 0 : ccv_get_dense_matrix(c); assert(CCV_GET_DATA_TYPE(da->type) == CCV_GET_DATA_TYPE(db->type) && CCV_GET_CHANNEL(da->type) == 1 && CCV_GET_CHANNEL(db->type) == 1 && ((transpose & CCV_A_TRANSPOSE) ? da->rows : da->cols) == ((transpose & CCV_B_TRANSPOSE) ? db->cols : db->rows)); if (dc != 0) assert(CCV_GET_DATA_TYPE(dc->type) == CCV_GET_DATA_TYPE(da->type) && CCV_GET_CHANNEL(dc->type) == 1 && ((transpose & CCV_A_TRANSPOSE) ? da->cols : da->rows) == dc->rows && ((transpose & CCV_B_TRANSPOSE) ? db->rows : db->cols) == dc->cols); ccv_declare_derived_signature_case(sig, ccv_sign_with_format(20, "ccv_gemm(%d)", transpose), ccv_sign_if(dc == 0 && da->sig != 0 && db->sig != 0, da->sig, db->sig, CCV_EOF_SIGN), ccv_sign_if(dc != 0 && da->sig != 0 && db->sig != 0 && dc->sig != 0, da->sig, db->sig, dc->sig, CCV_EOF_SIGN)); type = CCV_GET_DATA_TYPE(da->type) | CCV_GET_CHANNEL(da->type); ccv_dense_matrix_t* dd = *d = ccv_dense_matrix_renew(*d, (transpose & CCV_A_TRANSPOSE) ? da->cols : da->rows, (transpose & CCV_B_TRANSPOSE) ? db->rows : db->cols, type, type, sig); ccv_object_return_if_cached(, dd); if (dd != dc && dc != 0) memcpy(dd->data.u8, dc->data.u8, dc->step * dc->rows); else if (dc == 0) // clean up dd if dc is not provided memset(dd->data.u8, 0, dd->step * dd->rows); #if (defined HAVE_CBLAS || defined HAVE_ACCELERATE_FRAMEWORK) switch (CCV_GET_DATA_TYPE(dd->type)) { case CCV_32F: cblas_sgemm(CblasRowMajor, (transpose & CCV_A_TRANSPOSE) ? CblasTrans : CblasNoTrans, (transpose & CCV_B_TRANSPOSE) ? CblasTrans : CblasNoTrans, dd->rows, dd->cols, (transpose & CCV_A_TRANSPOSE) ? da->rows : da->cols, alpha, da->data.f32, da->cols, db->data.f32, db->cols, beta, dd->data.f32, dd->cols); break; case CCV_64F: cblas_dgemm(CblasRowMajor, (transpose & CCV_A_TRANSPOSE) ? CblasTrans : CblasNoTrans, (transpose & CCV_B_TRANSPOSE) ? CblasTrans : CblasNoTrans, dd->rows, dd->cols, (transpose & CCV_A_TRANSPOSE) ? da->rows : da->cols, alpha, da->data.f64, da->cols, db->data.f64, db->cols, beta, dd->data.f64, dd->cols); break; } #else assert(0 && "You need a BLAS compatible library for this function, e.g. libatlas."); #endif }
void ccv_flatten(ccv_matrix_t* a, ccv_matrix_t** b, int type, int flag) { ccv_dense_matrix_t* da = ccv_get_dense_matrix(a); ccv_declare_derived_signature(sig, da->sig != 0, ccv_sign_with_format(64, "ccv_flatten(%d)", flag), da->sig, CCV_EOF_SIGN); int no_8u_type = (da->type & CCV_8U) ? CCV_32S : da->type; type = (type == 0) ? CCV_GET_DATA_TYPE(no_8u_type) | CCV_C1 : CCV_GET_DATA_TYPE(type) | CCV_C1; ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, da->rows, da->cols, CCV_ALL_DATA_TYPE | CCV_C1, type, sig); ccv_object_return_if_cached(, db); int i, j, k, ch = CCV_GET_CHANNEL(da->type); unsigned char* aptr = da->data.u8; unsigned char* bptr = db->data.u8; #define for_block(_for_get, _for_type, _for_set) \ for (i = 0; i < da->rows; i++) \ { \ for (j = 0; j < da->cols; j++) \ { \ _for_type sum = 0; \ for (k = 0; k < ch; k++) \ sum += _for_get(aptr, j * ch + k, 0); \ _for_set(bptr, j, sum, 0); \ } \ aptr += da->step; \ bptr += db->step; \ } ccv_matrix_getter(da->type, ccv_matrix_typeof_setter, db->type, for_block); #undef for_block }
double ccv_sum(ccv_matrix_t* mat, int flag) { ccv_dense_matrix_t* dmt = ccv_get_dense_matrix(mat); double sum = 0; unsigned char* m_ptr = dmt->data.u8; int i, j, ch = CCV_GET_CHANNEL(dmt->type); #define for_block(_, _for_get) \ switch (flag) \ { \ case CCV_UNSIGNED: \ for (i = 0; i < dmt->rows; i++) \ { \ for (j = 0; j < dmt->cols * ch; j++) \ sum += fabs((double)(_for_get(m_ptr, j, 0))); \ m_ptr += dmt->step; \ } \ break; \ case CCV_SIGNED: \ default: \ for (i = 0; i < dmt->rows; i++) \ { \ for (j = 0; j < dmt->cols * ch; j++) \ sum += _for_get(m_ptr, j, 0); \ m_ptr += dmt->step; \ } \ } ccv_matrix_getter(dmt->type, for_block); #undef for_block return sum; }
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) {
double ccv_normalize(ccv_matrix_t* a, ccv_matrix_t** b, int btype, int flag) { ccv_dense_matrix_t* da = ccv_get_dense_matrix(a); assert(CCV_GET_CHANNEL(da->type) == CCV_C1); ccv_declare_derived_signature(sig, da->sig != 0, ccv_sign_with_format(20, "ccv_normalize(%d)", flag), da->sig, CCV_EOF_SIGN); btype = (btype == 0) ? CCV_GET_DATA_TYPE(da->type) | CCV_C1 : CCV_GET_DATA_TYPE(btype) | CCV_C1; ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, da->rows, da->cols, CCV_ALL_DATA_TYPE | CCV_C1, btype, sig); assert(db); ccv_object_return_if_cached(db->tag.f64, db); double sum = 0, inv; int i, j; unsigned char* a_ptr = da->data.u8; unsigned char* b_ptr = db->data.u8; switch (flag) { case CCV_L1_NORM: #define for_block(_for_set, _for_get) \ for (i = 0; i < da->rows; i++) \ { \ for (j = 0; j < da->cols; j++) \ sum += _for_get(a_ptr, j, 0); \ a_ptr += da->step; \ } \ inv = 1.0 / sum; \ a_ptr = da->data.u8; \ for (i = 0; i < da->rows; i++) \ { \ for (j = 0; j < da->cols; j++) \ _for_set(b_ptr, j, _for_get(a_ptr, j, 0) * inv, 0); \ a_ptr += da->step; \ b_ptr += db->step; \ } ccv_matrix_setter(db->type, ccv_matrix_getter, da->type, for_block); #undef for_block break; case CCV_L2_NORM: #define for_block(_for_set, _for_get) \ for (i = 0; i < da->rows; i++) \ { \ for (j = 0; j < da->cols; j++) \ sum += _for_get(a_ptr, j, 0) * _for_get(a_ptr, j, 0); \ a_ptr += da->step; \ } \ sum = sqrt(sum); \ inv = 1.0 / sum; \ a_ptr = da->data.u8; \ for (i = 0; i < da->rows; i++) \ { \ for (j = 0; j < da->cols; j++) \ _for_set(b_ptr, j, _for_get(a_ptr, j, 0) * inv, 0); \ a_ptr += da->step; \ b_ptr += db->step; \ } ccv_matrix_setter(db->type, ccv_matrix_getter, da->type, for_block); #undef for_block break; } return db->tag.f64 = sum; }
double ccv_variance(ccv_matrix_t* mat) { ccv_dense_matrix_t* dmt = ccv_get_dense_matrix(mat); double mean = 0, variance = 0; unsigned char* m_ptr = dmt->data.u8; int i, j, ch = CCV_GET_CHANNEL(dmt->type); #define for_block(_, _for_get) \ for (i = 0; i < dmt->rows; i++) \ { \ for (j = 0; j < dmt->cols * ch; j++) \ { \ mean += _for_get(m_ptr, j, 0); \ variance += _for_get(m_ptr, j, 0) * _for_get(m_ptr, j, 0); \ } \ m_ptr += dmt->step; \ } ccv_matrix_getter(dmt->type, for_block); #undef for_block mean = mean / (dmt->rows * dmt->cols * ch); variance = variance / (dmt->rows * dmt->cols * ch); return variance - mean * mean; }
int ccv_any_nan(ccv_matrix_t *a) { ccv_dense_matrix_t* da = ccv_get_dense_matrix(a); assert((da->type & CCV_32F) || (da->type & CCV_64F)); int ch = CCV_GET_CHANNEL(da->type); int i; if (da->type & CCV_32F) { for (i = 0; i < da->rows * da->cols * ch; i++) #ifdef isnanf if (isnanf(da->data.f32[i])) #else if (isnan(da->data.f32[i])) #endif return i + 1; } else { for (i = 0; i < da->rows * da->cols * ch; i++) if (isnan(da->data.f64[i])) return i + 1; } return 0; }
void ccv_visualize(ccv_matrix_t* a, ccv_dense_matrix_t** b, int type) { ccv_dense_matrix_t* da = ccv_get_dense_matrix(a); ccv_declare_derived_signature(sig, da->sig != 0, ccv_sign_with_literal("ccv_visualize"), da->sig, CCV_EOF_SIGN); ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, da->rows, da->cols, CCV_8U | CCV_C1, CCV_8U | CCV_C1, sig); ccv_object_return_if_cached(, db); ccv_dense_matrix_t* dc = 0; if (CCV_GET_CHANNEL(da->type) > CCV_C1) { ccv_flatten(da, (ccv_matrix_t**)&dc, 0, 0); da = dc; } int i, j; double minval = DBL_MAX, maxval = -DBL_MAX; unsigned char* aptr = da->data.u8; unsigned char* bptr = db->data.u8; #define for_block(_, _for_get) \ for (i = 0; i < da->rows; i++) \ { \ for (j = 0; j < da->cols; j++) \ { \ minval = ccv_min(minval, _for_get(aptr, j, 0)); \ maxval = ccv_max(maxval, _for_get(aptr, j, 0)); \ } \ aptr += da->step; \ } \ aptr = da->data.u8; \ for (i = 0; i < da->rows; i++) \ { \ for (j = 0; j < da->cols; j++) \ bptr[j] = ccv_clamp((_for_get(aptr, j, 0) - minval) * 255.0 / (maxval - minval), 0, 255); \ aptr += da->step; \ bptr += db->step; \ } ccv_matrix_getter(da->type, for_block); #undef for_block if (dc != 0) ccv_matrix_free(dc); }
void ccv_shift(ccv_matrix_t* a, ccv_matrix_t** b, int type, int lr, int rr) { ccv_dense_matrix_t* da = ccv_get_dense_matrix(a); ccv_declare_derived_signature(sig, da->sig != 0, ccv_sign_with_format(64, "ccv_shift(%d,%d)", lr, rr), da->sig, CCV_EOF_SIGN); type = (type == 0) ? CCV_GET_DATA_TYPE(da->type) | CCV_GET_CHANNEL(da->type) : CCV_GET_DATA_TYPE(type) | CCV_GET_CHANNEL(da->type); ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, da->rows, da->cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(da->type), type, sig); ccv_object_return_if_cached(, db); int i, j, ch = CCV_GET_CHANNEL(da->type); unsigned char* aptr = da->data.u8; unsigned char* bptr = db->data.u8; #define for_block(_for_get, _for_set) \ for (i = 0; i < da->rows; i++) \ { \ for (j = 0; j < da->cols * ch; j++) \ { \ _for_set(bptr, j, _for_get(aptr, j, lr), rr); \ } \ aptr += da->step; \ bptr += db->step; \ } ccv_matrix_getter(da->type, ccv_matrix_setter, db->type, for_block); #undef for_block }
void ccv_zero(ccv_matrix_t* mat) { ccv_dense_matrix_t* dmt = ccv_get_dense_matrix(mat); memset(dmt->data.u8, 0, dmt->step * dmt->rows); }