void QuadTree_delete(QuadTree q){ int i, dim; if (!q) return; dim = q->dim; FREE(q->center); FREE(q->average); if (q->data) FREE(q->data); if (q->qts){ for (i = 0; i < 1<<dim; i++){ QuadTree_delete(q->qts[i]); } FREE(q->qts); } SingleLinkedList_delete(q->l, node_data_delete); FREE(q); }
static mat barnes_hut(mat z) { mat lz = mat_new(z->r, z->c); real* x = (real*) malloc(sizeof(real)*z->r*z->c); real *center = NULL, *supernode_wgts = NULL, *distances = NULL; real bh = 0.65, counts = 0; /* Barnes-Hut constant, if width(snode)/dist[i,snode] < bh, treat snode as a supernode.*/ int flag, nsuper, nsupermax, dim = z->c, max_qtree_level = 10; //max_qtree_level, like bh, should also be a command line argument QuadTree qt = NULL; int i, j, node; for(i = 0; i < z->r; i++) { for(j = 0; j < z->c; j++) { x[i*z->c + j] = z->m[mindex(i,j,z)]; } } qt = QuadTree_new_from_point_list(dim, z->r, max_qtree_level, x, NULL); for(i = 0; i < z->r; i++) { QuadTree_get_supernodes(qt, bh, &(x[dim*i]), i, &nsuper, &nsupermax, ¢er, &supernode_wgts, &distances, &counts, &flag); for(j = 0; j < dim; j++) { for(node = 0; node < nsuper; node++) { if(distances[node] > EPSILON) { lz->m[mindex(i,j,lz)] += supernode_wgts[node] * (z->m[mindex(i,j,z)]-center[node*dim+j]) / distances[node]; } else { lz->m[mindex(i,j,lz)] = 0; } } } } free(x); free(center); free(supernode_wgts); free(distances); QuadTree_delete(qt); return lz; }
static mat barnes_hut_cluster(mat z, mat dij, int* clusters, int power) { mat lz = mat_new(z->r, z->c); int k = dij->r; int n = z->r; int i, j, qt_i, node; real** x = (real**) malloc(sizeof(real*)*k); real** wgts = (real**) malloc(sizeof(real*)*k); real* x_all = (real*) malloc(sizeof(real)*z->r*z->c); real *center = NULL, *supernode_wgts = NULL, *distances = NULL; real bh = 0.65, counts = 0; int flag, nsuper, nsupermax, dim = z->c, max_qtree_level = 10; QuadTree* qt = (QuadTree*) malloc(sizeof(QuadTree)*2*k); int* sizes = (int*) malloc(sizeof(int)*k); int* curr_loc = (int*) malloc(sizeof(int)*k); iarrset(sizes,k,0); iarrset(curr_loc,k,0); for(i = 0; i < n; i++) { sizes[clusters[i]]++; } for(i = 0; i < k; i++) { x[i] = (real*) malloc(sizeof(real)*sizes[i]*z->c); wgts[i] = (real*) malloc(sizeof(real)*sizes[i]); } for(i = 0; i < z->r; i++) { for(j = 0; j < z->c; j++) { x_all[i*z->c+j] = z->m[mindex(i,j,z)]; } } for(i = 0; i < n; i++) { int cluster = clusters[i]; for(j = 0; j < z->c; j++) { x[cluster][curr_loc[cluster]*z->c+j] = z->m[mindex(i,j,z)]; } curr_loc[cluster]++; } iarrset(curr_loc,k,0); for(i = 0; i < n; i++) { int cluster = clusters[i]; wgts[cluster][curr_loc[cluster]] = dij->m[mindex(cluster,i,dij)] < EPSILON ? 0 : 1.0/pow(dij->m[mindex(cluster,i,dij)],power-1); curr_loc[cluster]++; } for(i = 0; i < k; i++) { qt[i] = QuadTree_new_from_point_list(dim, sizes[i], max_qtree_level, x[i], NULL); } for(i = 0; i < k; i++) { qt[i+k] = QuadTree_new_from_point_list(dim, sizes[i], max_qtree_level, x[i], wgts[i]); } for(i = 0; i < z->r; i++) { for(qt_i = 0; qt_i < k; qt_i++) { double d = dij->m[mindex(qt_i,i,dij)]; if(d < EPSILON) { //Node i is the center of some cluster QuadTree_get_supernodes(qt[qt_i+k], bh, &(x_all[dim*i]), -1, &nsuper, &nsupermax, ¢er, &supernode_wgts, &distances, &counts, &flag); d = 1; } else { QuadTree_get_supernodes(qt[qt_i], bh, &(x_all[dim*i]), -1, &nsuper, &nsupermax, ¢er, &supernode_wgts, &distances, &counts, &flag); d = 1.0 / pow(d,power-1); } for(j = 0; j < dim; j++) { for(node = 0; node < nsuper; node++) { if(distances[node] > EPSILON && d > EPSILON) lz->m[mindex(i,j,lz)] += d*supernode_wgts[node] * (z->m[mindex(i,j,z)]-center[node*dim+j]) / distances[node]; } } } } for(i = 0; i < k; i++) { free(x[i]); free(wgts[i]); } for(i = 0; i < 2*k; i++) { QuadTree_delete(qt[i]); } free(qt); free(sizes); free(curr_loc); free(x_all); free(center); free(distances); free(supernode_wgts); return lz; }