lulu 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|