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.
data/ext/lulu/qt.h CHANGED
@@ -11,9 +11,9 @@
11
11
  #include "marker.h"
12
12
 
13
13
  typedef struct node_s {
14
- struct node_s *children;
15
- MARKER **markers;
16
- int marker_count, markers_size;
14
+ struct node_s *children;
15
+ MARKER **markers;
16
+ int marker_count, markers_size;
17
17
  } NODE;
18
18
 
19
19
  #define leaf_p(Node) ((Node)->children == NULL)
@@ -37,21 +37,22 @@ typedef struct node_s {
37
37
  #define NE 3
38
38
 
39
39
  typedef struct quadtree_s {
40
- double x, y, w, h;
41
- int max_depth;
42
- MARKER_INFO *info;
43
- NODE root[1];
40
+ MARKER_COORD x, y;
41
+ MARKER_DISTANCE w, h;
42
+ int max_depth;
43
+ MARKER_INFO *info;
44
+ NODE root[1];
44
45
  } QUADTREE;
45
46
 
46
47
  #define QUADTREE_DECL(Name) QUADTREE Name[1]; qt_init(Name)
47
48
 
48
49
  void qt_init(QUADTREE *qt);
49
- void qt_setup(QUADTREE *qt, int max_depth, double x, double y, double w, double h, MARKER_INFO *info);
50
+ void qt_setup(QUADTREE *qt, int max_depth,
51
+ MARKER_COORD x, MARKER_COORD y, MARKER_DISTANCE w, MARKER_DISTANCE h,
52
+ MARKER_INFO *info);
50
53
  void qt_insert(QUADTREE *qt, MARKER *marker);
51
54
  void qt_delete(QUADTREE *qt, MARKER *marker);
52
55
  MARKER *qt_nearest(QUADTREE *qt, MARKER *marker);
53
56
  int qt_nearest_wrt(MARKER *markers, QUADTREE *qt, int a);
54
- void qt_clear(QUADTREE *qt);
55
- int qt_test(int size);
56
57
 
57
58
  #endif /* QT_H_ */
data/ext/lulu/test.c CHANGED
@@ -5,78 +5,254 @@
5
5
  * Author: generessler
6
6
  */
7
7
 
8
+ #ifdef UNIT_TESTS
9
+
8
10
  #include <stdio.h>
9
11
  #include <stdlib.h>
10
12
  #include <stdarg.h>
11
13
  #include <time.h>
14
+ #include <sys/time.h>
12
15
  #include "test.h"
13
16
  #include "utility.h"
14
17
 
18
+ double rand_double(void)
19
+ {
20
+ unsigned i = rand();
21
+ i = (i << 8) ^ (unsigned)rand();
22
+ i = (i << 8) ^ (unsigned)rand();
23
+ i = (i << 8) ^ (unsigned)rand();
24
+ return i / (256.0 * 256.0 * 256.0 * 256.0);
25
+ }
26
+
15
27
  void emit_rectangle(FILE *f, double x, double y, double w, double h) {
16
- fprintf(f, " { kind: 'r', color: 'lightGray', p0: { x: %.2f, y: %.2f }, p1: { x: %.2f, y: %.2f } },\n", x, y, x + w, y + h);
28
+ fprintf(f, " { kind: 'r', color: 'lightGray', p0: { x: %.2f, y: %.2f }, p1: { x: %.2f, y: %.2f } },\n", x, y, x + w, y + h);
17
29
  }
18
30
 
19
31
  void emit_segment(FILE *f, MARKER *a, MARKER *b) {
20
- fprintf(f, " { kind: 's', color: 'red', p0: { x: %.2f, y: %.2f }, p1: { x: %.2f, y: %.2f } },\n",
21
- mr_x(a), mr_y(a), mr_x(b), mr_y(b));
32
+ fprintf(f, " { kind: 's', color: 'red', p0: { x: %.2f, y: %.2f }, p1: { x: %.2f, y: %.2f } },\n",
33
+ mr_x(a), mr_y(a), mr_x(b), mr_y(b));
22
34
  }
23
35
 
24
36
  int emit_marker_ptr_array(FILE *f, MARKER **markers, int n_markers) {
25
- int n_emitted = 0;
26
- for (int i = 0; i < n_markers; ++i) {
27
- MARKER *m = markers[i];
28
- if (!m->deleted_p) {
29
- fprintf(f, " { kind: 'm', x: %.2f, y: %.2f, r: %.2f }, // %d\n", mr_x(m), mr_y(m), mr_r(m), i);
30
- n_emitted++;
31
- }
32
- }
33
- return n_emitted;
37
+ int n_emitted = 0;
38
+ for (int i = 0; i < n_markers; ++i) {
39
+ MARKER *m = markers[i];
40
+ if (!m->deleted_p) {
41
+ fprintf(f, " { kind: 'm', x: %.2f, y: %.2f, r: %.2f }, // %d\n", mr_x(m), mr_y(m), mr_r(m), i);
42
+ n_emitted++;
43
+ }
44
+ }
45
+ return n_emitted;
34
46
  }
35
47
 
36
48
  int emit_marker_array(FILE *f, MARKER *markers, int n_markers) {
37
- int n_emitted = 0;
38
- for (int i = 0; i < n_markers; ++i) {
39
- MARKER *m = markers + i;
40
- if (!m->deleted_p) {
41
- fprintf(f, " { x: %.2f, y: %.2f, r: %.2f }, // %d\n", mr_x(m), mr_y(m), mr_r(m), i);
42
- n_emitted++;
43
- }
44
- }
45
- return n_emitted;
49
+ int n_emitted = 0;
50
+ for (int i = 0; i < n_markers; ++i) {
51
+ MARKER *m = markers + i;
52
+ if (!m->deleted_p) {
53
+ fprintf(f, " { x: %.2f, y: %.2f, r: %.2f }, // %d\n", mr_x(m), mr_y(m), mr_r(m), i);
54
+ n_emitted++;
55
+ }
56
+ }
57
+ return n_emitted;
46
58
  }
47
59
 
48
60
  int emit_markers(const char *name, MARKER *markers, int n_markers) {
49
- char buf[1024];
50
- sprintf(buf, "test/%s.js", name);
51
- FILE *f = fopen(buf, "w");
52
- if (!f)
53
- return -1;
54
- fprintf(f, "var %s = [\n", name);
55
- int n_emitted = emit_marker_array(f, markers, n_markers);
56
- fprintf(f, "];");
57
- fclose(f);
58
- return n_emitted;
61
+ char buf[1024];
62
+ sprintf(buf, "test/%s.js", name);
63
+ FILE *f = fopen(buf, "w");
64
+ if (!f)
65
+ return -1;
66
+ fprintf(f, "var %s = [\n", name);
67
+ int n_emitted = emit_marker_array(f, markers, n_markers);
68
+ fprintf(f, "];");
69
+ fclose(f);
70
+ return n_emitted;
59
71
  }
60
72
 
61
73
  void set_random_markers(MARKER_INFO *info, MARKER *markers, int n_markers) {
62
- unsigned t = (unsigned)time(0);
63
- fprintf(stderr, "seed=%u\n", t);
64
- srand(t);
65
- int size = 8;
66
- double x_size = 1024;
67
- double y_size = 760;
68
- for (int i = 0; i < n_markers; i++)
69
- mr_set(info, markers + i, x_size * rand_double(), y_size * rand_double(), 1 + random() % (size - 1));
74
+ unsigned t = (unsigned)time(0);
75
+ fprintf(stderr, "seed=%u\n", t);
76
+ srand(t);
77
+ int size = 8;
78
+ double x_size = 1024;
79
+ double y_size = 760;
80
+ for (int i = 0; i < n_markers; i++)
81
+ mr_set(info, markers + i, x_size * rand_double(), y_size * rand_double(), 1 + random() % (size - 1));
70
82
  }
71
83
 
72
84
  int trace_p = 1;
73
85
 
74
86
  void trace(const char *fmt, ...)
75
87
  {
76
- if (trace_p) {
77
- va_list ap;
78
- va_start(ap, fmt);
79
- vfprintf(stderr, fmt, ap);
80
- va_end(ap);
81
- }
88
+ if (trace_p) {
89
+ va_list ap;
90
+ va_start(ap, fmt);
91
+ vfprintf(stderr, fmt, ap);
92
+ va_end(ap);
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Generate many random markers and then merge them. Write
98
+ * results as a Javascript array to be included included in a test page.
99
+ */
100
+ int merge_test(int size) {
101
+ struct timeval start[1], stop[1], diff[1];
102
+
103
+ MARKER_INFO_DECL(info);
104
+ mr_info_set(info, CIRCLE, 2);
105
+
106
+ NewArrayDecl(MARKER, markers, 2 * size - 1);
107
+ mr_init(markers, 2 * size - 1);
108
+ set_random_markers(info, markers, size);
109
+
110
+ int m = emit_markers("before", markers, size);
111
+ fprintf(stderr, "before merge: %d\nmerging...\n", m);
112
+
113
+ gettimeofday(start, NULL);
114
+
115
+ size = merge_markers_fast(info, markers, size);
116
+
117
+ gettimeofday(stop, NULL);
118
+
119
+ int n = emit_markers("after", markers, size);
120
+ fprintf(stderr, "after merge: %d\n", n);
121
+
122
+ timersub(stop, start, diff);
123
+ fprintf(stderr, "%.3f seconds", diff->tv_sec + 1.0e-6 * diff->tv_usec);
124
+
125
+ return EXIT_SUCCESS;
126
+ }
127
+
128
+
129
+ /* Randomly permute the given distance array. */
130
+ void permute(PRIORITY_QUEUE_VALUE *a, int size) {
131
+ for (int i = size - 1; i > 0; i--) {
132
+ int j = rand() % (i + 1);
133
+ PRIORITY_QUEUE_VALUE tmp = a[i];
134
+ a[i] = a[j];
135
+ a[j] = tmp;
136
+ }
137
+ }
138
+
139
+ // Run a unit test on a priority queue of random data with given size.
140
+ int pq_test(int size) {
141
+ PRIORITY_QUEUE q[1];
142
+ pq_init(q);
143
+
144
+ fprintf(stderr, "test: heap_ops (n = %d):\n", size);
145
+
146
+ // Build linear pointer array of random keys.
147
+ PRIORITY_QUEUE_VALUE *dist;
148
+ NewArray(dist, size);
149
+ for (int i = 0; i < size; i++)
150
+ dist[i] = i;
151
+ permute(dist, size);
152
+ fprintf(stderr, " built random data\n");
153
+
154
+ pq_set_up(q, dist, size);
155
+ fprintf(stderr, " finished set up\n");
156
+
157
+ // Pull min repeatedly and verify vals are what they should be.
158
+ PRIORITY_QUEUE_VALUE should_be = 0;
159
+ for (int n = 0; n < size; n++) {
160
+ int i = pq_get_min(q);
161
+ if (dist[i] != should_be++) {
162
+ fprintf(stderr, "fail 1: %i -> %g\n", i, dist[i]);
163
+ return 42;
164
+ }
165
+ }
166
+ fprintf(stderr, " finished checking heapify\n");
167
+
168
+ // Now rebuild the heap by inserting one key at a time.
169
+ for (int n = 0; n < size; n++)
170
+ pq_add(q, n);
171
+ fprintf(stderr, " finished insertions\n");
172
+
173
+ // And verify values again.
174
+ should_be = 0;
175
+ for (int n = 0; n < size; n++) {
176
+ int i = pq_get_min(q);
177
+ if (dist[i] != should_be++) {
178
+ fprintf(stderr, " fail 2: %i -> %g\n", i, dist[i]);
179
+ return 4242;
180
+ }
181
+ }
182
+ fprintf(stderr, " finished checking insert\n");
183
+
184
+ // Now rebuild the heap by inserting one key at a time in reverse.
185
+ for (int n = size - 1; n >= 0; n--)
186
+ pq_add(q, n);
187
+ fprintf(stderr, " finished reverse insertions\n");
188
+
189
+ // Now delete one by one.
190
+ for (int n = 0; n < size; n++)
191
+ pq_delete(q, n);
192
+ fprintf(stderr, " finished reverse deletions\n");
193
+
194
+ pq_clear(q);
195
+ return 0;
82
196
  }
197
+
198
+ static void draw(FILE *f, NODE *node, double x, double y, double w, double h) {
199
+ emit_rectangle(f, x, y, w, h);
200
+ emit_marker_ptr_array(f, node->markers, node->marker_count);
201
+ if (internal_p(node)) {
202
+ for (int q = 0; q < 4; q++) {
203
+ QUADRANT_DECL(q, qx, qy, qw, qh, x, y, w, h);
204
+ draw(f, node->children + q, qx, qy, qw, qh);
205
+ }
206
+ }
207
+ }
208
+
209
+ static void draw_nearest(FILE *f, MARKER *markers, MARKER **nearest_markers, int n_markers) {
210
+ for (int i = 0; i < n_markers; i++) {
211
+ if (nearest_markers[i])
212
+ emit_segment(f, markers + i, nearest_markers[i]);
213
+ }
214
+ }
215
+
216
+ int qt_draw(QUADTREE *qt, MARKER *markers, MARKER **nearest_markers, int n_markers, const char *name) {
217
+ char buf[1024];
218
+ sprintf(buf, "test/%s.js", name);
219
+ FILE *f = fopen(buf, "w");
220
+ if (!f)
221
+ return -1;
222
+ fprintf(f, "var %s = [\n", name);
223
+ draw(f, qt->root, qt->x, qt->y, qt->w, qt->h);
224
+ draw_nearest(f, markers, nearest_markers, n_markers);
225
+ fprintf(f, "];\n");
226
+ fclose(f);
227
+ return EXIT_SUCCESS;
228
+ }
229
+
230
+ int qt_test(int size) {
231
+ QUADTREE_DECL(qt);
232
+ MARKER_INFO_DECL(info);
233
+ MARKER *markers, **nearest_markers;
234
+ NewArray(markers, size);
235
+ NewArray(nearest_markers, size);
236
+ set_random_markers(info, markers, size);
237
+ qt_setup(qt, 5, 0, 0, 1024, 724, info);
238
+ fprintf(stderr, "inserting %d:\n", size);
239
+ for (int i = 0; i < size; i++) {
240
+ qt_insert(qt, markers + i);
241
+ }
242
+ fprintf(stderr, "inserted %d\n", size);
243
+ for (int i = 0; i < size; i++) {
244
+ nearest_markers[i] = qt_nearest(qt, markers + i);
245
+ }
246
+ fprintf(stderr, "looked up %d\n", size);
247
+ qt_draw(qt, markers, nearest_markers, size, "qt");
248
+ fprintf(stderr, "drew %d\n", size);
249
+ for (int i = 0; i < size; i++) {
250
+ qt_delete(qt, markers + i);
251
+ }
252
+ fprintf(stderr, "after delete all, root is %s\n",
253
+ leaf_p(qt->root) ? "leaf (ok)" : "internal (not ok)");
254
+
255
+ return EXIT_SUCCESS;
256
+ }
257
+
258
+ #endif
data/ext/lulu/test.h CHANGED
@@ -15,6 +15,11 @@ void emit_rectangle(FILE *f, double x, double y, double w, double h);
15
15
  void emit_segment(FILE *f, MARKER *a, MARKER *b);
16
16
  int emit_marker_array(FILE *f, MARKER *markers, int n_markers);
17
17
  int emit_marker_ptr_array(FILE *f, MARKER **markers, int n_markers);
18
+ double rand_double(void);
18
19
  void set_random_markers(MARKER_INFO *info, MARKER *markers, int n_markers);
20
+ void qt_clear(QUADTREE *qt);
21
+ int qt_test(int size);
22
+ int pq_test(int size);
23
+ int merge_test(int test_markers_size);
19
24
 
20
25
  #endif /* TEST_H_ */
data/ext/lulu/utility.c CHANGED
@@ -9,41 +9,37 @@
9
9
  #include <stdlib.h>
10
10
  #include "utility.h"
11
11
 
12
+ #ifdef LULU_STD_C
13
+
12
14
  void *safe_malloc(size_t size, const char *file, int line) {
13
- void *p = malloc(size);
14
- if (!p) {
15
- fprintf(stderr, "%s:%d: out of memory\n", file, line);
16
- exit(1);
17
- }
18
- return p;
15
+ void *p = malloc(size);
16
+ if (!p) {
17
+ fprintf(stderr, "%s:%d: out of memory\n", file, line);
18
+ exit(1);
19
+ }
20
+ return p;
19
21
  }
20
22
 
21
23
  void *safe_realloc(void *p, size_t size, const char *file, int line) {
22
- p = realloc(p, size);
23
- if (!p) {
24
- fprintf(stderr, "%s:%d: out of memory\n", file, line);
25
- exit(1);
26
- }
27
- return p;
24
+ p = realloc(p, size);
25
+ if (!p) {
26
+ fprintf(stderr, "%s:%d: out of memory\n", file, line);
27
+ exit(1);
28
+ }
29
+ return p;
28
30
  }
29
31
 
32
+ #endif
33
+
30
34
  /**
31
35
  * Return the 0-based position of highest bit or -1 of zero.
32
36
  */
33
37
  int high_bit_position(unsigned n) {
34
- int p = -1;
35
- while (n) {
36
- p++;
37
- n >>= 1;
38
- }
39
- return p;
38
+ int p = -1;
39
+ while (n) {
40
+ p++;
41
+ n >>= 1;
42
+ }
43
+ return p;
40
44
  }
41
45
 
42
- double rand_double(void)
43
- {
44
- unsigned i = rand();
45
- i = (i << 8) ^ (unsigned)rand();
46
- i = (i << 8) ^ (unsigned)rand();
47
- i = (i << 8) ^ (unsigned)rand();
48
- return i / (256.0 * 256.0 * 256.0 * 256.0);
49
- }
data/ext/lulu/utility.h CHANGED
@@ -10,45 +10,51 @@
10
10
 
11
11
  #define STATIC_ARRAY_SIZE(A) ((int)(sizeof A / sizeof A[0]))
12
12
 
13
- #ifdef NOT_RUBY_EXTENSION
13
+ #ifdef LULU_STD_C
14
14
 
15
15
  // Our allocators.
16
16
  #define New(Ptr) do { \
17
- (Ptr) = safe_malloc(sizeof *(Ptr), __FILE__, __LINE__); \
17
+ (Ptr) = safe_malloc(sizeof *(Ptr), __FILE__, __LINE__); \
18
18
  } while (0)
19
19
 
20
20
  #define NewArray(Ptr, Size) do { \
21
- (Ptr) = safe_malloc((Size) * sizeof *(Ptr), __FILE__, __LINE__); \
21
+ (Ptr) = safe_malloc((Size) * sizeof *(Ptr), __FILE__, __LINE__); \
22
22
  } while (0)
23
23
 
24
24
  #define RenewArray(Ptr, Size) do { \
25
- (Ptr) = safe_realloc((Ptr), (Size) * sizeof *(Ptr), __FILE__, __LINE__); \
25
+ (Ptr) = safe_realloc((Ptr), (Size) * sizeof *(Ptr), __FILE__, __LINE__); \
26
26
  } while (0)
27
27
 
28
28
  #define Free(Ptr) do { \
29
- free(Ptr); \
30
- Ptr = NULL; \
29
+ free(Ptr); \
30
+ Ptr = NULL; \
31
31
  } while (0)
32
32
 
33
- #else
33
+ void *safe_malloc(size_t size, const char *file, int line);
34
+ void *safe_realloc(void *p, size_t size, const char *file, int line);
35
+
36
+ #endif
37
+
38
+ #ifdef LULU_GEM
34
39
 
35
40
  #include "ruby.h"
36
41
 
37
42
  // Ruby allocators. We can't use the macros without rewriting to include type parameters.
38
43
  #define New(Ptr) do { \
39
- (Ptr) = (void*)xmalloc(sizeof *(Ptr)); \
44
+ (Ptr) = (void*)xmalloc(sizeof *(Ptr)); \
40
45
  } while (0)
41
46
 
42
47
  #define NewArray(Ptr, Size) do { \
43
- (Ptr) = (void*)xmalloc2((Size), sizeof *(Ptr)); \
48
+ (Ptr) = (void*)xmalloc2((Size), sizeof *(Ptr)); \
44
49
  } while (0)
45
50
 
46
51
  #define RenewArray(Ptr, Size) do { \
47
- (Ptr) = (void*)xrealloc2((char*)(Ptr), (Size), sizeof *(Ptr)); \
52
+ (Ptr) = (void*)xrealloc2((char*)(Ptr), (Size), sizeof *(Ptr)); \
48
53
  } while (0)
49
54
 
50
55
  #define Free(Ptr) do { \
51
- Ptr = NULL; \
56
+ xfree(Ptr); \
57
+ Ptr = NULL; \
52
58
  } while (0)
53
59
 
54
60
  #endif
@@ -66,9 +72,6 @@ void trace(const char *fmt, ...);
66
72
  #define TRACE(Args)
67
73
  #endif
68
74
 
69
- void *safe_malloc(size_t size, const char *file, int line);
70
- void *safe_realloc(void *p, size_t size, const char *file, int line);
71
75
  int high_bit_position(unsigned n);
72
- double rand_double(void);
73
76
 
74
77
  #endif /* UTILITY_H_ */