tg_geometry 0.3.2 → 0.3.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.
@@ -5,7 +5,7 @@
5
5
  #include <string.h>
6
6
  #include <math.h>
7
7
  #include <stdbool.h>
8
- #include "rtree.h"
8
+ #include <stdlib.h>
9
9
 
10
10
  ////////////////////////////////
11
11
 
@@ -16,12 +16,28 @@
16
16
 
17
17
  ////////////////////////////////
18
18
 
19
- // used for splits
20
- #define MINITEMS_PERCENTAGE 10
21
- #define MINITEMS ((MAXITEMS) * (MINITEMS_PERCENTAGE) / 100 + 1)
19
+ #ifdef RTREE_USEPATHHINT
20
+ #define USEPATHHINT
21
+ #endif
22
+
23
+ #ifdef RTREE_MAXITEMS
24
+ #undef MAXITEMS
25
+ #define MAXITEMS RTREE_MAXITEMS
26
+ #endif
22
27
 
23
- #ifndef RTREE_NOPATHHINT
24
- #define USE_PATHHINT
28
+ #ifdef RTREE_DATATYPE
29
+ #undef DATATYPE
30
+ #define DATATYPE RTREE_DATATYPE
31
+ #endif
32
+
33
+ #ifdef RTREE_DIMS
34
+ #undef DIMS
35
+ #define DIMS RTREE_DIMS
36
+ #endif
37
+
38
+ #ifdef RTREE_NUMTYPE
39
+ #undef NUMTYPE
40
+ #define NUMTYPE RTREE_NUMTYPE
25
41
  #endif
26
42
 
27
43
  #ifdef RTREE_MAXITEMS
@@ -31,35 +47,32 @@
31
47
 
32
48
  #ifdef RTREE_NOATOMICS
33
49
  typedef int rc_t;
34
- static int rc_load(rc_t *ptr, bool relaxed) {
35
- (void)relaxed; // nothing to do
36
- return *ptr;
50
+ static void rc_init(rc_t *rc) {
51
+ *rc = 0;
52
+ }
53
+ static void rc_retain(rc_t *rc) {
54
+ (*rc)++;
37
55
  }
38
- static int rc_fetch_sub(rc_t *ptr, int val) {
39
- int rc = *ptr;
40
- *ptr -= val;
41
- return rc;
56
+ static int rc_release(rc_t *rc) {
57
+ return ((*rc)--) == 1;
42
58
  }
43
- static int rc_fetch_add(rc_t *ptr, int val) {
44
- int rc = *ptr;
45
- *ptr += val;
46
- return rc;
59
+ static int rc_shared(rc_t *rc) {
60
+ return (*rc) > 1;
47
61
  }
48
- #else
62
+ #else
49
63
  #include <stdatomic.h>
50
64
  typedef atomic_int rc_t;
51
- static int rc_load(rc_t *ptr, bool relaxed) {
52
- if (relaxed) {
53
- return atomic_load_explicit(ptr, memory_order_relaxed);
54
- } else {
55
- return atomic_load(ptr);
56
- }
65
+ static void rc_init(rc_t *rc) {
66
+ atomic_init(rc, 0);
67
+ }
68
+ static void rc_retain(rc_t *rc) {
69
+ atomic_fetch_add_explicit(rc, 1, __ATOMIC_RELAXED);
57
70
  }
58
- static int rc_fetch_sub(rc_t *ptr, int delta) {
59
- return atomic_fetch_sub(ptr, delta);
71
+ static int rc_release(rc_t *rc) {
72
+ return atomic_fetch_sub_explicit(rc, 1, __ATOMIC_ACQ_REL) == 1;
60
73
  }
61
- static int rc_fetch_add(rc_t *ptr, int delta) {
62
- return atomic_fetch_add(ptr, delta);
74
+ static int rc_shared(rc_t *rc) {
75
+ return atomic_load_explicit(rc, __ATOMIC_ACQUIRE) > 1;
63
76
  }
64
77
  #endif
65
78
 
@@ -93,10 +106,9 @@ struct rtree {
93
106
  struct node *root;
94
107
  size_t count;
95
108
  size_t height;
96
- #ifdef USE_PATHHINT
109
+ #ifdef USEPATHHINT
97
110
  int path_hint[16];
98
111
  #endif
99
- bool relaxed;
100
112
  void *(*malloc)(size_t);
101
113
  void (*free)(void *);
102
114
  void *udata;
@@ -116,7 +128,6 @@ static bool feq(NUMTYPE a, NUMTYPE b) {
116
128
  return !(a < b || a > b);
117
129
  }
118
130
 
119
-
120
131
  void rtree_set_udata(struct rtree *tr, void *udata) {
121
132
  tr->udata = udata;
122
133
  }
@@ -124,8 +135,10 @@ void rtree_set_udata(struct rtree *tr, void *udata) {
124
135
  static struct node *node_new(struct rtree *tr, enum kind kind) {
125
136
  struct node *node = (struct node *)tr->malloc(sizeof(struct node));
126
137
  if (!node) return NULL;
127
- memset(node, 0, sizeof(struct node));
138
+ rc_init(&node->rc);
139
+ rc_retain(&node->rc);
128
140
  node->kind = kind;
141
+ node->count = 0;
129
142
  return node;
130
143
  }
131
144
 
@@ -133,17 +146,18 @@ static struct node *node_copy(struct rtree *tr, struct node *node) {
133
146
  struct node *node2 = (struct node *)tr->malloc(sizeof(struct node));
134
147
  if (!node2) return NULL;
135
148
  memcpy(node2, node, sizeof(struct node));
136
- node2->rc = 0;
149
+ rc_init(&node2->rc);
150
+ rc_retain(&node2->rc);
137
151
  if (node2->kind == BRANCH) {
138
152
  for (int i = 0; i < node2->count; i++) {
139
- rc_fetch_add(&node2->nodes[i]->rc, 1);
153
+ rc_retain(&node2->nodes[i]->rc);
140
154
  }
141
155
  } else {
142
156
  if (tr->item_clone) {
143
157
  int n = 0;
144
158
  bool oom = false;
145
159
  for (int i = 0; i < node2->count; i++) {
146
- if (!tr->item_clone(node->datas[i].data,
160
+ if (!tr->item_clone(node->datas[i].data,
147
161
  (DATATYPE*)&node2->datas[i].data, tr->udata))
148
162
  {
149
163
  oom = true;
@@ -166,7 +180,9 @@ static struct node *node_copy(struct rtree *tr, struct node *node) {
166
180
  }
167
181
 
168
182
  static void node_free(struct rtree *tr, struct node *node) {
169
- if (rc_fetch_sub(&node->rc, 1) > 0) return;
183
+ if (!rc_release(&node->rc)) {
184
+ return;
185
+ }
170
186
  if (node->kind == BRANCH) {
171
187
  for (int i = 0; i < node->count; i++) {
172
188
  node_free(tr, node->nodes[i]);
@@ -182,7 +198,7 @@ static void node_free(struct rtree *tr, struct node *node) {
182
198
  }
183
199
 
184
200
  #define cow_node_or(rnode, code) { \
185
- if (rc_load(&(rnode)->rc, tr->relaxed) > 0) { \
201
+ if (rc_shared(&(rnode)->rc)) { \
186
202
  struct node *node2 = node_copy(tr, (rnode)); \
187
203
  if (!node2) { code; } \
188
204
  node_free(tr, rnode); \
@@ -206,12 +222,12 @@ static NUMTYPE rect_area(const struct rect *rect) {
206
222
  }
207
223
 
208
224
  // return the area of two rects expanded
209
- static NUMTYPE rect_unioned_area(const struct rect *rect,
225
+ static NUMTYPE rect_unioned_area(const struct rect *rect,
210
226
  const struct rect *other)
211
227
  {
212
228
  NUMTYPE result = 1;
213
229
  for (int i = 0; i < DIMS; i++) {
214
- result *= (max0(rect->max[i], other->max[i]) -
230
+ result *= (max0(rect->max[i], other->max[i]) -
215
231
  min0(rect->min[i], other->min[i]));
216
232
  }
217
233
  return result;
@@ -237,7 +253,7 @@ static bool rect_intersects(const struct rect *rect, const struct rect *other) {
237
253
 
238
254
  static bool rect_onedge(const struct rect *rect, const struct rect *other) {
239
255
  for (int i = 0; i < DIMS; i++) {
240
- if (feq(rect->min[i], other->min[i]) ||
256
+ if (feq(rect->min[i], other->min[i]) ||
241
257
  feq(rect->max[i], other->max[i]))
242
258
  {
243
259
  return true;
@@ -248,7 +264,7 @@ static bool rect_onedge(const struct rect *rect, const struct rect *other) {
248
264
 
249
265
  static bool rect_equals(const struct rect *rect, const struct rect *other) {
250
266
  for (int i = 0; i < DIMS; i++) {
251
- if (!feq(rect->min[i], other->min[i]) ||
267
+ if (!feq(rect->min[i], other->min[i]) ||
252
268
  !feq(rect->max[i], other->max[i]))
253
269
  {
254
270
  return false;
@@ -281,54 +297,7 @@ static int rect_largest_axis(const struct rect *rect) {
281
297
  return axis;
282
298
  }
283
299
 
284
- // swap two rectangles
285
- static void node_swap(struct node *node, int i, int j) {
286
- struct rect tmp = node->rects[i];
287
- node->rects[i] = node->rects[j];
288
- node->rects[j] = tmp;
289
- if (node->kind == LEAF) {
290
- struct item tmp = node->datas[i];
291
- node->datas[i] = node->datas[j];
292
- node->datas[j] = tmp;
293
- } else {
294
- struct node *tmp = node->nodes[i];
295
- node->nodes[i] = node->nodes[j];
296
- node->nodes[j] = tmp;
297
- }
298
- }
299
-
300
- struct rect4 {
301
- NUMTYPE all[DIMS*2];
302
- };
303
-
304
- static void node_qsort(struct node *node, int s, int e, int index) {
305
- int nrects = e - s;
306
- if (nrects < 2) {
307
- return;
308
- }
309
- int left = 0;
310
- int right = nrects-1;
311
- int pivot = nrects / 2;
312
- node_swap(node, s+pivot, s+right);
313
- struct rect4 *rects = (struct rect4 *)&node->rects[s];
314
- for (int i = 0; i < nrects; i++) {
315
- if (rects[right].all[index] < rects[i].all[index]) {
316
- node_swap(node, s+i, s+left);
317
- left++;
318
- }
319
- }
320
- node_swap(node, s+left, s+right);
321
- node_qsort(node, s, s+left, index);
322
- node_qsort(node, s+left+1, e, index);
323
- }
324
-
325
- // sort the node rectangles by the axis. used during splits
326
- static void node_sort_by_axis(struct node *node, int axis, bool max) {
327
- int by_index = max ? DIMS+axis : axis;
328
- node_qsort(node, 0, node->count, by_index);
329
- }
330
-
331
- static void node_move_rect_at_index_into(struct node *from, int index,
300
+ static void node_move_rect_at_index_into(struct node *from, int index,
332
301
  struct node *into)
333
302
  {
334
303
  into->rects[into->count] = from->rects[index];
@@ -344,8 +313,8 @@ static void node_move_rect_at_index_into(struct node *from, int index,
344
313
  into->count++;
345
314
  }
346
315
 
347
- static bool node_split_largest_axis_edge_snap(struct rtree *tr,
348
- struct rect *rect, struct node *node, struct node **right_out)
316
+ static bool node_split_largest_axis_edge_snap(struct rtree *tr,
317
+ struct rect *rect, struct node *node, struct node **right_out)
349
318
  {
350
319
  int axis = rect_largest_axis(rect);
351
320
  struct node *right = node_new(tr, node->kind);
@@ -361,36 +330,31 @@ static bool node_split_largest_axis_edge_snap(struct rtree *tr,
361
330
  i--;
362
331
  }
363
332
  }
364
- // Make sure that both left and right nodes have at least
365
- // MINITEMS by moving datas into underflowed nodes.
366
- if (node->count < MINITEMS) {
367
- // reverse sort by min axis
368
- node_sort_by_axis(right, axis, false);
369
- do {
370
- node_move_rect_at_index_into(right, right->count-1, node);
371
- } while (node->count < MINITEMS);
372
- } else if (right->count < MINITEMS) {
373
- // reverse sort by max axis
374
- node_sort_by_axis(node, axis, true);
375
- do {
376
- node_move_rect_at_index_into(node, node->count-1, right);
377
- } while (right->count < MINITEMS);
378
- }
379
- if (node->kind == BRANCH) {
380
- node_sort_by_axis(node, 0, false);
381
- node_sort_by_axis(right, 0, false);
333
+ if (right->count == 0) {
334
+ // There must be at least one item in a node.
335
+ // Choose the one closest to the right (max) edge
336
+ int j = 0;
337
+ double jdist = INFINITY;
338
+ for (int i = 0; i < node->count; i++) {
339
+ NUMTYPE max_dist = rect->max[axis] - node->rects[i].max[axis];
340
+ if (max_dist < jdist) {
341
+ j = i;
342
+ jdist = max_dist;
343
+ }
344
+ }
345
+ node_move_rect_at_index_into(node, j, right);
382
346
  }
383
347
  *right_out = right;
384
348
  return true;
385
349
  }
386
350
 
387
351
  static bool node_split(struct rtree *tr, struct rect *rect, struct node *node,
388
- struct node **right)
352
+ struct node **right)
389
353
  {
390
354
  return node_split_largest_axis_edge_snap(tr, rect, node, right);
391
355
  }
392
356
 
393
- static int node_choose_least_enlargement(const struct node *node,
357
+ static int node_choose_least_enlargement(const struct node *node,
394
358
  const struct rect *ir)
395
359
  {
396
360
  int j = 0;
@@ -408,10 +372,11 @@ static int node_choose_least_enlargement(const struct node *node,
408
372
  return j;
409
373
  }
410
374
 
411
- static int node_choose(struct rtree *tr, const struct node *node,
375
+ static int node_choose(struct rtree *tr, const struct node *node,
412
376
  const struct rect *rect, int depth)
413
377
  {
414
- #ifdef USE_PATHHINT
378
+ (void)tr, (void)depth;
379
+ #ifdef USEPATHHINT
415
380
  int h = tr->path_hint[depth];
416
381
  if (h < node->count) {
417
382
  if (rect_contains(&node->rects[h], rect)) {
@@ -422,7 +387,7 @@ static int node_choose(struct rtree *tr, const struct node *node,
422
387
  // Take a quick look for the first node that contain the rect.
423
388
  for (int i = 0; i < node->count; i++) {
424
389
  if (rect_contains(&node->rects[i], rect)) {
425
- #ifdef USE_PATHHINT
390
+ #ifdef USEPATHHINT
426
391
  tr->path_hint[depth] = i;
427
392
  #endif
428
393
  return i;
@@ -430,7 +395,7 @@ static int node_choose(struct rtree *tr, const struct node *node,
430
395
  }
431
396
  // Fallback to using che "choose least enlargment" algorithm.
432
397
  int i = node_choose_least_enlargement(node, rect);
433
- #ifdef USE_PATHHINT
398
+ #ifdef USEPATHHINT
434
399
  tr->path_hint[depth] = i;
435
400
  #endif
436
401
  return i;
@@ -445,7 +410,7 @@ static struct rect node_rect_calc(const struct node *node) {
445
410
  }
446
411
 
447
412
  // node_insert returns false if out of memory
448
- static bool node_insert(struct rtree *tr, struct rect *nr, struct node *node,
413
+ static bool node_insert(struct rtree *tr, struct rect *nr, struct node *node,
449
414
  struct rect *ir, struct item item, int depth, bool *split)
450
415
  {
451
416
  if (node->kind == LEAF) {
@@ -463,7 +428,7 @@ static bool node_insert(struct rtree *tr, struct rect *nr, struct node *node,
463
428
  // Choose a subtree for inserting the rectangle.
464
429
  int i = node_choose(tr, node, ir, depth);
465
430
  cow_node_or(node->nodes[i], return false);
466
- if (!node_insert(tr, &node->rects[i], node->nodes[i], ir, item, depth+1,
431
+ if (!node_insert(tr, &node->rects[i], node->nodes[i], ir, item, depth+1,
467
432
  split))
468
433
  {
469
434
  return false;
@@ -489,7 +454,7 @@ static bool node_insert(struct rtree *tr, struct rect *nr, struct node *node,
489
454
  return node_insert(tr, nr, node, ir, item, depth, split);
490
455
  }
491
456
 
492
- struct rtree *rtree_new_with_allocator(void *(*_malloc)(size_t),
457
+ struct rtree *rtree_new_with_allocator(void *(*_malloc)(size_t),
493
458
  void (*_free)(void*)
494
459
  ) {
495
460
  _malloc = _malloc ? _malloc : malloc;
@@ -514,14 +479,14 @@ void rtree_set_item_callbacks(struct rtree *tr,
514
479
  tr->item_free = free;
515
480
  }
516
481
 
517
- bool rtree_insert(struct rtree *tr, const NUMTYPE *min,
518
- const NUMTYPE *max, const DATATYPE data)
482
+ bool rtree_insert(struct rtree *tr, const NUMTYPE *min,
483
+ const NUMTYPE *max, const DATATYPE data)
519
484
  {
520
485
  // copy input rect
521
486
  struct rect rect;
522
487
  memcpy(&rect.min[0], min, sizeof(NUMTYPE)*DIMS);
523
488
  memcpy(&rect.max[0], max?max:min, sizeof(NUMTYPE)*DIMS);
524
-
489
+
525
490
  // copy input data
526
491
  struct item item;
527
492
  if (tr->item_clone) {
@@ -584,14 +549,14 @@ void rtree_free(struct rtree *tr) {
584
549
  }
585
550
 
586
551
  static bool node_search(struct node *node, struct rect *rect,
587
- bool (*iter)(const NUMTYPE *min, const NUMTYPE *max, const DATATYPE data,
588
- void *udata),
589
- void *udata)
552
+ bool (*iter)(const NUMTYPE *min, const NUMTYPE *max, const DATATYPE data,
553
+ void *udata),
554
+ void *udata)
590
555
  {
591
556
  if (node->kind == LEAF) {
592
557
  for (int i = 0; i < node->count; i++) {
593
558
  if (rect_intersects(&node->rects[i], rect)) {
594
- if (!iter(node->rects[i].min, node->rects[i].max,
559
+ if (!iter(node->rects[i].min, node->rects[i].max,
595
560
  node->datas[i].data, udata))
596
561
  {
597
562
  return false;
@@ -610,10 +575,10 @@ static bool node_search(struct node *node, struct rect *rect,
610
575
  return true;
611
576
  }
612
577
 
613
- void rtree_search(const struct rtree *tr, const NUMTYPE min[],
578
+ void rtree_search(const struct rtree *tr, const NUMTYPE min[],
614
579
  const NUMTYPE max[],
615
- bool (*iter)(const NUMTYPE min[], const NUMTYPE max[], const DATATYPE data,
616
- void *udata),
580
+ bool (*iter)(const NUMTYPE min[], const NUMTYPE max[], const DATATYPE data,
581
+ void *udata),
617
582
  void *udata)
618
583
  {
619
584
  // copy input rect
@@ -627,13 +592,13 @@ void rtree_search(const struct rtree *tr, const NUMTYPE min[],
627
592
  }
628
593
 
629
594
  static bool node_scan(struct node *node,
630
- bool (*iter)(const NUMTYPE *min, const NUMTYPE *max, const DATATYPE data,
631
- void *udata),
632
- void *udata)
595
+ bool (*iter)(const NUMTYPE *min, const NUMTYPE *max, const DATATYPE data,
596
+ void *udata),
597
+ void *udata)
633
598
  {
634
599
  if (node->kind == LEAF) {
635
600
  for (int i = 0; i < node->count; i++) {
636
- if (!iter(node->rects[i].min, node->rects[i].max,
601
+ if (!iter(node->rects[i].min, node->rects[i].max,
637
602
  node->datas[i].data, udata))
638
603
  {
639
604
  return false;
@@ -649,9 +614,9 @@ static bool node_scan(struct node *node,
649
614
  return true;
650
615
  }
651
616
 
652
- void rtree_scan(const struct rtree *tr,
653
- bool (*iter)(const NUMTYPE *min, const NUMTYPE *max, const DATATYPE data,
654
- void *udata),
617
+ void rtree_scan(const struct rtree *tr,
618
+ bool (*iter)(const NUMTYPE *min, const NUMTYPE *max, const DATATYPE data,
619
+ void *udata),
655
620
  void *udata)
656
621
  {
657
622
  if (tr->root) {
@@ -663,7 +628,7 @@ size_t rtree_count(const struct rtree *tr) {
663
628
  return tr->count;
664
629
  }
665
630
 
666
- static bool node_delete(struct rtree *tr, struct rect *nr, struct node *node,
631
+ static bool node_delete(struct rtree *tr, struct rect *nr, struct node *node,
667
632
  struct rect *ir, struct item item, int depth, bool *removed, bool *shrunk,
668
633
  int (*compare)(const DATATYPE a, const DATATYPE b, void *udata),
669
634
  void *udata)
@@ -694,7 +659,7 @@ static bool node_delete(struct rtree *tr, struct rect *nr, struct node *node,
694
659
  // We need to recalculate the node rect.
695
660
  *nr = node_rect_calc(node);
696
661
  // Notify the caller that we shrunk the rect.
697
- *shrunk = true;
662
+ *shrunk = true;
698
663
  }
699
664
  *removed = true;
700
665
  return true;
@@ -702,12 +667,12 @@ static bool node_delete(struct rtree *tr, struct rect *nr, struct node *node,
702
667
  return true;
703
668
  }
704
669
  int h = 0;
705
- #ifdef USE_PATHHINT
670
+ #ifdef USEPATHHINT
706
671
  h = tr->path_hint[depth];
707
672
  if (h < node->count) {
708
673
  if (rect_contains(&node->rects[h], ir)) {
709
674
  cow_node_or(node->nodes[h], return false);
710
- if (!node_delete(tr, &node->rects[h], node->nodes[h], ir, item,
675
+ if (!node_delete(tr, &node->rects[h], node->nodes[h], ir, item,
711
676
  depth+1,removed, shrunk, compare, udata))
712
677
  {
713
678
  return false;
@@ -733,7 +698,9 @@ static bool node_delete(struct rtree *tr, struct rect *nr, struct node *node,
733
698
  if (!*removed) {
734
699
  continue;
735
700
  }
701
+ #ifdef USEPATHHINT
736
702
  removed:
703
+ #endif
737
704
  if (node->nodes[h]->count == 0) {
738
705
  // underflow
739
706
  node_free(tr, node->nodes[h]);
@@ -744,7 +711,7 @@ static bool node_delete(struct rtree *tr, struct rect *nr, struct node *node,
744
711
  *shrunk = true;
745
712
  return true;
746
713
  }
747
- #ifdef USE_PATHHINT
714
+ #ifdef USEPATHHINT
748
715
  tr->path_hint[depth] = h;
749
716
  #endif
750
717
  if (*shrunk) {
@@ -759,7 +726,7 @@ static bool node_delete(struct rtree *tr, struct rect *nr, struct node *node,
759
726
  }
760
727
 
761
728
  // returns false if out of memory
762
- static bool rtree_delete0(struct rtree *tr, const NUMTYPE *min,
729
+ static bool rtree_delete0(struct rtree *tr, const NUMTYPE *min,
763
730
  const NUMTYPE *max, const DATATYPE data,
764
731
  int (*compare)(const DATATYPE a, const DATATYPE b, void *udata),
765
732
  void *udata)
@@ -779,7 +746,7 @@ static bool rtree_delete0(struct rtree *tr, const NUMTYPE *min,
779
746
  bool removed = false;
780
747
  bool shrunk = false;
781
748
  cow_node_or(tr->root, return false);
782
- if (!node_delete(tr, &tr->rect, tr->root, &rect, item, 0, &removed, &shrunk,
749
+ if (!node_delete(tr, &tr->rect, tr->root, &rect, item, 0, &removed, &shrunk,
783
750
  compare, udata))
784
751
  {
785
752
  return false;
@@ -808,13 +775,13 @@ static bool rtree_delete0(struct rtree *tr, const NUMTYPE *min,
808
775
  return true;
809
776
  }
810
777
 
811
- bool rtree_delete(struct rtree *tr, const NUMTYPE *min, const NUMTYPE *max,
778
+ bool rtree_delete(struct rtree *tr, const NUMTYPE *min, const NUMTYPE *max,
812
779
  const DATATYPE data)
813
780
  {
814
781
  return rtree_delete0(tr, min, max, data, NULL, NULL);
815
782
  }
816
783
 
817
- bool rtree_delete_with_comparator(struct rtree *tr, const NUMTYPE *min,
784
+ bool rtree_delete_with_comparator(struct rtree *tr, const NUMTYPE *min,
818
785
  const NUMTYPE *max, const DATATYPE data,
819
786
  int (*compare)(const DATATYPE a, const DATATYPE b, void *udata),
820
787
  void *udata)
@@ -827,14 +794,20 @@ struct rtree *rtree_clone(struct rtree *tr) {
827
794
  struct rtree *tr2 = tr->malloc(sizeof(struct rtree));
828
795
  if (!tr2) return NULL;
829
796
  memcpy(tr2, tr, sizeof(struct rtree));
830
- if (tr2->root) rc_fetch_add(&tr2->root->rc, 1);
797
+ if (tr2->root) rc_retain(&tr2->root->rc);
831
798
  return tr2;
832
- }
799
+ }
833
800
 
834
- void rtree_opt_relaxed_atomics(struct rtree *tr) {
835
- tr->relaxed = true;
801
+ void rtree_rect(struct rtree *tr, NUMTYPE *min, NUMTYPE *max) {
802
+ for (int i = 0; i < DIMS; i++) {
803
+ min[i] = tr->rect.min[i];
804
+ max[i] = tr->rect.max[i];
805
+ }
836
806
  }
837
807
 
808
+ // deprecated
809
+ void rtree_opt_relaxed_atomics(struct rtree *tr) { (void)tr; }
810
+
838
811
  #ifdef TEST_PRIVATE_FUNCTIONS
839
812
  #include "tests/priv_funcs.h"
840
813
  #endif
@@ -36,16 +36,16 @@ struct rtree *rtree_clone(struct rtree *tr);
36
36
  // The clone function should return true if the clone succeeded or false if the
37
37
  // system is out of memory.
38
38
  void rtree_set_item_callbacks(struct rtree *tr,
39
- bool (*clone)(const void *item, void **into, void *udata),
39
+ bool (*clone)(const void *item, void **into, void *udata),
40
40
  void (*free)(const void *item, void *udata));
41
41
 
42
- // rtree_set_udata sets the user-defined data.
42
+ // rtree_set_udata sets the user-defined data.
43
43
  //
44
- // This should be called once after rtree_new() and is only used for
44
+ // This should be called once after rtree_new() and is only used for
45
45
  // the item callbacks as defined in rtree_set_item_callbacks().
46
46
  void rtree_set_udata(struct rtree *tr, void *udata);
47
47
 
48
- // rtree_insert inserts an item into the rtree.
48
+ // rtree_insert inserts an item into the rtree.
49
49
  //
50
50
  // This operation performs a copy of the data that is pointed to in the second
51
51
  // and third arguments. The R-tree expects a rectangle, which is two arrays of
@@ -64,20 +64,20 @@ bool rtree_insert(struct rtree *tr, const double *min, const double *max, const
64
64
  //
65
65
  // Returning false from the iter will stop the search.
66
66
  void rtree_search(const struct rtree *tr, const double *min, const double *max,
67
- bool (*iter)(const double *min, const double *max, const void *data, void *udata),
67
+ bool (*iter)(const double *min, const double *max, const void *data, void *udata),
68
68
  void *udata);
69
69
 
70
70
  // rtree_scan iterates over every item in the rtree.
71
71
  //
72
72
  // Returning false from the iter will stop the scan.
73
73
  void rtree_scan(const struct rtree *tr,
74
- bool (*iter)(const double *min, const double *max, const void *data, void *udata),
74
+ bool (*iter)(const double *min, const double *max, const void *data, void *udata),
75
75
  void *udata);
76
76
 
77
77
  // rtree_count returns the number of items in the rtree.
78
78
  size_t rtree_count(const struct rtree *tr);
79
79
 
80
- // rtree_delete deletes an item from the rtree.
80
+ // rtree_delete deletes an item from the rtree.
81
81
  //
82
82
  // This searches the tree for an item that is contained within the provided
83
83
  // rectangle, and perform a binary comparison of its data to the provided
@@ -92,14 +92,17 @@ bool rtree_delete(struct rtree *tr, const double *min, const double *max, const
92
92
  // a compare function. The first item that is found is deleted.
93
93
  //
94
94
  // Returns false if the system is out of memory.
95
- bool rtree_delete_with_comparator(struct rtree *tr, const double *min,
95
+ bool rtree_delete_with_comparator(struct rtree *tr, const double *min,
96
96
  const double *max, const void *data,
97
97
  int (*compare)(const void *a, const void *b, void *udata),
98
98
  void *udata);
99
99
 
100
- // rtree_opt_relaxed_atomics activates memory_order_relaxed for all atomic
101
- // loads. This may increase performance for single-threaded programs.
102
- // Optionally, define RTREE_NOATOMICS to disbale all atomics.
100
+
101
+ // rtree_rect returns the MBR.
102
+ void rtree_rect(struct rtree *tr, double *min, double *max);
103
+
104
+
105
+ // deprecated
103
106
  void rtree_opt_relaxed_atomics(struct rtree *tr);
104
107
 
105
108
  #endif // RTREE_H
@@ -1,3 +1,3 @@
1
1
  repo=https://github.com/tidwall/tg.git
2
2
  ref=main
3
- commit=caf840504eaab4563280cf4ab16d618f69a23720
3
+ commit=532fc38e1a7bd440339cf83259a9d7983f04ad69