Ejemplo n.º 1
0
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);
    }
}
Ejemplo n.º 2
0
/* Insert a new value, ai, into one of the heaps. Use this function when
 * the heaps contain less than window-1 nodes. Returns the median value.
 * Once there are window-1 nodes in the heap, switch to using mm_update. */
inline ai_t
mm_update_init(mm_handle *mm, ai_t ai)
{

    mm_node *node;
    idx_t n_s = mm->n_s;
    idx_t n_l = mm->n_l;

    node = &mm->node_data[n_s + n_l];
    node->ai = ai;

    if (n_s == 0) {
        // the first node to appear in a heap
        mm->s_heap[0] = node;
        node->region = SH;
        node->idx = 0;
        mm->oldest = node; // only need to set the oldest node once
        mm->n_s = 1;
        mm->s_first_leaf = 0;
    }
    else
    {
        // at least one node already exists in the heaps
        mm->newest->next = node;
        if (n_s > n_l)
        {
            // add new node to large heap
            mm->l_heap[n_l] = node;
            node->region = LH;
            node->idx = n_l;
            ++mm->n_l;
            mm->l_first_leaf = FIRST_LEAF(mm->n_l);
            heapify_large_node(mm, n_l);
        }
        else
        {
            // add new node to small heap
            mm->s_heap[n_s] = node;
            node->region = SH;
            node->idx = n_s;
            ++mm->n_s;
            mm->s_first_leaf = FIRST_LEAF(mm->n_s);
            heapify_small_node(mm, n_s);
        }
    }

    mm->newest = node;

    return mm_get_median(mm);
}
Ejemplo n.º 3
0
/* Insert a new value, ai, into one of the heaps or the nan array. Use this
 * function when there are at least window-1 nodes. Returns the median value.
 * If there are less than window-1 nodes, use mm_update_init_nan. */
inline ai_t
mm_update_nan(mm_handle *mm, ai_t ai)
{

    // node is oldest node with ai of newest node
    mm_node *node = mm->oldest;
    idx_t idx = node->idx;
    node->ai = ai;

    // update oldest, newest
    mm->oldest = mm->oldest->next;
    mm->newest->next = node;
    mm->newest = node;

    mm_node **l_heap = mm->l_heap;
    mm_node **s_heap = mm->s_heap;
    mm_node **n_array = mm->n_array;

    idx_t n_s = mm->n_s;
    idx_t n_l = mm->n_l;
    idx_t n_n = mm->n_n;

    mm_node *node2;

    if (ai != ai) {

        if (node->region == SH) {

            /* Oldest node is in the small heap and needs to be moved
             * to the nan array. Resulting hole in the small heap will be
             * filled with the rightmost leaf of the last row of the small
             * heap. */

            // insert node into nan array
            node->region = NA;
            node->idx = n_n;
            n_array[n_n] = node;
            ++mm->n_n;

            // plug small heap hole
            --mm->n_s;
            if (mm->n_s == 0) {
                mm->s_first_leaf = 0;
                if (n_l > 0) {

                    // move head node from the large heap to the small heap
                    node2 = mm->l_heap[0];
                    node2->region = SH;
                    s_heap[0] = node2;
                    mm->n_s = 1;
                    mm->s_first_leaf = 0;

                    // plug hole in large heap
                    node2= mm->l_heap[mm->n_l - 1];
                    node2->idx = 0;
                    l_heap[0] = node2;
                    --mm->n_l;
                    if (mm->n_l == 0)
                        mm->l_first_leaf = 0;
                    else
                        mm->l_first_leaf = FIRST_LEAF(mm->n_l);
                    heapify_large_node(mm, 0);

                }
            } else {
                if (idx != n_s - 1) {
                    s_heap[idx] = s_heap[n_s - 1];
                    s_heap[idx]->idx = idx;
                    heapify_small_node(mm, idx);
                }
                if (mm->n_s < mm->n_l) {

                    // move head node from the large heap to the small heap
                    node2 = mm->l_heap[0];
                    node2->idx = mm->n_s;
                    node2->region = SH;
                    s_heap[mm->n_s] = node2;
                    ++mm->n_s;
                    mm->l_first_leaf = FIRST_LEAF(mm->n_s);
                    heapify_small_node(mm, node2->idx);

                    // plug hole in large heap
                    node2= mm->l_heap[mm->n_l - 1];
                    node2->idx = 0;
                    l_heap[0] = node2;
                    --mm->n_l;
                    if (mm->n_l == 0)
                        mm->l_first_leaf = 0;
                    else
                        mm->l_first_leaf = FIRST_LEAF(mm->n_l);
                    heapify_large_node(mm, 0);

                } else {
                    mm->s_first_leaf = FIRST_LEAF(mm->n_s);
                    heapify_small_node(mm, idx);
                }
            }

        } else if (node->region == LH) {

            /* Oldest node is in the large heap and needs to be moved
             * to the nan array. Resulting hole in the large heap will be
             * filled with the rightmost leaf of the last row of the large
             * heap. */

            // insert node into nan array
            node->region = NA;
            node->idx = n_n;
            n_array[n_n] = node;
            ++mm->n_n;

            // plug large heap hole
            if (idx != n_l - 1) {
                l_heap[idx] = l_heap[n_l - 1];
                l_heap[idx]->idx = idx;
                heapify_large_node(mm, idx);
            }
            --mm->n_l;
            if (mm->n_l == 0)
                mm->l_first_leaf = 0;
            else
                mm->l_first_leaf = FIRST_LEAF(mm->n_l);
            if (mm->n_l < mm->n_s - 1) {

                // move head node from the small heap to the large heap
                node2 = mm->s_heap[0];
                node2->idx = mm->n_l;
                node2->region = LH;
                l_heap[mm->n_l] = node2;
                ++mm->n_l;
                mm->l_first_leaf = FIRST_LEAF(mm->n_l);
                heapify_large_node(mm, node2->idx);

                // plug hole in small heap
                if (n_s != 1) {
                    node2 = mm->s_heap[mm->n_s - 1];
                    node2->idx = 0;
                    s_heap[0] = node2;
                }
                --mm->n_s;
                if (mm->n_s == 0)
                    mm->s_first_leaf = 0;
                else
                    mm->s_first_leaf = FIRST_LEAF(mm->n_s);
                heapify_small_node(mm, 0);

            }

            // reorder large heap if needed
            heapify_large_node(mm, idx);

        } else if (node->region == NA) {

            //  insert node into nan heap
            n_array[idx] = node;

        }
    } else {

        if (node->region == SH)
            heapify_small_node(mm, idx);
        else if (node->region == LH)
            heapify_large_node(mm, idx);
        else {

            // ai is not NaN but oldest node is in nan array

            if (n_s > n_l) {

                // insert into large heap
                node->region = LH;
                node->idx = n_l;
                l_heap[n_l] = node;
                ++mm->n_l;
                mm->l_first_leaf = FIRST_LEAF(mm->n_l);
                heapify_large_node(mm, n_l);

            } else {

                // insert into small heap
                node->region = SH;
                node->idx = n_s;
                s_heap[n_s] = node;
                ++mm->n_s;
                mm->s_first_leaf = FIRST_LEAF(mm->n_s);
                heapify_small_node(mm, n_s);

            }   

            // plug nan array hole
            if (idx != n_n - 1) {
                n_array[idx] = n_array[n_n - 1];
                n_array[idx]->idx = idx;
            }
            --mm->n_n;
        }

    }

    return mm_get_median(mm);
}
Ejemplo n.º 4
0
/* Insert a new value, ai, into one of the heaps or the nan array. Use this
 * function when there are less than window-1 nodes. Returns the median
 * value. Once there are window-1 nodes in the heap, switch to using
 * mm_update_nan. */
ai_t
mm_update_init_nan(mm_handle *mm, ai_t ai)
{

    mm_node *node;
    idx_t n_s = mm->n_s;
    idx_t n_l = mm->n_l;
    idx_t n_n = mm->n_n;

    node = &mm->node_data[n_s + n_l + n_n];
    node->ai = ai;

    if (ai != ai) {
        mm->n_array[n_n] = node;
        node->region = NA;
        node->idx = n_n;
        if (n_s + n_l + n_n == 0) {
            /* only need to set the oldest node once */
            mm->oldest = node;
        } else {
            mm->newest->next = node;
        }
        ++mm->n_n;
    } else {
        if (n_s == 0) {
            /* the first node to appear in a heap */
            mm->s_heap[0] = node;
            node->region = SH;
            node->idx = 0;
            if (n_s + n_l + n_n == 0) {
                /* only need to set the oldest node once */
                mm->oldest = node;
            } else {
                mm->newest->next = node;
            }
            mm->n_s = 1;
            mm->s_first_leaf = 0;
        }
        else
        {
            /* at least one node already exists in the heaps */
            mm->newest->next = node;
            if (n_s > n_l)
            {
                /* add new node to large heap */
                mm->l_heap[n_l] = node;
                node->region = LH;
                node->idx = n_l;
                ++mm->n_l;
                mm->l_first_leaf = FIRST_LEAF(mm->n_l);
                heapify_large_node(mm, n_l);
            }
            else
            {
                /* add new node to small heap */
                mm->s_heap[n_s] = node;
                node->region = SH;
                node->idx = n_s;
                ++mm->n_s;
                mm->s_first_leaf = FIRST_LEAF(mm->n_s);
                heapify_small_node(mm, n_s);
            }
        }
    }
    mm->newest = node;

    return mm_get_median(mm);
}