node<P> batch_create(DistanceCallback& dcb, v_array<P> points) { assert(points.index > 0); v_array<ds_node<P> > point_set; v_array<v_array<ds_node<P> > > stack; for (int i = 1; i < points.index; i++) { ds_node<P> temp; push(temp.dist, distance(dcb, points[0], points[i], std::numeric_limits<ScalarType>::max())); temp.p = points[i]; push(point_set,temp); } v_array<ds_node<P> > consumed_set; ScalarType max_dist = max_set(point_set); node<P> top = batch_insert (dcb, points[0], get_scale(max_dist), get_scale(max_dist), point_set, consumed_set, stack); for (int i = 0; i<consumed_set.index;i++) free(consumed_set[i].dist.elements); free(consumed_set.elements); for (int i = 0; i<stack.index;i++) free(stack[i].elements); free(stack.elements); free(point_set.elements); return top; }
template<class T> node<T> batch_create(const std::vector<T> &points, typename distfn<T>::Type distance, const double* dist_params, void* dist_extra) { v_array<ds_node<T> > point_set; v_array<v_array<ds_node<T> > > stack; ds_node<T> initial_pt; initial_pt.p = points[0]; for (std::vector<point>::size_type i = 1; i < points.size(); i++) { ds_node<T> temp; push(temp.dist, distance(points[0], points[i], std::numeric_limits< double >::max(), dist_params, dist_extra)); temp.p = points[i]; push(point_set,temp); } v_array< ds_node < T > > consumed_set; double max_dist = max_set(point_set); node<T> top = batch_insert(initial_pt, get_scale(max_dist), get_scale(max_dist), point_set, consumed_set, stack, distance, dist_params, dist_extra); for (int i = 0; i<consumed_set.index;i++) free(consumed_set[i].dist.elements); free(consumed_set.elements); for (int i = 0; i<stack.index;i++) free(stack[i].elements); free(stack.elements); free(point_set.elements); return top; }
node<T> batch_insert(const ds_node<T>& p, int max_scale, int top_scale, v_array< ds_node<T> >& point_set, v_array< ds_node<T> >& consumed_set, v_array<v_array< ds_node<T> > >& stack, typename distfn<T>::Type distance, const double* dist_params, void* dist_extra) { if (point_set.index == 0) { return new_leaf(p); } else { double max_dist = max_set(point_set); //O(|point_set|) int next_scale = min (max_scale - 1, get_scale(max_dist)); /* if ((next_scale == -2147483648) || (top_scale - next_scale > 100) ) { printf("whoawhoawhoa\n"); printf("max_set %f\n", max_dist); printf("next scale %d %d %d\n", max_scale-1, get_scale(max_dist), next_scale); //printf("p %f %f %f %f\n", p.p.pt1[0], p.p.pt1[1], p.p.pt2[0], p.p.pt2[1]); //printf("p %f %f\n", p.p.p[0], p.p.p[1]); //printf("ps %f %f %f %f\n", point_set[0].p.pt1[0], point_set[0].p.pt1[1], point_set[0].p.pt2[0], point_set[0].p.pt2[1]); printf("distance %f\n", distance(point_set[0].p, p.p, std::numeric_limits< double >::max(), dist_params, dist_extra)); }*/ if ((next_scale == -2147483648) || (top_scale - next_scale >= 100)) // We have points with distance 0. { v_array< node<T> > children; push(children,new_leaf(p)); while (point_set.index > 0) { push(children,new_leaf(point_set.last())); push(consumed_set,point_set.last()); point_set.decr(); } node<T> n = new_node(p); n.scale = 100; // A magic number meant to be larger than all scales. n.max_dist = 0; alloc(children,children.index); n.num_children = children.index; n.children = children.elements; return n; } else { v_array< ds_node<T> > far = pop(stack); split(point_set,far,max_scale); //O(|point_set|) node<T> child = batch_insert(p, next_scale, top_scale, point_set, consumed_set, stack, distance, dist_params, dist_extra); if (point_set.index == 0) { push(stack,point_set); point_set=far; return child; } else { node<T> n = new_node(p); v_array< node<T> > children; push(children, child); v_array<ds_node<T> > new_point_set = pop(stack); v_array<ds_node<T> > new_consumed_set = pop(stack); while (point_set.index != 0) { //O(|point_set| * num_children) ds_node<T> new_point_node = point_set.last(); T new_point = point_set.last().p; double new_dist = point_set.last().dist.last(); push(consumed_set, point_set.last()); point_set.decr(); dist_split(point_set, new_point_set, new_point, max_scale, distance, dist_params, dist_extra); //O(|point_saet|) dist_split(far,new_point_set,new_point,max_scale, distance, dist_params, dist_extra); //O(|far|) node<T> new_child = batch_insert(new_point_node, next_scale, top_scale, new_point_set, new_consumed_set, stack, distance, dist_params, dist_extra); new_child.parent_dist = new_dist; push(children, new_child); double fmax = dist_of_scale(max_scale); for(int i = 0; i< new_point_set.index; i++) //O(|new_point_set|) { new_point_set[i].dist.decr(); if (new_point_set[i].dist.last() <= fmax) push(point_set, new_point_set[i]); else push(far, new_point_set[i]); } for(int i = 0; i< new_consumed_set.index; i++) //O(|new_point_set|) { new_consumed_set[i].dist.decr(); push(consumed_set, new_consumed_set[i]); } new_point_set.index = 0; new_consumed_set.index = 0; } push(stack,new_point_set); push(stack,new_consumed_set); push(stack,point_set); point_set=far; n.scale = top_scale - max_scale; n.max_dist = max_set(consumed_set); alloc(children,children.index); n.num_children = children.index; n.children = children.elements; return n; } } } }
node<P> batch_insert(DistanceCallback& dcb, const P& p, int max_scale, int top_scale, v_array<ds_node<P> >& point_set, v_array<ds_node<P> >& consumed_set, v_array<v_array<ds_node<P> > >& stack) { if (point_set.index == 0) return new_leaf(p); else { ScalarType max_dist = max_set(point_set); //O(|point_set|) int next_scale = std::min(max_scale - 1, get_scale(max_dist)); if (next_scale == -2147483647-1) // We have points with distance 0. { v_array<node<P> > children; push(children,new_leaf(p)); while (point_set.index > 0) { push(children,new_leaf(point_set.last().p)); push(consumed_set,point_set.last()); point_set.decr(); } node<P> n = new_node(p); n.scale = 100; // A magic number meant to be larger than all scales. n.max_dist = 0; alloc(children,children.index); n.num_children = children.index; n.children = children.elements; return n; } else { v_array<ds_node<P> > far = pop(stack); split(point_set,far,max_scale); //O(|point_set|) node<P> child = batch_insert(dcb, p, next_scale, top_scale, point_set, consumed_set, stack); if (point_set.index == 0) { push(stack,point_set); point_set=far; return child; } else { node<P> n = new_node(p); v_array<node<P> > children; push(children, child); v_array<ds_node<P> > new_point_set = pop(stack); v_array<ds_node<P> > new_consumed_set = pop(stack); while (point_set.index != 0) { //O(|point_set| * num_children) P new_point = point_set.last().p; ScalarType new_dist = point_set.last().dist.last(); push(consumed_set, point_set.last()); point_set.decr(); dist_split(dcb,point_set,new_point_set,new_point,max_scale); //O(|point_saet|) dist_split(dcb,far,new_point_set,new_point,max_scale); //O(|far|) node<P> new_child = batch_insert(dcb, new_point, next_scale, top_scale, new_point_set, new_consumed_set, stack); new_child.parent_dist = new_dist; push(children, new_child); ScalarType fmax = dist_of_scale(max_scale); for(int i = 0; i< new_point_set.index; i++) //O(|new_point_set|) { new_point_set[i].dist.decr(); if (new_point_set[i].dist.last() <= fmax) push(point_set, new_point_set[i]); else push(far, new_point_set[i]); } for(int i = 0; i< new_consumed_set.index; i++) //O(|new_point_set|) { new_consumed_set[i].dist.decr(); push(consumed_set, new_consumed_set[i]); } new_point_set.index = 0; new_consumed_set.index = 0; } push(stack,new_point_set); push(stack,new_consumed_set); push(stack,point_set); point_set=far; n.scale = top_scale - max_scale; n.max_dist = max_set(consumed_set); alloc(children,children.index); n.num_children = children.index; n.children = children.elements; return n; } } } }