#include "copy.h"
void pbdo(int nr, string fp)
{
int lv, sz;
double d;
ton(tr); ALLOCATED = 0;
getkeys(fp);
for (REP = 0; REP < nr; ++REP)
{
ton(tx);
d = TAILRATE; d /= 100;
d *= NBYTES; d /= NKEYS;
TAILSIZE = MIN(d, TAILSIZE0);
TAILSIZE4 = TAILSIZE + RPSIZE;
lv = 0; sz = BINSIZE0;
while (sz < CACHESIZE)
{
THR[lv] = sz / TAILSIZE4;
sz *= 2;
++lv;
}
THR[lv] = CACHESIZE / (TAILSIZE + 8);
NODES = BINS = NULLBINS = 0;
MAXALLOCATED = ALLOCATED;
listinputs();
ton(ti); pbs(INBUF);
}
--INBUF; FREE(INBUF, MAXBYTES + 1);
ton(0);
}
void pbs(string ib)
{
NODE2 *rt;
rt = GETNODE(NODE2); ++NODES;
if (SAMPLERATE)
{
ton(ts);
psample(ib, rt, NKEYS / SAMPLERATE);
pclear(rt);
ton(ti);
}
padd(ib, NKEYS, rt);
UPDATEMEM; FREEBURSTS = 0; ton(tc);
ptraverse(rt); UPDATEMEM;
if (WRITEFILE)
{
ton(tw); psavetrie(rt, OUTPUTDIR, DATANAME);
}
ton(tk); pkill(rt);
}
void psample(string b0, NODE2 *rt, int n)
{
NODE2 *t; NODE2 *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->lv == -1)
{
t = (NODE2*) bn->bp;
bn = t + (c = *b++);
}
if (!c) continue;
ct = ++bn->ct;
if (ct == 1)
{
++BINS;
s = bn->bp = (string) MALLOC(BINSIZE0);
while ((*s++ = *b++) != 0) ;
bn->ap = s;
}
else
{
s=bn->ap;
while ((*s++ = *b++) !=0 ) ;
bn->ap = s;
if (s + MAXKEYLEN > bn->bp + BINSIZE0)
psamburst(bn);
}
}
}
void psamburst(NODE2 *bn)
{
string b0, b, s; NODE2 *rt; int ct, n; unsigned char c;
rt = GETNODE(NODE2); ++NODES;
b = b0 = bn->bp;
bn->bp = (string) rt;
n = bn->ct;
bn->lv = -1;
while (n--)
{
bn = rt + (c = *b++);
if (c == 0) continue; ct = ++bn->ct;
if (ct == 1)
{
++BINS; s = bn->bp = (string) MALLOC (BINSIZE0);
while ((*s++ = *b++) != 0) ; bn->ap = s;
}
else
{
s = bn->ap;
while ((*s++ = *b++) != 0) ;
bn->ap = s;
if (s + MAXKEYLEN > bn->bp + BINSIZE0)
psamburst(bn);
}
}
UPDATEMEM; ALLOCATED -= BINSIZE0; free(b0); --BINS;
}
void pclear(NODE2 *nd)
{
int c;
NODE2 *bn;
for (c = LOCHAR; c <= HICHAR; ++c)
{
bn = nd + c;
if (bn != NULL && bn->lv == -1) pclear((NODE2*) bn->bp);
else if (bn->ct)
{
bn->ap = bn->bp; bn->ct = 0;
}
}
}
void padd(string b, int n, NODE2 *rt) {
NODE2 *bn, *nd; string rp, s, bp, ap, t;
int ct, lv, sz; unsigned char c;
while (n--)
{
rp = b;
bn = rt + (c = *b++);
while (bn != NULL && bn->lv == -1) {
nd = (NODE2*) bn->bp;
bn = nd + (c = *b++);
}
ct=++bn->ct;
if (c == 0)
{
if (ct == 1)
{
++NULLBINS;
s = bn->bp = (string) MALLOC(BINSIZE0);
RP(s) = rp; bn->ap = s + RPSIZE;
}
else
{
RP(bn->ap) = rp;
bn->ap += RPSIZE;
sz = BINSIZE0<<bn->lv;
if (ct * sizeof(string*) == sz)
{
bp = bn->bp = (string)realloc(bn->bp, sz<<1);
ALLOCATED += sz; ++bn->lv; bn->ap = bp + sz;
}
}
}
else
{
if ((bp = bn->bp)==NULL) {
++BINS;
s = bn->bp = (string) MALLOC(BINSIZE0);
ap = bn->ap = s + TAILSIZE4;
RP(s) = b; s += RPSIZE;
do {*s++ = c = *b++;} while (c > 0 && s < ap);
}
else
{
s = bn->ap;
ap = bn->ap += TAILSIZE4;
RP(s) = b; s += RPSIZE;
do {*s++ = c = *b++;} while (c > 0 && s < ap);
if (ct == THR[lv = bn->lv])
{
sz = BINSIZE0<<lv;
if (FREEBURSTS > 0 || sz == CACHESIZE)
{
ton(tb); pburst(bn);
} else {
ton(tg);
s = bn->bp = (string) malloc(sz<<1);
ALLOCATED += sz; ++bn->lv;
t = bp; while (t < ap) *s++ = *t++;
free(bp); bn->ap=s;
}
ton(ti);
}
}
if (c) while (*b++) ;
}
}
}
void pburst(NODE2 *bn) {
NODE2 *rt; string b, b0, b1, rp, s, bp, ap, t;
int c, ct, lv, n, nc, nn, sz, sz0;
nc=BINS; nn=NULLBINS;
do
{
b1 = b0 = bn->bp;
sz0 = BINSIZE0<<bn->lv; n = bn->ct;
bn->lv = -1;
rt = GETNODE(NODE2); ++NODES;
bn->bp = (string) rt;
while (n-->0)
{
rp = RP(b1);
c = *(b1 + RPSIZE);
b1 += TAILSIZE4;
if (c == 0)
{
rp = allof(rp);
ct = ++rt->ct;
if (ct == 1)
{
++NULLBINS;
s = rt->bp = (string) MALLOC(BINSIZE0);
RP(s) = rp;
rt->ap = s + RPSIZE;
}
else
{
RP(rt->ap) = rp;
rt->ap += RPSIZE;
sz = BINSIZE0<<rt->lv;
if (ct * sizeof(string*) == sz)
{
rt->ap = rt->bp = (string)realloc(rt->bp, sz<<1);
ALLOCATED += sz; ++rt->lv; rt->ap += sz;
}
}
}
else
{
b = ++rp;
bn = rt + c; ct = ++bn->ct;
if ((bp = bn->bp) == NULL)
{
++BINS;
s = bn->bp = (string) MALLOC(BINSIZE0);
ap = bn->ap = s + TAILSIZE4;
RP(s) = b; s += RPSIZE;
do {*s++ = c = *b++;} while (c > 0 && s < ap);
}
else
{
s = bn->ap;
ap = bn->ap += TAILSIZE4;
RP(s) = b; s += RPSIZE;
do {*s++ = c = *b++;} while (c > 0 && s < ap);
if (ct == THR[lv = bn->lv])
{
sz = BINSIZE0<<lv;
s = bn->bp = (string) malloc(sz<<1);
ALLOCATED += sz; ++bn->lv;
t = bp; while (t < ap) *s++ = *t++;
free(bp); bn->ap = s;
}
}
}
}
UPDATEMEM; FREE(b0, sz0); --BINS;
} while (BINS == nc && NULLBINS == nn); --FREEBURSTS;
}
void ptraverse(NODE2 *nd)
{
int c, ct, tpsz;
NODE2 *bn;
string bp, ap, s, *tp, *tp0;
for (c = LOCHAR; c <= HICHAR; ++c)
{
bn = nd + c;
if (bn != NULL && bn->lv == -1)
{
ptraverse((NODE2*) bn->bp);
continue;
}
if ((bp = bn->bp) == NULL) continue;
ct = bn->ct;
tpsz = ct * sizeof(string*);
s = bp;
ap = bn->ap;
tp = tp0 = (string*) MALLOC(tpsz);
bn->ap = (string) tp0; s += RPSIZE;
while (s < ap) {*tp++ = s; s += TAILSIZE4;}
if (ct > 1) mkqsortp(tp0, ct, 0);
tp=tp0;
while (ct--)
{
s = *tp - RPSIZE;
*tp++ = allof(RP(s));
}
UPDATEMEM; ALLOCATED -= BINSIZE0<<bn->lv;
free(bp); --BINS;
}
}
void pkill(NODE2 *nd)
{
int c, ct;
NODE2 *bn;
for (c = LOCHAR; c <= HICHAR; ++c)
{
bn = nd + c;
if (bn != NULL && bn->lv == -1)
pkill((NODE2*) bn->bp);
else if ((ct = bn->ct) > 0)
{
FREE(bn->ap, ct * sizeof(string*));
}
}
if (nd->ct)
{
--NULLBINS;
FREE(nd->bp, BINSIZE0<<nd->lv);
}
FREE(nd, 256*sizeof(NODE2));
--NODES;
}
void psavetrie(NODE2 *nd, const char* path, const char* dset)
{
FILE *f;
char* s;
if ((f = fopen(s = fp(path, dset, "cpl-burstsort"), "w+")) == NULL)
{
say("could not open "); brp(s);
}
else
{
pputtrie(nd, f);
fflush(f);
fclose(f);
}
}
void pputtrie(NODE2 *nd, FILE *f)
{
int ct, c; string *tp; NODE2 *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 && bn->lv == -1)
pputtrie((NODE2*) bn->bp, f);
else if ((ct = bn->ct) > 0)
{
tp = (string*) bn->ap;
while (ct--)
{
fputs((char*)*tp++, f);
fputc('\n', f);
}
}
}
}
string* pputtrie_strout;
void tb_pputtrie(NODE2 *nd)
{
int ct, c; string *tp; NODE2 *bn;
ct = nd->ct;
tp = (string*) nd->bp;
while (ct--)
{
*pputtrie_strout++ = *tp++;
}
for (c = LOCHAR; c <= HICHAR; ++c)
{
bn = nd + c;
if (bn != NULL && bn->lv == -1)
tb_pputtrie((NODE2*) bn->bp);
else if ((ct = bn->ct) > 0)
{
tp = (string*) bn->ap;
while (ct--)
{
*pputtrie_strout++ = *tp++;
}
}
}
}
void tb_psavetrie(NODE2 *nd, string* strout)
{
pputtrie_strout = strout;
tb_pputtrie(nd);
}
void inssortp(string *tp, int n, int d)
{
string *rp, *lp, ls, rs, rd, ld;
int o;
for (rp = tp + 1; --n > 0; ++rp)
{
for (rs = *rp, lp = rp; lp > tp; --lp)
{
ls = *(lp - 1);
rd = rs + d;
ld = ls + d;
o = d;
while (*ld == *rd && *rd != 0)
{
if (++o == TAILSIZE)
{
ld = *(string*) (ls - RPSIZE) + TAILSIZE;
rd = *(string*) (rs - RPSIZE) + TAILSIZE;
}
else
{
++ld; ++rd;
}
}
if (*rd < *ld || (*rd == 0 && rs < ls))
*lp = ls;
else
break;
}
*lp = rs;
}
}
void mkqsortp(string *tp, int n, int d)
{
int k, nl, ne, nr, pv;
string *ol, *il, *ir, *_or, *l, *m, *r, t, s, rp, *q;
if (d == TAILSIZE)
{
d = 0;
for (k = 0; k < n; ++k)
{
s = tp[k];
q = (string*) (s - RPSIZE);
rp = *q += TAILSIZE;
t = s + TAILSIZE;
do
{
*s++ = *rp++;
} while (s < t);
}
}
if (n < 13)
{
inssortp(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
mkqsortp(tp + nl, ne, d + 1);
}
if (nl > 1)
mkqsortp(tp, nl, d);
if (nr > 1)
mkqsortp(r - nr, nr, d);
}