/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2009, 2011, 2012 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009-12, 2014 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "data/subcase.h"
#include "libpspp/array.h"
#include "libpspp/assertion.h"
+#include "libpspp/bt.h"
#include "math/merge.h"
#include "gl/xalloc.h"
struct pqueue
{
struct subcase ordering;
- struct pqueue_record *records;
- size_t record_cnt; /* Current number of records. */
- size_t record_cap; /* Space currently allocated for records. */
- size_t record_max; /* Max space we are willing to allocate. */
+ struct bt bt;
+ size_t record_max;
casenumber idx;
};
struct pqueue_record
{
+ struct bt_node bt_node;
casenumber id;
struct ccase *c;
casenumber idx;
};
-static int compare_pqueue_records_minheap (const void *a, const void *b,
- const void *pq_);
+static int compare_pqueue_records (const struct bt_node *a,
+ const struct bt_node *b,
+ const void *ordering);
static struct pqueue *
pqueue_create (const struct subcase *ordering, const struct caseproto *proto)
pq->record_max = max_buffers;
else if (pq->record_max < min_buffers)
pq->record_max = min_buffers;
- pq->record_cnt = 0;
- pq->record_cap = 0;
- pq->records = NULL;
+ bt_init (&pq->bt, compare_pqueue_records, &pq->ordering);
pq->idx = 0;
return pq;
case_unref (c);
}
subcase_destroy (&pq->ordering);
- free (pq->records);
free (pq);
}
}
static bool
pqueue_is_full (const struct pqueue *pq)
{
- return pq->record_cnt >= pq->record_max;
+ return bt_count (&pq->bt) >= pq->record_max;
}
static bool
pqueue_is_empty (const struct pqueue *pq)
{
- return pq->record_cnt == 0;
+ return bt_is_empty (&pq->bt);
}
static void
assert (!pqueue_is_full (pq));
- if (pq->record_cnt >= pq->record_cap)
- {
- pq->record_cap = pq->record_cap * 2;
- if (pq->record_cap < 16)
- pq->record_cap = 16;
- else if (pq->record_cap > pq->record_max)
- pq->record_cap = pq->record_max;
- pq->records = xrealloc (pq->records,
- pq->record_cap * sizeof *pq->records);
- }
-
- r = &pq->records[pq->record_cnt++];
+ r = xmalloc (sizeof *r);
r->id = id;
r->c = c;
r->idx = pq->idx++;
-
- push_heap (pq->records, pq->record_cnt, sizeof *pq->records,
- compare_pqueue_records_minheap, pq);
+ bt_insert (&pq->bt, &r->bt_node);
}
static struct ccase *
pqueue_pop (struct pqueue *pq, casenumber *id)
{
struct pqueue_record *r;
+ struct ccase *c;
assert (!pqueue_is_empty (pq));
- pop_heap (pq->records, pq->record_cnt--, sizeof *pq->records,
- compare_pqueue_records_minheap, pq);
-
- r = &pq->records[pq->record_cnt];
+ r = bt_data (bt_first (&pq->bt), struct pqueue_record, bt_node);
+ bt_delete (&pq->bt, &r->bt_node);
*id = r->id;
- return r->c;
+ c = r->c;
+ free (r);
+ return c;
}
/* Compares record-run tuples A and B on id, then on case data,
- then on insertion order, in descending order. */
+ then on insertion order. */
static int
-compare_pqueue_records_minheap (const void *a_, const void *b_,
- const void *pq_)
+compare_pqueue_records (const struct bt_node *a_, const struct bt_node *b_,
+ const void *ordering_)
{
- const struct pqueue_record *a = a_;
- const struct pqueue_record *b = b_;
- const struct pqueue *pq = pq_;
+ const struct pqueue_record *a = bt_data (a_, struct pqueue_record, bt_node);
+ const struct pqueue_record *b = bt_data (b_, struct pqueue_record, bt_node);
+ const struct subcase *ordering = ordering_;
int result = a->id < b->id ? -1 : a->id > b->id;
if (result == 0)
- result = subcase_compare_3way (&pq->ordering, a->c, &pq->ordering, b->c);
+ result = subcase_compare_3way (ordering, a->c, ordering, b->c);
if (result == 0)
result = a->idx < b->idx ? -1 : a->idx > b->idx;
- return -result;
+ return result;
}