lulu 0.0.2 → 0.0.3
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.
- checksums.yaml +8 -8
- data/.gitignore +1 -1
- data/ext/lulu/extconf.rb +3 -0
- data/ext/lulu/lulu.c +6 -6
- data/ext/lulu/marker.c +65 -65
- data/ext/lulu/marker.h +22 -22
- data/ext/lulu/merger.c +116 -154
- data/ext/lulu/merger.h +0 -2
- data/ext/lulu/pq.c +106 -179
- data/ext/lulu/pq.h +10 -13
- data/ext/lulu/qt.c +135 -191
- data/ext/lulu/qt.h +11 -10
- data/ext/lulu/test.c +221 -45
- data/ext/lulu/test.h +5 -0
- data/ext/lulu/utility.c +22 -26
- data/ext/lulu/utility.h +17 -14
- data/lib/lulu/version.rb +1 -1
- data/lulu.gemspec +10 -10
- metadata +6 -8
- data/ext/lulu/Makefile +0 -220
- data/lib/lulu/lulu.bundle +0 -0
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZWFjMGJjNzk1NGM5YzRjYTQxYmZkMDUxMTA4OWJhZmI1YjMyYzZjYg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YTRkMjY0YzcyNWVlZWVjN2I2NWI5MmE3ZjI3NGE0M2Y1NzkxMzhkMQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NTE3YmQxOTljNzA2MjU5MDljYmRkZGE1ZjNjMWIyNTgyNzczYzZmNzM2ODdh
|
10
|
+
Y2M2Mzg4NDk1OGM5MzNmNjgzZTY5ZmYyZGJkNzg0MGRmYmYwNDBkYzU0MDc5
|
11
|
+
ZWM2NmRhNTk0MzZhZWFlZjMzOWI2MjkzYWVlNmU0Y2E2YjFmYWE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NTFhMzc0MDY1YjhjMWUwYjE1ZTgwY2FlZTAyOTk0NTI4MmFkNGNiMzkxYjAw
|
14
|
+
NTY1M2Q5ODQ4YThmZjNhYzRkN2UxYjk2OTk0OTVjOWQ0ODQ1NjRhM2U1NjA2
|
15
|
+
NzBjYmMwNWE3NGEyODA2MDBjYjM2MjNmMTM5N2UwMjFlN2Q1ZTc=
|
data/.gitignore
CHANGED
data/ext/lulu/extconf.rb
CHANGED
data/ext/lulu/lulu.c
CHANGED
@@ -53,7 +53,7 @@ void free_marker_list(MARKER_LIST *list) {
|
|
53
53
|
Free(list);
|
54
54
|
}
|
55
55
|
|
56
|
-
void add_marker(MARKER_LIST *list,
|
56
|
+
void add_marker(MARKER_LIST *list, MARKER_COORD x, MARKER_COORD y, MARKER_SIZE size) {
|
57
57
|
if (list->size >= list->max_size) {
|
58
58
|
list->max_size = 4 + 2 * list->max_size;
|
59
59
|
RenewArray(list->markers, list->max_size);
|
@@ -85,12 +85,12 @@ void compress(MARKER_LIST *list) {
|
|
85
85
|
// -------- Ruby API implementation --------------------------------------------
|
86
86
|
|
87
87
|
static void rb_api_free_marker_list(void *list) {
|
88
|
-
|
88
|
+
free_marker_list(list);
|
89
89
|
}
|
90
90
|
|
91
91
|
static VALUE rb_api_new_marker_list(VALUE klass) {
|
92
|
-
|
93
|
-
|
92
|
+
MARKER_LIST *list = new_marker_list();
|
93
|
+
return Data_Wrap_Struct(klass, 0, rb_api_free_marker_list, list);
|
94
94
|
}
|
95
95
|
|
96
96
|
#define MARKER_LIST_FOR_VALUE_DECL(Var) MARKER_LIST *Var; Data_Get_Struct(Var ## _value, MARKER_LIST, Var)
|
@@ -247,8 +247,8 @@ static struct ft_entry {
|
|
247
247
|
#define STRING_CONST_TABLE_ENTRY(Name) { #Name, Name }
|
248
248
|
|
249
249
|
static struct sct_entry {
|
250
|
-
|
251
|
-
|
250
|
+
const char *name;
|
251
|
+
const char *val;
|
252
252
|
} string_const_table[] = {
|
253
253
|
STRING_CONST_TABLE_ENTRY(EXT_VERSION)
|
254
254
|
};
|
data/ext/lulu/marker.c
CHANGED
@@ -16,24 +16,24 @@
|
|
16
16
|
void mr_info_init(MARKER_INFO *info) {
|
17
17
|
info->kind = CIRCLE;
|
18
18
|
info->scale = 1;
|
19
|
-
|
19
|
+
info->c = SQRT_1_PI;
|
20
20
|
}
|
21
21
|
|
22
|
-
void mr_info_set(MARKER_INFO *info, MARKER_KIND kind,
|
22
|
+
void mr_info_set(MARKER_INFO *info, MARKER_KIND kind, MARKER_DISTANCE scale) {
|
23
23
|
info->kind = kind;
|
24
24
|
info->scale = scale;
|
25
|
-
|
25
|
+
info->c = scale * (kind == SQUARE ? 0.5 : SQRT_1_PI);
|
26
26
|
}
|
27
27
|
|
28
28
|
void mr_init(MARKER *markers, int n_markers) {
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
37
|
}
|
38
38
|
|
39
39
|
void mr_reset_parts(MARKER *marker) {
|
@@ -41,71 +41,71 @@ void mr_reset_parts(MARKER *marker) {
|
|
41
41
|
marker->part_b = 0;
|
42
42
|
}
|
43
43
|
|
44
|
-
void mr_set(MARKER_INFO *info, MARKER *marker,
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
44
|
+
void mr_set(MARKER_INFO *info, MARKER *marker, MARKER_COORD x, MARKER_COORD y, MARKER_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
52
|
}
|
53
53
|
|
54
54
|
void mr_merge(MARKER_INFO *info, MARKER *markers, int i_merged, int ia, int ib) {
|
55
55
|
MARKER *merged = markers + i_merged;
|
56
56
|
MARKER *a = markers + ia;
|
57
57
|
MARKER *b = markers + ib;
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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
67
|
}
|
68
68
|
|
69
|
-
|
70
|
-
|
69
|
+
MARKER_DISTANCE size_to_radius(MARKER_INFO *info, MARKER_SIZE size) {
|
70
|
+
return info->c * sqrt(size);
|
71
71
|
}
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
73
|
+
MARKER_DISTANCE mr_distance(MARKER_INFO *info, MARKER *a, MARKER *b) {
|
74
|
+
if (info->kind == SQUARE) {
|
75
|
+
MARKER_DISTANCE r_sum = mr_r(a) + mr_r(b);
|
76
|
+
MARKER_DISTANCE dx = fabs(mr_x(b) - mr_x(a)) - r_sum;
|
77
|
+
MARKER_DISTANCE dy = fabs(mr_y(b) - mr_y(a)) - r_sum;
|
78
|
+
MARKER_DISTANCE d = dx < 0 && dy < 0 ? fmax(dx, dy) : sqrt(dx * dx + dy * dy);
|
79
|
+
return d;
|
80
|
+
}
|
81
|
+
MARKER_DISTANCE dx = mr_x(b) - mr_x(a);
|
82
|
+
MARKER_DISTANCE dy = mr_y(b) - mr_y(a);
|
83
|
+
return sqrt(dx * dx + dy * dy) - mr_r(a) - mr_r(b);
|
84
84
|
}
|
85
85
|
|
86
86
|
void get_marker_array_extent(MARKER *a, int n_markers, MARKER_EXTENT *ext) {
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
87
|
+
if (n_markers > 0) {
|
88
|
+
MARKER_DISTANCE ew = mr_w(a);
|
89
|
+
MARKER_DISTANCE ee = mr_e(a);
|
90
|
+
MARKER_DISTANCE es = mr_s(a);
|
91
|
+
MARKER_DISTANCE en = mr_n(a);
|
92
|
+
for (int i = 1; i < n_markers; i++) {
|
93
|
+
MARKER_DISTANCE w = mr_w(a + i);
|
94
|
+
MARKER_DISTANCE e = mr_e(a + i);
|
95
|
+
MARKER_DISTANCE s = mr_s(a + i);
|
96
|
+
MARKER_DISTANCE 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
111
|
}
|
data/ext/lulu/marker.h
CHANGED
@@ -8,46 +8,46 @@
|
|
8
8
|
#ifndef MARKER_H_
|
9
9
|
#define MARKER_H_
|
10
10
|
|
11
|
-
typedef double
|
12
|
-
typedef double
|
11
|
+
typedef double MARKER_COORD;
|
12
|
+
typedef double MARKER_DISTANCE;
|
13
13
|
/**
|
14
14
|
* Size of population represented by the marker. For
|
15
15
|
* discrete populations, this can be an unsigned int.
|
16
16
|
*/
|
17
|
-
typedef double
|
17
|
+
typedef double MARKER_SIZE;
|
18
18
|
|
19
19
|
typedef struct marker_s {
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
MARKER_SIZE size;
|
21
|
+
MARKER_DISTANCE r;
|
22
|
+
MARKER_COORD x, y, x_sum, y_sum;
|
23
|
+
int part_a;
|
24
|
+
unsigned deleted_p:1, part_b:31;
|
25
25
|
} MARKER;
|
26
26
|
|
27
27
|
typedef enum marker_kind_e {
|
28
|
-
|
29
|
-
|
28
|
+
CIRCLE,
|
29
|
+
SQUARE,
|
30
30
|
} MARKER_KIND;
|
31
31
|
|
32
32
|
/**
|
33
33
|
* Holds parameters of the distance function and merging.
|
34
34
|
*/
|
35
35
|
typedef struct marker_type_info_s {
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
MARKER_KIND kind;
|
37
|
+
// User scale applied to radii of markers during distance computation.
|
38
|
+
MARKER_DISTANCE scale;
|
39
|
+
// A scale factor that depends on both kind and user scale.
|
40
|
+
MARKER_DISTANCE c;
|
41
41
|
} MARKER_INFO;
|
42
42
|
|
43
43
|
#define MARKER_INFO_DECL(I) MARKER_INFO I[1]; mr_info_init(I)
|
44
44
|
|
45
45
|
typedef struct marker_extent_s {
|
46
|
-
|
46
|
+
MARKER_COORD x, y, w, h;
|
47
47
|
} MARKER_EXTENT;
|
48
48
|
|
49
|
-
#define mr_deleted_p(M)
|
50
|
-
#define mr_set_deleted(M)
|
49
|
+
#define mr_deleted_p(M) ((M)->deleted_p)
|
50
|
+
#define mr_set_deleted(M) do { (M)->deleted_p = 1; } while (0)
|
51
51
|
#define mr_merged(M) ((M)->part_a >= 0)
|
52
52
|
#define mr_x(M) ((M)->x)
|
53
53
|
#define mr_y(M) ((M)->y)
|
@@ -60,11 +60,11 @@ typedef struct marker_extent_s {
|
|
60
60
|
void mr_init(MARKER *marker, int n_markers);
|
61
61
|
void mr_reset_parts(MARKER *marker);
|
62
62
|
void mr_info_init(MARKER_INFO *info);
|
63
|
-
void mr_info_set(MARKER_INFO *info, MARKER_KIND kind,
|
64
|
-
void mr_set(MARKER_INFO *info, MARKER *marker,
|
63
|
+
void mr_info_set(MARKER_INFO *info, MARKER_KIND kind, MARKER_DISTANCE scale);
|
64
|
+
void mr_set(MARKER_INFO *info, MARKER *marker, MARKER_COORD x, MARKER_COORD y, MARKER_SIZE size);
|
65
65
|
void mr_merge(MARKER_INFO *info, MARKER *markers, int merged, int a, int b);
|
66
|
-
|
67
|
-
|
66
|
+
MARKER_DISTANCE mr_distance(MARKER_INFO *info, MARKER *a, MARKER *b);
|
67
|
+
MARKER_DISTANCE size_to_radius(MARKER_INFO *info, MARKER_SIZE size);
|
68
68
|
void get_marker_array_extent(MARKER *a, int n_markers, MARKER_EXTENT *ext);
|
69
69
|
|
70
70
|
#endif /* MARKER_H_ */
|
data/ext/lulu/merger.c
CHANGED
@@ -34,158 +34,120 @@
|
|
34
34
|
* overlapping markers in the original, unmerged set.
|
35
35
|
*/
|
36
36
|
int merge_markers_fast(MARKER_INFO *info, MARKER *markers, int n_markers) {
|
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
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
37
|
+
int augmented_length = 2 * n_markers - 1;
|
38
|
+
NewArrayDecl(int, n_nghbr, augmented_length);
|
39
|
+
NewArrayDecl(MARKER_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
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
|