void mm_check(mm_handle *mm) { int ndiff; idx_t i; mm_node *child; mm_node *parent; // small heap for (i=0; i<mm->n_s; i++) { assert(mm->s_heap[i]->idx == i); assert(mm->s_heap[i]->ai == mm->s_heap[i]->ai); if (i > 0) { child = mm->s_heap[i]; parent = mm->s_heap[P_IDX(child->idx)]; assert(child->ai <= parent->ai); } } // large heap for (i=0; i<mm->n_l; i++) { assert(mm->l_heap[i]->idx == i); assert(mm->l_heap[i]->ai == mm->l_heap[i]->ai); if (i > 0) { child = mm->l_heap[i]; parent = mm->l_heap[P_IDX(child->idx)]; assert(child->ai >= parent->ai); } } // nan array for (i=0; i<mm->n_n; i++) { assert(mm->n_array[i]->idx == i); assert(mm->n_array[i]->ai != mm->n_array[i]->ai); } // handle assert(mm->window >= mm->n_s + mm->n_l + mm->n_n); assert(mm->min_count <= mm->window); if (mm->n_s == 0) { assert(mm->s_first_leaf == 0); } else { assert(mm->s_first_leaf == FIRST_LEAF(mm->n_s)); } if (mm->n_l == 0) { assert(mm->l_first_leaf == 0); } else { assert(mm->l_first_leaf == FIRST_LEAF(mm->n_l)); } ndiff = (int)mm->n_s - (int)mm->n_l; if (ndiff < 0) { ndiff *= -1; } assert(ndiff <= 1); if (mm->n_s > 0 && mm->n_l > 0) { assert(mm->s_heap[0]->ai <= mm->l_heap[0]->ai); } }
/* Move the given node down through the heap to the appropriate position. */ static inline void mm_move_down_large(mm_node **heap, idx_t idx, mm_node *node, idx_t p_idx, mm_node *parent) { do { SWAP_NODES(heap, idx, node, p_idx, parent); if (idx == 0) { break; } p_idx = P_IDX(idx); parent = heap[p_idx]; } while (node->ai < parent->ai); }
static inline void heapify_large_node(mm_handle *mm, idx_t idx) { idx_t idx2; mm_node *node; mm_node *node2; mm_node **s_heap; mm_node **l_heap; idx_t n_s, n_l; ai_t ai; s_heap = mm->s_heap; l_heap = mm->l_heap; node = l_heap[idx]; n_s = mm->n_s; n_l = mm->n_l; ai = node->ai; // Internal or leaf node. if (idx > 0) { idx2 = P_IDX(idx); node2 = l_heap[idx2]; // Move down. if (ai < node2->ai) { mm_move_down_large(l_heap, idx, node, idx2, node2); // Maybe swap between heaps. node2 = s_heap[0]; if (ai < node2->ai) { mm_swap_heap_heads(s_heap, n_s, l_heap, n_l, node2, node); } } // Move up. else if (idx < mm->l_first_leaf) { mm_move_up_large(l_heap, n_l, idx, node); } } // Head node. else { node2 = s_heap[0]; if (n_s > 0 && ai < node2->ai) { mm_swap_heap_heads(s_heap, n_s, l_heap, n_l, node2, node); } else { mm_move_up_large(l_heap, n_l, idx, node); } } }
static inline void heapify_small_node(mm_handle *mm, idx_t idx) { idx_t idx2; mm_node *node; mm_node *node2; mm_node **s_heap; mm_node **l_heap; idx_t n_s, n_l; ai_t ai; s_heap = mm->s_heap; l_heap = mm->l_heap; node = s_heap[idx]; n_s = mm->n_s; n_l = mm->n_l; ai = node->ai; /* Internal or leaf node */ if (idx > 0) { idx2 = P_IDX(idx); node2 = s_heap[idx2]; /* Move up */ if (ai > node2->ai) { mm_move_up_small(s_heap, idx, node, idx2, node2); /* Maybe swap between heaps */ node2 = l_heap[0]; if (ai > node2->ai) { mm_swap_heap_heads(s_heap, n_s, l_heap, n_l, node, node2); } } /* Move down */ else if (idx < mm->s_first_leaf) { mm_move_down_small(s_heap, n_s, idx, node); } } /* Head node */ else { node2 = l_heap[0]; if (n_l > 0 && ai > node2->ai) { mm_swap_heap_heads(s_heap, n_s, l_heap, n_l, node, node2); } else { mm_move_down_small(s_heap, n_s, idx, node); } } }