Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/librecsort/rs-rasp.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1996-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Phong Vo <[email protected]> *
18
* Glenn Fowler <[email protected]> *
19
* *
20
***********************************************************************/
21
/* Radix + splay tree
22
** Strategy:
23
** 1. Records are partitioned by first bytes.
24
** 2. Short records are sorted by a radix sort.
25
** 3. Long records are sorted in splay trees.
26
** 4. A final merge phase put things back together.
27
**
28
** Written by Kiem-Phong Vo (07/08/96).
29
*/
30
31
#include "rshdr.h"
32
33
#define SLOT SIZEOF_LONG
34
#define PREFIX (SLOT + 1)
35
36
typedef struct rsrasp_s
37
{ Rsobj_t* empty;
38
Rsobj_t* slot[SLOT][UCHAR_MAX+1];
39
Rsobj_t* tree[UCHAR_MAX+1];
40
} Rsrasp_t;
41
42
#define SPLAYCMP(one,two,o,t,endo,mp,cr) \
43
{ if(one->order != two->order) \
44
cr = one->order < two->order ? -1 : 1; \
45
else \
46
{ if((mp = (cr = one->keylen) - two->keylen) > 0) cr -= mp; \
47
o = one->key+PREFIX; t = two->key+PREFIX; \
48
for(endo = one->key+cr;; ) \
49
{ if(o >= endo) { cr = mp; break; } \
50
else if((cr = (int)*o++ - (int)*t++)) break; \
51
} \
52
} \
53
}
54
55
#if __STD_C
56
static int raspinsert(Rs_t* rs, reg Rsobj_t* obj)
57
#else
58
static int raspinsert(rs, obj)
59
Rs_t* rs;
60
reg Rsobj_t* obj;
61
#endif
62
{
63
reg ssize_t cr, mp;
64
reg uchar *o, *k;
65
reg Rsobj_t *r, *root, *t, *l;
66
reg uchar* endo;
67
reg int index;
68
Rsobj_t link;
69
reg Rsrasp_t* rasp = (Rsrasp_t*)rs->methdata;
70
71
obj->equal = NIL(Rsobj_t*);
72
73
if((cr = obj->keylen) == 0)
74
{ if((r = rasp->empty) )
75
{ EQUAL(r,obj,t); }
76
else rasp->empty = obj;
77
return 0;
78
}
79
80
index = *(k = obj->key);
81
82
if(cr == 1)
83
{ if((r = rasp->slot[0][index]) )
84
{ EQUAL(r,obj,t); }
85
else rasp->slot[0][index] = obj;
86
return 0;
87
}
88
else if((cr -= 1) < SLOT)
89
{ if((r = rasp->slot[cr][index]) )
90
r->left->right = obj;
91
else r = rasp->slot[cr][index] = obj;
92
r->left = obj;
93
return 0;
94
}
95
96
#if SIZEOF_LONG == 8
97
obj->order = (((ulong)k[1]) << (CHAR_BIT*7)) |
98
(((ulong)k[2]) << (CHAR_BIT*6)) |
99
(((ulong)k[3]) << (CHAR_BIT*5)) |
100
(((ulong)k[4]) << (CHAR_BIT*4)) |
101
(((ulong)k[5]) << (CHAR_BIT*3)) |
102
(((ulong)k[6]) << (CHAR_BIT*2)) |
103
(((ulong)k[7]) << (CHAR_BIT*1)) |
104
(((ulong)k[8]) << (CHAR_BIT*0)) ;
105
#else /* sizeof(long) == 4 */
106
obj->order = (k[1] << (CHAR_BIT*3)) | (k[2] << (CHAR_BIT*2)) |
107
(k[3] << (CHAR_BIT*1)) | (k[4] << (CHAR_BIT*0)) ;
108
#endif
109
110
if(!(root = rasp->tree[index]))
111
{ rasp->tree[index] = obj;
112
obj->left = obj->right = NIL(Rsobj_t*);
113
return 0;
114
}
115
116
SPLAYCMP(obj,root,o,k,endo,mp,cr);
117
if(cr == 0)
118
{ EQUAL(root,obj,t);
119
return 0;
120
}
121
122
for(l = r = &link;; )
123
{ if(cr < 0)
124
{ if((t = root->left))
125
{ SPLAYCMP(obj,t,o,k,endo,mp,cr);
126
if(cr < 0)
127
{ RROTATE(root,t);
128
RLINK(r,root);
129
if(!(root = root->left))
130
goto no_root;
131
}
132
else if(cr == 0)
133
{ RROTATE(root,t);
134
goto has_root;
135
}
136
else
137
{ LLINK(l,t);
138
RLINK(r,root);
139
if(!(root = t->right))
140
goto no_root;
141
}
142
}
143
else
144
{ RLINK(r,root);
145
goto no_root;
146
}
147
}
148
else /*if(cr > 0)*/
149
{ if((t = root->right))
150
{ SPLAYCMP(obj,t,o,k,endo,mp,cr);
151
if(cr > 0)
152
{ LROTATE(root,t);
153
LLINK(l,root);
154
if(!(root = root->right))
155
goto no_root;
156
}
157
else if(cr == 0)
158
{ LROTATE(root,t);
159
goto has_root;
160
}
161
else
162
{ RLINK(r,t);
163
LLINK(l,root);
164
if(!(root = t->left))
165
goto no_root;
166
}
167
}
168
else
169
{ LLINK(l,root);
170
goto no_root;
171
}
172
}
173
SPLAYCMP(obj,root,o,k,endo,mp,cr);
174
if(cr == 0)
175
goto has_root;
176
}
177
178
has_root:
179
EQUAL(root,obj,t);
180
181
l->right = root->left;
182
r->left = root->right;
183
184
root->left = link.right;
185
root->right = link.left;
186
rasp->tree[index] = root;
187
return 0;
188
189
no_root:
190
l->right = NIL(Rsobj_t*);
191
r->left = NIL(Rsobj_t*);
192
193
obj->left = link.right;
194
obj->right = link.left;
195
rasp->tree[index] = obj;
196
return 0;
197
}
198
199
#if __STD_C
200
static Rsobj_t* radix(Rsobj_t* list)
201
#else
202
static Rsobj_t* radix(list)
203
Rsobj_t* list;
204
#endif
205
{
206
reg Rsobj_t *work, *r;
207
reg ssize_t ph;
208
reg Rsobj_t **bin, *t, *endl, *next, **lo, **maxpart;
209
reg ssize_t n, maxph;
210
Rsobj_t *part[UCHAR_MAX+1];
211
212
for(lo = part, maxpart = part + UCHAR_MAX+1; lo < maxpart; ++lo)
213
*lo = NIL(Rsobj_t*);
214
215
work = list; list = NIL(Rsobj_t*);
216
work->left->right = NIL(Rsobj_t*);
217
maxph = work->keylen-1;
218
219
for(work->order = 1; work; )
220
{ next = work->left->right; work->left->right = NIL(Rsobj_t*);
221
222
lo = maxpart; n = 0;
223
if((ph = (ssize_t)work->order) == maxph)
224
{ for(; work; work = work->right)
225
{ bin = part + work->key[ph];
226
if(!(r = *bin) )
227
{ *bin = work;
228
if(lo > bin)
229
lo = bin;
230
n += 1;
231
}
232
else EQUAL(r,work,t);
233
}
234
235
if(list)
236
endl = (endl->right = *lo);
237
else endl = (list = *lo);
238
*lo = NIL(Rsobj_t*);
239
for(bin = lo+1, n -= 1; n > 0; ++bin)
240
{ if((r = *bin) )
241
{ n -= 1;
242
endl = (endl->right = r);
243
*bin = NIL(Rsobj_t*);
244
}
245
}
246
247
work = next;
248
}
249
else
250
{ for(; work; work = work->right)
251
{ bin = part + work->key[ph];
252
if((r = *bin) )
253
r->left->right = work;
254
else
255
{ r = *bin = work;
256
if(lo > bin)
257
lo = bin;
258
n += 1;
259
}
260
r->left = work;
261
}
262
263
ph += 1;
264
work = *lo; t = work->left; *lo = NIL(Rsobj_t*);
265
work->order = ph;
266
for(bin = lo+1, n -= 1; n > 0; ++bin)
267
{ if((r = *bin) )
268
{ n -= 1;
269
270
r->order = ph;
271
t->right = r;
272
t = r->left;
273
274
*bin = NIL(Rsobj_t*);
275
}
276
}
277
278
t->right = next;
279
}
280
281
if(work && work->left == work)
282
{ if(list)
283
endl = (endl->right = work);
284
else endl = (list = work);
285
for(work = work->right; work; work = work->right)
286
{ if(work->left != work)
287
break;
288
endl = (endl->right = work);
289
}
290
}
291
}
292
293
list->left = endl;
294
return list;
295
}
296
297
#define CHARCMP(k1,k2,v,i) (v = (int)k1[i] - (int)k2[i])
298
#define STRNCMP(k1,k2,v,i,n) \
299
{ if(CHARCMP(k1,k2,v,1) == 0) \
300
{ for(i = 2; i <= n; ++i) \
301
if(CHARCMP(k1,k2,v,i) != 0) \
302
break; \
303
} \
304
}
305
306
#if __STD_C
307
static Rsobj_t* listmerge(reg Rsobj_t* one, reg Rsobj_t* two, reg int n)
308
#else
309
static Rsobj_t* listmerge(one, two, n)
310
reg Rsobj_t* one;
311
reg Rsobj_t* two;
312
reg int n; /* number of bytes to compare */
313
#endif
314
{
315
reg int v, i;
316
reg uchar *k1, *k2;
317
reg Rsobj_t *list, *endl, *endone, *endtwo;
318
319
endone = one->left; one->left->right = NIL(Rsobj_t*);
320
endtwo = two->left; two->left->right = NIL(Rsobj_t*);
321
322
k1 = one->key; k2 = two->key;
323
STRNCMP(k1,k2,v,i,n);
324
if(v <= 0)
325
{ list = endl = one;
326
if((one = one->right) )
327
k1 = one->key;
328
}
329
else
330
{ list = endl = two;
331
if((two = two->right) )
332
k2 = two->key;
333
}
334
335
if(one && two)
336
{ for(;;)
337
{ STRNCMP(k1,k2,v,i,n);
338
if(v <= 0)
339
{ endl = (endl->right = one);
340
341
if((one = one->right) )
342
k1 = one->key;
343
else break;
344
}
345
else
346
{ endl = (endl->right = two);
347
348
if((two = two->right) )
349
k2 = two->key;
350
else break;
351
}
352
}
353
}
354
355
if(one)
356
{ endl->right = one;
357
endl = endone;
358
}
359
else if(two)
360
{ endl->right = two;
361
endl = endtwo;
362
}
363
364
list->left = endl;
365
return list;
366
}
367
368
#if __STD_C
369
static Rsobj_t* flatten(reg Rsobj_t* r)
370
#else
371
static Rsobj_t* flatten(r)
372
reg Rsobj_t* r;
373
#endif
374
{ reg Rsobj_t *t, *p, *list;
375
376
/* find smallest element and make it head of list */
377
while((t = r->left) )
378
RROTATE(r,t);
379
380
/* flatten tree */
381
for(list = p = r, r = r->right;; p = r, r = r->right)
382
{ if(!r)
383
{ list->left = p;
384
return list;
385
}
386
else if((t = r->left) )
387
{ do RROTATE(r,t);
388
while((t = r->left) );
389
390
p->right = r;
391
}
392
}
393
}
394
395
#if __STD_C
396
static Rsobj_t* rasplist(Rs_t* rs)
397
#else
398
static Rsobj_t* rasplist(rs)
399
Rs_t* rs;
400
#endif
401
{
402
reg Rsobj_t *r, *t, *list, *endl;
403
reg int n, e;
404
reg Rsrasp_t* rasp = (Rsrasp_t*)rs->methdata;
405
406
list = endl = rasp->empty; rasp->empty = NIL(Rsobj_t*);
407
408
for(n = 0, t = NIL(Rsobj_t*); n <= UCHAR_MAX; ++n)
409
{
410
if((r = rasp->tree[n]) )
411
{ t = flatten(r);
412
rasp->tree[n] = NIL(Rsobj_t*);
413
}
414
415
for(e = SLOT-1; e > 0; --e)
416
{ if(!(r = rasp->slot[e][n]) )
417
continue;
418
419
r = radix(r);
420
t = t ? listmerge(r,t,e) : r;
421
422
rasp->slot[e][n] = NIL(Rsobj_t*);
423
}
424
425
if((r = rasp->slot[0][n]) )
426
{ if((r->right = t) )
427
r->left = t->left;
428
else r->left = r;
429
t = r;
430
431
rasp->slot[0][n] = NIL(Rsobj_t*);
432
}
433
434
if(t)
435
{ if(list)
436
endl->right = t;
437
else list = t;
438
endl = t->left;
439
440
t = NIL(Rsobj_t*);
441
}
442
}
443
444
if(list)
445
{ list->left = endl;
446
endl->right = NIL(Rsobj_t*);
447
}
448
449
return list;
450
}
451
452
/* public method */
453
static Rsmethod_t _Rsrasp =
454
{ raspinsert,
455
rasplist,
456
sizeof(Rsrasp_t),
457
RS_MTRASP,
458
"rasp",
459
"Initial radix split into a forest of splay trees."
460
};
461
462
__DEFINE__(Rsmethod_t*, Rsrasp, &_Rsrasp);
463
464
#ifdef NoF
465
NoF(rsrasp)
466
#endif
467
468