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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- Y2E5ZGRjNDExMGVlYWQwNjUyNzYzYmFhNWFlNTU1OTVkZWM0ZjY5OA==
4
+ ZWFjMGJjNzk1NGM5YzRjYTQxYmZkMDUxMTA4OWJhZmI1YjMyYzZjYg==
5
5
  data.tar.gz: !binary |-
6
- MGQ2NDZjZTk5Njc1NzE4OWM5ZDJiNmNkZDAwNTlkNjMzYWY4NmJkZg==
6
+ YTRkMjY0YzcyNWVlZWVjN2I2NWI5MmE3ZjI3NGE0M2Y1NzkxMzhkMQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NTkzODkzOTUxNGIyYjY2OTNjMmUxYjA3MTI0MDUxNDU4MDEwMzJjYTcxMzU5
10
- NTVhZmVkNjZjMzMyYzIyYjVmOTUzZjM2MmVhMTZjNWI0MTIzYmI2MTcwYmNh
11
- NjE5MzU5NDVmNTRhMjQwN2JmZjJhMDQ0MGUwMTgxNjYxYzVlYTU=
9
+ NTE3YmQxOTljNzA2MjU5MDljYmRkZGE1ZjNjMWIyNTgyNzczYzZmNzM2ODdh
10
+ Y2M2Mzg4NDk1OGM5MzNmNjgzZTY5ZmYyZGJkNzg0MGRmYmYwNDBkYzU0MDc5
11
+ ZWM2NmRhNTk0MzZhZWFlZjMzOWI2MjkzYWVlNmU0Y2E2YjFmYWE=
12
12
  data.tar.gz: !binary |-
13
- MWVjNjUxNTgwZGJiNjVkYWMyZWY3NWVmMDUxY2ZkOWQzMWRiNDYxNWZkNzlj
14
- MWZmZTQyMDU5MmM1Nzk2ZGFmOTk5ZGEzYWI0MDAwNTRjOGFiNWVlMDY5YzY5
15
- NDk4Mzc4ZjIyNWU3ZjljZWRmNGNjNTFlOWZhOGE4ZGQwODVjYmM=
13
+ NTFhMzc0MDY1YjhjMWUwYjE1ZTgwY2FlZTAyOTk0NTI4MmFkNGNiMzkxYjAw
14
+ NTY1M2Q5ODQ4YThmZjNhYzRkN2UxYjk2OTk0OTVjOWQ0ODQ1NjRhM2U1NjA2
15
+ NzBjYmMwNWE3NGEyODA2MDBjYjM2MjNmMTM5N2UwMjFlN2Q1ZTc=
data/.gitignore CHANGED
@@ -2,7 +2,7 @@
2
2
  *.rbc
3
3
  *.o
4
4
  *.d
5
- .bundle
5
+ *.bundle
6
6
  .config
7
7
  .yardoc
8
8
  .idea/
data/ext/lulu/extconf.rb CHANGED
@@ -3,4 +3,7 @@ require 'mkmf'
3
3
  # Turn off warnings about declarations mixed with code.
4
4
  $CFLAGS += ' -std=c99 -Wno-declaration-after-statement'
5
5
 
6
+ # Select Ruby gem code
7
+ $CFLAGS += ' -DLULU_GEM'
8
+
6
9
  create_makefile('lulu/lulu')
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, COORD x, COORD y, SIZE size) {
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
- free_marker_list(list);
88
+ free_marker_list(list);
89
89
  }
90
90
 
91
91
  static VALUE rb_api_new_marker_list(VALUE klass) {
92
- MARKER_LIST *list = new_marker_list();
93
- return Data_Wrap_Struct(klass, 0, rb_api_free_marker_list, list);
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
- const char *name;
251
- const char *val;
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
- info->c = SQRT_1_PI;
19
+ info->c = SQRT_1_PI;
20
20
  }
21
21
 
22
- void mr_info_set(MARKER_INFO *info, MARKER_KIND kind, DISTANCE scale) {
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
- info->c = scale * (kind == SQUARE ? 0.5 : SQRT_1_PI);
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
- 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
- }
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, 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;
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
- 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;
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
- DISTANCE size_to_radius(MARKER_INFO *info, SIZE size) {
70
- return info->c * sqrt(size);
69
+ MARKER_DISTANCE size_to_radius(MARKER_INFO *info, MARKER_SIZE size) {
70
+ return info->c * sqrt(size);
71
71
  }
72
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);
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
- 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
- }
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 COORD;
12
- typedef double DISTANCE;
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 SIZE;
17
+ typedef double MARKER_SIZE;
18
18
 
19
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;
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
- CIRCLE,
29
- SQUARE,
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
- 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;
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
- COORD x, y, w, h;
46
+ MARKER_COORD x, y, w, h;
47
47
  } MARKER_EXTENT;
48
48
 
49
- #define mr_deleted_p(M) ((M)->deleted_p)
50
- #define mr_set_deleted(M) do { (M)->deleted_p = 1; } while (0)
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, DISTANCE scale);
64
- void mr_set(MARKER_INFO *info, MARKER *marker, COORD x, COORD y, SIZE size);
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
- DISTANCE mr_distance(MARKER_INFO *info, MARKER *a, MARKER *b);
67
- DISTANCE size_to_radius(MARKER_INFO *info, SIZE size);
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
- 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;
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