bad char
[vg.git] / src / vg / vg_store.h
1 #ifndef VG_STORE_H
2 #define VG_STORE_H
3
4 typedef struct aatree aatree;
5 typedef struct aatree_node aatree_node;
6
7 typedef u32 aatree_ptr;
8 #define AATREE_PTR_NIL 0xffffffff
9
10 struct aatree
11 {
12 u32 offset, stride; /* distance between elements */
13 void *base;
14
15 int (*p_cmp)( void *a, void *b );
16 int (*p_cmpv)( void *a, void *v );
17 };
18
19 struct aatree_node
20 {
21 aatree_ptr left, right, parent;
22 u32 level, count;
23 };
24
25 static void *aatree_get_data( aatree *tree, aatree_ptr t )
26 {
27 return tree->base + tree->stride*t;
28 }
29
30 static aatree_node *aatree_get_node( aatree *tree, aatree_ptr t )
31 {
32 return tree->base + tree->stride*t + tree->offset;
33 }
34
35 static void aatree_recount( aatree *tree, aatree_ptr n )
36 {
37 aatree_node *pnode = aatree_get_node( tree, n );
38 pnode->count = 1;
39
40 if( pnode->left != AATREE_PTR_NIL )
41 pnode->count += aatree_get_node( tree, pnode->left )->count;
42
43 if( pnode->right != AATREE_PTR_NIL )
44 pnode->count += aatree_get_node( tree, pnode->right )->count;
45 }
46
47 /* . .
48 * | |
49 * L <- T L -> T
50 * / \ \ -> / / \
51 * A B R A B R
52 */
53 static aatree_ptr aatree_skew( aatree *tree, u32 t )
54 {
55 if( t == AATREE_PTR_NIL ) return t;
56
57 aatree_node *ptnode = aatree_get_node( tree, t );
58 if( ptnode->left == AATREE_PTR_NIL ) return t;
59
60 aatree_node *plnode = aatree_get_node( tree, ptnode->left );
61 if( plnode->level == ptnode->level )
62 {
63 aatree_ptr l = ptnode->left;
64 ptnode->left = plnode->right;
65 plnode->right = t;
66
67 aatree_recount( tree, t );
68 aatree_recount( tree, l );
69
70 /* B's parent is now T,
71 * T's parent is now L,
72 * L's parent is now T's old parent */
73 plnode->parent = ptnode->parent;
74 ptnode->parent = l;
75 if( ptnode->left != AATREE_PTR_NIL )
76 aatree_get_node( tree, ptnode->left )->parent = t;
77
78 return l;
79 }
80
81 return t;
82 }
83
84 /* . .
85 * | |
86 * T -> R -> X -> R
87 * / / / \
88 * A B T X
89 * / \
90 * A B
91 */
92 static aatree_ptr aatree_split( aatree *tree, aatree_ptr t )
93 {
94 if( t == AATREE_PTR_NIL ) return t;
95
96 aatree_node *ptnode = aatree_get_node( tree, t );
97 if( ptnode->right == AATREE_PTR_NIL ) return t;
98
99 aatree_node *prnode = aatree_get_node( tree, ptnode->right );
100 if( prnode->right == AATREE_PTR_NIL ) return t;
101
102 aatree_node *prrnode = aatree_get_node( tree, prnode->right );
103 if( ptnode->level == prrnode->level )
104 {
105 aatree_ptr r = ptnode->right;
106 ptnode->right = prnode->left;
107 prnode->left = t;
108 prnode->level ++;
109
110 aatree_recount( tree, t );
111 aatree_recount( tree, r );
112
113 /* B's parent is now T,
114 * T's parent is now R,
115 * R's parent is now T's old parent */
116 prnode->parent = ptnode->parent;
117 ptnode->parent = r;
118 if( ptnode->right != AATREE_PTR_NIL )
119 aatree_get_node( tree, ptnode->right )->parent = t;
120
121 return r;
122 }
123
124 return t;
125 }
126
127 static int aatree_verify( aatree *tree, aatree_ptr t );
128
129 static aatree_ptr aatree_insert( aatree *tree, aatree_ptr t, aatree_ptr x )
130 {
131 aatree_node *pxnode = aatree_get_node( tree, x );
132
133 if( t == AATREE_PTR_NIL )
134 {
135 pxnode->left = AATREE_PTR_NIL;
136 pxnode->right = AATREE_PTR_NIL;
137 pxnode->parent = AATREE_PTR_NIL;
138 pxnode->level = 0;
139 pxnode->count = 1;
140 return x;
141 }
142
143 aatree_node *ptnode = aatree_get_node( tree, t );
144 int cmp_result = tree->p_cmp( aatree_get_data( tree, t ),
145 aatree_get_data( tree, x ) );
146
147 ptnode->count ++;
148
149 if( cmp_result <= 0 )
150 {
151 ptnode->left = aatree_insert( tree, ptnode->left, x );
152 aatree_node *plnode = aatree_get_node( tree, ptnode->left );
153 plnode->parent = t;
154 }
155 else
156 {
157 ptnode->right = aatree_insert( tree, ptnode->right, x );
158 aatree_node *prnode = aatree_get_node( tree, ptnode->right );
159 prnode->parent = t;
160 }
161
162 t = aatree_skew( tree, t );
163 t = aatree_split( tree, t );
164 return t;
165 }
166
167 static void aatree_link_down( aatree *tree, aatree_ptr p, aatree_ptr *pl,
168 aatree_ptr l )
169 {
170 *pl = l;
171
172 if( *pl != AATREE_PTR_NIL )
173 aatree_get_node( tree, *pl )->parent = p;
174 }
175
176 static aatree_ptr aatree_del( aatree *tree, aatree_ptr x )
177 {
178 /* Simulate what we would have created on the tail,
179 * we work along the tail in order, doing the same as the regular
180 * implementation. This only works because we have parent pointers. */
181
182 aatree_ptr it = x,
183 up[32];
184
185 int count = 1, dir = 0;
186
187 aatree_node *search = aatree_get_node( tree, x );
188 while(1)
189 if( search->parent == AATREE_PTR_NIL ) break;
190 else
191 {
192 search = aatree_get_node( tree, search->parent );
193 count ++;
194 }
195
196 int top=0;
197 while(1)
198 {
199 int index = count - (++top);
200
201 up[ index ] = it;
202 aatree_node *itnode = aatree_get_node( tree, it );
203 if( itnode->parent == AATREE_PTR_NIL )
204 break;
205 else
206 it = itnode->parent;
207 }
208
209 aatree_ptr _ptrswap_src = AATREE_PTR_NIL,
210 _ptrswap_dst = AATREE_PTR_NIL;
211
212 aatree_node *pxnode = aatree_get_node( tree, x );
213 aatree_ptr root = up[ count-1 ];
214 if( pxnode->left == AATREE_PTR_NIL || pxnode->right == AATREE_PTR_NIL )
215 {
216 if( --top != 0 )
217 {
218 aatree_node *pnode = aatree_get_node( tree, up[top-1] ),
219 *parent = aatree_get_node( tree, pxnode->parent );
220
221 aatree_ptr next = pxnode->left == AATREE_PTR_NIL?
222 pxnode->right:
223 pxnode->left;
224
225 if( parent->left == x ) pnode->left = next;
226 else pnode->right = next;
227
228 if( next != AATREE_PTR_NIL )
229 {
230 aatree_node *pnext = aatree_get_node( tree, next );
231 pnext->parent = up[top-1];
232 }
233 }
234 else
235 {
236 if( pxnode->right != AATREE_PTR_NIL ) root = pxnode->right;
237 else if( pxnode->left != AATREE_PTR_NIL ) root = pxnode->left;
238 else return AATREE_PTR_NIL;
239
240 aatree_node *newroot = aatree_get_node( tree, root );
241 newroot->parent = AATREE_PTR_NIL;
242 }
243 }
244 else
245 {
246 aatree_ptr heir = pxnode->right,
247 prev = x;
248
249 aatree_node *pheir = aatree_get_node( tree, heir );
250
251 while( pheir->left != AATREE_PTR_NIL )
252 {
253 up[top++] = prev = heir;
254 heir = pheir->left;
255 pheir = aatree_get_node( tree, heir );
256 }
257
258 _ptrswap_dst = heir;
259 _ptrswap_src = x;
260
261 aatree_node *pprev = aatree_get_node( tree, prev );
262
263 if( prev == x )
264 aatree_link_down( tree, prev, &pprev->right, pheir->right );
265 else
266 aatree_link_down( tree, prev, &pprev->left, pheir->right );
267 }
268
269 while( --top >= 0 )
270 {
271 if( top != 0 )
272 {
273 aatree_node *above = aatree_get_node( tree, up[top-1] );
274 dir = above->right == up[top];
275 }
276
277 aatree_recount( tree, up[top] );
278 aatree_node *pntop = aatree_get_node( tree, up[top] );
279 if( pntop->left == AATREE_PTR_NIL || pntop->right == AATREE_PTR_NIL ){}
280 else
281 {
282 aatree_node
283 *pnl = aatree_get_node( tree, pntop->left ),
284 *pnr = aatree_get_node( tree, pntop->right );
285
286 if( pnl->level < pntop->level-1 || pnr->level < pntop->level-1 )
287 {
288 if( pnr->level > --pntop->level )
289 pnr->level = pntop->level;
290
291 up[top] = aatree_skew( tree, up[top] );
292
293 aatree_node *ut = aatree_get_node( tree, up[top] );
294 ut->right = aatree_skew( tree, ut->right );
295
296 aatree_node *utr = aatree_get_node( tree, ut->right );
297 utr->right = aatree_skew( tree, utr->right );
298
299 up[top] = aatree_split( tree, up[top] );
300 ut = aatree_get_node( tree, up[top] );
301
302 ut->right = aatree_split( tree, ut->right );
303 }
304 }
305
306 if( top != 0 )
307 {
308 aatree_node *ut1 = aatree_get_node( tree, up[top-1] );
309
310 if( dir == 1 )
311 aatree_link_down( tree, up[top-1], &ut1->right, up[top] );
312 else
313 aatree_link_down( tree, up[top-1], &ut1->left, up[top] );
314 }
315 else
316 {
317 root = up[top];
318 aatree_get_node( tree, root )->parent = AATREE_PTR_NIL;
319 }
320 }
321
322 if( _ptrswap_dst != AATREE_PTR_NIL )
323 {
324 /* Copy everything except data from _src to _dst, relink.
325 * This is a bit of a messy addon, since the algorithm is originally
326 * based around moving the actual data(key) around, but we have the
327 * requirement that data can't move, so everything is done normally but
328 * the pointers are just swapped afterwards.
329 */
330
331 aatree_node *pdst = aatree_get_node( tree, _ptrswap_dst ),
332 *psrc = aatree_get_node( tree, _ptrswap_src );
333
334 pdst->count = psrc->count;
335 pdst->level = psrc->level;
336 pdst->left = psrc->left;
337 pdst->right = psrc->right;
338 pdst->parent = psrc->parent;
339
340 if( pdst->parent != AATREE_PTR_NIL )
341 {
342 aatree_node *parent = aatree_get_node( tree, pdst->parent );
343
344 if( parent->left == _ptrswap_src )
345 parent->left = _ptrswap_dst;
346 else if( parent->right == _ptrswap_src )
347 parent->right = _ptrswap_dst;
348 }
349 else
350 {
351 root = _ptrswap_dst;
352 }
353
354 if( pdst->left != AATREE_PTR_NIL )
355 aatree_get_node( tree, pdst->left )->parent = _ptrswap_dst;
356 if( pdst->right != AATREE_PTR_NIL )
357 aatree_get_node( tree, pdst->right )->parent = _ptrswap_dst;
358 }
359
360 return root;
361 }
362
363 /*
364 * Accessors
365 */
366
367 static aatree_ptr aatree_kth( aatree *tree, aatree_ptr t, u32 k )
368 {
369 u32 i = 0;
370
371 while( t != AATREE_PTR_NIL )
372 {
373 aatree_node *ptnode = aatree_get_node( tree, t );
374
375 u32 j = i;
376 if( ptnode->left != AATREE_PTR_NIL )
377 j += aatree_get_node( tree, ptnode->left )->count;
378
379 if( j < k )
380 {
381 i = j+1;
382 t = ptnode->right;
383 }
384 else
385 {
386 if( j > k )
387 {
388 t = ptnode->left;
389 }
390 else
391 {
392 return t;
393 }
394 }
395 }
396
397 return AATREE_PTR_NIL;
398 }
399
400 static aatree_ptr aatree_ptrof( aatree *tree, aatree_ptr t, void *value )
401 {
402 while( t != AATREE_PTR_NIL )
403 {
404 int cmp_result = tree->p_cmpv( aatree_get_data( tree, t ), value );
405
406 if( cmp_result == 0 )
407 return t;
408 else
409 {
410 aatree_node *ptnode = aatree_get_node( tree, t );
411
412 if( cmp_result < 0 )
413 t = ptnode->left;
414 else
415 t = ptnode->right;
416 }
417 }
418 return t;
419 }
420
421
422 /*
423 * Debugging stuff, everything below is scaffholding and will be removed
424 * =============================================================================
425 */
426
427 static int aatree_verify_split( aatree *tree, aatree_ptr t )
428 {
429 if( t == AATREE_PTR_NIL ) return 1;
430
431 aatree_node *ptnode = aatree_get_node( tree, t );
432 if( ptnode->right == AATREE_PTR_NIL ) return 1;
433
434 aatree_node *prnode = aatree_get_node( tree, ptnode->right );
435 if( prnode->right == AATREE_PTR_NIL ) return 1;
436
437 aatree_node *prrnode = aatree_get_node( tree, prnode->right );
438 if( ptnode->level == prrnode->level )
439 return 0;
440
441 return 1;
442 }
443
444 static int aatree_verify_skew( aatree *tree, aatree_ptr t )
445 {
446 if( t == AATREE_PTR_NIL ) return 1;
447
448 aatree_node *ptnode = aatree_get_node( tree, t );
449 if( ptnode->left == AATREE_PTR_NIL ) return 1;
450
451 aatree_node *plnode = aatree_get_node( tree, ptnode->left );
452 if( plnode->level == ptnode->level )
453 return 0;
454
455 return 1;
456 }
457
458 static int aatree_verify( aatree *tree, aatree_ptr t )
459 {
460 aatree_node *ptnode = aatree_get_node( tree, t );
461 if( ptnode->parent != AATREE_PTR_NIL )
462 {
463 aatree_node *parent = aatree_get_node( tree, ptnode->parent );
464 if( !(parent->left == t || parent->right == t) )
465 return 0;
466 }
467
468 if( ptnode->left != AATREE_PTR_NIL )
469 if( aatree_get_node( tree, ptnode->left )->parent != t )
470 return 0;
471 if( ptnode->right != AATREE_PTR_NIL )
472 if( aatree_get_node( tree, ptnode->right )->parent != t )
473 return 0;
474
475 return aatree_verify_skew( tree, t ) &&
476 aatree_verify_split( tree, t );
477 }
478
479
480 static void aatree_show_r( aatree *tree, aatree_ptr t, int lvl,
481 void(*p_show)(void *data) )
482 {
483 if( t != AATREE_PTR_NIL )
484 {
485 aatree_node *ptnode = aatree_get_node( tree, t );
486 aatree_show_r( tree, ptnode->left, lvl+1, p_show );
487
488 void *data = aatree_get_data( tree, t );
489
490 for( int i=0; i<lvl; i++ )
491 {
492 printf( " " );
493 }
494 p_show( data );
495 printf( " (%d) \n", t );
496
497 aatree_show_r( tree, ptnode->right, lvl+1, p_show );
498 }
499 }
500
501 static void aatree_show( aatree *tree, aatree_ptr t, void(*p_show)(void *data))
502 {
503 if( t != AATREE_PTR_NIL )
504 {
505 aatree_node *ptnode = aatree_get_node( tree, t );
506 aatree_show( tree, ptnode->left, p_show );
507 void *data = aatree_get_data( tree, t );
508
509 for( int i=0; i<ptnode->level; i++ )
510 {
511 printf( " " );
512 }
513 p_show( data );
514 printf( " (%d) \n", t );
515
516 aatree_show( tree, ptnode->right, p_show );
517 }
518 }
519
520 static void aatree_show_counts( aatree *tree, aatree_ptr t, int lvl, int *ln,
521 int *err,
522 void(*p_show)(void *data), int show )
523 {
524 if( lvl > 20 )
525 return;
526 if( t == AATREE_PTR_NIL ) return;
527
528 aatree_node *ptnode = aatree_get_node( tree, t );
529 void *data = aatree_get_data( tree, t );
530
531 aatree_show_counts( tree, ptnode->left, lvl+1, ln, err, p_show, show );
532
533 if( show ) printf( " %03d| ", *ln );
534 *ln = *ln +1;
535
536 if( show )
537 for( int i=0; i<lvl; i++ )
538 printf( " " );
539
540 if( show )
541 {
542 p_show( data );
543
544 if( ptnode->left != AATREE_PTR_NIL && ptnode->right != AATREE_PTR_NIL )
545 printf( "|" );
546 if( ptnode->left != AATREE_PTR_NIL && ptnode->right == AATREE_PTR_NIL )
547 printf( "/" );
548 if( ptnode->left == AATREE_PTR_NIL && ptnode->right != AATREE_PTR_NIL )
549 printf( "\\" );
550
551 printf( " (%d, %d, parent: %d. V: %d, level: %d) \n", t,
552 ptnode->count, ptnode->parent,
553 aatree_verify( tree, t ), ptnode->level);
554 }
555
556 if( !aatree_verify( tree, t ) )
557 {
558 if( show )
559 printf( "error\n" );
560 *err = 1;
561 }
562
563 aatree_show_counts( tree, ptnode->right, lvl+1, ln, err, p_show, show );
564 }
565
566 #endif /* VG_STORE_H */