/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009, 2010 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 <config.h>
-#include "sort.h"
+#include "math/sort.h"
#include <stdio.h>
-#include <data/case.h>
-#include <data/casereader.h>
-#include <data/casewriter.h>
-#include <data/casewriter-provider.h>
-#include <data/settings.h>
-#include <data/subcase.h>
-#include <libpspp/array.h>
-#include <libpspp/assertion.h>
-#include <math/merge.h>
+#include "data/case.h"
+#include "data/casereader.h"
+#include "data/casewriter.h"
+#include "data/casewriter-provider.h"
+#include "data/settings.h"
+#include "data/subcase.h"
+#include "libpspp/assertion.h"
+#include "libpspp/bt.h"
+#include "math/merge.h"
-#include "xalloc.h"
+#include "gl/xalloc.h"
#include "gettext.h"
#define _(msgid) gettext (msgid)
struct pqueue
{
struct subcase ordering;
- struct pqueue_record *records;
- size_t record_cnt;
+ struct bt bt;
size_t record_cap;
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_cap = max_buffers;
else if (pq->record_cap < min_buffers)
pq->record_cap = min_buffers;
- pq->record_cnt = 0;
- pq->records = xnmalloc (pq->record_cap, sizeof *pq->records);
+ 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_cap;
+ return bt_count (&pq->bt) >= pq->record_cap;
}
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));
- 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;
}