void annPlaneSplit( // split points by a plane ANNpointArray pa, // points to split ANNidxArray pidx, // point indices int n, // number of points int d, // dimension along which to split ANNcoord cv, // cutting value int &br1, // first break (values < cv) int &br2) // second break (values == cv) { int l = 0; int r = n-1; for(;;) { // partition pa[0..n-1] about cv while (l < n && PA(l,d) < cv) l++; while (r >= 0 && PA(r,d) >= cv) r--; if (l > r) break; PASWAP(l,r); l++; r--; } br1 = l; // now: pa[0..br1-1] < cv <= pa[br1..n-1] r = n-1; for(;;) { // partition pa[br1..n-1] about cv while (l < n && PA(l,d) <= cv) l++; while (r >= br1 && PA(r,d) > cv) r--; if (l > r) break; PASWAP(l,r); l++; r--; } br2 = l; // now: pa[br1..br2-1] == cv < pa[br2..n-1] }
void annMedianSplit( ANNpointArray pa, // points to split ANNidxArray pidx, // point indices int n, // number of points int d, // dimension along which to split ANNcoord &cv, // cutting value int n_lo) // split into n_lo and n-n_lo { int l = 0; // left end of current subarray int r = n-1; // right end of current subarray while (l < r) { register int i = (r+l)/2; // select middle as pivot register int k; if (PA(i,d) > PA(r,d)) // make sure last > pivot PASWAP(i,r) PASWAP(l,i); // move pivot to first position ANNcoord c = PA(l,d); // pivot value i = l; k = r; for(;;) { // pivot about c while (PA(++i,d) < c) ; while (PA(--k,d) > c) ; if (i < k) PASWAP(i,k) else break; } PASWAP(l,k); // pivot winds up in location k if (k > n_lo) r = k-1; // recurse on proper subarray else if (k < n_lo) l = k+1; else break; // got the median exactly } if (n_lo > 0) { // search for next smaller item ANNcoord c = PA(0,d); // candidate for max int k = 0; // candidate's index for (int i = 1; i < n_lo; i++) { if (PA(i,d) > c) { c = PA(i,d); k = i; } } PASWAP(n_lo-1, k); // max among pa[0..n_lo-1] to pa[n_lo-1] } // cut value is midpoint value cv = (PA(n_lo-1,d) + PA(n_lo,d))/2.0; }
void annBoxSplit( // split points by a box ANNpointArray pa, // points to split ANNidxArray pidx, // point indices int n, // number of points int dim, // dimension of space ANNorthRect &box, // the box int &n_in) // number of points inside (returned) { int l = 0; int r = n-1; for(;;) { // partition pa[0..n-1] about box while (l < n && box.inside(dim, PP(l))) l++; while (r >= 0 && !box.inside(dim, PP(r))) r--; if (l > r) break; PASWAP(l,r); l++; r--; } n_in = l; // now: pa[0..n_in-1] inside and rest outside }
void annPlaneSplit( // split points by a plane ES_INFO* es_info, ANNpointArray pa, // points to split ANNidxArray pidx, // point indices int n, // number of points int d, // dimension along which to split ANNcoord cv, // cutting value int &br1, // first break (values < cv) int &br2) // second break (values == cv) { int l = 0; int r = n-1; for(;;) { // partition pa[0..n-1] about cv #if 1 // es code es_info->get_value_by_index(pidx[l]); #endif while (l < n && PA(l,d) < cv) { l++; #if 1 // es code es_info->get_value_by_index(pidx[l]); #endif } #if 1 // es code es_info->get_value_by_index(pidx[r]); #endif while (r >= 0 && PA(r,d) >= cv) { r--; #if 1 // es code es_info->get_value_by_index(pidx[r]); #endif } if (l > r) break; PASWAP(l,r); l++; r--; } br1 = l; // now: pa[0..br1-1] < cv <= pa[br1..n-1] r = n-1; for(;;) { // partition pa[br1..n-1] about cv #if 1 // es code es_info->get_value_by_index(pidx[l]); #endif while (l < n && PA(l,d) <= cv) { l++; #if 1 // es code es_info->get_value_by_index(pidx[l]); #endif } #if 1 // es code es_info->get_value_by_index(pidx[r]); #endif while (r >= br1 && PA(r,d) > cv) { r--; #if 1 // es code es_info->get_value_by_index(pidx[r]); #endif } if (l > r) break; PASWAP(l,r); l++; r--; } br2 = l; // now: pa[br1..br2-1] == cv < pa[br2..n-1] }
/************************************************ Partition a range of data points by manipulation the permutation index. The sliding midpoint rule is used for the partitioning. Params: pa : data points pidx : permutation index of data points no_dims: number of dimensions start_idx : index of first data point to use n : number of data points bbox : bounding box of data points cut_dim : dimension used for partition (return) cut_val : value of cutting point (return) n_lo : number of point below cutting plane (return) ************************************************/ int partition_float(float *pa, uint32_t *pidx, int8_t no_dims, uint32_t start_idx, uint32_t n, float *bbox, int8_t *cut_dim, float *cut_val, uint32_t *n_lo) { int8_t dim = 0, i; uint32_t p, q, i2; float size = 0, min_val, max_val, split, side_len, cur_val; uint32_t end_idx = start_idx + n - 1; /* Find largest bounding box side */ for (i = 0; i < no_dims; i++) { side_len = bbox[2 * i + 1] - bbox[2 * i]; if (side_len > size) { dim = i; size = side_len; } } min_val = bbox[2 * dim]; max_val = bbox[2 * dim + 1]; /* Check for zero length or inconsistent */ if (min_val >= max_val) return 1; /* Use middle for splitting */ split = (min_val + max_val) / 2; /* Partition all data points around middle */ p = start_idx; q = end_idx; while (p <= q) { if (PA(p, dim) < split) { p++; } else if (PA(q, dim) >= split) { /* Guard for underflow */ if (q > 0) { q--; } else { break; } } else { PASWAP(p, q); p++; q--; } } /* Check for empty splits */ if (p == start_idx) { /* No points less than split. Split at lowest point instead. Minimum 1 point will be in lower box. */ uint32_t j = start_idx; split = PA(j, dim); for (i2 = start_idx + 1; i2 <= end_idx; i2++) { /* Find lowest point */ cur_val = PA(i2, dim); if (cur_val < split) { j = i2; split = cur_val; } } PASWAP(j, start_idx); p = start_idx + 1; } else if (p == end_idx + 1) { /* No points greater than split. Split at highest point instead. Minimum 1 point will be in higher box. */ uint32_t j = end_idx; split = PA(j, dim); for (i2 = start_idx; i2 < end_idx; i2++) { /* Find highest point */ cur_val = PA(i2, dim); if (cur_val > split) { j = i2; split = cur_val; } } PASWAP(j, end_idx); p = end_idx; } /* Set return values */ *cut_dim = dim; *cut_val = split; *n_lo = p - start_idx; return 0; }