void diy::detail::KDTreeSamplingPartition<Block,Point>:: operator()(Block* b, const diy::ReduceProxy& srp, const KDTreePartners& partners) const { int dim; if (srp.round() < partners.rounds()) dim = partners.dim(srp.round()); else dim = partners.dim(srp.round() - 1); if (srp.round() == partners.rounds()) update_links(b, srp, dim, partners.sub_round(srp.round() - 2), partners.swap_rounds(), partners.wrap, partners.domain); // -1 would be the "uninformative" link round else if (partners.swap_round(srp.round()) && partners.sub_round(srp.round()) < 0) // link round { dequeue_exchange(b, srp, dim); // from the swap round split_to_neighbors(b, srp, dim); } else if (partners.swap_round(srp.round())) { Samples samples; receive_samples(b, srp, samples); enqueue_exchange(b, srp, dim, samples); } else if (partners.sub_round(srp.round()) == 0) { if (srp.round() > 0) { int prev_dim = dim - 1; if (prev_dim < 0) prev_dim += dim_; update_links(b, srp, prev_dim, partners.sub_round(srp.round() - 2), partners.swap_rounds(), partners.wrap, partners.domain); // -1 would be the "uninformative" link round } compute_local_samples(b, srp, dim); } else if (partners.sub_round(srp.round()) < (int) partners.histogram.rounds()/2) // we are reusing partners class, so really we are talking about the samples rounds here { Samples samples; add_samples(b, srp, samples); srp.enqueue(srp.out_link().target(0), samples); } else { Samples samples; add_samples(b, srp, samples); if (samples.size() != 1) { // pick the median std::nth_element(samples.begin(), samples.begin() + samples.size()/2, samples.end()); std::swap(samples[0], samples[samples.size()/2]); //std::sort(samples.begin(), samples.end()); //samples[0] = (samples[samples.size()/2] + samples[samples.size()/2 + 1])/2; samples.resize(1); } forward_samples(b, srp, samples); } }
/* Insert a new entry in the skip list. Bad things happen if you try to insert a duplicate. */ static void insert_check(const char *ref) { MEM *chk, *node, *prev; int n; chk = alloc_memcheck_node(ref); /* Empty list */ if (!memcheck_head->links[0]) { for (n = 0; n < chk->link_count; n += 1) memcheck_head->links[n] = chk; return; } /* Find where to insert the new node, using a simple linked list walk. Ideally, this should be using a standard skip list insertion algorithm to avoid O(N) performance, but insertions occur infrequently once the mush is running, so I don't care that much. */ for (node = memcheck_head->links[0], prev = NULL; node; prev = node, node = node->links[0]) { if (strcmp(ref, node->ref_name) < 0) { if (prev) { chk->links[0] = node; prev->links[0] = chk; } else { /* First element */ chk->links[0] = memcheck_head->links[0]; memcheck_head->links[0] = chk; } break; } } if (!node) /* Insert at end of list */ prev->links[0] = chk; /* Now adjust forward pointers */ update_links(memcheck_head, chk); }
/* Update forward skip links for a new element of the list */ static void update_links(MEM *src, MEM *newnode) { int n = min(src->link_count, newnode->link_count) - 1; for (; n > 0; n -= 1) { if (!src->links[n]) src->links[n] = newnode; else { int cmp = strcmp(src->links[n]->ref_name, newnode->ref_name); if (cmp < 0) { /* Advance along the skip list and adjust as needed. */ update_links(src->links[n], newnode); return; } else if (cmp > 0) { /* Insert into skip chain */ newnode->links[n] = src->links[n]; src->links[n] = newnode; } } } }