/** * add an mtree into an existing tree * * @param[in] parent handle to the parent to be added to * @param[in] h handle to the tree to add in * @returns handle of newly added (sub) tree * * this function is destructive in that the task is accomplished by copying * the values from the tree at h, and then freeing it. * */ H _m_add(H parent,H h) { L *pl,*l; H r; int x = _m_children(parent)+1; int i,levels = h.m->levels; H p = parent; Mindex d = parent.a.i; for (i=0;i<levels;i++) { __m_new_init(p,&r,&pl); l = _GET_LEVEL(h,i); N *np = __m_add_nodes(r,pl,l->nodes); N *n = &l->nP[0]; Mindex j = l->nodes; while (j--) { *np = *n; if (np->parenti == NULL_ADDR) np->parenti = 0; np->parenti += d; np++; n++; } d = pl->nodes-l->nodes; p.a.l++; } r.a = _m_child(parent,x); __m_free(h,0); //free h but not it's surfaces which were copied into the parent return r; }
/** * return the number of children of a given mtree node * * @param[in] h handle to the node * @returns child count */ int _m_children(H h) { Mlevel levels = h.m->levels; if (h.a.l >= levels) { raise_error("address too deep!"); } else if (h.a.l == levels-1) { return 0; } L *l = _GET_LEVEL(h,h.a.l+1); Mindex c = 0; Mindex i = 0,pi = h.a.i; Mindex max = l->nodes; N *n = &l->nP[0]; /* this works if nodes are sorted while (i < max && n->parenti != h.a.i) { n++;i++; } while (i < max && n->parenti == h.a.i) { n++;i++;c++; } */ while (i < max) { if (!(n->flags & TFLAG_DELETED) && pi == n->parenti) c++; n++;i++; } return c; }
/** * free the memory used by an mtree * * @param[in] h handle to mtree to free * @param[in] free_surface boolean to indicate whether to free the surface values */ void __m_free(H h,int free_surface) { int i = h.m->levels; while(i--) { L *l = _GET_LEVEL(h,i); Mindex j = l->nodes; if (free_surface) { while(j--) { N *n = _GET_NODE(h,l,j); if (n->flags & TFLAG_ALLOCATED) { free(n->surface); } } } free(l->nP); } free(h.m->lP); free(h.m); }
/** * free the memory used by an mtree * * @param[in] h handle to mtree to free * @param[in] free_surface boolean to indicate whether to free the surface values */ void __m_free(H h,int free_surface) { int i = h.m->levels; while(i--) { L *l = _GET_LEVEL(h,i); Mindex j = l->nodes; if (free_surface) { while(j--) { N *n = _GET_NODE(h,l,j); if (!(n->flags & TFLAG_REFERENCE)) { if (n->flags & TFLAG_SURFACE_IS_RECEPTOR) raise_error("mtree can't free receptor!"); if (n->flags & TFLAG_SURFACE_IS_TREE && !(n->flags & TFLAG_SURFACE_IS_RECEPTOR)) { _m_free(*(H *)n->surface); } if (n->flags & TFLAG_ALLOCATED) { free(n->surface); } } } } free(l->nP); } free(h.m->lP); free(h.m); }