void leaf_cut ( Leaf * leaf, int w, int h ) { gboolean b = leaf->w - w > leaf->h - h; if ( leaf->w - w > smallest.width ) leaf_new( leaf->x + w, leaf->y, leaf->w - w, b ? leaf->h : h ); if ( leaf->h - h > smallest.height ) leaf_new( leaf->x, leaf->y + h, b ? w : leaf->w, leaf->h - h ); g_sequence_remove_sorted( leaves_sorted_by_area, leaf, leaf_compare, AREA ); free( leaf ); }
/* * EFFECT: * - split leaf&lmb into two leaves:a & b * a&b are both the half of the lmb * * PROCESS: * - leaf: * +-----------------------------------+ * | 0 | 1 | 2 | 3 | 4 | 5 | * +-----------------------------------+ * * - split: * root * +--------+ * | 2 | * +--------+ * / \ * +-----------------+ +------------------+ * | 0 | 1 | 2 | | 3 | 4 | 5 | * +-----------------+ +------------------+ * nodea nodeb * * ENTER: * - leaf is already locked (L_WRITE) * EXITS: * - a is locked * - b is locked */ void leaf_split(void *tree, struct node *node, struct node **a, struct node **b, struct msg **split_key) { struct partition *pa; struct partition *pb; struct node *leafa; struct node *leafb; struct lmb *mb; struct lmb *mba; struct lmb *mbb; struct msg *sp_key = NULL; struct buftree *t = (struct buftree*)tree; leafa = node; pa = &leafa->parts[0]; /* split lmb of leaf to mba & mbb */ mb = pa->msgbuf; lmb_split(mb, &mba, &mbb, &sp_key); lmb_free(mb); /* reset leafa buffer */ pa->msgbuf = mba; /* new leafb */ NID nid = hdr_next_nid(t->hdr); leaf_new(t->hdr, nid, 0, 1, &leafb); leaf_msgbuf_init(leafb); cache_put_and_pin(t->cf, nid, leafb); pb = &leafb->parts[0]; lmb_free(pb->msgbuf); pb->msgbuf = mbb; /* set dirty */ node_set_dirty(leafa); node_set_dirty(leafb); *a = leafa; *b = leafb; *split_key = sp_key; }
static int bplus_tree_insert(struct bplus_tree *tree, int key, int data) { int i; struct bplus_node *node = tree->root; struct bplus_non_leaf *nln; struct bplus_leaf *ln, *root; while (node != NULL) { switch (node->type) { case BPLUS_TREE_NON_LEAF: nln = (struct bplus_non_leaf *)node; i = key_binary_search(nln->key, nln->children - 1, key); if (i >= 0) { node = nln->sub_ptr[i + 1]; } else { i = -i - 1; node = nln->sub_ptr[i]; } break; case BPLUS_TREE_LEAF: ln = (struct bplus_leaf *)node; return leaf_insert(tree, ln, key, data); default: assert(0); } } /* new root */ root = leaf_new(); root->key[0] = key; root->data[0] = data; root->entries = 1; tree->head[0] = (struct bplus_node *)root; tree->root = (struct bplus_node *)root; return 0; }
void bplus_tree_insert(struct tree *tree, int key, int data) { int i, j, level; struct node *node = tree->root; struct non_leaf *nln, *rank_nln; struct leaf *ln; struct rank_recorder recorder[MAX_LEVEL]; if (node == NULL) { struct leaf *leaf = leaf_new(); leaf->key[0] = key; leaf->data[0] = data; leaf->entries = 1; tree->head[0] = (struct node *)leaf; tree->root = (struct node *)leaf; return; } memset(recorder, 0, sizeof(recorder)); level = MAX_LEVEL; while (--level > 0) { if (tree->head[level] == node) { break; } } rank_nln = (struct non_leaf *)tree->head[level]; while (node != NULL) { switch (node->type) { case BPLUS_TREE_NON_LEAF: nln = (struct non_leaf *)node; /* rank inheritance */ recorder[level].rank = level == MAX_LEVEL - 1 ? 0 : recorder[level + 1].rank; while (rank_nln != nln) { for (j = 0; j < rank_nln->children - 2; j++) { recorder[level].rank += rank_nln->span[j]; } rank_nln = rank_nln->next; } /* search key */ i = key_binary_search(nln->key, nln->children - 1, key); if (i >= 0) { node = nln->sub_ptr[i + 1]; if (i < nln->children - 2) { recorder[level].node = nln; recorder[level].index = i + 1; for (j = 0; j < i + 1; j++) { recorder[level].rank += nln->span[j]; } } else { recorder[level].node = nln->next; recorder[level].index = 0; for (j = 0; j < nln->children - 1; j++) { recorder[level].rank += nln->span[j]; } } } else { i = -i - 1; node = nln->sub_ptr[i]; if (i < nln->children - 1) { recorder[level].node = nln; recorder[level].index = i; for (j = 0; j < i; j++) { recorder[level].rank += nln->span[j]; } } else { recorder[level].node = nln->next; recorder[level].index = 0; for (j = 0; j < nln->children - 1; j++) { recorder[level].rank += nln->span[j]; } } } if (node->type != BPLUS_TREE_LEAF) { rank_nln = (struct non_leaf *)node; } level--; break; case BPLUS_TREE_LEAF: ln = (struct leaf *)node; leaf_insert(tree, ln, key, data, &recorder[0]); return; default: break; } } }
static void leaf_insert(struct tree *tree, struct leaf *leaf, int key, int data, struct rank_recorder *recorder) { int i, j, split = 0; struct leaf *sibling; int insert = key_binary_search(leaf->key, leaf->entries, key); if (insert >= 0) { /* Already exists */ return; } insert = -insert - 1; /* node full */ if (leaf->entries == ENTRIES) { /* split = [m/2] */ split = (ENTRIES + 1) / 2; /* splited sibling node */ sibling = leaf_new(); sibling->next = leaf->next; leaf->next = sibling; leaf->entries = split; /* sibling leaf replication */ if (insert < split) { for (i = split - 1, j = 0; i < ENTRIES; i++, j++) { sibling->key[j] = leaf->key[i]; sibling->data[j] = leaf->data[i]; } sibling->entries = j; /* leaf insertion and its entry count stays unchanged(split + 1) */ for (i = leaf->entries; i > insert; i--) { leaf->key[i] = leaf->key[i - 1]; leaf->data[i] = leaf->data[i - 1]; } leaf->key[i] = key; leaf->data[i] = data; } else { i = split, j = 0; while (i < ENTRIES) { if (j != insert - split) { sibling->key[j] = leaf->key[i]; sibling->data[j] = leaf->data[i]; i++; } j++; } /* sibling leaf entries */ if (j > insert - split) { sibling->entries = j; } else { sibling->entries = insert - split + 1; } /* insert new key */ j = insert - split; sibling->key[j] = key; sibling->data[j] = data; } } else { /* simple insertion */ for (i = leaf->entries; i > insert; i--) { leaf->key[i] = leaf->key[i - 1]; leaf->data[i] = leaf->data[i - 1]; } leaf->key[i] = key; leaf->data[i] = data; leaf->entries++; } if (split) { struct non_leaf *parent = leaf->parent; if (parent == NULL) { parent = non_leaf_new(); parent->key[0] = sibling->key[0]; parent->sub_ptr[0] = (struct node *)leaf; parent->sub_ptr[1] = (struct node *)sibling; parent->children = 2; /* new root */ tree->root = (struct node *)parent; tree->head[1] = (struct node *)parent; leaf->parent = parent; sibling->parent = parent; } else { /* trace upwards */ sibling->parent = parent; non_leaf_insert(tree, parent, (struct node *)sibling, sibling->key[0], 1, recorder); } } }
void octree_insert(octree_t* tree, point_t* point, int index) { if (tree->root == NULL) // Empty tree { octree_node_t* node = leaf_new(point, index); tree->root = node; ++tree->num_points; } else if (tree->root->type == OCTREE_LEAF_NODE) { point_t center = {.x = 0.5 * (tree->bbox.x1 + tree->bbox.x2), .y = 0.5 * (tree->bbox.y1 + tree->bbox.y2), .z = 0.5 * (tree->bbox.z1 + tree->bbox.z2)}; // The tree consists of a single node. octree_node_t* root = tree->root; // Does the given point already exist here? if (point_distance(&root->leaf_node.point, point) == 0.0) return; // We need to create a branch node here. octree_node_t* node = root; tree->root = branch_new(); int slot = find_slot(¢er, point); tree->root->branch_node.children[slot] = node; } // Now we proceed with the normal logic, given that the root node // is a branch node. ASSERT(tree->root->type == OCTREE_BRANCH_NODE); octree_node_t* node = tree->root; point_t center = {.x = 0.5 * (tree->bbox.x1 + tree->bbox.x2), .y = 0.5 * (tree->bbox.y1 + tree->bbox.y2), .z = 0.5 * (tree->bbox.z1 + tree->bbox.z2)}; real_t lx = tree->bbox.x2 - tree->bbox.x1; real_t ly = tree->bbox.y2 - tree->bbox.y1; real_t lz = tree->bbox.z2 - tree->bbox.z1; int slot = find_slot(¢er, point); static real_t xf[] = {-0.25, -0.25, -0.25, -0.25, +0.25, +0.25, +0.25, +0.25}; static real_t yf[] = {-0.25, -0.25, +0.25, +0.25, -0.25, -0.25, +0.25, +0.25}; static real_t zf[] = {-0.25, +0.25, -0.25, +0.25, -0.25, +0.25, -0.25, +0.25}; while ((node->branch_node.children[slot] != NULL) && (node->branch_node.children[slot]->type == OCTREE_BRANCH_NODE)) { node = node->branch_node.children[slot]; center.x += xf[slot]*lx; lx *= 0.5; center.y += yf[slot]*ly; ly *= 0.5; center.z += zf[slot]*lz; lz *= 0.5; slot = find_slot(¢er, point); } octree_node_t* leaf = node->branch_node.children[slot]; if (leaf == NULL) { // No leaf here, so we create a new one! leaf = leaf_new(point, index); node->branch_node.children[slot] = leaf; ++tree->num_points; } else { // Is the point already in this node? if (point_distance(&leaf->leaf_node.point, point) == 0.0) return; else { // We have to make a new branch. int old_slot, new_slot; do { node->branch_node.children[slot] = branch_new(); node = node->branch_node.children[slot]; center.x += xf[slot]*lx; lx *= 0.5; center.y += yf[slot]*ly; ly *= 0.5; center.z += zf[slot]*lz; lz *= 0.5; new_slot = find_slot(¢er, point); old_slot = find_slot(¢er, &leaf->leaf_node.point); } while (new_slot == old_slot); node->branch_node.children[old_slot] = leaf; octree_node_t* new_leaf = leaf_new(point, index); node->branch_node.children[new_slot] = new_leaf; ++tree->num_points; } } } void octree_delete(octree_t* tree, point_t* point, int index) { // FIXME } int octree_size(octree_t* tree) { return tree->num_points; } static void node_clear(octree_node_t* node) { if (node == NULL) { return; } else if (node->type == OCTREE_LEAF_NODE) { polymec_free(node); } else { ASSERT(node->type == OCTREE_BRANCH_NODE); for (int i = 0; i < 8; ++i) node_clear(node->branch_node.children[i]); } } void octree_clear(octree_t* tree) { node_clear(tree->root); tree->root = NULL; tree->num_points = 0; }