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 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