#ifndef COPY_H
#define COPY_H
	#include <time.h>
	#include <stdio.h>
	#include <string.h>
	#include <stdlib.h>
	#include <math.h>
	#include <float.h>
	#include <limits.h>
	
	#define MIN(X, Y) ((X) <= (Y) ? (X) : (Y))
	
	#define MAX(X, Y) ((X) >= (Y) ? (X) : (Y))
	
	#define DR(X, Y) ((double) (X) / (double) (Y))
	
	#define DP(X, Y) ((double) (X) * (double) (Y))
	
	#define DPR(X, Y, Z) (((double) (X) * (double) (Y)) / (double) (Z))
	
	#define PSWAP(X, Y, Z) {Z = *(X); *(X) = *(Y); *(Y) = Z;}
	
	#define P2C(TP, D) (*(*(TP) + D))
	
	#define SC(T, S, N) while (N-- > 0) *T++ = *S++
	
	#define GETNODE(typ) (typ*) CALLOC(256, sizeof(typ))
	
	#define RP(x) *((string*) (x))
        
        #define RPSIZE  sizeof(string*)
 
	
        
        #define UPDATEMEM
	
	
        #define MALLOC(x) malloc(x);
	
        
        #define CALLOC(x, y) calloc(x, y);
	
        
        #define FREE(x, y) free(x)
	
	#define MAXREPS 12
	
	#define MAXTMRS 12
	
	#define MSEC_PER_CLOCK ((double) 1000.0 / (double) CLOCKS_PER_SEC)
	
	#define tr 1 
	#define tx 2 
	#define ts 3 
	#define ti 4 
	#define tb 5 
	#define tg 6 
	#define tc 7 
	#define th 8 
	#define tk 9 
	#define tw 10 
#define DUMP {\
	isaye(TAILSIZE,"TAILSIZE"); cr();\
	isaye(NKEYS,"NKEYS"); isaye(NBYTES,"NBYTES"); cr();\
	isaye(LOCHAR,"LOCHAR"); isaye(HICHAR,"HICHAR"); cr();\
	isaye(NCHARS,"NCHARS"); isaye(MAXKEYLEN,"MAXKEYLEN"); cr();\
	isaye(NSEGS,"NSEGS"); isaye(SEGSIZE,"SEGSIZE"); cr();\
	isaye(BINSIZE0,"BINSIZE0"); isaye(LIMSIZE0,"LIMSIZE0"); cr();\
	isaye(FREEBURSTS,"FREEBURSTS"); isaye(SAMPLERATE,"SAMPLERATE"); cr();\
	isaye(INPUTORDER,"INPUTORDER"); isaye(WRITEFILE,"WRITEFILE"); cr();\
	isaye(CACHESIZE,"CACHESIZE"); isaye(NODES,"NODES"); cr();\
	isaye(BINS,"BINS"); isaye(NULLBINS,"NULLBINS"); cr();\
	isaye(ALLOCATED,"ALLOCATED"); isaye(MAXALLOCATED,"MAXALLOCATED"); br();\
}
	typedef unsigned char *string;
	
	typedef struct {
		string *a;	
		int n;		
		int d;		
	} run;
	
	typedef struct {int n; double t[MAXREPS];} timer;
	
	typedef struct trierec {char **ntp; char lv[256]; int ct[256]; char **p[256];} trie0;
	
	typedef struct {
		int ct;	  
		string bp; 
		string ap; 
		string lp; 
	} NODE1;
	
	typedef struct {
		int lv, 		
		ct;			
		string bp, 	
		ap;			
	} NODE2;
	
	typedef void (*sort1) (string *a, int n, int d);
	typedef void (*test) (int nr, string fp);
	
	size_t	
                MAXKEYS, 		
	        MAXBYTES, 		
		NKEYS, 			
		NBYTES, 			
                CHARCOUNT[256], 	
		LOCHAR, 			
		HICHAR, 			
                NCHARS, 			
		
                NSEGS0, 			
		NSEGS, 			
                SEGSIZE0, 		
		SEGSIZE, 		
		CACHESIZE, 		
		BINSIZE0, 		
		MAXKEYLEN, 		
		LIMSIZE0, 		
                FREEBURSTS0, 	
	 	FREEBURSTS, 	
                SAMPLERATE0, 	
		SAMPLERATE,		
		TAILSIZE0, 		
		TAILRATE, 		
		TAILSIZE, 		
		TAILSIZE4, 		
		THR[20], 		
		
                INPUTORDER, 	
		WRITEFILE, 				
		TIMERPHASE, 	
		REP, 				
		NODES, 			
		BINS, 			
		NULLBINS, 		
		OUTOFORDER, 	
		UNSTABLE, 		
		UNIQUE, 			
		SORTEDBYTES, 	
		EXHAUSTEDKEYS, 
		ALLOCATED, 		
		MAXALLOCATED;	
	double
		TMIN, 			
		TNORM;			
        char
		*INPUTDIR, 		
                *DATANAME, 		
		*FILETYPE, 		
		*OUTPUTDIR, 		
		*SORTNAME, 		
                *HELPERNAME;	        
        string
		INBUF, 			
		*SEGMENTS, 		
		*SEGLIMITS;		
	FILE
		*ERRORLOG;		
	test
		TEST;				
	timer
		*TMR, 			
		TR[MAXTMRS];	
	
	int main(int argc, char *argv[]);
	void showhelp();
	void setsort(int sn);
	void listinputs();
	void doreps(int nr);
	void getsegs(string fp);
	void getkeys(string fp);
	
	void sbdo(int nr, string fp);
        void sbs(string *seg, string *seglim);
	void ssample(string *seg, string *seglim, NODE1 *rt, int n);
	void samburst(NODE1 *bn);
	void clear(NODE1 *t);
	void sadd(string b, string bn, NODE1 *rt);
	void sburst(NODE1 *bn);
	void straverse(NODE1 *t);
	void scheck(NODE1 *t, int d);
	void skill(NODE1 *t);
	void ssavetrie(NODE1 *t, const char* path, const char* dset);
	void sputtrie(NODE1 *t, FILE *f, string pfx, int d);
	void inssort(string *a, int n, int d);
	void mkqsort(string *a, int n, int d);
	
	void rbdo(int nr, string fp);
	void rbs(string b);
	void rsample(string b, NODE1 *rt, int n);
	void radd(string b, int n, NODE1 *rt);
	void rburst(NODE1 *bn0);
	void rtraverse(NODE1 *t);
	void rcheck(NODE1 *t, int d);
	void rkill(NODE1 *t);
	void savetrie(NODE1 *t, const char* path, const char* dset);
	void puttrie(NODE1 *t, FILE *f);
	void inssorts(string *a, int n, int d);
	void stabilize(string *a, int n);
	void mkqsorts(string *a, int n, int d);
	
	void pbdo(int nr, string fp);
	void pbs(string b);
	void psample(string b, NODE2 *rt, int n);
	void psamburst(NODE2 *bn);
	void pclear(NODE2 *t);
	void padd(string b, int n, NODE2 *rt);
	void pburst(NODE2 *bn0);
	void ptraverse(NODE2 *t);
	void pcheck(NODE2 *t, int d);
	void pkill(NODE2 *t);
	void psavetrie(NODE2 *t, const char* path, const char* dset);
	void pputtrie(NODE2 *t, FILE *f);
	void inssortp(string *a, int n, int d);
	void mkqsortp(string *a, int n, int d);
	
	void vswap(string *a, string *b, int n);
	string *med3(string *a, string *b, string *c, int d);
	string *med3s(string *a, string *b, string *c);
	
	void cr();
	void dot();
	void say(const char* s);
	void sayln(const char* s);
	void isay(int i);	  void isaye(int i, const char* s);
	void dsay(double d, int n);
	void esay(const char* s);
	void br();
	void brp(const char* s);
	
	string allof(string s);
	int tokenize(string s, string *tok, char d, char dd);
	
	char* fp(const char* dir, const char* fn, const char* ft);
	
	void treset(int nt, int nr);
        static inline void ton(int x) {}
	timer *tsort(int i);
	double tmean(int i);
	double tmed(int i);
	void tmin(int nr);
	void tminsay();
	void tnormsay();
	void isaye(int i,string s);	
#endif