lulu 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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_ */