// Mahalanobis distance
float nv_mahalanobis(const nv_cov_t *cov, const nv_matrix_t *x, int xm)
{
	int n;
	nv_matrix_t *y = nv_matrix_alloc(x->n, 1);
	nv_matrix_t *x2 = nv_matrix_alloc(x->n, 1);
	float distance;
	float delta2 = 0.0f;

	nv_matrix_zero(y);
	nv_matrix_zero(x2);
	for (n = 0; n < x2->n; ++n) {
		NV_MAT_V(x2, 0, n) = NV_MAT_V(x, xm, n) - NV_MAT_V(cov->u, 0, n);
	}
	nv_gemv(y, 0, NV_MAT_TR, cov->eigen_vec, x2, xm);
	for (n = 0; n < x->n; ++n) {
		float ev = NV_MAT_V(cov->eigen_val, n, 0);
		float xv = NV_MAT_V(y, 0, n);
		delta2 += (xv * xv) / ev;
	}

	distance = sqrtf(delta2);
	nv_matrix_free(&x2);
	nv_matrix_free(&y);

	return distance;
}
static float tangent_angle(float r, 
						   float y, float x,
						   const nv_matrix_t *points, int pc)
{
	int i, dot_m = 0;
	float tan_angle;
	int info;
#if 0
	nv_matrix_t *dot = nv_matrix_alloc(2, (int)(2.0f * r * 2.0f *r));
#else
	nv_matrix_t *dot = nv_matrix_alloc(2, 10 * 8);
#endif
	nv_matrix_t *test_val = nv_matrix_alloc(2, 1);
	nv_matrix_t *test_ret = nv_matrix_alloc(2, 1);
	nv_cov_t *cov = nv_cov_alloc(2);

	NV_MAT_V(dot, 0, 0) = 0.0f;
	NV_MAT_V(dot, 0, 1) = 0.0f;
	++dot_m;

	for (i = 0; i < pc; ++i) {
		float dy = NV_MAT_V(points, i, 0) - y;
		float dx = NV_MAT_V(points, i, 1) - x;
#if 0
		if ((dx * dx + dy * dy) <= r * r) {
#else
		if ((dx * dx + dy * dy) <= 4.0f * 4.0f) {
#endif
			NV_MAT_V(dot, dot_m, 0) = dy;
			NV_MAT_V(dot, dot_m, 1) = dx;
			++dot_m;
		}
	}
	nv_matrix_m(dot, dot_m);
	nv_cov(cov->cov, cov->u, cov->s, dot);
	info = nv_eigen_sym(cov->eigen_vec, cov->eigen_val, cov->cov, 50);
	NV_MAT_V(test_val, 0, 0) = 0.0f;
	NV_MAT_V(test_val, 0, 1) = 1.0f;
	nv_gemv(test_ret, 0, NV_MAT_TR, cov->eigen_vec, test_val, 0);

	y = NV_MAT_V(test_ret, 0, 0);
	x = NV_MAT_V(test_ret, 0, 1);
/*
	if (x < 0.0f) {
		x *= -1.0f;
		y *= -1.0f;
	}
*/
	tan_angle = atan2f(x, y);
/*
	if (tan_angle < 0.0f) {
		tan_angle = 2.0f * NV_PI + tan_angle;
	}
*/
	nv_matrix_free(&dot);
	nv_matrix_free(&test_val);
	nv_matrix_free(&test_ret);
	nv_cov_free(&cov);

	return tan_angle;
}
#endif

nv_shapecontext_t *nv_shapecontext_alloc(int n)
{
	nv_shapecontext_t *sctx = (nv_shapecontext_t *)nv_malloc(sizeof(nv_shapecontext_t));
	sctx->sctx = nv_matrix3d_list_alloc(1, NV_SC_LOG_R_BIN, NV_SC_THETA_BIN, n);
	sctx->tan_angle = nv_matrix_alloc(1, n);
	sctx->coodinate = nv_matrix_alloc(2, n);
	sctx->radius = nv_matrix_alloc(1, n);

	return sctx;
}