local void upward_pass(kdxptr kd, int cell) { kdnode *ntab = kd->ntab; if (ntab[cell].dim != -1) { // not a terminal node? upward_pass(kd, Lower(cell)); upward_pass(kd, Upper(cell)); combine_nodes(&ntab[cell], &ntab[Lower(cell)], &ntab[Upper(cell)]); } else // scan bodies in node set_bounds(&ntab[cell].bnd, kd->bptr, ntab[cell].first, ntab[cell].last); }
void FMM2D::recalculate() { if (!m_tree) { build_tree(); } reset(); upward_pass(); downward_pass(); }
void FMM2D::calculate(bool precond) { reset(); m_make_prec = precond; build_tree(); upward_pass(); downward_pass(); m_make_prec = false; }
void build_kdtree(kdxptr kd, int nbucket) { int k, n, i, d, m, j, ct; kdnode *ntab; n = kd->ngas; k = 1; while (n > nbucket) { n = n>>1; k = k<<1; } kd->nnode = k<<1; kd->nsplit = k; ntab = kd->ntab = (kdnode *) allocate(kd->nnode * sizeof(kdnode)); ntab[KDROOT].first = 0; /* initialize root node */ ntab[KDROOT].last = kd->ngas-1; ntab[KDROOT].bnd = kd->bnd; i = KDROOT; ct = KDROOT; SetNext(ct); for ( ; ; ) { /* loop splitting nodes */ if (i < kd->nsplit) { d = 0; /* find longest dimension */ for (j=1; j<3; ++j) { if (ntab[i].bnd.maxb[j]-ntab[i].bnd.minb[j] > ntab[i].bnd.maxb[d]-ntab[i].bnd.minb[d]) d = j; } m = median_index(kd->bptr, d, ntab[i].first, ntab[i].last); ntab[i].dim = d; ntab[i].split = Pos(kd->bptr[m])[d]; ntab[Lower(i)].bnd = ntab[i].bnd; ntab[Lower(i)].bnd.maxb[d] = ntab[i].split; ntab[Lower(i)].first = ntab[i].first; ntab[Lower(i)].last = m-1; ntab[Upper(i)].bnd = ntab[i].bnd; ntab[Upper(i)].bnd.minb[d] = ntab[i].split; ntab[Upper(i)].first = m; ntab[Upper(i)].last = ntab[i].last; i = Lower(i); } else { ntab[i].dim = -1; SetNext(i); if (i == ct) break; } } upward_pass(kd, KDROOT); }