lulu 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/lulu/marker.c ADDED
@@ -0,0 +1,111 @@
1
+ /*
2
+ * marker.c
3
+ *
4
+ * Created on: Feb 24, 2014
5
+ * Author: generessler
6
+ */
7
+
8
+ #include <stdio.h>
9
+ #include <stdlib.h>
10
+ #include <math.h>
11
+ #include "marker.h"
12
+ #include "utility.h"
13
+
14
+ #define SQRT_1_PI 0.564189583547756286948079451560772585844050629328998856844085
15
+
16
+ void mr_info_init(MARKER_INFO *info) {
17
+ info->kind = CIRCLE;
18
+ info->scale = 1;
19
+ info->c = SQRT_1_PI;
20
+ }
21
+
22
+ void mr_info_set(MARKER_INFO *info, MARKER_KIND kind, DISTANCE scale) {
23
+ info->kind = kind;
24
+ info->scale = scale;
25
+ info->c = scale * (kind == SQUARE ? 0.5 : SQRT_1_PI);
26
+ }
27
+
28
+ void mr_init(MARKER *markers, int n_markers) {
29
+ for (int i = 0; i < n_markers; i++) {
30
+ MARKER *marker = markers + i;
31
+ marker->deleted_p = 0;
32
+ marker->size = 0;
33
+ marker->r = 0;
34
+ marker->x = marker->y = marker->x_sum = marker->y_sum = 0;
35
+ mr_reset_parts(marker);
36
+ }
37
+ }
38
+
39
+ void mr_reset_parts(MARKER *marker) {
40
+ marker->part_a = -1;
41
+ marker->part_b = 0;
42
+ }
43
+
44
+ void mr_set(MARKER_INFO *info, MARKER *marker, COORD x, COORD y, SIZE size) {
45
+ mr_init(marker, 1);
46
+ marker->size = size;
47
+ marker->r = size_to_radius(info, size);
48
+ marker->x = x;
49
+ marker->y = y;
50
+ marker->x_sum = x * size;
51
+ marker->y_sum = y * size;
52
+ }
53
+
54
+ void mr_merge(MARKER_INFO *info, MARKER *markers, int i_merged, int ia, int ib) {
55
+ MARKER *merged = markers + i_merged;
56
+ MARKER *a = markers + ia;
57
+ MARKER *b = markers + ib;
58
+ merged->deleted_p = 0;
59
+ merged->size = a->size + b->size;
60
+ merged->r = size_to_radius(info, merged->size);
61
+ merged->x_sum = a->x_sum + b->x_sum;
62
+ merged->y_sum = a->y_sum + b->y_sum;
63
+ merged->x = merged->x_sum / merged->size;
64
+ merged->y = merged->y_sum / merged->size;
65
+ merged->part_a = ia;
66
+ merged->part_b = ib;
67
+ }
68
+
69
+ DISTANCE size_to_radius(MARKER_INFO *info, SIZE size) {
70
+ return info->c * sqrt(size);
71
+ }
72
+
73
+ DISTANCE mr_distance(MARKER_INFO *info, MARKER *a, MARKER *b) {
74
+ if (info->kind == SQUARE) {
75
+ double r_sum = mr_r(a) + mr_r(b);
76
+ double dx = fabs(mr_x(b) - mr_x(a)) - r_sum;
77
+ double dy = fabs(mr_y(b) - mr_y(a)) - r_sum;
78
+ DISTANCE d = dx < 0 && dy < 0 ? fmax(dx, dy) : sqrt(dx * dx + dy * dy);
79
+ return d;
80
+ }
81
+ double dx = mr_x(b) - mr_x(a);
82
+ double dy = mr_y(b) - mr_y(a);
83
+ return sqrt(dx * dx + dy * dy) - mr_r(a) - mr_r(b);
84
+ }
85
+
86
+ void get_marker_array_extent(MARKER *a, int n_markers, MARKER_EXTENT *ext) {
87
+ if (n_markers > 0) {
88
+ double ew = mr_w(a);
89
+ double ee = mr_e(a);
90
+ double es = mr_s(a);
91
+ double en = mr_n(a);
92
+ for (int i = 1; i < n_markers; i++) {
93
+ double w = mr_w(a + i);
94
+ double e = mr_e(a + i);
95
+ double s = mr_s(a + i);
96
+ double n = mr_n(a + i);
97
+ if (w < ew)
98
+ ew = w;
99
+ if (e > ee)
100
+ ee = e;
101
+ if (s < es)
102
+ es = s;
103
+ if (n > en)
104
+ en = n;
105
+ }
106
+ ext->x = ew;
107
+ ext->y = es;
108
+ ext->w = ee - ew;
109
+ ext->h = en - es;
110
+ }
111
+ }
data/ext/lulu/marker.h ADDED
@@ -0,0 +1,70 @@
1
+ /*
2
+ * marker.h
3
+ *
4
+ * Created on: Feb 24, 2014
5
+ * Author: generessler
6
+ */
7
+
8
+ #ifndef MARKER_H_
9
+ #define MARKER_H_
10
+
11
+ typedef double COORD;
12
+ typedef double DISTANCE;
13
+ /**
14
+ * Size of population represented by the marker. For
15
+ * discrete populations, this can be an unsigned int.
16
+ */
17
+ typedef double SIZE;
18
+
19
+ typedef struct marker_s {
20
+ SIZE size;
21
+ DISTANCE r;
22
+ COORD x, y, x_sum, y_sum;
23
+ int part_a;
24
+ unsigned deleted_p:1, part_b:31;
25
+ } MARKER;
26
+
27
+ typedef enum marker_kind_e {
28
+ CIRCLE,
29
+ SQUARE,
30
+ } MARKER_KIND;
31
+
32
+ /**
33
+ * Holds parameters of the distance function and merging.
34
+ */
35
+ typedef struct marker_type_info_s {
36
+ MARKER_KIND kind;
37
+ // User scale applied to radii of markers during distance computation.
38
+ DISTANCE scale;
39
+ // A scale factor that depends on both kind and user scale.
40
+ DISTANCE c;
41
+ } MARKER_INFO;
42
+
43
+ #define MARKER_INFO_DECL(I) MARKER_INFO I[1]; mr_info_init(I)
44
+
45
+ typedef struct marker_extent_s {
46
+ COORD x, y, w, h;
47
+ } MARKER_EXTENT;
48
+
49
+ #define mr_deleted_p(M) ((M)->deleted_p)
50
+ #define mr_set_deleted(M) do { (M)->deleted_p = 1; } while (0)
51
+ #define mr_merged(M) ((M)->part_a >= 0)
52
+ #define mr_x(M) ((M)->x)
53
+ #define mr_y(M) ((M)->y)
54
+ #define mr_r(M) ((M)->r)
55
+ #define mr_w(M) ((M)->x - (M)->r)
56
+ #define mr_e(M) ((M)->x + (M)->r)
57
+ #define mr_s(M) ((M)->y - (M)->r)
58
+ #define mr_n(M) ((M)->y + (M)->r)
59
+
60
+ void mr_init(MARKER *marker, int n_markers);
61
+ void mr_reset_parts(MARKER *marker);
62
+ void mr_info_init(MARKER_INFO *info);
63
+ void mr_info_set(MARKER_INFO *info, MARKER_KIND kind, DISTANCE scale);
64
+ void mr_set(MARKER_INFO *info, MARKER *marker, COORD x, COORD y, SIZE size);
65
+ void mr_merge(MARKER_INFO *info, MARKER *markers, int merged, int a, int b);
66
+ DISTANCE mr_distance(MARKER_INFO *info, MARKER *a, MARKER *b);
67
+ DISTANCE size_to_radius(MARKER_INFO *info, SIZE size);
68
+ void get_marker_array_extent(MARKER *a, int n_markers, MARKER_EXTENT *ext);
69
+
70
+ #endif /* MARKER_H_ */
data/ext/lulu/merger.c ADDED
@@ -0,0 +1,191 @@
1
+ /*
2
+ * merger.c
3
+ *
4
+ * Created on: Feb 24, 2014
5
+ * Author: generessler
6
+ */
7
+
8
+ #include <stdio.h>
9
+ #include <stdlib.h>
10
+ #include <float.h>
11
+ #include <assert.h>
12
+ #include <time.h>
13
+ #include "merger.h"
14
+ #include "utility.h"
15
+ #include "pq.h"
16
+ #include "qt.h"
17
+ #include "test.h"
18
+
19
+ /**
20
+ * Repeatedly merge the closest pair of the given markers until they don't overlap.
21
+ *
22
+ * The centroid rule is used for merging. I.e. each marker's area represents
23
+ * a population of points. Merging two markers removes the originals and creates a
24
+ * new marker with area the sum of the originals and center at the average position
25
+ * of the two merged populations.
26
+ *
27
+ * The markers array must include extra buffer space. If there are n markers, the
28
+ * array must have 2n-1 spaces, with only the first n initialized.
29
+ *
30
+ * The number of markers after merging is returned. Zero or more of these will be
31
+ * marked deleted_p and should be ignored.
32
+ *
33
+ * This algorithm is O(n k log n), where k is the maximum number of simultaneously
34
+ * overlapping markers in the original, unmerged set.
35
+ */
36
+ int merge_markers_fast(MARKER_INFO *info, MARKER *markers, int n_markers) {
37
+ int augmented_length = 2 * n_markers - 1;
38
+ NewArrayDecl(int, n_nghbr, augmented_length);
39
+ NewArrayDecl(DISTANCE, mindist, augmented_length);
40
+ NewArrayDecl(int, inv_nghbr_head, augmented_length);
41
+ NewArrayDecl(int, inv_nghbr_next, augmented_length);
42
+ NewArrayDecl(int, tmp, augmented_length); // Too big
43
+ // Do not free the following array! It's owned by the priority queue.
44
+ NewArrayDecl(int, heap, augmented_length); // Too big
45
+
46
+ // Specialized quadtree supports finding closest marker to any given one.
47
+ QUADTREE_DECL(qt);
48
+
49
+ // Priority queue keyed on distances of overlapping pairs of markers.
50
+ PRIORITY_QUEUE_DECL(pq);
51
+
52
+ /// Extent of markers in the domain.
53
+ MARKER_EXTENT ext[1];
54
+
55
+ // Get a bounding box for the whole collection of markers.
56
+ get_marker_array_extent(markers, n_markers, ext);
57
+
58
+ // Set up the quadtree with the bounding box. Choose tree depth heuristically.
59
+ int max_depth = high_bit_position(n_markers) / 4 + 3;
60
+ qt_setup(qt, max_depth, ext->x, ext->y, ext->w, ext->h, info);
61
+
62
+ // Insert all the markers in the quadtree.
63
+ for (int i = 0; i < n_markers; i++)
64
+ qt_insert(qt, markers + i);
65
+
66
+ // Set all the inverse nearest neighbor links to null.
67
+ for (int i = 0; i < augmented_length; i++)
68
+ inv_nghbr_head[i] = inv_nghbr_next[i] = -1;
69
+
70
+ // Initialize the heap by adding an index for each overlapping pair. The
71
+ // The heap holds indices into the array of min-distance keys. An index for
72
+ // pair a->bis added iff markers with indices a and b overlap and b < a.
73
+ int heap_size = 0;
74
+ for (int a = 0; a < n_markers; a++) {
75
+ int b = qt_nearest_wrt(markers, qt, a);
76
+ if (0 <= b && b < a) {
77
+ n_nghbr[a] = b;
78
+ mindist[a] = mr_distance(info, markers + a, markers + b);
79
+ heap[heap_size++] = a;
80
+
81
+ // Here we are building a linked list of markers that have b as nearest.
82
+ inv_nghbr_next[a] = inv_nghbr_head[b];
83
+ inv_nghbr_head[b] = a;
84
+ }
85
+ }
86
+
87
+ // Now install the raw heap array into the priority queue. After this it's owned by the queue.
88
+ pq_set_up_heap(pq, heap, heap_size, mindist, augmented_length); // Too big
89
+
90
+ while (!pq_empty_p(pq)) {
91
+
92
+ // Get nearest pair from priority queue.
93
+ int a = pq_get_min(pq);
94
+ int b = n_nghbr[a];
95
+
96
+ // Delete both of the nearest pair from all data structures.
97
+ pq_delete(pq, b);
98
+ qt_delete(qt, markers + a);
99
+ qt_delete(qt, markers + b);
100
+ mr_set_deleted(markers + a);
101
+ mr_set_deleted(markers + b);
102
+
103
+ // Capture the inv lists of both a and b in tmp.
104
+ int tmp_size = 0;
105
+ for (int p = inv_nghbr_head[a]; p >= 0; p = inv_nghbr_next[p])
106
+ if (!markers[p].deleted_p)
107
+ tmp[tmp_size++] = p;
108
+ for (int p = inv_nghbr_head[b]; p >= 0; p = inv_nghbr_next[p])
109
+ if (!markers[p].deleted_p)
110
+ tmp[tmp_size++] = p;
111
+
112
+ // Create a new merged marker. Adding it after all others means
113
+ // nothing already in the heap could have it as nearest.
114
+ int aa = n_markers++;
115
+ mr_merge(info, markers, aa, a, b);
116
+
117
+ // Add to quadtree.
118
+ qt_insert(qt, markers + aa);
119
+
120
+ // Find nearest overlapping neighbor of the merged marker, if any.
121
+ int bb = qt_nearest_wrt(markers, qt, aa);
122
+ if (0 <= bb) {
123
+ n_nghbr[aa] = bb;
124
+ mindist[aa] = mr_distance(info, markers + aa, markers + bb);
125
+ pq_add(pq, aa);
126
+ inv_nghbr_next[aa] = inv_nghbr_head[bb];
127
+ inv_nghbr_head[bb] = aa;
128
+ }
129
+
130
+ // Reset the nearest neighbors of the inverse neighbors of the deletions.
131
+ for (int i = 0; i < tmp_size; i++) {
132
+ int aa = tmp[i];
133
+ int bb = qt_nearest_wrt(markers, qt, aa);
134
+ if (0 <= bb && bb < aa) {
135
+ n_nghbr[aa] = bb;
136
+ mindist[aa] = mr_distance(info, markers + aa, markers + bb);
137
+ pq_update(pq, aa);
138
+ inv_nghbr_next[aa] = inv_nghbr_head[bb];
139
+ inv_nghbr_head[bb] = aa;
140
+ } else {
141
+ pq_delete(pq, aa);
142
+ }
143
+ }
144
+ }
145
+ qt_clear(qt);
146
+ pq_clear(pq);
147
+ Free(n_nghbr);
148
+ Free(mindist);
149
+ Free(inv_nghbr_head);
150
+ Free(inv_nghbr_next);
151
+ Free(tmp);
152
+ return n_markers;
153
+ }
154
+
155
+ #ifndef EXCLUDE_UNIT_TEST
156
+
157
+ #include <sys/time.h>
158
+
159
+ /**
160
+ * Generate many random markers and then merge them. Write
161
+ * results as a Javascript array to be included included in a test page.
162
+ */
163
+ int merge_test(int size) {
164
+ struct timeval start[1], stop[1], diff[1];
165
+
166
+ MARKER_INFO_DECL(info);
167
+ mr_info_set(info, CIRCLE, 2);
168
+
169
+ NewArrayDecl(MARKER, markers, 2 * size - 1);
170
+ mr_init(markers, 2 * size - 1);
171
+ set_random_markers(info, markers, size);
172
+
173
+ int m = emit_markers("before", markers, size);
174
+ fprintf(stderr, "before merge: %d\nmerging...\n", m);
175
+
176
+ gettimeofday(start, NULL);
177
+
178
+ size = merge_markers_fast(info, markers, size);
179
+
180
+ gettimeofday(stop, NULL);
181
+
182
+ int n = emit_markers("after", markers, size);
183
+ fprintf(stderr, "after merge: %d\n", n);
184
+
185
+ timersub(stop, start, diff);
186
+ fprintf(stderr, "%.3f seconds", diff->tv_sec + 1.0e-6 * diff->tv_usec);
187
+
188
+ return EXIT_SUCCESS;
189
+ }
190
+
191
+ #endif
data/ext/lulu/merger.h ADDED
@@ -0,0 +1,17 @@
1
+ /*
2
+ * merger.h
3
+ *
4
+ * Created on: Feb 24, 2014
5
+ * Author: generessler
6
+ */
7
+
8
+ #ifndef MERGER_H_
9
+ #define MERGER_H_
10
+
11
+ #include "marker.h"
12
+
13
+ void merge_markers(MARKER_INFO *info, MARKER *markers, int markers_size);
14
+ int merge_markers_fast(MARKER_INFO *info, MARKER *markers, int markers_size);
15
+ int merge_test(int test_markers_size);
16
+
17
+ #endif /* MERGER_H_ */
data/ext/lulu/pq.c ADDED
@@ -0,0 +1,244 @@
1
+ /*
2
+ * priority_queue.c
3
+ *
4
+ * A priority queue with a min heap. This accepts an array
5
+ * of values and maintains a min heap of indices into the values array.
6
+ * There is also a reverse map that takes a value index to the heap
7
+ * element that refers to it. This allows values to be adjusted.
8
+ *
9
+ * Created on: Feb 23, 2014
10
+ * Author: generessler
11
+ */
12
+ #include <stdio.h>
13
+ #include <stdlib.h>
14
+ #include <assert.h>
15
+ #include "utility.h"
16
+ #include "pq.h"
17
+
18
+ // Move index at heap location j upward until its parent's value is no bigger.
19
+ static void pq_sift_up(PRIORITY_QUEUE *q, int j) {
20
+ int i = q->heap[j];
21
+ PRIORITY_QUEUE_VALUE val = q->values[i];
22
+ while (j > 0) {
23
+ int j_pnt = (j - 1) / 2;
24
+ if (q->values[q->heap[j_pnt]] <= val)
25
+ break;
26
+ int k = q->heap[j] = q->heap[j_pnt];
27
+ q->locs[k] = j;
28
+ j = j_pnt;
29
+ }
30
+ int k = q->heap[j] = i;
31
+ q->locs[k] = j;
32
+ }
33
+
34
+ // Move index at heap location j downward until its children's values are no smaller.
35
+ // Pay some attention to efficiency because this is bottleneck code.
36
+ static void pq_sift_down(PRIORITY_QUEUE *q, int j) {
37
+ int i = q->heap[j];
38
+ PRIORITY_QUEUE_VALUE val = q->values[i];
39
+ for (;;) {
40
+ int j_rgt = 2 * j + 2;
41
+ if (j_rgt < q->size) {
42
+ // two children
43
+ int j_lft = j_rgt - 1;
44
+ PRIORITY_QUEUE_VALUE val_lft = q->values[q->heap[j_lft]];
45
+ PRIORITY_QUEUE_VALUE val_rgt = q->values[q->heap[j_rgt]];
46
+ if (val_lft < val_rgt) {
47
+ if (val <= val_lft)
48
+ break;
49
+ int k = q->heap[j] = q->heap[j_lft];
50
+ q->locs[k] = j;
51
+ j = j_lft;
52
+ } else {
53
+ if (val <= val_rgt)
54
+ break;
55
+ int k = q->heap[j] = q->heap[j_rgt];
56
+ q->locs[k] = j;
57
+ j = j_rgt;
58
+ }
59
+ } else if (j_rgt == q->size) {
60
+ // left child only
61
+ int j_lft = j_rgt - 1;
62
+ if (val <= q->values[q->heap[j_lft]])
63
+ break;
64
+ int k = q->heap[j] = q->heap[j_lft];
65
+ q->locs[k] = j;
66
+ j = j_lft;
67
+ break; // this node has no children
68
+ } else {
69
+ break; // no children at all
70
+ }
71
+ }
72
+ int k = q->heap[j] = i;
73
+ q->locs[k] = j;
74
+ }
75
+
76
+ // Initialize a newly allocated priority queue structure.
77
+ void pq_init(PRIORITY_QUEUE *q) {
78
+ q->max_size = q->size = 0;
79
+ q->heap = NULL;
80
+ q->locs = NULL;
81
+ q->values = NULL;
82
+ }
83
+
84
+ // Clear a previously initialized and possibly set up priority queue, returning
85
+ // it to the initialized state but with all resourced freed. Note the values
86
+ // are owned by the user and are not freed here.
87
+ void pq_clear(PRIORITY_QUEUE *q) {
88
+ Free(q->heap);
89
+ Free(q->locs);
90
+ pq_init(q);
91
+ }
92
+
93
+ // Build the queue with given pre-allocated and filled array of values.
94
+ void pq_set_up(PRIORITY_QUEUE *q, PRIORITY_QUEUE_VALUE *values, int size) {
95
+ q->max_size = q->size = size;
96
+ q->values = values;
97
+ NewArray(q->heap, size);
98
+ NewArray(q->locs, size);
99
+ for (int i = 0; i < size; i++)
100
+ q->heap[i] = q->locs[i] = i;
101
+ // heapify
102
+ for (int j = size / 2 - 1; j >= 0; j--)
103
+ pq_sift_down(q, j);
104
+ }
105
+
106
+ // Build the queue with given pre-allocated and filled array of values
107
+ // and given heap indices. Note the indices are owned by the heap
108
+ // after set up and will be freed with the heap.
109
+ void pq_set_up_heap(PRIORITY_QUEUE *q, int *heap, int size,
110
+ PRIORITY_QUEUE_VALUE *values, int max_size) {
111
+ q->max_size = max_size;
112
+ q->values = values;
113
+ q->size = size;
114
+ q->heap = heap;
115
+ NewArray(q->locs, max_size);
116
+ for (int i = 0; i < max_size; i++)
117
+ q->locs[i] = -1;
118
+ for (int j = 0; j < size; j++)
119
+ q->locs[heap[j]] = j;
120
+ for (int j = size / 2 - 1; j >= 0; j--)
121
+ pq_sift_down(q, j);
122
+ }
123
+
124
+ // Return the index of the minimum value on the queue.
125
+ int pq_peek_min(PRIORITY_QUEUE *q) {
126
+ return q->size <= 0 ? -1 : q->heap[0];
127
+ }
128
+
129
+ // Remove and return the index of the minimum value on the queue.
130
+ int pq_get_min(PRIORITY_QUEUE *q) {
131
+ if (q->size <= 0)
132
+ return -1;
133
+ int i = q->heap[0];
134
+ q->locs[i] = -1;
135
+ if (--q->size > 0) {
136
+ q->heap[0] = q->heap[q->size];
137
+ pq_sift_down(q, 0);
138
+ }
139
+ return i;
140
+ }
141
+
142
+ // Add a new value with index i into the queue.
143
+ void pq_add(PRIORITY_QUEUE *q, int i) {
144
+ if (q->size >= q->max_size)
145
+ return;
146
+ int j = q->size++;
147
+ q->heap[j] = i;
148
+ pq_sift_up(q, j);
149
+ }
150
+
151
+ // Restore the heap after the value at index i is changed.
152
+ void pq_update(PRIORITY_QUEUE *q, int i) {
153
+ int j = q->locs[i];
154
+ if (j >= 0) {
155
+ pq_sift_down(q, j);
156
+ pq_sift_up(q, j);
157
+ }
158
+ }
159
+
160
+ // Delete index i from the heap, making the corresponding key an orphan.
161
+ void pq_delete(PRIORITY_QUEUE *q, int i) {
162
+ int j = q->locs[i];
163
+ if (0 <= j) {
164
+ q->locs[i] = -1;
165
+ if (j < --q->size) {
166
+ q->heap[j] = q->heap[q->size];
167
+ pq_sift_down(q, j);
168
+ pq_sift_up(q, j);
169
+ }
170
+ }
171
+ }
172
+
173
+ #ifndef EXCLUDE_UNIT_TEST
174
+
175
+ /* Randomly permute the given distance array. */
176
+ void permute(PRIORITY_QUEUE_VALUE *a, int size) {
177
+ for (int i = size - 1; i > 0; i--) {
178
+ int j = rand() % (i + 1);
179
+ PRIORITY_QUEUE_VALUE tmp = a[i];
180
+ a[i] = a[j];
181
+ a[j] = tmp;
182
+ }
183
+ }
184
+
185
+ // Run a unit test on a priority queue of random data with given size.
186
+ int pq_test(int size) {
187
+ PRIORITY_QUEUE q[1];
188
+ pq_init(q);
189
+
190
+ fprintf(stderr, "test: heap_ops (n = %d):\n", size);
191
+
192
+ // Build linear pointer array of random keys.
193
+ PRIORITY_QUEUE_VALUE *dist;
194
+ NewArray(dist, size);
195
+ for (int i = 0; i < size; i++)
196
+ dist[i] = i;
197
+ permute(dist, size);
198
+ fprintf(stderr, " built random data\n");
199
+
200
+ pq_set_up(q, dist, size);
201
+ fprintf(stderr, " finished set up\n");
202
+
203
+ // Pull min repeatedly and verify vals are what they should be.
204
+ PRIORITY_QUEUE_VALUE should_be = 0;
205
+ for (int n = 0; n < size; n++) {
206
+ int i = pq_get_min(q);
207
+ if (dist[i] != should_be++) {
208
+ fprintf(stderr, "fail 1: %i -> %g\n", i, dist[i]);
209
+ return 42;
210
+ }
211
+ }
212
+ fprintf(stderr, " finished checking heapify\n");
213
+
214
+ // Now rebuild the heap by inserting one key at a time.
215
+ for (int n = 0; n < size; n++)
216
+ pq_add(q, n);
217
+ fprintf(stderr, " finished insertions\n");
218
+
219
+ // And verify values again.
220
+ should_be = 0;
221
+ for (int n = 0; n < size; n++) {
222
+ int i = pq_get_min(q);
223
+ if (dist[i] != should_be++) {
224
+ fprintf(stderr, " fail 2: %i -> %g\n", i, dist[i]);
225
+ return 4242;
226
+ }
227
+ }
228
+ fprintf(stderr, " finished checking insert\n");
229
+
230
+ // Now rebuild the heap by inserting one key at a time in reverse.
231
+ for (int n = size - 1; n >= 0; n--)
232
+ pq_add(q, n);
233
+ fprintf(stderr, " finished reverse insertions\n");
234
+
235
+ // Now delete one by one.
236
+ for (int n = 0; n < size; n++)
237
+ pq_delete(q, n);
238
+ fprintf(stderr, " finished reverse deletions\n");
239
+
240
+ pq_clear(q);
241
+ return 0;
242
+ }
243
+
244
+ #endif
data/ext/lulu/pq.h ADDED
@@ -0,0 +1,70 @@
1
+ /*
2
+ * priority_queue.h
3
+ *
4
+ * Created on: Feb 23, 2014
5
+ * Author: generessler
6
+ */
7
+
8
+ #ifndef PRIORITY_QUEUE_H_
9
+ #define PRIORITY_QUEUE_H_
10
+
11
+ typedef double PRIORITY_QUEUE_VALUE;
12
+
13
+ typedef struct priority_queue_s {
14
+ int max_size; // max number of items in heap
15
+ int size; // current number of items in heap
16
+ int *heap; // heap of indices to values
17
+ int *locs; // map of value indices to heap locations
18
+ PRIORITY_QUEUE_VALUE *values; // values referred to by heap
19
+ } PRIORITY_QUEUE;
20
+
21
+ // Initialize a newly allocated priority queue structure.
22
+ void pq_init(PRIORITY_QUEUE *q);
23
+
24
+ #define PRIORITY_QUEUE_DECL(Q) PRIORITY_QUEUE Q[1]; pq_init(Q)
25
+
26
+ // Clear a previously initialized and possibly set up priority queue, returning
27
+ // it to the initialized state but with all resourced freed.
28
+ void pq_clear(PRIORITY_QUEUE *q);
29
+
30
+ // Build the queue with given pre-allocated and filled array of values.
31
+ void pq_set_up(PRIORITY_QUEUE *q, PRIORITY_QUEUE_VALUE *values, int size);
32
+
33
+ // Build the queue with given pre-allocated and filled array of values
34
+ // and given heap indices. Note the indices are owned by the heap
35
+ // after set up and will be freed with the heap.
36
+ void pq_set_up_heap(PRIORITY_QUEUE *q,
37
+ int *heap, int size,
38
+ PRIORITY_QUEUE_VALUE *values, int max_size);
39
+
40
+ // Return the index of the minimum value on the queue.
41
+ int pq_peek_min(PRIORITY_QUEUE *q);
42
+
43
+ // Remove and return the index of the minimum value on the queue.
44
+ int pq_get_min(PRIORITY_QUEUE *q);
45
+
46
+ // Update the queue given that the value at index i has changed.
47
+ void pq_update(PRIORITY_QUEUE *q, int i);
48
+
49
+ // Add a new value with index i into the queue.
50
+ void pq_add(PRIORITY_QUEUE *q, int i);
51
+
52
+ // Delete index i from the heap, making the corresponding key an orphan.
53
+ void pq_delete(PRIORITY_QUEUE *q, int i);
54
+
55
+ // Return an array containing indices currently in the heap.
56
+ #define pq_index_set(Q) ((Q)->heap)
57
+
58
+ // Return an array containing indices currently in the heap.
59
+ #define pq_index(Q, I) ((Q)->heap[I])
60
+
61
+ // Return the size of the index array contained above.
62
+ #define pq_index_set_size(Q) ((Q)->size)
63
+
64
+ // Return non-zero iff the queue is empty.
65
+ #define pq_empty_p(Q) ((Q)->size <= 0)
66
+
67
+ // Run the heap module through some unit tests.
68
+ int pq_test(int size);
69
+
70
+ #endif /* PRIORITY_QUEUE_H_ */