/* * call-seq: * difcost(GSL::Matrix, GSL::Matrix) -> Float * * Calculates the geometric distance between two matrices */ static VALUE difcost_wrap(VALUE obj, VALUE matrix1, VALUE matrix2) { gsl_matrix *m1, *m2; Data_Get_Struct(matrix1, gsl_matrix, m1); Data_Get_Struct(matrix2, gsl_matrix, m2); return rb_float_new(difcost(m1, m2)); }
static double update(gsl_matrix *v, gsl_matrix *w, gsl_matrix *h) { double dist = 0; gsl_matrix *wt=NULL, *ht=NULL, *wh=NULL; gsl_matrix *w_h=NULL, *wt_w=NULL; gsl_matrix *wt_v = NULL; gsl_matrix *v_ht=NULL, *wt_w_h=NULL, *w_h_ht=NULL; wt = gsl_matrix_alloc(w->size2, w->size1); gsl_matrix_transpose_memcpy(wt, w); ht = gsl_matrix_alloc(h->size2, h->size1); gsl_matrix_transpose_memcpy(ht, h); // wt * v wt_v = mm(wt, v); // wt * w * h wt_w = mm(wt, w); wt_w_h = mm(wt_w, h); gsl_matrix_free(wt_w); // h = h.mul_elements(wt * v).div_elements(wt * w * h) gsl_matrix_mul_elements(h, wt_v); gsl_matrix_div_elements(h, wt_w_h); gsl_matrix_free(wt_v); gsl_matrix_free(wt_w_h); // v * ht v_ht = mm(v, ht); // w * h * ht w_h = mm(w, h); w_h_ht = mm(w_h, ht); gsl_matrix_free(w_h); // w = w.mul_elements(v * ht).div_elements(w * h * ht) gsl_matrix_mul_elements(w, v_ht); gsl_matrix_div_elements(w, w_h_ht); gsl_matrix_free(v_ht); gsl_matrix_free(w_h_ht); gsl_matrix_free(wt); gsl_matrix_free(ht); wh = mm(w, h); dist = difcost(v, wh); gsl_matrix_free(wh); // w and h were modified in place return dist; }