File: PQueue.cpp

package info (click to toggle)
storm-lang 0.7.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,028 kB
  • sloc: ansic: 261,471; cpp: 140,432; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (122 lines) | stat: -rw-r--r-- 2,796 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include "stdafx.h"
#include "PQueue.h"
#include "Sort.h"

namespace storm {

	static GcArray<byte> *copyArray(const ArrayBase *src) {
		const Handle &h = src->handle;
		GcArray<byte> *r = runtime::allocArray<byte>(src->engine(), h.gcArrayType, src->count() + 1);

		for (Nat i = 0; i < src->count(); i++) {
			r->filled = i + 1;
			h.safeCopy(r->v + i*h.size, src->getRaw(i));
		}

		return r;
	}

	PQueueBase::PQueueBase(const Handle &type) : handle(type), data(null), compare(null) {}

	PQueueBase::PQueueBase(const ArrayBase *src) : handle(src->handle), compare(null) {
		data = copyArray(src);

		SortData d(data, handle);
		makeHeap(d);
	}

	PQueueBase::PQueueBase(const Handle &type, FnBase *compare) : handle(type), data(null), compare(compare) {}

	PQueueBase::PQueueBase(const ArrayBase *src, FnBase *compare) : handle(src->handle), compare(compare) {
		data = copyArray(src);

		SortData d(data, handle, compare);
		makeHeap(d);
	}

	PQueueBase::PQueueBase(const PQueueBase &o) : handle(o.handle), compare(o.compare) {
		ensure(o.count());

		for (Nat i = 0; i < o.count(); i++) {
			data->filled = i + 1;
			handle.safeCopy(data->v + i*handle.size, o.data->v + i*handle.size);
		}
	}

	void PQueueBase::deepCopy(CloneEnv *env) {
		if (handle.deepCopyFn) {
			for (Nat i = 0; i < count(); i++)
				(*handle.deepCopyFn)(data->v + i*handle.size, env);
		}

		if (compare)
			cloned(compare, env);
	}

	void PQueueBase::reserve(Nat count) {
		ensure(count);
	}

	void PQueueBase::pop() {
		SortData d(data, handle, compare);
		heapRemove(d);

		handle.safeDestroy(data->v + data->filled*handle.size);
		data->filled--;
	}

	void PQueueBase::pushRaw(const void *src) {
		ensure(count() + 1);

		SortData d(data, handle, compare);
		heapInsert(src, d);

		data->filled++;
	}

	void PQueueBase::throwError() const {
		throw new (this) PQueueError(S("Trying to access elements in an empty priority queue."));
	}

	void PQueueBase::ensure(Nat n) {
		if (n == 0)
			return;

		n++; // We need an additional element for swap space during heap operations.

		Nat oldCap = data ? Nat(data->count) : 0;
		if (oldCap >= n)
			return;

		Nat oldCount = count();

		// We need to grow 'data'. How much?
		Nat newCap = max(Nat(16), oldCap * 2);
		if (newCap < n)
			newCap = n;
		GcArray<byte> *newData = runtime::allocArray<byte>(engine(), handle.gcArrayType, newCap);

		// Move data.
		if (data) {
			memcpy(newData->v, data->v, handle.size*oldCount);
			data->filled = 0;
			newData->filled = oldCount;
		}

		// Swap contents.
		data = newData;
	}

	void PQueueBase::toS(StrBuf *to) const {
		*to << S("PQ:{");
		if (count() > 0)
			(*handle.toSFn)(data->v, to);

		for (nat i = 1; i < count(); i++) {
			*to << S(", ");
			(*handle.toSFn)(data->v + i*handle.size, to);
		}
		*to << S("}");
	}

}