patron 0.4.16 → 0.4.17

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1952 @@
1
+ /*
2
+
3
+ This is SGLIB version 1.0.3
4
+
5
+ (C) by Marian Vittek, Bratislava, http://www.xref-tech.com/sglib, 2003-5
6
+
7
+ License Conditions: You can use a verbatim copy (including this
8
+ copyright notice) of sglib freely in any project, commercial or not.
9
+ You can also use derivative forms freely under terms of Open Source
10
+ Software license or under terms of GNU Public License. If you need
11
+ to use a derivative form in a commercial project, or you need sglib
12
+ under any other license conditions, contact the author.
13
+
14
+
15
+
16
+ */
17
+
18
+
19
+ #ifndef _SGLIB__h_
20
+ #define _SGLIB__h_
21
+
22
+ /* the assert is used exclusively to write unexpected error messages */
23
+ #include <assert.h>
24
+
25
+
26
+ /* ---------------------------------------------------------------------------- */
27
+ /* ---------------------------------------------------------------------------- */
28
+ /* - LEVEL - 0 INTERFACE - */
29
+ /* ---------------------------------------------------------------------------- */
30
+ /* ---------------------------------------------------------------------------- */
31
+
32
+
33
+ /* ---------------------------------------------------------------------------- */
34
+ /* ------------------------------ STATIC ARRAYS ------------------------------- */
35
+ /* ---------------------------------------------------------------------------- */
36
+
37
+ /*
38
+
39
+ Basic algorithms for sorting arrays. Multiple depending arrays can
40
+ be rearranged using user defined 'elem_exchangers'
41
+
42
+ */
43
+
44
+ /* HEAP - SORT (level 0) */
45
+
46
+ #define SGLIB_ARRAY_SINGLE_HEAP_SORT(type, a, max, comparator) {\
47
+ SGLIB_ARRAY_HEAP_SORT(type, a, max, comparator, SGLIB_ARRAY_ELEMENTS_EXCHANGER);\
48
+ }
49
+
50
+ #define SGLIB_ARRAY_HEAP_SORT(type, a, max, comparator, elem_exchanger) {\
51
+ int _k_;\
52
+ for(_k_=(max)/2; _k_>=0; _k_--) {\
53
+ SGLIB___ARRAY_HEAP_DOWN(type, a, _k_, max, comparator, elem_exchanger);\
54
+ }\
55
+ for(_k_=(max)-1; _k_>=0; _k_--) {\
56
+ elem_exchanger(type, a, 0, _k_);\
57
+ SGLIB___ARRAY_HEAP_DOWN(type, a, 0, _k_, comparator, elem_exchanger);\
58
+ }\
59
+ }
60
+
61
+ #define SGLIB___ARRAY_HEAP_DOWN(type, a, ind, max, comparator, elem_exchanger) {\
62
+ type _t_;\
63
+ int _m_, _l_, _r_, _i_;\
64
+ _i_ = (ind);\
65
+ _m_ = _i_;\
66
+ do {\
67
+ _i_ = _m_; \
68
+ _l_ = 2*_i_+1;\
69
+ _r_ = _l_+1;\
70
+ if (_l_ < (max)){\
71
+ if (comparator(((a)[_m_]), ((a)[_l_])) < 0) _m_ = _l_;\
72
+ if (_r_ < (max)) {\
73
+ if (comparator(((a)[_m_]), ((a)[_r_])) < 0) _m_ = _r_;\
74
+ }\
75
+ }\
76
+ if (_m_ != _i_) {\
77
+ elem_exchanger(type, a, _i_, _m_);\
78
+ }\
79
+ } while (_m_ != _i_);\
80
+ }
81
+
82
+
83
+ /* QUICK - SORT (level 0) */
84
+
85
+ #define SGLIB_ARRAY_SINGLE_QUICK_SORT(type, a, max, comparator) {\
86
+ SGLIB_ARRAY_QUICK_SORT(type, a, max, comparator, SGLIB_ARRAY_ELEMENTS_EXCHANGER);\
87
+ }
88
+
89
+ #define SGLIB_ARRAY_QUICK_SORT(type, a, max, comparator, elem_exchanger) {\
90
+ int _i_, _j_, _p_, _stacki_, _start_, _end_;\
91
+ /* can sort up to 2^64 elements */\
92
+ int _startStack_[64]; \
93
+ int _endStack_[64];\
94
+ type _tmp_;\
95
+ _startStack_[0] = 0;\
96
+ _endStack_[0] = (max);\
97
+ _stacki_ = 1;\
98
+ while (_stacki_ > 0) {\
99
+ _stacki_ --;\
100
+ _start_ = _startStack_[_stacki_];\
101
+ _end_ = _endStack_[_stacki_];\
102
+ while (_end_ - _start_ > 2) {\
103
+ _p_ = _start_;\
104
+ _i_ = _start_ + 1;\
105
+ _j_ = _end_ - 1;\
106
+ while (_i_<_j_) {\
107
+ for(; _i_<=_j_ && comparator(((a)[_i_]),((a)[_p_]))<=0; _i_++) ;\
108
+ if (_i_ > _j_) {\
109
+ /* all remaining elements lesseq than pivot */\
110
+ elem_exchanger(type, a, _j_, _p_);\
111
+ _i_ = _j_;\
112
+ } else {\
113
+ for(; _i_<=_j_ && comparator(((a)[_j_]),((a)[_p_]))>=0; _j_--) ;\
114
+ if (_i_ > _j_) {\
115
+ /* all remaining elements greater than pivot */\
116
+ elem_exchanger(type, a, _j_, _p_);\
117
+ _i_ = _j_;\
118
+ } else if (_i_ < _j_) {\
119
+ elem_exchanger(type, a, _i_, _j_);\
120
+ if (_i_+2 < _j_) {_i_++; _j_--;}\
121
+ else if (_i_+1 < _j_) _i_++;\
122
+ }\
123
+ }\
124
+ }\
125
+ /* O.K. i==j and pivot is on a[i] == a[j] */\
126
+ /* handle recursive calls without recursion */\
127
+ if (_i_-_start_ > 1 && _end_-_j_ > 1) {\
128
+ /* two recursive calls, use array-stack */\
129
+ if (_i_-_start_ < _end_-_j_-1) {\
130
+ _startStack_[_stacki_] = _j_+1;\
131
+ _endStack_[_stacki_] = _end_;\
132
+ _stacki_ ++;\
133
+ _end_ = _i_;\
134
+ } else {\
135
+ _startStack_[_stacki_] = _start_;\
136
+ _endStack_[_stacki_] = _i_;\
137
+ _stacki_ ++;\
138
+ _start_ = _j_+1;\
139
+ }\
140
+ } else {\
141
+ if (_i_-_start_ > 1) {\
142
+ _end_ = _i_;\
143
+ } else {\
144
+ _start_ = _j_+1;\
145
+ }\
146
+ }\
147
+ }\
148
+ if (_end_ - _start_ == 2) {\
149
+ if (comparator(((a)[_start_]),((a)[_end_-1])) > 0) {\
150
+ elem_exchanger(type, a, _start_, _end_-1);\
151
+ }\
152
+ }\
153
+ }\
154
+ }
155
+
156
+ /* BINARY SEARCH (level 0) */
157
+
158
+ #define SGLIB_ARRAY_BINARY_SEARCH(type, a, start_index, end_index, key, comparator, found, result_index) {\
159
+ int _kk_, _cc_, _ii_, _jj_, _ff_;\
160
+ _ii_ = (start_index); \
161
+ _jj_ = (end_index);\
162
+ _ff_ = 0;\
163
+ while (_ii_ <= _jj_ && _ff_==0) {\
164
+ _kk_ = (_jj_+_ii_)/2;\
165
+ _cc_ = comparator(((a)[_kk_]), (key));\
166
+ if (_cc_ == 0) {\
167
+ (result_index) = _kk_; \
168
+ _ff_ = 1;\
169
+ } else if (_cc_ < 0) {\
170
+ _ii_ = _kk_+1;\
171
+ } else {\
172
+ _jj_ = _kk_-1;\
173
+ }\
174
+ }\
175
+ if (_ff_ == 0) {\
176
+ /* not found, but set its resulting place in the array */\
177
+ (result_index) = _jj_+1;\
178
+ }\
179
+ (found) = _ff_;\
180
+ }
181
+
182
+ /* -------------------------------- queue (in an array) ------------------ */
183
+ /* queue is a quadruple (a,i,j,dim) such that: */
184
+ /* a is the array storing values */
185
+ /* i is the index of the first used element in the array */
186
+ /* j is the index of the first free element in the array */
187
+ /* dim is the size of the array a */
188
+ /* !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! */
189
+
190
+ #define SGLIB_QUEUE_INIT(type, a, i, j) { i = j = 0; }
191
+ #define SGLIB_QUEUE_IS_EMPTY(type, a, i, j) ((i)==(j))
192
+ #define SGLIB_QUEUE_IS_FULL(type, a, i, j, dim) ((i)==((j)+1)%(dim))
193
+ #define SGLIB_QUEUE_FIRST_ELEMENT(type, a, i, j) (a[i])
194
+ #define SGLIB_QUEUE_ADD_NEXT(type, a, i, j, dim) {\
195
+ if (SGLIB_QUEUE_IS_FULL(type, a, i, j, dim)) assert(0 && "the queue is full");\
196
+ (j) = ((j)+1) % (dim);\
197
+ }
198
+ #define SGLIB_QUEUE_ADD(type, a, elem, i, j, dim) {\
199
+ a[j] = (elem);\
200
+ SGLIB_QUEUE_ADD_NEXT(type, a, i, j, dim);\
201
+ }
202
+ #define SGLIB_QUEUE_DELETE_FIRST(type, a, i, j, dim) {\
203
+ if (SGLIB_QUEUE_IS_EMPTY(type, a, i, j)) assert(0 && "the queue is empty");\
204
+ (i) = ((i)+1) % (dim);\
205
+ }
206
+ #define SGLIB_QUEUE_DELETE(type, a, i, j, dim) {\
207
+ SGLIB_QUEUE_DELETE_FIRST(type, a, i, j, dim);\
208
+ }
209
+
210
+ /* ----------------- priority queue (heap) (in an array) -------------------- */
211
+ /* heap is a triple (a,i,dim) such that: */
212
+ /* a is the array storing values */
213
+ /* i is the index of the first free element in the array */
214
+ /* dim is the size of the array a */
215
+ /* !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! */
216
+
217
+ #define SGLIB_HEAP_INIT(type, a, i) { i = 0; }
218
+ #define SGLIB_HEAP_IS_EMPTY(type, a, i) ((i)==0)
219
+ #define SGLIB_HEAP_IS_FULL(type, a, i, dim) ((i)==(dim))
220
+ #define SGLIB_HEAP_FIRST_ELEMENT(type, a, i) (a[0])
221
+ #define SGLIB_HEAP_ADD_NEXT(type, a, i, dim, comparator, elem_exchanger) {\
222
+ int _i_;\
223
+ if (SGLIB_HEAP_IS_FULL(type, a, i, dim)) assert(0 && "the heap is full");\
224
+ _i_ = (i)++;\
225
+ while (_i_ > 0 && comparator(a[_i_/2], a[_i_]) < 0) {\
226
+ elem_exchanger(type, a, (_i_/2), _i_);\
227
+ _i_ = _i_/2;\
228
+ }\
229
+ }
230
+ #define SGLIB_HEAP_ADD(type, a, elem, i, dim, comparator) {\
231
+ if (SGLIB_HEAP_IS_FULL(type, a, i, dim)) assert(0 && "the heap is full");\
232
+ a[i] = (elem);\
233
+ SGLIB_HEAP_ADD_NEXT(type, a, i, dim, comparator, SGLIB_ARRAY_ELEMENTS_EXCHANGER);\
234
+ }
235
+ #define SGLIB_HEAP_DELETE_FIRST(type, a, i, dim, comparator, elem_exchanger) {\
236
+ if (SGLIB_HEAP_IS_EMPTY(type, a, i)) assert(0 && "the heap is empty");\
237
+ (i)--;\
238
+ a[0] = a[i];\
239
+ SGLIB___ARRAY_HEAP_DOWN(type, a, 0, i, comparator, elem_exchanger);\
240
+ }
241
+ #define SGLIB_HEAP_DELETE(type, a, i, dim, comparator) {\
242
+ SGLIB_HEAP_DELETE_FIRST(type, a, i, dim, comparator, SGLIB_ARRAY_ELEMENTS_EXCHANGER);\
243
+ }
244
+
245
+
246
+ /* ----------------- hashed table of pointers (in an array) -------------------- */
247
+
248
+ /*
249
+
250
+ This hashed table is storing pointers to objects (not containers).
251
+ In this table there is a one-to-one mapping between 'objects' stored
252
+ in the table and indexes where they are placed. Each index is
253
+ pointing to exactly one 'object' and each 'object' stored in the
254
+ table occurs on exactly one index. Once an object is stored in the
255
+ table, it can be represented via its index.
256
+
257
+ In case of collision while adding an object the index shifted
258
+ by SGLIB_HASH_TAB_SHIFT_CONSTANT (constant can be redefined)
259
+
260
+ You can NOT delete an element from such hash table. The only
261
+ justification (I can see) for this data structure is an exchange
262
+ file format, having an index table at the beginning and then
263
+ refering objects via indexes.
264
+
265
+ !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!!
266
+
267
+ */
268
+
269
+ #define SGLIB_HASH_TAB_INIT(type, table, dim) {\
270
+ int _i_;\
271
+ for(_i_ = 0; _i_ < (dim); _i_++) (table)[_i_] = NULL;\
272
+ }
273
+
274
+ #define SGLIB_HASH_TAB_ADD_IF_NOT_MEMBER(type, table, dim, elem, hash_function, comparator, member){\
275
+ unsigned _pos_;\
276
+ type *_elem_;\
277
+ SGLIB_HASH_TAB_FIND_MEMBER(type, table, dim, elem, _pos_, _elem_);\
278
+ (member) = (table)[_pos_];\
279
+ if (_elem_ == NULL) {\
280
+ if ((table)[_pos_] != NULL) assert(0 && "the hash table is full");\
281
+ (table)[_pos_] = (elem);\
282
+ }\
283
+ }
284
+
285
+ #define SGLIB_HASH_TAB_FIND_MEMBER(type, table, dim, elem, hash_function, comparator, resultIndex, resultMember) {\
286
+ unsigned _i_;\
287
+ int _count_;\
288
+ type *_e_;\
289
+ _count = 0;\
290
+ _i_ = hash_function(elem);\
291
+ _i_ %= (dim);\
292
+ while ((_e_=(table)[_i_])!=NULL && comparator(_e_, (elem))!=0 && _count_<(dim)) {\
293
+ _count_ ++;\
294
+ _i_ = (_i_ + SGLIB_HASH_TAB_SHIFT_CONSTANT) % (dim);\
295
+ }\
296
+ (resultIndex) = _i_;\
297
+ if (_count_ < (dim)) (resultMember) = _e_;\
298
+ else (resultMember) = NULL;\
299
+ }
300
+
301
+ #define SGLIB_HASH_TAB_IS_MEMBER(type, table, dim, elem, hash_function, resultIndex) {\
302
+ unsigned _i_;\
303
+ int _c_;\
304
+ type *_e_;\
305
+ _count = 0;\
306
+ _i_ = hash_function(elem);\
307
+ _i_ %= (dim);\
308
+ while ((_e_=(table)[_i_])!=NULL && _e_!=(elem) && _c_<(dim)) {\
309
+ _c_ ++;\
310
+ _i_ = (_i_ + SGLIB_HASH_TAB_SHIFT_CONSTANT) % (dim);\
311
+ }\
312
+ if (_e_==(elem)) (resultIndex) = _i_;\
313
+ else (resultIndex) = -1;\
314
+ }
315
+
316
+ #define SGLIB_HASH_TAB_MAP_ON_ELEMENTS(type, table, dim, iteratedIndex, iteratedVariable, command) {\
317
+ unsigned iteratedIndex;\
318
+ type *iteratedVariable;\
319
+ for(iteratedIndex=0; iteratedIndex < (dim); iteratedIndex++) {\
320
+ iteratedVariable = (table)[iteratedIndex];\
321
+ if (iteratedVariable != NULL) {command;}\
322
+ }\
323
+ }
324
+
325
+
326
+ /* ---------------------------------------------------------------------------- */
327
+ /* ------------------------- DYNAMIC DATA STRUCTURES -------------------------- */
328
+ /* ---------------------------------------------------------------------------- */
329
+
330
+ /* ------------------------------------ lists (level 0) --------------------- */
331
+
332
+ #define SGLIB_LIST_ADD(type, list, elem, next) {\
333
+ (elem)->next = (list);\
334
+ (list) = (elem);\
335
+ }
336
+
337
+ #define SGLIB_LIST_CONCAT(type, first, second, next) {\
338
+ if ((first)==NULL) {\
339
+ (first) = (second);\
340
+ } else {\
341
+ type *_p_;\
342
+ for(_p_ = (first); _p_->next!=NULL; _p_=_p_->next) ;\
343
+ _p_->next = (second);\
344
+ }\
345
+ }
346
+
347
+ #define SGLIB_LIST_DELETE(type, list, elem, next) {\
348
+ type **_p_;\
349
+ for(_p_ = &(list); *_p_!=NULL && *_p_!=(elem); _p_= &(*_p_)->next) ;\
350
+ assert(*_p_!=NULL && "element is not member of the container, use DELETE_IF_MEMBER instead"!=NULL);\
351
+ *_p_ = (*_p_)->next;\
352
+ }
353
+
354
+ #define SGLIB_LIST_ADD_IF_NOT_MEMBER(type, list, elem, comparator, next, member) {\
355
+ type *_p_;\
356
+ for(_p_ = (list); _p_!=NULL && comparator(_p_, (elem)) != 0; _p_= _p_->next) ;\
357
+ (member) = _p_;\
358
+ if (_p_ == NULL) {\
359
+ SGLIB_LIST_ADD(type, list, elem, next);\
360
+ }\
361
+ }
362
+
363
+ #define SGLIB_LIST_DELETE_IF_MEMBER(type, list, elem, comparator, next, member) {\
364
+ type **_p_;\
365
+ for(_p_ = &(list); *_p_!=NULL && comparator((*_p_), (elem)) != 0; _p_= &(*_p_)->next) ;\
366
+ (member) = *_p_;\
367
+ if (*_p_ != NULL) {\
368
+ *_p_ = (*_p_)->next;\
369
+ }\
370
+ }
371
+
372
+ #define SGLIB_LIST_IS_MEMBER(type, list, elem, next, result) {\
373
+ type *_p_;\
374
+ for(_p_ = (list); _p_!=NULL && _p_ != (elem); _p_= _p_->next) ;\
375
+ (result) = (_p_!=NULL);\
376
+ }
377
+
378
+ #define SGLIB_LIST_FIND_MEMBER(type, list, elem, comparator, next, member) {\
379
+ type *_p_;\
380
+ for(_p_ = (list); _p_!=NULL && comparator(_p_, (elem)) != 0; _p_= _p_->next) ;\
381
+ (member) = _p_;\
382
+ }
383
+
384
+ #define SGLIB_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, next, command) {\
385
+ type *_ne_;\
386
+ type *iteratedVariable;\
387
+ (iteratedVariable) = (list); \
388
+ while ((iteratedVariable)!=NULL) {\
389
+ _ne_ = (iteratedVariable)->next;\
390
+ {command;};\
391
+ (iteratedVariable) = _ne_;\
392
+ }\
393
+ }
394
+
395
+ #define SGLIB_LIST_LEN(type, list, next, result) {\
396
+ type *_ce_;\
397
+ (result) = 0;\
398
+ SGLIB_LIST_MAP_ON_ELEMENTS(type, list, _ce_, next, (result)++);\
399
+ }
400
+
401
+ #define SGLIB_LIST_REVERSE(type, list, next) {\
402
+ type *_list_,*_tmp_,*_res_;\
403
+ _list_ = (list);\
404
+ _res_ = NULL;\
405
+ while (_list_!=NULL) {\
406
+ _tmp_ = _list_->next; _list_->next = _res_;\
407
+ _res_ = _list_; _list_ = _tmp_;\
408
+ }\
409
+ (list) = _res_;\
410
+ }
411
+
412
+ #define SGLIB_LIST_SORT(type, list, comparator, next) {\
413
+ /* a non-recursive merge sort on lists */\
414
+ type *_r_;\
415
+ type *_a_, *_b_, *_todo_, *_t_, **_restail_;\
416
+ int _i_, _n_, _contFlag_;\
417
+ _r_ = (list);\
418
+ _contFlag_ = 1;\
419
+ for(_n_ = 1; _contFlag_; _n_ = _n_+_n_) {\
420
+ _todo_ = _r_; _r_ = NULL; _restail_ = &_r_; _contFlag_ =0;\
421
+ while (_todo_!=NULL) {\
422
+ _a_ = _todo_;\
423
+ for(_i_ = 1, _t_ = _a_; _i_ < _n_ && _t_!=NULL; _i_++, _t_ = _t_->next) ;\
424
+ if (_t_ ==NULL) {\
425
+ *_restail_ = _a_;\
426
+ break;\
427
+ }\
428
+ _b_ = _t_->next; _t_->next=NULL;\
429
+ for(_i_ =1, _t_ = _b_; _i_<_n_ && _t_!=NULL; _i_++, _t_ = _t_->next) ;\
430
+ if (_t_ ==NULL) {\
431
+ _todo_ =NULL;\
432
+ } else {\
433
+ _todo_ = _t_->next; _t_->next=NULL;\
434
+ }\
435
+ /* merge */\
436
+ while (_a_!=NULL && _b_!=NULL) {\
437
+ if (comparator(_a_, _b_) < 0) {\
438
+ *_restail_ = _a_; _restail_ = &(_a_->next); _a_ = _a_->next;\
439
+ } else {\
440
+ *_restail_ = _b_; _restail_ = &(_b_->next); _b_ = _b_->next;\
441
+ }\
442
+ }\
443
+ if (_a_!=NULL) *_restail_ = _a_;\
444
+ else *_restail_ = _b_;\
445
+ while (*_restail_!=NULL) _restail_ = &((*_restail_)->next);\
446
+ _contFlag_ =1;\
447
+ }\
448
+ }\
449
+ (list) = _r_;\
450
+ }
451
+
452
+ /* --------------------------------- sorted list (level 0) --------------------- */
453
+ /*
454
+ All operations suppose that the list is sorted and they preserve
455
+ this property.
456
+ */
457
+
458
+
459
+ #define SGLIB_SORTED_LIST_ADD(type, list, elem, comparator, next) {\
460
+ type **_e_;\
461
+ int _cmpres_;\
462
+ SGLIB_SORTED_LIST_FIND_MEMBER_OR_PLACE(type, list, elem, comparator, next, _cmpres_, _e_);\
463
+ (elem)->next = *_e_;\
464
+ *_e_ = (elem);\
465
+ }
466
+
467
+ #define SGLIB_SORTED_LIST_ADD_IF_NOT_MEMBER(type, list, elem, comparator, next, member) {\
468
+ type **_e_;\
469
+ int _cmp_res_;\
470
+ SGLIB_SORTED_LIST_FIND_MEMBER_OR_PLACE(type, list, elem, comparator, next, _cmp_res_, _e_);\
471
+ if (_cmp_res_ != 0) {\
472
+ (elem)->next = *_e_;\
473
+ *_e_ = (elem);\
474
+ (member) = NULL;\
475
+ } else {\
476
+ (member) = *_e_;\
477
+ }\
478
+ }
479
+
480
+ #define SGLIB_SORTED_LIST_DELETE(type, list, elem, next) {\
481
+ SGLIB_LIST_DELETE(type, list, elem, next);\
482
+ }
483
+
484
+ #define SGLIB_SORTED_LIST_DELETE_IF_MEMBER(type, list, elem, comparator, next, member) {\
485
+ type **_e_;\
486
+ int _cmp_res_;\
487
+ SGLIB_SORTED_LIST_FIND_MEMBER_OR_PLACE(type, list, elem, comparator, next, _cmp_res_, _e_);\
488
+ if (_cmp_res_ == 0) {\
489
+ (member) = *_e_;\
490
+ *_e_ = (*_e_)->next;\
491
+ } else {\
492
+ (member) = NULL;\
493
+ }\
494
+ }
495
+
496
+ #define SGLIB_SORTED_LIST_FIND_MEMBER(type, list, elem, comparator, next, member) {\
497
+ type *_p_;\
498
+ int _cmpres_ = 1;\
499
+ for(_p_ = (list); _p_!=NULL && (_cmpres_=comparator(_p_, (elem))) < 0; _p_=_p_->next) ;\
500
+ if (_cmpres_ != 0) (member) = NULL;\
501
+ else (member) = _p_;\
502
+ }
503
+
504
+ #define SGLIB_SORTED_LIST_IS_MEMBER(type, list, elem, comparator, next, result) {\
505
+ type *_p_;\
506
+ for(_p_ = (list); _p_!=NULL && comparator(_p_, (elem)) < 0; _p_=_p_->next) ;\
507
+ while (_p_ != NULL && _p_ != (elem) && comparator(_p_, (elem)) == 0) _p_=_p_->next;\
508
+ (result) = (_p_ == (elem));\
509
+ }
510
+
511
+ #define SGLIB_SORTED_LIST_FIND_MEMBER_OR_PLACE(type, list, elem, comparator, next, comparator_result, member_ptr) {\
512
+ (comparator_result) = -1;\
513
+ for((member_ptr) = &(list); \
514
+ *(member_ptr)!=NULL && ((comparator_result)=comparator((*member_ptr), (elem))) < 0; \
515
+ (member_ptr) = &(*(member_ptr))->next) ;\
516
+ }
517
+
518
+ #define SGLIB_SORTED_LIST_LEN(type, list, next, result) {\
519
+ SGLIB_LIST_LEN(type, list, next, result);\
520
+ }
521
+
522
+ #define SGLIB_SORTED_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, next, command) {\
523
+ SGLIB_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, next, command);\
524
+ }
525
+
526
+
527
+ /* ------------------------------- double linked list (level 0) ------------------------- */
528
+ /*
529
+ Lists with back pointer to previous element. Those lists implements deletion
530
+ of an element in a constant time.
531
+ */
532
+
533
+ #define SGLIB___DL_LIST_CREATE_SINGLETON(type, list, elem, previous, next) {\
534
+ (list) = (elem);\
535
+ (list)->next = (list)->previous = NULL;\
536
+ }
537
+
538
+ #define SGLIB_DL_LIST_ADD_AFTER(type, place, elem, previous, next) {\
539
+ if ((place) == NULL) {\
540
+ SGLIB___DL_LIST_CREATE_SINGLETON(type, place, elem, previous, next);\
541
+ } else {\
542
+ (elem)->next = (place)->next;\
543
+ (elem)->previous = (place);\
544
+ (place)->next = (elem);\
545
+ if ((elem)->next != NULL) (elem)->next->previous = (elem);\
546
+ }\
547
+ }
548
+
549
+ #define SGLIB_DL_LIST_ADD_BEFORE(type, place, elem, previous, next) {\
550
+ if ((place) == NULL) {\
551
+ SGLIB___DL_LIST_CREATE_SINGLETON(type, place, elem, previous, next);\
552
+ } else {\
553
+ (elem)->next = (place);\
554
+ (elem)->previous = (place)->previous;\
555
+ (place)->previous = (elem);\
556
+ if ((elem)->previous != NULL) (elem)->previous->next = (elem);\
557
+ }\
558
+ }
559
+
560
+ #define SGLIB_DL_LIST_ADD(type, list, elem, previous, next) {\
561
+ SGLIB_DL_LIST_ADD_BEFORE(type, list, elem, previous, next)\
562
+ }
563
+
564
+ #define SGLIB___DL_LIST_GENERIC_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member, the_add_operation) {\
565
+ type *_dlp_;\
566
+ for(_dlp_ = (list); _dlp_!=NULL && comparator(_dlp_, (elem)) != 0; _dlp_= _dlp_->previous) ;\
567
+ if (_dlp_ == NULL && (list) != NULL) {\
568
+ for(_dlp_ = (list)->next; _dlp_!=NULL && comparator(_dlp_, (elem)) != 0; _dlp_= _dlp_->next) ;\
569
+ }\
570
+ (member) = _dlp_;\
571
+ if (_dlp_ == NULL) {\
572
+ the_add_operation(type, list, elem, previous, next);\
573
+ }\
574
+ }
575
+
576
+ #define SGLIB_DL_LIST_ADD_BEFORE_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member) {\
577
+ SGLIB___DL_LIST_GENERIC_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member, SGLIB_DL_LIST_ADD_BEFORE);\
578
+ }
579
+
580
+ #define SGLIB_DL_LIST_ADD_AFTER_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member) {\
581
+ SGLIB___DL_LIST_GENERIC_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member, SGLIB_DL_LIST_ADD_AFTER);\
582
+ }
583
+
584
+ #define SGLIB_DL_LIST_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member) {\
585
+ SGLIB___DL_LIST_GENERIC_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member, SGLIB_DL_LIST_ADD);\
586
+ }
587
+
588
+ #define SGLIB_DL_LIST_CONCAT(type, first, second, previous, next) {\
589
+ if ((first)==NULL) {\
590
+ (first) = (second);\
591
+ } else if ((second)!=NULL) {\
592
+ type *_dlp_;\
593
+ for(_dlp_ = (first); _dlp_->next!=NULL; _dlp_=_dlp_->next) ;\
594
+ SGLIB_DL_LIST_ADD_AFTER(type, _dlp_, second, previous, next);\
595
+ }\
596
+ }
597
+
598
+ #define SGLIB_DL_LIST_DELETE(type, list, elem, previous, next) {\
599
+ type *_l_;\
600
+ _l_ = (list);\
601
+ if (_l_ == (elem)) {\
602
+ if ((elem)->previous != NULL) _l_ = (elem)->previous;\
603
+ else _l_ = (elem)->next;\
604
+ }\
605
+ if ((elem)->next != NULL) (elem)->next->previous = (elem)->previous;\
606
+ if ((elem)->previous != NULL) (elem)->previous->next = (elem)->next;\
607
+ (list) = _l_;\
608
+ }
609
+
610
+ #define SGLIB_DL_LIST_DELETE_IF_MEMBER(type, list, elem, comparator, previous, next, member) {\
611
+ type *_dlp_;\
612
+ for(_dlp_ = (list); _dlp_!=NULL && comparator(_dlp_, (elem)) != 0; _dlp_= _dlp_->previous) ;\
613
+ if (_dlp_ == NULL && (list) != NULL) {\
614
+ for(_dlp_ = (list)->next; _dlp_!=NULL && comparator(_dlp_, (elem)) != 0; _dlp_= _dlp_->next) ;\
615
+ }\
616
+ (member) = _dlp_;\
617
+ if (_dlp_ != NULL) {\
618
+ SGLIB_DL_LIST_DELETE(type, list, _dlp_, previous, next);\
619
+ }\
620
+ }
621
+
622
+ #define SGLIB_DL_LIST_IS_MEMBER(type, list, elem, previous, next, result) {\
623
+ type *_dlp_;\
624
+ SGLIB_LIST_IS_MEMBER(type, list, elem, previous, result);\
625
+ if (result == 0 && (list) != NULL) {\
626
+ _dlp_ = (list)->next;\
627
+ SGLIB_LIST_IS_MEMBER(type, _dlp_, elem, next, result);\
628
+ }\
629
+ }
630
+
631
+ #define SGLIB_DL_LIST_FIND_MEMBER(type, list, elem, comparator, previous, next, member) {\
632
+ type *_dlp_;\
633
+ SGLIB_LIST_FIND_MEMBER(type, list, elem, comparator, previous, member);\
634
+ if ((member) == NULL && (list) != NULL) {\
635
+ _dlp_ = (list)->next;\
636
+ SGLIB_LIST_FIND_MEMBER(type, _dlp_, elem, comparator, next, member);\
637
+ }\
638
+ }
639
+
640
+ #define SGLIB_DL_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, previous, next, command) {\
641
+ type *_dl_;\
642
+ type *iteratedVariable;\
643
+ if ((list)!=NULL) {\
644
+ _dl_ = (list)->next;\
645
+ SGLIB_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, previous, command);\
646
+ SGLIB_LIST_MAP_ON_ELEMENTS(type, _dl_, iteratedVariable, next, command);\
647
+ }\
648
+ }
649
+
650
+ #define SGLIB_DL_LIST_SORT(type, list, comparator, previous, next) {\
651
+ type *_dll_, *_dlp_, *_dlt_;\
652
+ _dll_ = (list);\
653
+ if (_dll_ != NULL) {\
654
+ for(; _dll_->previous!=NULL; _dll_=_dll_->previous) ;\
655
+ SGLIB_LIST_SORT(type, _dll_, comparator, next);\
656
+ SGLIB___DL_LIST_CREATE_FROM_LIST(type, _dll_, previous, next);\
657
+ (list) = _dll_;\
658
+ }\
659
+ }
660
+
661
+ #define SGLIB_DL_LIST_GET_FIRST(type, list, previous, next, result) {\
662
+ type *_dll_;\
663
+ _dll_ = (list);\
664
+ if (_dll_ != NULL) {\
665
+ for(; _dll_->previous!=NULL; _dll_=_dll_->previous) ;\
666
+ }\
667
+ (result) = _dll_;\
668
+ }
669
+
670
+ #define SGLIB_DL_LIST_GET_LAST(type, list, previous, next, result) {\
671
+ type *_dll_;\
672
+ _dll_ = (list);\
673
+ if (_dll_ != NULL) {\
674
+ for(; _dll_->next!=NULL; _dll_=_dll_->next) ;\
675
+ }\
676
+ (result) = _dll_;\
677
+ }
678
+
679
+ #define SGLIB_DL_LIST_LEN(type, list, previous, next, result) {\
680
+ type *_dl_;\
681
+ int _r1_, _r2_;\
682
+ if ((list)==NULL) {\
683
+ (result) = 0;\
684
+ } else {\
685
+ SGLIB_LIST_LEN(type, list, previous, _r1_);\
686
+ _dl_ = (list)->next;\
687
+ SGLIB_LIST_LEN(type, _dl_, next, _r2_);\
688
+ (result) = _r1_ + _r2_;\
689
+ }\
690
+ }
691
+
692
+ #define SGLIB_DL_LIST_REVERSE(type, list, previous, next) {\
693
+ type *_list_,*_nlist_,*_dlp_,*_dln_;\
694
+ _list_ = (list);\
695
+ if (_list_!=NULL) {\
696
+ _nlist_ = _list_->next;\
697
+ while (_list_!=NULL) {\
698
+ _dln_ = _list_->next; \
699
+ _dlp_ = _list_->previous; \
700
+ _list_->next = _dlp_;\
701
+ _list_->previous = _dln_;\
702
+ _list_ = _dlp_;\
703
+ }\
704
+ while (_nlist_!=NULL) {\
705
+ _dln_ = _nlist_->next; \
706
+ _dlp_ = _nlist_->previous; \
707
+ _nlist_->next = _dlp_;\
708
+ _nlist_->previous = _dln_;\
709
+ _nlist_ = _dln_;\
710
+ }\
711
+ }\
712
+ }
713
+
714
+ #define SGLIB___DL_LIST_CREATE_FROM_LIST(type, list, previous, next) {\
715
+ type *_dlp_, *_dlt_;\
716
+ _dlp_ = NULL;\
717
+ for(_dlt_ = (list); _dlt_!=NULL; _dlt_ = _dlt_->next) {\
718
+ _dlt_->previous = _dlp_;\
719
+ _dlp_ = _dlt_;\
720
+ }\
721
+ }
722
+
723
+
724
+ /* ------------------------------- binary tree traversal (level 0) -------------------- */
725
+
726
+
727
+ #define SGLIB___BIN_TREE_MAP_ON_ELEMENTS(type, tree, iteratedVariable, order, left, right, command) {\
728
+ /* this is non-recursive implementation of tree traversal */\
729
+ /* it maintains the path to the current node in the array '_path_' */\
730
+ /* the _path_[0] contains the root of the tree; */\
731
+ /* the _path_[_pathi_] contains the _current_element_ */\
732
+ /* the macro does not use the _current_element_ after execution of command */\
733
+ /* command can destroy it, it can free the element for example */\
734
+ type *_path_[SGLIB_MAX_TREE_DEEP];\
735
+ type *_right_[SGLIB_MAX_TREE_DEEP];\
736
+ char _pass_[SGLIB_MAX_TREE_DEEP];\
737
+ type *_cn_;\
738
+ int _pathi_;\
739
+ type *iteratedVariable;\
740
+ _cn_ = (tree);\
741
+ _pathi_ = 0;\
742
+ while (_cn_!=NULL) {\
743
+ /* push down to leftmost innermost element */\
744
+ while(_cn_!=NULL) {\
745
+ _path_[_pathi_] = _cn_;\
746
+ _right_[_pathi_] = _cn_->right;\
747
+ _pass_[_pathi_] = 0;\
748
+ _cn_ = _cn_->left;\
749
+ if (order == 0) {\
750
+ iteratedVariable = _path_[_pathi_];\
751
+ {command;}\
752
+ }\
753
+ _pathi_ ++;\
754
+ if (_pathi_ >= SGLIB_MAX_TREE_DEEP) assert(0 && "the binary_tree is too deep");\
755
+ }\
756
+ do {\
757
+ _pathi_ --;\
758
+ if ((order==1 && _pass_[_pathi_] == 0)\
759
+ || (order == 2 && (_pass_[_pathi_] == 1 || _right_[_pathi_]==NULL))) {\
760
+ iteratedVariable = _path_[_pathi_];\
761
+ {command;}\
762
+ }\
763
+ _pass_[_pathi_] ++;\
764
+ } while (_pathi_>0 && _right_[_pathi_]==NULL) ;\
765
+ _cn_ = _right_[_pathi_];\
766
+ _right_[_pathi_] = NULL;\
767
+ _pathi_ ++;\
768
+ }\
769
+ }
770
+
771
+ #define SGLIB_BIN_TREE_MAP_ON_ELEMENTS(type, tree, _current_element_, left, right, command) {\
772
+ SGLIB___BIN_TREE_MAP_ON_ELEMENTS(type, tree, _current_element_, 1, left, right, command);\
773
+ }
774
+
775
+ #define SGLIB_BIN_TREE_MAP_ON_ELEMENTS_PREORDER(type, tree, _current_element_, left, right, command) {\
776
+ SGLIB___BIN_TREE_MAP_ON_ELEMENTS(type, tree, _current_element_, 0, left, right, command);\
777
+ }
778
+
779
+ #define SGLIB_BIN_TREE_MAP_ON_ELEMENTS_POSTORDER(type, tree, _current_element_, left, right, command) {\
780
+ SGLIB___BIN_TREE_MAP_ON_ELEMENTS(type, tree, _current_element_, 2, left, right, command);\
781
+ }
782
+
783
+ #define SGLIB___BIN_TREE_FIND_MEMBER(type, tree, elem, left, right, comparator, res) {\
784
+ type *_s_;\
785
+ int _c_;\
786
+ _s_ = (tree);\
787
+ while (_s_!=NULL) {\
788
+ _c_ = comparator((elem), _s_);\
789
+ if (_c_ < 0) _s_ = _s_->left;\
790
+ else if (_c_ > 0) _s_ = _s_->right;\
791
+ else break;\
792
+ }\
793
+ (res) = _s_;\
794
+ }
795
+
796
+ /* ---------------------------------------------------------------------------- */
797
+ /* ---------------------------------------------------------------------------- */
798
+ /* - LEVEL - 1 INTERFACE - */
799
+ /* ---------------------------------------------------------------------------- */
800
+ /* ---------------------------------------------------------------------------- */
801
+
802
+
803
+
804
+ /* ---------------------------------------------------------------------------- */
805
+ /* ------------------------------ STATIC ARRAYS ------------------------------- */
806
+ /* ---------------------------------------------------------------------------- */
807
+
808
+ /* ----------------------------- array sorting (level 1) ---------------------- */
809
+
810
+ #define SGLIB_DEFINE_ARRAY_SORTING_PROTOTYPES(type, comparator) \
811
+ extern void sglib_##type##_array_quick_sort(type *a, int max);\
812
+ extern void sglib_##type##_array_heap_sort(type *a, int max);\
813
+
814
+
815
+ #define SGLIB_DEFINE_ARRAY_SORTING_FUNCTIONS(type, comparator) \
816
+ void sglib_##type##_array_quick_sort(type *a, int max) {\
817
+ SGLIB_ARRAY_SINGLE_QUICK_SORT(type, a, max, comparator);\
818
+ }\
819
+ void sglib_##type##_array_heap_sort(type *a, int max) {\
820
+ SGLIB_ARRAY_SINGLE_HEAP_SORT(type, a, max, comparator);\
821
+ }\
822
+
823
+
824
+ /* ----------------------------- array queue (level 1) ------------------- */
825
+ /* sglib's queue is stored in a fixed sized array */
826
+ /* queue_type MUST be a structure containing fields: */
827
+ /* afield is the array storing elem_type */
828
+ /* ifield is the index of the first element in the queue */
829
+ /* jfield is the index of the first free element after the queue */
830
+ /* dim is the size of the array afield */
831
+ /* !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! */
832
+
833
+
834
+ #define SGLIB_DEFINE_QUEUE_PROTOTYPES(queue_type, elem_type, afield, ifield, jfield, dim) \
835
+ extern void sglib_##queue_type##_init(queue_type *q); \
836
+ extern int sglib_##queue_type##_is_empty(queue_type *q); \
837
+ extern int sglib_##queue_type##_is_full(queue_type *q); \
838
+ extern elem_type sglib_##queue_type##_first_element(queue_type *q); \
839
+ extern elem_type *sglib_##queue_type##_first_element_ptr(queue_type *q); \
840
+ extern void sglib_##queue_type##_add_next(queue_type *q); \
841
+ extern void sglib_##queue_type##_add(queue_type *q, elem_type elem); \
842
+ extern void sglib_##queue_type##_delete_first(queue_type *q); \
843
+ extern void sglib_##queue_type##_delete(queue_type *q);
844
+
845
+
846
+ #define SGLIB_DEFINE_QUEUE_FUNCTIONS(queue_type, elem_type, afield, ifield, jfield, dim) \
847
+ void sglib_##queue_type##_init(queue_type *q) {\
848
+ SGLIB_QUEUE_INIT(elem_type, q->afield, q->ifield, q->jfield);\
849
+ }\
850
+ int sglib_##queue_type##_is_empty(queue_type *q) {\
851
+ return(SGLIB_QUEUE_IS_EMPTY(elem_type, q->afield, q->ifield, q->jfield));\
852
+ }\
853
+ int sglib_##queue_type##_is_full(queue_type *q) {\
854
+ return(SGLIB_QUEUE_IS_FULL(elem_type, q->afield, q->ifield, q->jfield));\
855
+ }\
856
+ elem_type sglib_##queue_type##_first_element(queue_type *q) {\
857
+ return(SGLIB_QUEUE_FIRST_ELEMENT(elem_type, q->afield, q->ifield, q->jfield));\
858
+ }\
859
+ elem_type *sglib_##queue_type##_first_element_ptr(queue_type *q) {\
860
+ return(& SGLIB_QUEUE_FIRST_ELEMENT(elem_type, q->afield, q->ifield, q->jfield));\
861
+ }\
862
+ void sglib_##queue_type##_add_next(queue_type *q) {\
863
+ SGLIB_QUEUE_ADD_NEXT(elem_type, q->afield, q->ifield, q->jfield, dim);\
864
+ }\
865
+ void sglib_##queue_type##_add(queue_type *q, elem_type elem) {\
866
+ SGLIB_QUEUE_ADD(elem_type, q->afield, elem, q->ifield, q->jfield, dim);\
867
+ }\
868
+ void sglib_##queue_type##_delete_first(queue_type *q) {\
869
+ SGLIB_QUEUE_DELETE_FIRST(elem_type, q->afield, q->ifield, q->jfield, dim);\
870
+ }\
871
+ void sglib_##queue_type##_delete(queue_type *q) {\
872
+ SGLIB_QUEUE_DELETE_FIRST(elem_type, q->afield, q->ifield, q->jfield, dim);\
873
+ }
874
+
875
+
876
+ /* ------------------------ array heap (level 1) ------------------------- */
877
+ /* sglib's heap is a priority queue implemented in a fixed sized array */
878
+ /* heap_type MUST be a structure containing fields: */
879
+ /* afield is the array of size dim storing elem_type */
880
+ /* ifield is the index of the first free element after the queue */
881
+ /* !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! */
882
+
883
+
884
+ #define SGLIB_DEFINE_HEAP_PROTOTYPES(heap_type, elem_type, afield, ifield, dim, comparator, elem_exchanger) \
885
+ extern void sglib_##heap_type##_init(heap_type *q); \
886
+ extern int sglib_##heap_type##_is_empty(heap_type *q); \
887
+ extern int sglib_##heap_type##_is_full(heap_type *q); \
888
+ extern elem_type sglib_##heap_type##_first_element(heap_type *q); \
889
+ extern elem_type *sglib_##heap_type##_first_element_ptr(heap_type *q); \
890
+ extern void sglib_##heap_type##_add_next(heap_type *q); \
891
+ extern void sglib_##heap_type##_add(heap_type *q, elem_type elem); \
892
+ extern void sglib_##heap_type##_delete_first(heap_type *q); \
893
+ extern void sglib_##heap_type##_delete(heap_type *q)
894
+
895
+ #define SGLIB_DEFINE_HEAP_FUNCTIONS(heap_type, elem_type, afield, ifield, dim, comparator, elem_exchanger) \
896
+ void sglib_##heap_type##_init(heap_type *q) {\
897
+ SGLIB_HEAP_INIT(elem_type, q->afield, q->ifield);\
898
+ }\
899
+ int sglib_##heap_type##_is_empty(heap_type *q) {\
900
+ return(SGLIB_HEAP_IS_EMPTY(elem_type, q->afield, q->ifield));\
901
+ }\
902
+ int sglib_##heap_type##_is_full(heap_type *q) {\
903
+ return(SGLIB_HEAP_IS_FULL(elem_type, q->afield, q->ifield));\
904
+ }\
905
+ elem_type sglib_##heap_type##_first_element(heap_type *q) {\
906
+ return(SGLIB_HEAP_FIRST_ELEMENT(elem_type, q->afield, q->ifield));\
907
+ }\
908
+ elem_type *sglib_##heap_type##_first_element_ptr(heap_type *q) {\
909
+ return(& SGLIB_HEAP_FIRST_ELEMENT(elem_type, q->afield, q->ifield));\
910
+ }\
911
+ void sglib_##heap_type##_add_next(heap_type *q) {\
912
+ SGLIB_HEAP_ADD_NEXT(elem_type, q->afield, q->ifield, dim, comparator, elem_exchanger);\
913
+ }\
914
+ void sglib_##heap_type##_add(heap_type *q, elem_type elem) {\
915
+ SGLIB_HEAP_ADD(elem_type, q->afield, elem, q->ifield, dim, comparator, elem_exchanger);\
916
+ }\
917
+ void sglib_##heap_type##_delete_first(heap_type *q) {\
918
+ SGLIB_HEAP_DELETE_FIRST(elem_type, q->afield, q->ifield, dim, comparator, elem_exchanger);\
919
+ }\
920
+ void sglib_##heap_type##_delete(heap_type *q) {\
921
+ SGLIB_HEAP_DELETE_FIRST(elem_type, q->afield, q->ifield, dim, comparator, elem_exchanger);\
922
+ }
923
+
924
+
925
+ /* ------------------------ hashed table (level 1) ------------------------- */
926
+ /*
927
+
928
+ sglib's hash table is an array storing directly pointers to objects (not containers).
929
+ In this table there is a one-to-one mapping between 'objects' stored
930
+ in the table and indexes where they are placed. Each index is
931
+ pointing to exactly one 'object' and each 'object' stored in the
932
+ table occurs on exactly one index. Once an object is stored in the
933
+ table, it can be represented via its index.
934
+
935
+ type - is the type of elements
936
+ dim - is the size of the hash array
937
+ hash_function - is a hashing function mapping type* to unsigned
938
+ comparator - is a comparator on elements
939
+
940
+ !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!!
941
+ */
942
+
943
+ #define SGLIB_DEFINE_HASHED_TABLE_PROTOTYPES(type, dim, hash_function, comparator) \
944
+ struct sglib_hashed_##type##_iterator {\
945
+ int currentIndex;\
946
+ int (*subcomparator)(type *, type *);\
947
+ type *equalto;\
948
+ };\
949
+ extern void sglib_hashed_##type##_init(type *table[dim]);\
950
+ extern int sglib_hashed_##type##_add_if_not_member(type *table[dim], type *elem, type **member);\
951
+ extern int sglib_hashed_##type##_is_member(type *table[dim], type *elem);\
952
+ extern type * sglib_hashed_##type##_find_member(type *table[dim], type *elem);\
953
+ extern type *sglib_hashed_##type##_it_init(struct sglib_hashed_##type##_iterator *it, type *table[dim]); \
954
+ extern type *sglib_hashed_##type##_it_init_on_equal(struct sglib_hashed_##type##_iterator *it, type *table[dim], int (*subcomparator)(type *, type *), type *equalto); \
955
+ extern type *sglib_hashed_##type##_it_current(struct sglib_hashed_##type##_iterator *it); \
956
+ extern type *sglib_hashed_##type##_it_next(struct sglib_hashed_##type##_iterator *it);
957
+
958
+ #define SGLIB_DEFINE_HASHED_TABLE_FUNCTIONS(type, dim, hash_function, comparator) \
959
+ struct sglib_hashed_##type##_iterator {\
960
+ int currentIndex;\
961
+ type **table;\
962
+ int (*subcomparator)(type *, type *);\
963
+ type *equalto;\
964
+ };\
965
+ void sglib_hashed_##type##_init(type *table[dim]) {\
966
+ SGLIB_HASH_TAB_INIT(type, table, dim);\
967
+ }\
968
+ int sglib_hashed_##type##_add_if_not_member(type *table[dim], type *elem, type **member) {\
969
+ SGLIB_HASH_TAB_ADD_IF_NOT_MEMBER(type, table, dim, elem, hash_function, comparator, *member);\
970
+ }\
971
+ int sglib_hashed_##type##_is_member(type *table[dim], type *elem) {\
972
+ int ind;\
973
+ SGLIB_HASH_TAB_IS_MEMBER(type, table, dim, elem, hash_function, ind);\
974
+ return(ind != -1);\
975
+ }\
976
+ type * sglib_hashed_##type##_find_member(type *table[dim], type *elem) {\
977
+ type *mmb;\
978
+ int ind;\
979
+ SGLIB_HASH_TAB_FIND_MEMBER(type, table, dim, elem, hash_function, comparator, ind, mmb);\
980
+ return(mmb);\
981
+ }\
982
+ type *sglib_hashed_##type##_it_init_on_equal(struct sglib_hashed_##type##_iterator *it, type *table[dim], int (*subcomparator)(type *, type *), type *equalto) {\
983
+ int i;\
984
+ it->table = table;\
985
+ it->subcomparator = subcomparator;\
986
+ it->equalto = equalto;\
987
+ for(i=0; i<(dim) && table[i]==NULL; i++) ;\
988
+ it->currentIndex = i;\
989
+ if (i<(dim)) return(table[i]);\
990
+ return(NULL);\
991
+ }\
992
+ type *sglib_hashed_##type##_it_init(struct sglib_hashed_##type##_iterator *it, type *table[dim]) {\
993
+ sglib_hashed_##type##_it_init_on_equal(it, table, NULL, NULL);\
994
+ }\
995
+ type *sglib_hashed_##type##_it_current(struct sglib_hashed_##type##_iterator *it) {\
996
+ return(table[it->currentIndex]);\
997
+ }\
998
+ type *sglib_hashed_##type##_it_next(struct sglib_hashed_##type##_iterator *it) {\
999
+ i=it->currentIndex;\
1000
+ if (i<(dim)) {\
1001
+ for(i++; i<(dim) && table[i]==NULL; i++) ;\
1002
+ }\
1003
+ it->currentIndex = i;\
1004
+ if (i<(dim)) return(table[i]);\
1005
+ return(NULL);\
1006
+ }
1007
+
1008
+
1009
+ /* ------------------- hashed container (only for level 1) -------------------- */
1010
+ /*
1011
+ hashed container is a table of given fixed size containing another
1012
+ (dynamic) base container in each cell. Once an object should be
1013
+ inserted into the hashed container, a hash function is used to
1014
+ determine the cell where the object belongs and the object is
1015
+ inserted into the base container stored in this cell. Usually the
1016
+ base container is simply a list or a sorted list, but it can be a
1017
+ red-black tree as well.
1018
+
1019
+ parameters:
1020
+ type - the type of the container stored in each cell.
1021
+ dim - the size of the hashed array
1022
+ hash_function - the hashing function hashing 'type *' to unsigned.
1023
+
1024
+ */
1025
+
1026
+ #define SGLIB_DEFINE_HASHED_CONTAINER_PROTOTYPES(type, dim, hash_function) \
1027
+ struct sglib_hashed_##type##_iterator {\
1028
+ struct sglib_##type##_iterator containerIt;\
1029
+ type **table;\
1030
+ int currentIndex;\
1031
+ int (*subcomparator)(type *, type *);\
1032
+ type *equalto;\
1033
+ };\
1034
+ extern void sglib_hashed_##type##_init(type *table[dim]);\
1035
+ extern void sglib_hashed_##type##_add(type *table[dim], type *elem);\
1036
+ extern int sglib_hashed_##type##_add_if_not_member(type *table[dim], type *elem, type **member);\
1037
+ extern void sglib_hashed_##type##_delete(type *table[dim], type *elem);\
1038
+ extern int sglib_hashed_##type##_delete_if_member(type *table[dim], type *elem, type **memb);\
1039
+ extern int sglib_hashed_##type##_is_member(type *table[dim], type *elem);\
1040
+ extern type * sglib_hashed_##type##_find_member(type *table[dim], type *elem);\
1041
+ extern type *sglib_hashed_##type##_it_init(struct sglib_hashed_##type##_iterator *it, type *table[dim]); \
1042
+ extern type *sglib_hashed_##type##_it_init_on_equal(struct sglib_hashed_##type##_iterator *it, type *table[dim], int (*subcomparator)(type *, type *), type *equalto); \
1043
+ extern type *sglib_hashed_##type##_it_current(struct sglib_hashed_##type##_iterator *it); \
1044
+ extern type *sglib_hashed_##type##_it_next(struct sglib_hashed_##type##_iterator *it);
1045
+
1046
+ #define SGLIB_DEFINE_HASHED_CONTAINER_FUNCTIONS(type, dim, hash_function) \
1047
+ /*extern unsigned hash_function(type *elem);*/\
1048
+ void sglib_hashed_##type##_init(type *table[dim]) {\
1049
+ unsigned i;\
1050
+ for(i=0; i<(dim); i++) table[i] = NULL;\
1051
+ }\
1052
+ void sglib_hashed_##type##_add(type *table[dim], type *elem) {\
1053
+ unsigned i;\
1054
+ i = ((unsigned)hash_function(elem)) % (dim);\
1055
+ sglib_##type##_add(&(table)[i], elem);\
1056
+ }\
1057
+ int sglib_hashed_##type##_add_if_not_member(type *table[dim], type *elem, type **member) {\
1058
+ unsigned i;\
1059
+ i = ((unsigned)hash_function(elem)) % (dim);\
1060
+ return(sglib_##type##_add_if_not_member(&(table)[i], elem, member));\
1061
+ }\
1062
+ void sglib_hashed_##type##_delete(type *table[dim], type *elem) {\
1063
+ unsigned i;\
1064
+ i = ((unsigned)hash_function(elem)) % (dim);\
1065
+ sglib_##type##_delete(&(table)[i], elem);\
1066
+ }\
1067
+ int sglib_hashed_##type##_delete_if_member(type *table[dim], type *elem, type **memb) {\
1068
+ unsigned i;\
1069
+ i = ((unsigned)hash_function(elem)) % (dim);\
1070
+ return(sglib_##type##_delete_if_member(&(table)[i], elem, memb));\
1071
+ }\
1072
+ int sglib_hashed_##type##_is_member(type *table[dim], type *elem) {\
1073
+ unsigned i;\
1074
+ i = ((unsigned)hash_function(elem)) % (dim);\
1075
+ return(sglib_##type##_is_member((table)[i], elem));\
1076
+ }\
1077
+ type * sglib_hashed_##type##_find_member(type *table[dim], type *elem) {\
1078
+ unsigned i;\
1079
+ i = ((unsigned)hash_function(elem)) % (dim);\
1080
+ return(sglib_##type##_find_member((table)[i], elem));\
1081
+ }\
1082
+ type *sglib_hashed_##type##_it_init_on_equal(struct sglib_hashed_##type##_iterator *it, type *table[dim], int (*subcomparator)(type *, type *), type *equalto) {\
1083
+ type *e;\
1084
+ it->table = table;\
1085
+ it->currentIndex = 0;\
1086
+ it->subcomparator = subcomparator;\
1087
+ it->equalto = equalto;\
1088
+ e = sglib_##type##_it_init_on_equal(&it->containerIt, table[it->currentIndex], it->subcomparator, it->equalto);\
1089
+ if (e==NULL) e = sglib_hashed_##type##_it_next(it);\
1090
+ return(e);\
1091
+ }\
1092
+ type *sglib_hashed_##type##_it_init(struct sglib_hashed_##type##_iterator *it, type *table[dim]) {\
1093
+ return(sglib_hashed_##type##_it_init_on_equal(it, table, NULL, NULL));\
1094
+ }\
1095
+ type *sglib_hashed_##type##_it_current(struct sglib_hashed_##type##_iterator *it) {\
1096
+ return(sglib_##type##_it_current(&it->containerIt));\
1097
+ }\
1098
+ type *sglib_hashed_##type##_it_next(struct sglib_hashed_##type##_iterator *it) {\
1099
+ type *e;\
1100
+ e = sglib_##type##_it_next(&it->containerIt);\
1101
+ while (e==NULL && (++(it->currentIndex))<(dim)) {\
1102
+ e = sglib_##type##_it_init_on_equal(&it->containerIt, it->table[it->currentIndex], it->subcomparator, it->equalto);\
1103
+ }\
1104
+ return(e);\
1105
+ }
1106
+
1107
+
1108
+
1109
+ /* ---------------------------------------------------------------------------- */
1110
+ /* ------------------------- DYNAMIC DATA STRUCTURES -------------------------- */
1111
+ /* ---------------------------------------------------------------------------- */
1112
+
1113
+
1114
+
1115
+ /* ------------------------------------ list (level 1) -------------------------------- */
1116
+
1117
+ #define SGLIB_DEFINE_LIST_PROTOTYPES(type, comparator, next) \
1118
+ struct sglib_##type##_iterator {\
1119
+ type *currentelem;\
1120
+ type *nextelem;\
1121
+ int (*subcomparator)(type *, type *);\
1122
+ type *equalto;\
1123
+ };\
1124
+ extern void sglib_##type##_add(type **list, type *elem);\
1125
+ extern int sglib_##type##_add_if_not_member(type **list, type *elem, type **member);\
1126
+ extern void sglib_##type##_concat(type **first, type *second);\
1127
+ extern void sglib_##type##_delete(type **list, type *elem);\
1128
+ extern int sglib_##type##_delete_if_member(type **list, type *elem, type **member);\
1129
+ extern int sglib_##type##_is_member(type *list, type *elem);\
1130
+ extern type *sglib_##type##_find_member(type *list, type *elem);\
1131
+ extern void sglib_##type##_sort(type **list);\
1132
+ extern int sglib_##type##_len(type *list);\
1133
+ extern void sglib_##type##_reverse(type **list);\
1134
+ extern type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list); \
1135
+ extern type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto); \
1136
+ extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \
1137
+ extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it);
1138
+
1139
+
1140
+ #define SGLIB_DEFINE_LIST_FUNCTIONS(type, comparator, next) \
1141
+ int sglib_##type##_is_member(type *list, type *elem) {\
1142
+ int result;\
1143
+ SGLIB_LIST_IS_MEMBER(type, list, elem, next, result);\
1144
+ return(result);\
1145
+ }\
1146
+ type *sglib_##type##_find_member(type *list, type *elem) {\
1147
+ type *result;\
1148
+ SGLIB_LIST_FIND_MEMBER(type, list, elem, comparator, next, result);\
1149
+ return(result);\
1150
+ }\
1151
+ int sglib_##type##_add_if_not_member(type **list, type *elem, type **member) {\
1152
+ SGLIB_LIST_ADD_IF_NOT_MEMBER(type, *list, elem, comparator, next, *member);\
1153
+ return(*member==NULL);\
1154
+ }\
1155
+ void sglib_##type##_add(type **list, type *elem) {\
1156
+ SGLIB_LIST_ADD(type, *list, elem, next);\
1157
+ }\
1158
+ void sglib_##type##_concat(type **first, type *second) {\
1159
+ SGLIB_LIST_CONCAT(type, *first, second, next);\
1160
+ }\
1161
+ void sglib_##type##_delete(type **list, type *elem) {\
1162
+ SGLIB_LIST_DELETE(type, *list, elem, next);\
1163
+ }\
1164
+ int sglib_##type##_delete_if_member(type **list, type *elem, type **member) {\
1165
+ SGLIB_LIST_DELETE_IF_MEMBER(type, *list, elem, comparator, next, *member);\
1166
+ return(*member!=NULL);\
1167
+ }\
1168
+ void sglib_##type##_sort(type **list) { \
1169
+ SGLIB_LIST_SORT(type, *list, comparator, next);\
1170
+ }\
1171
+ int sglib_##type##_len(type *list) {\
1172
+ int res;\
1173
+ SGLIB_LIST_LEN(type, list, next, res);\
1174
+ return(res);\
1175
+ }\
1176
+ void sglib_##type##_reverse(type **list) {\
1177
+ SGLIB_LIST_REVERSE(type, *list, next);\
1178
+ }\
1179
+ \
1180
+ type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto) {\
1181
+ it->subcomparator = subcomparator;\
1182
+ it->equalto = equalto;\
1183
+ it->nextelem = list;\
1184
+ return(sglib_##type##_it_next(it));\
1185
+ }\
1186
+ type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list) {\
1187
+ return(sglib_##type##_it_init_on_equal(it, list, NULL, NULL));\
1188
+ }\
1189
+ type *sglib_##type##_it_current(struct sglib_##type##_iterator *it) {\
1190
+ return(it->currentelem);\
1191
+ }\
1192
+ type *sglib_##type##_it_next(struct sglib_##type##_iterator *it) {\
1193
+ type *ce, *eq;\
1194
+ int (*scp)(type *, type *);\
1195
+ ce = it->nextelem;\
1196
+ it->nextelem = NULL;\
1197
+ if (it->subcomparator != NULL) {\
1198
+ eq = it->equalto; \
1199
+ scp = it->subcomparator;\
1200
+ while (ce!=NULL && scp(ce, eq)!=0) ce = ce->next;\
1201
+ }\
1202
+ it->currentelem = ce;\
1203
+ if (ce != NULL) it->nextelem = ce->next;\
1204
+ return(ce);\
1205
+ }
1206
+
1207
+ /* ----------------------------- sorted list (level 1) ----------------------------------- */
1208
+
1209
+
1210
+ #define SGLIB_DEFINE_SORTED_LIST_PROTOTYPES(type, comparator, next) \
1211
+ struct sglib_##type##_iterator {\
1212
+ type *currentelem;\
1213
+ type *nextelem;\
1214
+ int (*subcomparator)(type *, type *);\
1215
+ type *equalto;\
1216
+ };\
1217
+ extern void sglib_##type##_add(type **list, type *elem);\
1218
+ extern int sglib_##type##_add_if_not_member(type **list, type *elem, type **member);\
1219
+ extern void sglib_##type##_delete(type **list, type *elem);\
1220
+ extern int sglib_##type##_delete_if_member(type **list, type *elem, type **member);\
1221
+ extern int sglib_##type##_is_member(type *list, type *elem);\
1222
+ extern type *sglib_##type##_find_member(type *list, type *elem);\
1223
+ extern int sglib_##type##_len(type *list);\
1224
+ extern void sglib_##type##_sort(type **list);\
1225
+ extern type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list); \
1226
+ extern type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto); \
1227
+ extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \
1228
+ extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it);
1229
+
1230
+
1231
+ #define SGLIB_DEFINE_SORTED_LIST_FUNCTIONS(type, comparator, next) \
1232
+ int sglib_##type##_is_member(type *list, type *elem) {\
1233
+ int result;\
1234
+ SGLIB_SORTED_LIST_IS_MEMBER(type, list, elem, comparator, next, result);\
1235
+ return(result);\
1236
+ }\
1237
+ type *sglib_##type##_find_member(type *list, type *elem) {\
1238
+ type *result;\
1239
+ SGLIB_SORTED_LIST_FIND_MEMBER(type, list, elem, comparator, next, result);\
1240
+ return(result);\
1241
+ }\
1242
+ int sglib_##type##_add_if_not_member(type **list, type *elem, type **member) {\
1243
+ SGLIB_SORTED_LIST_ADD_IF_NOT_MEMBER(type, *list, elem, comparator, next, *member);\
1244
+ return(*member==NULL);\
1245
+ }\
1246
+ void sglib_##type##_add(type **list, type *elem) {\
1247
+ SGLIB_SORTED_LIST_ADD(type, *list, elem, comparator, next);\
1248
+ }\
1249
+ void sglib_##type##_delete(type **list, type *elem) {\
1250
+ SGLIB_SORTED_LIST_DELETE(type, *list, elem, next);\
1251
+ }\
1252
+ int sglib_##type##_delete_if_member(type **list, type *elem, type **member) {\
1253
+ SGLIB_SORTED_LIST_DELETE_IF_MEMBER(type, *list, elem, comparator, next, *member);\
1254
+ return(*member!=NULL);\
1255
+ }\
1256
+ int sglib_##type##_len(type *list) {\
1257
+ int res;\
1258
+ SGLIB_SORTED_LIST_LEN(type, list, next, res);\
1259
+ return(res);\
1260
+ }\
1261
+ void sglib_##type##_sort(type **list) { \
1262
+ SGLIB_LIST_SORT(type, *list, comparator, next);\
1263
+ }\
1264
+ \
1265
+ type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto) {\
1266
+ it->subcomparator = subcomparator;\
1267
+ it->equalto = equalto;\
1268
+ it->nextelem = list;\
1269
+ return(sglib_##type##_it_next(it));\
1270
+ }\
1271
+ type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list) {\
1272
+ return(sglib_##type##_it_init_on_equal(it, list, NULL, NULL));\
1273
+ }\
1274
+ type *sglib_##type##_it_current(struct sglib_##type##_iterator *it) {\
1275
+ return(it->currentelem);\
1276
+ }\
1277
+ type *sglib_##type##_it_next(struct sglib_##type##_iterator *it) {\
1278
+ type *ce, *eq;\
1279
+ int (*scp)(type *, type *);\
1280
+ int c;\
1281
+ ce = it->nextelem;\
1282
+ it->nextelem = NULL;\
1283
+ if (it->subcomparator != NULL) {\
1284
+ eq = it->equalto; \
1285
+ scp = it->subcomparator;\
1286
+ while (ce!=NULL && (c=scp(ce, eq)) < 0) ce = ce->next;\
1287
+ if (ce != NULL && c > 0) ce = NULL;\
1288
+ }\
1289
+ it->currentelem = ce;\
1290
+ if (ce != NULL) it->nextelem = ce->next;\
1291
+ return(ce);\
1292
+ }
1293
+
1294
+
1295
+ /* ----------------------------- double linked list (level 1) ------------------------------ */
1296
+
1297
+
1298
+ #define SGLIB_DEFINE_DL_LIST_PROTOTYPES(type, comparator, previous, next) \
1299
+ struct sglib_##type##_iterator {\
1300
+ type *currentelem;\
1301
+ type *prevelem;\
1302
+ type *nextelem;\
1303
+ int (*subcomparator)(type *, type *);\
1304
+ type *equalto;\
1305
+ };\
1306
+ extern void sglib_##type##_add(type **list, type *elem);\
1307
+ extern void sglib_##type##_add_before(type **list, type *elem);\
1308
+ extern void sglib_##type##_add_after(type **list, type *elem);\
1309
+ extern int sglib_##type##_add_if_not_member(type **list, type *elem, type **member);\
1310
+ extern int sglib_##type##_add_before_if_not_member(type **list, type *elem, type **member);\
1311
+ extern int sglib_##type##_add_after_if_not_member(type **list, type *elem, type **member);\
1312
+ extern void sglib_##type##_concat(type **first, type *second);\
1313
+ extern void sglib_##type##_delete(type **list, type *elem);\
1314
+ extern int sglib_##type##_delete_if_member(type **list, type *elem, type **member);\
1315
+ extern int sglib_##type##_is_member(type *list, type *elem);\
1316
+ extern type *sglib_##type##_find_member(type *list, type *elem);\
1317
+ extern type *sglib_##type##_get_first(type *list);\
1318
+ extern type *sglib_##type##_get_last(type *list);\
1319
+ extern void sglib_##type##_sort(type **list);\
1320
+ extern int sglib_##type##_len(type *list);\
1321
+ extern void sglib_##type##_reverse(type **list);\
1322
+ extern type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list); \
1323
+ extern type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto); \
1324
+ extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \
1325
+ extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it);
1326
+
1327
+
1328
+ #define SGLIB_DEFINE_DL_LIST_FUNCTIONS(type, comparator, previous, next) \
1329
+ void sglib_##type##_add(type **list, type *elem) {\
1330
+ SGLIB_DL_LIST_ADD(type, *list, elem, previous, next);\
1331
+ }\
1332
+ void sglib_##type##_add_after(type **list, type *elem) {\
1333
+ SGLIB_DL_LIST_ADD_AFTER(type, *list, elem, previous, next);\
1334
+ }\
1335
+ void sglib_##type##_add_before(type **list, type *elem) {\
1336
+ SGLIB_DL_LIST_ADD_BEFORE(type, *list, elem, previous, next);\
1337
+ }\
1338
+ int sglib_##type##_add_if_not_member(type **list, type *elem, type **member) {\
1339
+ SGLIB_DL_LIST_ADD_IF_NOT_MEMBER(type, *list, elem, comparator, previous, next, *member);\
1340
+ return(*member==NULL);\
1341
+ }\
1342
+ int sglib_##type##_add_after_if_not_member(type **list, type *elem, type **member) {\
1343
+ SGLIB_DL_LIST_ADD_AFTER_IF_NOT_MEMBER(type, *list, elem, comparator, previous, next, *member);\
1344
+ return(*member==NULL);\
1345
+ }\
1346
+ int sglib_##type##_add_before_if_not_member(type **list, type *elem, type **member) {\
1347
+ SGLIB_DL_LIST_ADD_BEFORE_IF_NOT_MEMBER(type, *list, elem, comparator, previous, next, *member);\
1348
+ return(*member==NULL);\
1349
+ }\
1350
+ void sglib_##type##_concat(type **first, type *second) {\
1351
+ SGLIB_DL_LIST_CONCAT(type, *first, second, previous, next);\
1352
+ }\
1353
+ void sglib_##type##_delete(type **list, type *elem) {\
1354
+ SGLIB_DL_LIST_DELETE(type, *list, elem, previous, next);\
1355
+ }\
1356
+ int sglib_##type##_delete_if_member(type **list, type *elem, type **member) {\
1357
+ SGLIB_DL_LIST_DELETE_IF_MEMBER(type, *list, elem, comparator, previous, next, *member);\
1358
+ return(*member!=NULL);\
1359
+ }\
1360
+ int sglib_##type##_is_member(type *list, type *elem) {\
1361
+ int result;\
1362
+ SGLIB_DL_LIST_IS_MEMBER(type, list, elem, previous, next, result);\
1363
+ return(result);\
1364
+ }\
1365
+ type *sglib_##type##_find_member(type *list, type *elem) {\
1366
+ type *result;\
1367
+ SGLIB_DL_LIST_FIND_MEMBER(type, list, elem, comparator, previous, next, result);\
1368
+ return(result);\
1369
+ }\
1370
+ type *sglib_##type##_get_first(type *list) {\
1371
+ type *result;\
1372
+ SGLIB_DL_LIST_GET_FIRST(type, list, previous, next, result);\
1373
+ return(result);\
1374
+ }\
1375
+ type *sglib_##type##_get_last(type *list) {\
1376
+ type *result;\
1377
+ SGLIB_DL_LIST_GET_LAST(type, list, previous, next, result);\
1378
+ return(result);\
1379
+ }\
1380
+ void sglib_##type##_sort(type **list) {\
1381
+ SGLIB_DL_LIST_SORT(type, *list, comparator, previous, next);\
1382
+ }\
1383
+ int sglib_##type##_len(type *list) {\
1384
+ int res;\
1385
+ SGLIB_DL_LIST_LEN(type, list, previous, next, res);\
1386
+ return(res);\
1387
+ }\
1388
+ void sglib_##type##_reverse(type **list) {\
1389
+ SGLIB_DL_LIST_REVERSE(type, *list, previous, next);\
1390
+ }\
1391
+ \
1392
+ type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto) {\
1393
+ it->subcomparator = subcomparator;\
1394
+ it->equalto = equalto;\
1395
+ it->prevelem = list;\
1396
+ it->nextelem = list;\
1397
+ if (list != NULL) it->nextelem = list->next;\
1398
+ return(sglib_##type##_it_next(it));\
1399
+ }\
1400
+ type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list) {\
1401
+ return(sglib_##type##_it_init_on_equal(it, list, NULL, NULL));\
1402
+ }\
1403
+ type *sglib_##type##_it_current(struct sglib_##type##_iterator *it) {\
1404
+ return(it->currentelem);\
1405
+ }\
1406
+ type *sglib_##type##_it_next(struct sglib_##type##_iterator *it) {\
1407
+ type *ce, *eq;\
1408
+ int (*scp)(type *, type *);\
1409
+ ce = it->prevelem;\
1410
+ it->prevelem = NULL;\
1411
+ if (it->subcomparator != NULL) {\
1412
+ eq = it->equalto; \
1413
+ scp = it->subcomparator;\
1414
+ while (ce!=NULL && scp(eq, ce)!=0) ce = ce->previous;\
1415
+ }\
1416
+ if (ce != NULL) {\
1417
+ it->prevelem = ce->previous;\
1418
+ } else {\
1419
+ ce = it->nextelem;\
1420
+ it->nextelem = NULL;\
1421
+ if (it->subcomparator != NULL) {\
1422
+ eq = it->equalto; \
1423
+ scp = it->subcomparator;\
1424
+ while (ce!=NULL && scp(ce, eq)!=0) ce = ce->next;\
1425
+ }\
1426
+ if (ce != NULL) it->nextelem = ce->next;\
1427
+ }\
1428
+ it->currentelem = ce;\
1429
+ return(ce);\
1430
+ }
1431
+
1432
+
1433
+ /* --------------------------------- red-black trees (level 1) -------------------------------- */
1434
+
1435
+ /*
1436
+
1437
+ This implementation requires pointers to left and right sons (no
1438
+ parent pointer is needed) and one bit of additional information
1439
+ storing the color of the node. The implementation follows discrepancy
1440
+ fixing rules from:
1441
+ http://www.cis.ohio-state.edu/~gurari/course/cis680/cis680Ch11.html
1442
+
1443
+ */
1444
+
1445
+ #define SGLIB___RBTREE_FIX_INSERTION_DISCREPANCY(type, tree, leftt, rightt, bits, RED, BLACK) {\
1446
+ type *t, *tl, *a, *b, *c, *ar, *bl, *br, *cl, *cr;\
1447
+ t = *tree;\
1448
+ tl = t->leftt;\
1449
+ if (t->rightt!=NULL && SGLIB___GET_VALUE(t->rightt->bits)==RED) {\
1450
+ if (SGLIB___GET_VALUE(tl->bits)==RED) {\
1451
+ if ((tl->leftt!=NULL && SGLIB___GET_VALUE(tl->leftt->bits)==RED) \
1452
+ || (tl->rightt!=NULL && SGLIB___GET_VALUE(tl->rightt->bits)==RED)) {\
1453
+ SGLIB___SET_VALUE(t->leftt->bits,BLACK);\
1454
+ SGLIB___SET_VALUE(t->rightt->bits,BLACK);\
1455
+ SGLIB___SET_VALUE(t->bits,RED);\
1456
+ }\
1457
+ }\
1458
+ } else {\
1459
+ if (SGLIB___GET_VALUE(tl->bits)==RED) {\
1460
+ if (tl->leftt!=NULL && SGLIB___GET_VALUE(tl->leftt->bits)==RED) {\
1461
+ a = t; b = tl; c = tl->leftt;\
1462
+ br = b->rightt;\
1463
+ a->leftt = br;\
1464
+ b->leftt = c; b->rightt = a;\
1465
+ SGLIB___SET_VALUE(a->bits,RED);\
1466
+ SGLIB___SET_VALUE(b->bits,BLACK);\
1467
+ *tree = b;\
1468
+ } else if (tl->rightt!=NULL && SGLIB___GET_VALUE(tl->rightt->bits)==RED) {\
1469
+ a = t; b = tl; ar=a->rightt;\
1470
+ bl=b->leftt; c=b->rightt;\
1471
+ cl=c->leftt; cr=c->rightt;\
1472
+ b->rightt = cl;\
1473
+ a->leftt = cr;\
1474
+ c->leftt = b;\
1475
+ c->rightt = a;\
1476
+ SGLIB___SET_VALUE(c->bits,BLACK);\
1477
+ SGLIB___SET_VALUE(a->bits,RED);\
1478
+ *tree = c;\
1479
+ }\
1480
+ }\
1481
+ }\
1482
+ }
1483
+
1484
+ #define SGLIB___RBTREE_FIX_DELETION_DISCREPANCY(type, tree, leftt, rightt, bits, RED, BLACK, res) {\
1485
+ type *t, *a, *b, *c, *d, *ar, *bl, *br, *cl, *cr, *dl, *dr;\
1486
+ t = a = *tree;\
1487
+ assert(t!=NULL);\
1488
+ ar = a->rightt;\
1489
+ b = t->leftt;\
1490
+ if (b==NULL) {\
1491
+ assert(SGLIB___GET_VALUE(t->bits)==RED);\
1492
+ SGLIB___SET_VALUE(t->bits,BLACK);\
1493
+ res = 0;\
1494
+ } else {\
1495
+ bl = b->leftt;\
1496
+ br = b->rightt;\
1497
+ if (SGLIB___GET_VALUE(b->bits)==RED) {\
1498
+ if (br==NULL) {\
1499
+ *tree = b;\
1500
+ SGLIB___SET_VALUE(b->bits,BLACK);\
1501
+ b->rightt = a;\
1502
+ a->leftt = br;\
1503
+ res = 0;\
1504
+ } else {\
1505
+ c = br;\
1506
+ assert(c!=NULL && SGLIB___GET_VALUE(c->bits)==BLACK);\
1507
+ cl = c->leftt;\
1508
+ cr = c->rightt;\
1509
+ if ((cl==NULL||SGLIB___GET_VALUE(cl->bits)==BLACK) && (cr==NULL||SGLIB___GET_VALUE(cr->bits)==BLACK)) {\
1510
+ *tree = b;\
1511
+ b->rightt = a;\
1512
+ SGLIB___SET_VALUE(b->bits,BLACK);\
1513
+ a->leftt = c;\
1514
+ SGLIB___SET_VALUE(c->bits,RED);\
1515
+ res = 0;\
1516
+ } else if (cl!=NULL && SGLIB___GET_VALUE(cl->bits)==RED) {\
1517
+ if (cr!=NULL && SGLIB___GET_VALUE(cr->bits)==RED) {\
1518
+ d = cr;\
1519
+ dl = d->leftt;\
1520
+ dr = d->rightt;\
1521
+ *tree = d;\
1522
+ SGLIB___SET_VALUE(d->bits,BLACK);\
1523
+ d->leftt = b;\
1524
+ c->rightt = dl;\
1525
+ d->rightt = a;\
1526
+ a->leftt = dr;\
1527
+ res = 0;\
1528
+ } else {\
1529
+ *tree = c;\
1530
+ c->leftt = b;\
1531
+ c->rightt = a;\
1532
+ b->leftt = bl;\
1533
+ b->rightt = cl;\
1534
+ a->leftt = cr;\
1535
+ SGLIB___SET_VALUE(cl->bits,BLACK);\
1536
+ res = 0;\
1537
+ }\
1538
+ } else if (cr!=NULL && SGLIB___GET_VALUE(cr->bits)==RED) {\
1539
+ assert(cl==NULL || SGLIB___GET_VALUE(cl->bits)==BLACK);\
1540
+ d = cr;\
1541
+ dl = d->leftt;\
1542
+ dr = d->rightt;\
1543
+ *tree = d;\
1544
+ SGLIB___SET_VALUE(d->bits,BLACK);\
1545
+ d->leftt = b;\
1546
+ c->rightt = dl;\
1547
+ d->rightt = a;\
1548
+ a->leftt = dr;\
1549
+ res = 0;\
1550
+ } else {\
1551
+ assert(0);\
1552
+ res = 0;\
1553
+ }\
1554
+ }\
1555
+ } else {\
1556
+ if ((bl==NULL || SGLIB___GET_VALUE(bl->bits)==BLACK) && (br==NULL || SGLIB___GET_VALUE(br->bits)==BLACK)) {\
1557
+ res = (SGLIB___GET_VALUE(a->bits)==BLACK);\
1558
+ SGLIB___SET_VALUE(a->bits,BLACK);\
1559
+ SGLIB___SET_VALUE(b->bits,RED);\
1560
+ } else if (bl!=NULL && SGLIB___GET_VALUE(bl->bits)==RED) {\
1561
+ if (br==NULL || SGLIB___GET_VALUE(br->bits)==BLACK) {\
1562
+ *tree = b;\
1563
+ SGLIB___SET_VALUE(b->bits,SGLIB___GET_VALUE(a->bits));\
1564
+ SGLIB___SET_VALUE(a->bits,BLACK);\
1565
+ b->rightt = a;\
1566
+ a->leftt = br;\
1567
+ SGLIB___SET_VALUE(bl->bits,BLACK);\
1568
+ res = 0;\
1569
+ } else {\
1570
+ assert(bl!=NULL);\
1571
+ assert(br!=NULL);\
1572
+ assert(SGLIB___GET_VALUE(bl->bits)==RED);\
1573
+ assert(SGLIB___GET_VALUE(br->bits)==RED);\
1574
+ c = br;\
1575
+ cl = c->leftt;\
1576
+ cr = c->rightt;\
1577
+ *tree = c;\
1578
+ SGLIB___SET_VALUE(c->bits,SGLIB___GET_VALUE(a->bits));\
1579
+ SGLIB___SET_VALUE(a->bits,BLACK);\
1580
+ c->leftt = b;\
1581
+ c->rightt = a;\
1582
+ b->rightt = cl;\
1583
+ a->leftt = cr;\
1584
+ res = 0;\
1585
+ }\
1586
+ } else {\
1587
+ assert(br!=NULL && SGLIB___GET_VALUE(br->bits)==RED);\
1588
+ c = br;\
1589
+ cl = c->leftt;\
1590
+ cr = c->rightt;\
1591
+ *tree = c;\
1592
+ SGLIB___SET_VALUE(c->bits,SGLIB___GET_VALUE(a->bits));\
1593
+ SGLIB___SET_VALUE(a->bits,BLACK);\
1594
+ c->leftt = b;\
1595
+ c->rightt = a;\
1596
+ b->rightt = cl;\
1597
+ a->leftt = cr;\
1598
+ res = 0;\
1599
+ }\
1600
+ }\
1601
+ }\
1602
+ }
1603
+
1604
+
1605
+ #define SGLIB_DEFINE_RBTREE_FUNCTIONS_GENERAL(type, left, right, bits, comparator, RED, BLACK) \
1606
+ static void sglib___##type##_fix_left_insertion_discrepancy(type **tree) {\
1607
+ SGLIB___RBTREE_FIX_INSERTION_DISCREPANCY(type, tree, left, right, bits, RED, BLACK);\
1608
+ }\
1609
+ \
1610
+ static void sglib___##type##_fix_right_insertion_discrepancy(type **tree) {\
1611
+ SGLIB___RBTREE_FIX_INSERTION_DISCREPANCY(type, tree, right, left, bits, RED, BLACK);\
1612
+ }\
1613
+ \
1614
+ static int sglib___##type##_fix_left_deletion_discrepancy(type **tree) {\
1615
+ int res;\
1616
+ SGLIB___RBTREE_FIX_DELETION_DISCREPANCY(type, tree, right, left, bits, RED, BLACK, res);\
1617
+ return(res);\
1618
+ }\
1619
+ \
1620
+ static int sglib___##type##_fix_right_deletion_discrepancy(type **tree) {\
1621
+ int res;\
1622
+ SGLIB___RBTREE_FIX_DELETION_DISCREPANCY(type, tree, left, right, bits, RED, BLACK, res);\
1623
+ return(res);\
1624
+ }\
1625
+ \
1626
+ static void sglib___##type##_add_recursive(type **tree, type *elem) {\
1627
+ int cmp;\
1628
+ type *t;\
1629
+ t = *tree;\
1630
+ if (t == NULL) {\
1631
+ SGLIB___SET_VALUE(elem->bits,RED);\
1632
+ *tree =elem;\
1633
+ } else {\
1634
+ cmp = comparator(elem, t);\
1635
+ if (cmp < 0 || (cmp==0 && elem<t)) {\
1636
+ sglib___##type##_add_recursive(&t->left, elem);\
1637
+ if (SGLIB___GET_VALUE(t->bits)==BLACK) sglib___##type##_fix_left_insertion_discrepancy(tree);\
1638
+ } else {\
1639
+ sglib___##type##_add_recursive(&t->right, elem);\
1640
+ if (SGLIB___GET_VALUE(t->bits)==BLACK) sglib___##type##_fix_right_insertion_discrepancy(tree);\
1641
+ }\
1642
+ }\
1643
+ }\
1644
+ \
1645
+ static int sglib___##type##_delete_rightmost_leaf(type **tree, type **theLeaf) {\
1646
+ type *t;\
1647
+ int res, deepDecreased;\
1648
+ t = *tree;\
1649
+ res = 0;\
1650
+ assert(t!=NULL);\
1651
+ if (t->right == NULL) {\
1652
+ *theLeaf = t;\
1653
+ if (t->left!=NULL) {\
1654
+ if (SGLIB___GET_VALUE(t->bits)==BLACK && SGLIB___GET_VALUE(t->left->bits)==BLACK) res = 1;\
1655
+ SGLIB___SET_VALUE(t->left->bits,BLACK);\
1656
+ *tree = t->left;\
1657
+ } else {\
1658
+ *tree = NULL;\
1659
+ res = (SGLIB___GET_VALUE(t->bits)==BLACK);\
1660
+ }\
1661
+ } else {\
1662
+ deepDecreased = sglib___##type##_delete_rightmost_leaf(&t->right, theLeaf);\
1663
+ if (deepDecreased) res = sglib___##type##_fix_right_deletion_discrepancy(tree);\
1664
+ }\
1665
+ return(res);\
1666
+ }\
1667
+ \
1668
+ int sglib___##type##_delete_recursive(type **tree, type *elem) {\
1669
+ type *t, *theLeaf;\
1670
+ int cmp, res, deepDecreased;\
1671
+ t = *tree;\
1672
+ res = 0;\
1673
+ if (t==NULL) {\
1674
+ assert(0 && "The element to delete not found in the tree, use 'delete_if_member'"!=NULL);\
1675
+ } else {\
1676
+ cmp = comparator(elem, t);\
1677
+ if (cmp < 0 || (cmp==0 && elem<t)) {\
1678
+ deepDecreased = sglib___##type##_delete_recursive(&t->left, elem);\
1679
+ if (deepDecreased) {\
1680
+ res = sglib___##type##_fix_left_deletion_discrepancy(tree);\
1681
+ }\
1682
+ } else if (cmp > 0 || (cmp==0 && elem>t)) {\
1683
+ deepDecreased = sglib___##type##_delete_recursive(&t->right, elem);\
1684
+ if (deepDecreased) {\
1685
+ res = sglib___##type##_fix_right_deletion_discrepancy(tree);\
1686
+ }\
1687
+ } else {\
1688
+ assert(elem==t && "Deleting an element which is non member of the tree, use 'delete_if_member'"!=NULL);\
1689
+ if (t->left == NULL) {\
1690
+ if (t->right == NULL) {\
1691
+ /* a leaf, delete, it; */\
1692
+ *tree = NULL;\
1693
+ res = (SGLIB___GET_VALUE(t->bits)==BLACK);\
1694
+ } else {\
1695
+ if (SGLIB___GET_VALUE(t->bits)==0 && SGLIB___GET_VALUE(t->right->bits)==0) res = 1;\
1696
+ SGLIB___SET_VALUE(t->right->bits,BLACK);\
1697
+ *tree = t->right;\
1698
+ }\
1699
+ } else {\
1700
+ /* propagate deletion until righmost leaf of left subtree */\
1701
+ deepDecreased = sglib___##type##_delete_rightmost_leaf(&t->left, &theLeaf);\
1702
+ theLeaf->left = t->left;\
1703
+ theLeaf->right = t->right;\
1704
+ SGLIB___SET_VALUE(theLeaf->bits,SGLIB___GET_VALUE(t->bits));\
1705
+ *tree = theLeaf;\
1706
+ if (deepDecreased) res = sglib___##type##_fix_left_deletion_discrepancy(tree);\
1707
+ }\
1708
+ }\
1709
+ }\
1710
+ return(res);\
1711
+ }\
1712
+ \
1713
+ void sglib_##type##_add(type **tree, type *elem) {\
1714
+ elem->left = elem->right = NULL;\
1715
+ sglib___##type##_add_recursive(tree, elem);\
1716
+ SGLIB___SET_VALUE((*tree)->bits,BLACK);\
1717
+ }\
1718
+ \
1719
+ void sglib_##type##_delete(type **tree, type *elem) {\
1720
+ sglib___##type##_delete_recursive(tree, elem);\
1721
+ if (*tree!=NULL) SGLIB___SET_VALUE((*tree)->bits,BLACK);\
1722
+ }\
1723
+ \
1724
+ type *sglib_##type##_find_member(type *t, type *elem) {\
1725
+ type *res;\
1726
+ SGLIB___BIN_TREE_FIND_MEMBER(type, t, elem, left, right, comparator, res);\
1727
+ return(res);\
1728
+ }\
1729
+ \
1730
+ int sglib_##type##_is_member(type *t, type *elem) {\
1731
+ int cmp;\
1732
+ while (t!=NULL) {\
1733
+ cmp = comparator(elem, t);\
1734
+ if (cmp < 0 || (cmp==0 && elem<t)) {\
1735
+ t = t->left;\
1736
+ } else if (cmp > 0 || (cmp==0 && elem>t)) {\
1737
+ t = t->right;\
1738
+ } else {\
1739
+ assert(t == elem);\
1740
+ return(1);\
1741
+ }\
1742
+ }\
1743
+ return(0);\
1744
+ }\
1745
+ \
1746
+ int sglib_##type##_delete_if_member(type **tree, type *elem, type **memb) {\
1747
+ if ((*memb=sglib_##type##_find_member(*tree, elem))!=NULL) {\
1748
+ sglib_##type##_delete(tree, *memb);\
1749
+ return(1);\
1750
+ } else {\
1751
+ return(0);\
1752
+ }\
1753
+ }\
1754
+ int sglib_##type##_add_if_not_member(type **tree, type *elem, type **memb) {\
1755
+ if ((*memb=sglib_##type##_find_member(*tree, elem))==NULL) {\
1756
+ sglib_##type##_add(tree, elem);\
1757
+ return(1);\
1758
+ } else {\
1759
+ return(0);\
1760
+ }\
1761
+ }\
1762
+ int sglib_##type##_len(type *t) {\
1763
+ int n;\
1764
+ type *e;\
1765
+ n = 0;\
1766
+ SGLIB_BIN_TREE_MAP_ON_ELEMENTS(type, t, e, left, right, n++);\
1767
+ return(n);\
1768
+ }\
1769
+ \
1770
+ void sglib__##type##_it_compute_current_elem(struct sglib_##type##_iterator *it) {\
1771
+ int i,j,cmp;\
1772
+ type *s, *eqt;\
1773
+ int (*subcomparator)(type *, type *);\
1774
+ eqt = it->equalto;\
1775
+ subcomparator = it->subcomparator;\
1776
+ it->currentelem = NULL;\
1777
+ while(it->pathi > 0 && it->currentelem==NULL) {\
1778
+ i = it->pathi-1;\
1779
+ if (i >= 0) {\
1780
+ if (it->pass[i] >= 2) {\
1781
+ /* goto up */\
1782
+ it->pathi --;\
1783
+ } else {\
1784
+ if (it->pass[i] == 0) {\
1785
+ /* goto left */\
1786
+ s = it->path[i]->left;\
1787
+ } else {\
1788
+ /* goto right */\
1789
+ s = it->path[i]->right;\
1790
+ }\
1791
+ if (eqt != NULL) {\
1792
+ if (subcomparator == NULL) {\
1793
+ SGLIB___BIN_TREE_FIND_MEMBER(type, s, eqt, left, right, comparator, s);\
1794
+ } else {\
1795
+ SGLIB___BIN_TREE_FIND_MEMBER(type, s, eqt, left, right, subcomparator, s);\
1796
+ }\
1797
+ }\
1798
+ if (s != NULL) {\
1799
+ j = i+1;\
1800
+ it->path[j] = s;\
1801
+ it->pass[j] = 0;\
1802
+ it->pathi ++;\
1803
+ }\
1804
+ it->pass[i] ++;\
1805
+ }\
1806
+ }\
1807
+ if (it->pathi>0 && it->order == it->pass[it->pathi-1]) {\
1808
+ it->currentelem = it->path[it->pathi-1];\
1809
+ }\
1810
+ }\
1811
+ }\
1812
+ type *sglib__##type##_it_init(struct sglib_##type##_iterator *it, type *tree, int order, int (*subcomparator)(type *, type *), type *equalto) {\
1813
+ type *t;\
1814
+ assert(it!=NULL);\
1815
+ it->order = order;\
1816
+ it->equalto = equalto;\
1817
+ it->subcomparator = subcomparator;\
1818
+ if (equalto == NULL) { \
1819
+ t = tree;\
1820
+ } else {\
1821
+ if (subcomparator == NULL) {\
1822
+ SGLIB___BIN_TREE_FIND_MEMBER(type, tree, equalto, left, right, comparator, t);\
1823
+ } else {\
1824
+ SGLIB___BIN_TREE_FIND_MEMBER(type, tree, equalto, left, right, subcomparator, t);\
1825
+ }\
1826
+ }\
1827
+ if (t == NULL) {\
1828
+ it->pathi = 0;\
1829
+ it->currentelem = NULL;\
1830
+ } else {\
1831
+ it->pathi = 1;\
1832
+ it->pass[0] = 0;\
1833
+ it->path[0] = t;\
1834
+ if (order == 0) {\
1835
+ it->currentelem = t;\
1836
+ } else {\
1837
+ sglib__##type##_it_compute_current_elem(it);\
1838
+ }\
1839
+ }\
1840
+ return(it->currentelem);\
1841
+ }\
1842
+ type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *tree) {\
1843
+ return(sglib__##type##_it_init(it, tree, 2, NULL, NULL));\
1844
+ }\
1845
+ type *sglib_##type##_it_init_preorder(struct sglib_##type##_iterator *it, type *tree) {\
1846
+ return(sglib__##type##_it_init(it, tree, 0, NULL, NULL));\
1847
+ }\
1848
+ type *sglib_##type##_it_init_inorder(struct sglib_##type##_iterator *it, type *tree) {\
1849
+ return(sglib__##type##_it_init(it, tree, 1, NULL, NULL));\
1850
+ }\
1851
+ type *sglib_##type##_it_init_postorder(struct sglib_##type##_iterator *it, type *tree) {\
1852
+ return(sglib__##type##_it_init(it, tree, 2, NULL, NULL));\
1853
+ }\
1854
+ type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *tree, int (*subcomparator)(type *, type *), type *equalto) {\
1855
+ return(sglib__##type##_it_init(it, tree, 1, subcomparator, equalto));\
1856
+ }\
1857
+ type *sglib_##type##_it_current(struct sglib_##type##_iterator *it) {\
1858
+ return(it->currentelem);\
1859
+ }\
1860
+ type *sglib_##type##_it_next(struct sglib_##type##_iterator *it) {\
1861
+ sglib__##type##_it_compute_current_elem(it);\
1862
+ return(it->currentelem);\
1863
+ }\
1864
+ \
1865
+ static void sglib___##type##_consistency_check_recursive(type *t, int *pathdeep, int cdeep) {\
1866
+ if (t==NULL) {\
1867
+ if (*pathdeep < 0) *pathdeep = cdeep;\
1868
+ else assert(*pathdeep == cdeep);\
1869
+ } else {\
1870
+ if (t->left!=NULL) assert(comparator(t->left, t) <= 0);\
1871
+ if (t->right!=NULL) assert(comparator(t, t->right) <= 0);\
1872
+ if (SGLIB___GET_VALUE(t->bits) == RED) {\
1873
+ assert(t->left == NULL || SGLIB___GET_VALUE(t->left->bits)==BLACK);\
1874
+ assert(t->right == NULL || SGLIB___GET_VALUE(t->right->bits)==BLACK);\
1875
+ sglib___##type##_consistency_check_recursive(t->left, pathdeep, cdeep);\
1876
+ sglib___##type##_consistency_check_recursive(t->right, pathdeep, cdeep);\
1877
+ } else {\
1878
+ sglib___##type##_consistency_check_recursive(t->left, pathdeep, cdeep+1);\
1879
+ sglib___##type##_consistency_check_recursive(t->right, pathdeep, cdeep+1);\
1880
+ }\
1881
+ }\
1882
+ }\
1883
+ \
1884
+ void sglib___##type##_consistency_check(type *t) {\
1885
+ int pathDeep;\
1886
+ assert(t==NULL || SGLIB___GET_VALUE(t->bits) == BLACK);\
1887
+ pathDeep = -1;\
1888
+ sglib___##type##_consistency_check_recursive(t, &pathDeep, 0);\
1889
+ }
1890
+
1891
+
1892
+ #define SGLIB_DEFINE_RBTREE_PROTOTYPES(type, left, right, colorbit, comparator) \
1893
+ struct sglib_##type##_iterator {\
1894
+ type *currentelem;\
1895
+ char pass[SGLIB_MAX_TREE_DEEP];\
1896
+ type *path[SGLIB_MAX_TREE_DEEP];\
1897
+ short int pathi;\
1898
+ short int order;\
1899
+ type *equalto;\
1900
+ int (*subcomparator)(type *, type *);\
1901
+ };\
1902
+ extern void sglib___##type##_consistency_check(type *t); \
1903
+ extern void sglib_##type##_add(type **tree, type *elem); \
1904
+ extern int sglib_##type##_add_if_not_member(type **tree, type *elem, type **memb); \
1905
+ extern void sglib_##type##_delete(type **tree, type *elem); \
1906
+ extern int sglib_##type##_delete_if_member(type **tree, type *elem, type **memb); \
1907
+ extern int sglib_##type##_is_member(type *t, type *elem); \
1908
+ extern type *sglib_##type##_find_member(type *t, type *elem); \
1909
+ extern int sglib_##type##_len(type *t); \
1910
+ extern type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *tree); \
1911
+ extern type *sglib_##type##_it_init_preorder(struct sglib_##type##_iterator *it, type *tree); \
1912
+ extern type *sglib_##type##_it_init_inorder(struct sglib_##type##_iterator *it, type *tree); \
1913
+ extern type *sglib_##type##_it_init_postorder(struct sglib_##type##_iterator *it, type *tree); \
1914
+ extern type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *tree, int (*subcomparator)(type *, type *), type *equalto); \
1915
+ extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \
1916
+ extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it); \
1917
+
1918
+
1919
+ #define SGLIB_DEFINE_RBTREE_FUNCTIONS(type, left, right, colorbit, comparator) \
1920
+ SGLIB_DEFINE_RBTREE_FUNCTIONS_GENERAL(type, left, right, colorbit, comparator, 1, 0)
1921
+
1922
+
1923
+
1924
+ /* ---------------------------------------------------------------------------- */
1925
+ /* ---------------------------------------------------------------------------- */
1926
+ /* - SUPPLEMENTARY DEFINITIONS - */
1927
+ /* ---------------------------------------------------------------------------- */
1928
+ /* ---------------------------------------------------------------------------- */
1929
+
1930
+
1931
+ #define SGLIB___GET_VALUE(x) (x)
1932
+ #define SGLIB___SET_VALUE(x, value) {(x) = (value);}
1933
+ #define SGLIB_ARRAY_ELEMENTS_EXCHANGER(type, a, i, j) {type _sgl_aee_tmp_; _sgl_aee_tmp_=(a)[(i)]; (a)[(i)]=(a)[(j)]; (a)[(j)]= _sgl_aee_tmp_;}
1934
+
1935
+
1936
+ #define SGLIB_SAFE_NUMERIC_COMPARATOR(x, y) (((x)>(y)?1:((x)<(y)?-1:0)))
1937
+ #define SGLIB_SAFE_REVERSE_NUMERIC_COMPARATOR(x, y) (((x)>(y)?-1:((x)<(y)?1:0)))
1938
+ #define SGLIB_FAST_NUMERIC_COMPARATOR(x, y) ((int)((x) - (y)))
1939
+ #define SGLIB_FAST_REVERSE_NUMERIC_COMPARATOR(x, y) ((int)((y) - (x)))
1940
+ #define SGLIB_NUMERIC_COMPARATOR(x, y) SGLIB_SAFE_NUMERIC_COMPARATOR(x, y)
1941
+ #define SGLIB_REVERSE_NUMERIC_COMPARATOR(x, y) SGLIB_SAFE_REVERSE_NUMERIC_COMPARATOR(x, y)
1942
+
1943
+ #ifndef SGLIB_MAX_TREE_DEEP
1944
+ #define SGLIB_MAX_TREE_DEEP 128
1945
+ #endif
1946
+
1947
+ #ifndef SGLIB_HASH_TAB_SHIFT_CONSTANT
1948
+ #define SGLIB_HASH_TAB_SHIFT_CONSTANT 16381 /* should be a prime */
1949
+ /* #define SGLIB_HASH_TAB_SHIFT_CONSTANT 536870912*/ /* for large tables :) */
1950
+ #endif
1951
+
1952
+ #endif /* _SGLIB__h_ */