#include "copy.h"
void rbdo(int nr, string fp)
{
ton(tr); ALLOCATED = 0;
getkeys(fp);
for (REP = 0; REP < nr; ++REP)
{
ton(tx);
TAILSIZE = NODES = BINS = NULLBINS = 0;
MAXALLOCATED = ALLOCATED;
listinputs();
ton(ti);
rbs(INBUF);
}
--INBUF; FREE(INBUF, MAXBYTES + 1); ton(0);
}
void rbs(string ib)
{
NODE1 *rt;
rt = GETNODE(NODE1); ++NODES;
if (SAMPLERATE)
{
ton(ts); rsample(ib, rt, NKEYS / SAMPLERATE);
clear(rt);
ton(ti);
}
radd(ib, NKEYS, rt);
UPDATEMEM; FREEBURSTS = 0; ton(tc);
rtraverse(rt); UPDATEMEM;
if (WRITEFILE)
{
ton(tw); savetrie(rt, OUTPUTDIR, DATANAME);
}
ton(tk); rkill(rt);
}
void rsample(string b0, NODE1 *rt, int n)
{
NODE1 *t; NODE1 *bn;
int ct;
unsigned char c;
string b, s, lim;
srand(clock());
lim = b0 + NBYTES;
while (n--)
{
b = b0 + rand() % (NBYTES);
while (*b) --b; ++b;
bn = rt + (c = *b++);
while (bn != NULL && bn->ct == -1)
{
t = (NODE1*) bn->bp;
bn = t + (c = *b++);
}
if (c == 0) continue;
ct = ++bn->ct;
if (ct == 1)
{
++BINS;
s = bn->bp = (string) MALLOC(BINSIZE0);
bn->lp = s + LIMSIZE0;
while ((*s++ = *b++) != 0) ;
bn->ap = s;
}
else
{
s = bn->ap;
while ((*s++ = *b++) != 0) ;
bn->ap = s;
if (s > bn->lp) samburst(bn);
}
}
}
void radd(string b, int n, NODE1 *rt)
{
NODE1 *bn, *nd;
string rp, s, t, bp, ap, lp;
int c, ct, sz, sz2;
while (n--)
{
rp = b;
bn = rt + (c = *b++);
while (bn != NULL && bn->ct == -1)
{
nd = (NODE1*) bn->bp;
bn = nd + (c = *b++);
}
ct = ++bn->ct;
if (c == 0)
{
if (ct == 1)
{
++NULLBINS;
s = bn->bp = (string) MALLOC(BINSIZE0);
bn->lp = s + BINSIZE0;
RP(s) = rp;
bn->ap = s + RPSIZE;
}
else
{
RP(bn->ap) = rp;
s = bn->ap += RPSIZE;
if (s == bn->lp)
{
sz = s - bn->bp;
sz2 = sz<<1; ALLOCATED += sz;
bp = bn->bp = (string)realloc(bn->bp, sz2);
bn->lp = bp + sz2;
bn->ap = bp + sz;
}
}
}
else
{
if ((bp = bn->bp) == NULL)
{
++BINS;
s = bn->bp = (string) MALLOC(BINSIZE0);
bn->lp = s + LIMSIZE0;
RP(s) = rp; s += RPSIZE;
while ((*s++ = *b++) != 0) ;
bn->ap = s;
}
else
{
s = bn->ap;
RP(s) = rp; s += RPSIZE;
while ((*s++ = *b++) != 0) ;
bn->ap = s;
if (s >= (lp = bn->lp))
{
sz = lp + MAXKEYLEN - bp;
if (FREEBURSTS > 0 || sz == CACHESIZE)
{
ton(tb); rburst(bn);
}
else
{
ton(tg);
sz2 = sz<<1; ALLOCATED += sz;
ap = bn->bp = (string) malloc(sz2);
bn->lp = ap + sz2 - MAXKEYLEN;
t = bp; while (t < s) *ap++ = *t++;
free(bp); bn->ap = ap;
}
ton(ti);
}
}
}
}
}
void rburst(NODE1 *bn)
{
NODE1 *rt, *nd;
string b, b0, s, t, bp, ap, lp, rp;
int c, ct, n, nc, nn, sz0, sz, sz2;
nc = BINS; nn = NULLBINS;
do
{
b = b0 = bn->bp;
sz0 = bn->lp + MAXKEYLEN - b; n = bn->ct;
bn->ct = -1;
rt = GETNODE(NODE1); ++NODES;
bn->bp = (string) rt;
while (n--)
{
rp = RP(b); b += RPSIZE;
bn = rt + (c = *b++);
while (bn != NULL && bn->ct == -1)
{
nd = (NODE1*) bn->bp;
bn = nd + (c = *b++);
}
ct = ++bn->ct;
if (c == 0)
{
if (ct == 1)
{
++NULLBINS;
s = bn->bp = (string) MALLOC(BINSIZE0);
bn->lp = s + BINSIZE0;
RP(s) = rp; bn->ap = s + RPSIZE;
}
else
{
s = bn->ap;
RP(s) = rp; s += RPSIZE;
bn->ap = s;
if (s == bn->lp)
{
sz = s - bn->bp;
sz2 = sz<<1; ALLOCATED += sz;
bp = bn->bp = (string)realloc(bn->bp, sz2);
bn->lp = bp + sz2; bn->ap = bp + sz;
}
}
}
else
{
if ((bp = bn->bp) == NULL)
{
++BINS;
s = bn->bp = (string) MALLOC(BINSIZE0);
bn->lp = s + LIMSIZE0;
RP(s) = rp; s += RPSIZE;
while ((*s++ = *b++) != 0) ;
bn->ap = s;
}
else
{
s = bn->ap;
RP(s) = rp; s += RPSIZE;
while ((*s++ = *b++) != 0) ;
bn->ap = s;
if (s >= (lp = bn->lp))
{
sz = lp + MAXKEYLEN - bp;
sz2 = sz<<1; ALLOCATED += sz;
ap = bn->bp = (string) malloc(sz2);
bn->lp = ap + sz2 - MAXKEYLEN;
t = bp; while (t < s) *ap++ = *t++;
free(bp); bn->ap = ap;
}
}
}
}
UPDATEMEM; FREE(b0, sz0); --BINS;
} while (BINS == nc && NULLBINS == nn);
--FREEBURSTS;
}
void rtraverse(NODE1 *nd)
{
int c, ct, tpsz;
NODE1 *bn;
string s, bp, ap, *tp, *tp0;
for (c = LOCHAR; c <= HICHAR; ++c)
{
bn = nd + c;
if (bn != NULL && (ct = bn->ct) == -1) rtraverse((NODE1*) bn->bp);
if (ct < 1) continue;
tpsz = ct * sizeof(string*);
s = bp = bn->bp; ap = bn->ap;
if (ap + tpsz > bp + CACHESIZE)
{
ton(tb); rburst(bn);
ton(tc); rtraverse((NODE1*) bn->bp);
continue;
}
tp = tp0 = (string*) MALLOC(tpsz);
bn->ap = (string) tp0;
while (s < ap)
{
s += RPSIZE;
*tp++ = s;
while (*s++) ;
}
if (ct > 1) mkqsorts(tp0, ct, 0);
for (tp = tp0; ct-- > 0; ++tp) *tp = RP(*tp - RPSIZE);
UPDATEMEM; ALLOCATED -= (MAXKEYLEN + bn->lp - bp);
free(bp); --BINS;
}
}
void rkill(NODE1 *nd)
{
int c, ct;
NODE1 *bn;
for (c = LOCHAR; c <= HICHAR; ++c)
{
bn = nd + c;
if (bn != NULL && (ct = bn->ct) == -1) rkill((NODE1*) bn->bp);
else if (ct)
{
FREE(bn->ap, bn->ct * sizeof(string*));
}
}
if (nd->ct)
{
--NULLBINS;
FREE(nd->bp, nd->lp-nd->bp);
}
FREE(nd, 256*sizeof(NODE1)); --NODES;
}
void savetrie(NODE1 *nd, const char* path, const char* dset)
{
FILE *f;
char* s;
if ((f = fopen(s = fp(path, dset, "cp-burstsort"), "w+")) == NULL)
{
say("could not open "); brp(s);
}
else
{
puttrie(nd, f);
fflush(f);
fclose(f);
}
}
void puttrie(NODE1 *nd, FILE *f)
{
int ct, c; string *tp; NODE1 *bn;
ct = nd->ct;
tp = (string*) nd->bp;
while (ct--)
{
fputs((char*)*tp++, f);
fputc('\n', f);
}
for (c = LOCHAR; c <= HICHAR; ++c)
{
bn = nd + c;
if (bn != NULL && (ct = bn->ct) == -1)
puttrie((NODE1*) bn->bp, f);
else if (ct)
{
tp = (string*) bn->ap;
while (ct--)
{
fputs((char*)*tp++, f);
fputc('\n', f);
}
}
}
}
string* puttrie_strout;
void tb_puttrie(NODE1 *nd)
{
int ct, c; string *tp; NODE1 *bn;
ct = nd->ct;
tp = (string*) nd->bp;
while (ct--)
{
*puttrie_strout++ = *tp++;
}
for (c = LOCHAR; c <= HICHAR; ++c)
{
bn = nd + c;
if (bn != NULL && (ct = bn->ct) == -1)
tb_puttrie((NODE1*) bn->bp);
else if (ct)
{
tp = (string*) bn->ap;
while (ct--)
{
*puttrie_strout++ = *tp++;
}
}
}
}
void tb_savetrie(NODE1 *nd, string* strout)
{
puttrie_strout = strout;
tb_puttrie(nd);
}
void inssorts(string *tp, int n, int d)
{
string *rp, *lp, ls, rs, rd, ld;
for (rp = tp + 1; --n > 0; ++rp)
{
for (rs = *rp, lp = rp; lp > tp; --lp)
{
ls = *(lp - 1);
rd = rs + d;
ld = ls + d;
while (*ld == *rd && *rd != 0)
{
++ld; ++rd;
}
if (*rd < *ld || (*rd == 0 && rs < ls))
*lp = ls;
else
break;
}
*lp = rs;
}
}
void stabilize(string *tp, int n)
{
int n1, n2, n3;
string *l, *m, *r, pv, t;
if (n < 13)
{
for (r = tp + 1; --n > 0; ++r)
{
pv = *r;
for (l = r; l > tp; --l)
{
t = *(l - 1);
if (pv < t) *l = t;
else
break;
}
*l = pv;
}
return;
}
n1 = n>>1; n2 = n1>>1; n3 = n2>>1;
l = tp; m = tp + n1; r = tp + n - 1;
if (n > 31)
{
l = med3s(l, l + n3, l + n2);
m = med3s(m - n3, m, m + n3);
r = med3s(r - n2, r - n3, r);
}
m = med3s(l, m, r);
PSWAP(tp, m, t);
pv = *tp;
l = tp + 1; r = tp + n - 1;
for (;;)
{
while (l <= r && *l < pv) ++l;
while (l <= r && *r > pv) --r;
if (l > r)
break;
PSWAP(l, r, t);
++l; --r;
}
PSWAP(tp, r, t);
--r; n1 = l - tp; n2 = n - n1;
if (n1 > 1)
stabilize(tp, n1);
if (n2 > 1)
stabilize(tp + n1, n2);
}
void mkqsorts(string *tp, int n, int d)
{
int k, nl, ne, nr, pv;
string *ol, *il, *ir, *_or, *l, *m, *r, t;
if (n < 13)
{
inssorts(tp, n, d);
return;
}
l = tp; m = tp + (n>>1); r = tp + n - 1;
if (n > 31)
{
k = n>>3;
l = med3(l, l + k, l + k * 2, d);
m = med3(m - k, m, m + k, d);
r = med3(r - k * 2, r - k, r, d);
}
m = med3(l, m, r, d);
PSWAP(tp, m, t);
pv=P2C(tp, d);
r = tp + n; ol = il =tp + 1; ir = _or = r - 1;
while (il <= ir && P2C(il, d) == pv)
{
++ol; ++il;
}
while (il <= ir && P2C(ir, d) == pv)
{
--_or; --ir;
}
for (;;)
{
while (il <= ir && (k = P2C(il, d) - pv) <= 0)
{
if (k == 0)
{
PSWAP(ol, il, t); ++ol;
}
++il;
}
while (il <= ir && (k = P2C(ir, d) - pv) >= 0)
{
if (k == 0)
{
PSWAP(ir, _or, t); --_or;
}
--ir;
}
if (il > ir)
break;
PSWAP(il, ir, t);
++il; --ir;
}
nl = il - ol; nr = _or - ir; ne = n - (nl + nr);
k = MIN(ol - tp, nl);
vswap(tp, il - k, k);
k = MIN(nr, r - _or - 1);
vswap(r - k, il, k);
if (ne > 1)
{
if (pv == 0)
stabilize(tp + nl, ne);
else
mkqsorts(tp + nl, ne, d + 1);
}
if (nl > 1)
mkqsorts(tp, nl, d);
if (nr > 1)
mkqsorts(r - nr, nr, d);
}