/* free the memory used by the vetting structure */ void mtsFreeWork (vetting_t ** w) { vetting_t *work = (*w); if (work->desired.X != -SPECIAL || work->desired.Y != -SPECIAL) { heap_free (work->untested.h, free); heap_destroy (&work->untested.h); heap_free (work->no_fix.h, free); heap_destroy (&work->no_fix.h); heap_free (work->no_hi.h, free); heap_destroy (&work->no_hi.h); heap_free (work->hi_candidate.h, free); heap_destroy (&work->hi_candidate.h); } else { while (!vector_is_empty (work->untested.v)) free (vector_remove_last (work->untested.v)); vector_destroy (&work->untested.v); while (!vector_is_empty (work->no_fix.v)) free (vector_remove_last (work->no_fix.v)); vector_destroy (&work->no_fix.v); while (!vector_is_empty (work->no_hi.v)) free (vector_remove_last (work->no_hi.v)); vector_destroy (&work->no_hi.v); while (!vector_is_empty (work->hi_candidate.v)) free (vector_remove_last (work->hi_candidate.v)); vector_destroy (&work->hi_candidate.v); } free (work); (*w) = NULL; }
/* qloop takes a vector (or heap) of regions to check (checking) if they don't intersect * anything. If a region does intersect something, it is broken into * pieces that don't intersect that thing (if possible) which are * put back into the vector/heap of regions to check. * qloop returns false when it finds the first empty region * it returns true if it has exhausted the region vector/heap and never * found an empty area. */ static void qloop (struct query_closure *qc, rtree_t * tree, heap_or_vector res, bool is_vec) { BoxType *cbox; #ifndef NDEBUG int n; #endif while (!(qc->desired ? heap_is_empty (qc->checking.h) : vector_is_empty (qc->checking.v))) { cbox = qc->desired ? (BoxTypePtr)heap_remove_smallest (qc->checking.h) : (BoxTypePtr)vector_remove_last (qc->checking.v); if (setjmp (qc->env) == 0) { assert (box_is_good (cbox)); qc->cbox = cbox; #ifndef NDEBUG n = #endif r_search (tree, cbox, NULL, query_one, qc); assert (n == 0); /* nothing intersected with this tree, put it in the result vector */ if (is_vec) vector_append (res.v, cbox); else { if (qc->desired) heap_append (res.h, qc->desired, cbox); else vector_append (res.v, cbox); } return; /* found one - perhaps one answer is good enough */ } } }
void vector_set(kld_vector_t * v, int i, void * data) { if(vector_is_empty(v)) { v->data = (void **) calloc(DEFAULT_VECTOR_CAPACITY, sizeof(void*)); } v->data[i] = data; }
void * vector_get(kld_vector_t *v, int i) { // TODO Determine if this is acceptable functionality for all data structures if(vector_is_empty(v)) { return NULL; } return v->data[i]; }
void vector_insert_at(kld_vector_t * v, int i, void * data) { if(vector_is_empty(v)) { v->data = (void **) calloc(DEFAULT_VECTOR_CAPACITY, sizeof(void*)); } if (i > v->size) { // If the desired index is outside of our current size // We need to fill the vector up to the desired index point // Then insert the value we want. int idx; for(idx = v->size; idx < i; idx++) { // Grow if at capacity // TODO The following six lines could be refactored // with the others below. if(v->size == v->capacity) { vector_grow(v); } v->data[v->size] = NULL; v->size++; } } else { // If the desired index is within our current size // We want to shift all the values after the insertion point to the right. // Then insert our desired value. int idx; for(idx = v->size; idx > i; idx--) { v->data[idx] = v->data[idx-1]; } } // Grow if at capacity // TODO The following six lines could be refactored // with the others above. if(v->size == v->capacity) { vector_grow(v); } v->data[i] = data; v->size++; }
} END_TEST START_TEST(test_graph_node_neighbors) { kld_graph_t * g = (kld_graph_t *) new_graph(); int data = 1; kld_graph_node_t * n1 = (kld_graph_node_t *) new_graph_node(g); kld_graph_node_t * n2 = (kld_graph_node_t *) new_graph_node(g); kld_graph_node_t * n3 = (kld_graph_node_t *) new_graph_node(g); kld_vector_t * v = new_vector(); vector_append(v, NULL); vector_append(v, &data); vector_append(v, NULL); matrix_append_row(g->adj_matrix, v); kld_vector_t * v2 = new_vector(); vector_append(v2, &data); vector_append(v2, NULL); vector_append(v2, NULL); matrix_append_row(g->adj_matrix, v2); kld_vector_t * v3 = new_vector(); vector_append(v3, NULL); vector_append(v3, NULL); vector_append(v3, NULL); matrix_append_row(g->adj_matrix, v3); fail_if(graph_is_empty(g), "Graph should not be empty upon initialization"); kld_vector_t * nbrs1 = (kld_vector_t *) graph_node_neighbors(g, n1); kld_vector_t * nbrs2 = (kld_vector_t *) graph_node_neighbors(g, n2); kld_vector_t * nbrs3 = (kld_vector_t *) graph_node_neighbors(g, n3); fail_if(vector_get(nbrs1, 0) != n2, "After appending an edge from n1 to n2 in the graph, it should mark n2 as a neighbor of n1."); fail_if(vector_get(nbrs2, 0) != n1, "After appending an edge from n2 to n1 in the graph, it should mark n1 as a neighbor of n2."); fail_if(!vector_is_empty(nbrs3), "After appending null edges to the graph, it should have no neighbors"); } END_TEST
/* returns some empty spaces in 'region' (or former narrowed regions) * that may hold a feature with the specified radius and keepaway * It tries first to find Completely empty regions (which are appended * to the free_space_vec vector). If that fails, it looks for regions * filled only by objects generated by the previous pass (which are * appended to the lo_conflict_space_vec vector). Then it looks for * regions that are filled by objects generated during *this* pass * (which are appended to the hi_conflict_space_vec vector). The * current pass identity is given by 'is_odd'. As soon as one completely * free region is found, it returns with that answer. It saves partially * searched regions in vectors "untested", "no_fix", "no_hi", and * "hi_candidate" which can be passed to future calls of this function * to search harder for such regions if the computation becomes * necessary. */ vetting_t * mtspace_query_rect (mtspace_t * mtspace, const BoxType * region, Coord radius, Coord keepaway, vetting_t * work, vector_t * free_space_vec, vector_t * lo_conflict_space_vec, vector_t * hi_conflict_space_vec, bool is_odd, bool with_conflicts, CheapPointType *desired) { struct query_closure qc; /* pre-assertions */ assert (free_space_vec); assert (lo_conflict_space_vec); assert (hi_conflict_space_vec); /* search out to anything that might matter */ if (region) { BoxType *cbox; assert (work == NULL); assert (box_is_good (region)); assert(vector_is_empty (free_space_vec)); assert(vector_is_empty (lo_conflict_space_vec)); assert(vector_is_empty (hi_conflict_space_vec)); work = (vetting_t *) malloc (sizeof (vetting_t)); work->keepaway = keepaway; work->radius = radius; cbox = (BoxType *) malloc (sizeof (BoxType)); *cbox = bloat_box (region, keepaway + radius); if (desired) { work->untested.h = heap_create (); work->no_fix.h = heap_create (); work->hi_candidate.h = heap_create (); work->no_hi.h =heap_create (); assert (work->untested.h && work->no_fix.h && work->no_hi.h && work->hi_candidate.h); heap_insert (work->untested.h, 0, cbox); work->desired = *desired; } else { work->untested.v = vector_create (); work->no_fix.v = vector_create (); work->hi_candidate.v = vector_create (); work->no_hi.v = vector_create (); assert (work->untested.v && work->no_fix.v && work->no_hi.v && work->hi_candidate.v); vector_append (work->untested.v, cbox); work->desired.X = work->desired.Y = -SPECIAL; } return work; } qc.keepaway = work->keepaway; qc.radius = work->radius; if (work->desired.X == -SPECIAL && work->desired.Y == -SPECIAL) qc.desired = NULL; else qc.desired = &work->desired; /* do the query */ do { heap_or_vector temporary = {free_space_vec}; /* search the fixed object tree discarding any intersections * and placing empty regions in the no_fix vector. */ qc.checking = work->untested; qc.touching.v = NULL; qloop (&qc, mtspace->ftree, work->no_fix, false); /* search the hi-conflict tree placing intersectors in the * hi_candidate vector (if conflicts are allowed) and * placing empty regions in the no_hi vector. */ qc.checking.v = work->no_fix.v; qc.touching.v = with_conflicts ? work->hi_candidate.v : NULL; qc.touch_is_vec = false; qloop (&qc, is_odd ? mtspace->otree : mtspace->etree, work->no_hi, false); /* search the lo-conflict tree placing intersectors in the * lo-conflict answer vector (if conflicts allowed) and * placing emptry regions in the free-space answer vector. */ qc.checking = work->no_hi; /* XXX lo_conflict_space_vec will be treated like a heap! */ qc.touching.v = (with_conflicts ? lo_conflict_space_vec : NULL); qc.touch_is_vec = true; qloop (&qc, is_odd ? mtspace->etree : mtspace->otree, temporary, true); /* qloop (&qc, is_odd ? mtspace->etree : mtspace->otree, (heap_or_vector)free_space_vec, true); */ if (!vector_is_empty (free_space_vec)) { if (qc.desired) { if (heap_is_empty (work->untested.h)) break; } else { if (vector_is_empty (work->untested.v)) break; } return work; } /* finally check the hi-conflict intersectors against the * lo-conflict tree discarding intersectors (two types of conflict is real bad) * and placing empty regions in the hi-conflict answer vector. */ if (with_conflicts) { heap_or_vector temporary = {hi_conflict_space_vec}; qc.checking = work->hi_candidate; qc.touching.v = NULL; qloop (&qc, is_odd ? mtspace->etree : mtspace->otree, temporary, true); /* qloop (&qc, is_odd ? mtspace->etree : mtspace->otree, */ /* (heap_or_vector)hi_conflict_space_vec, true); */ } } while (!(qc.desired ? heap_is_empty(work->untested.h) : vector_is_empty (work->untested.v))); if (qc.desired) { if (heap_is_empty (work->no_fix.h) && heap_is_empty (work->no_hi.h) && heap_is_empty (work->hi_candidate.h)) { mtsFreeWork (&work); return NULL; } } else { if (vector_is_empty (work->no_fix.v) && vector_is_empty (work->no_hi.v) && vector_is_empty (work->hi_candidate.v)) { mtsFreeWork (&work); return NULL; } } return work; }