/****Copyright (c) 1997-2005 All rights reserved
 ****A. V. Gerbessiotis and C. J. Siniolakis
 ****Permission to use, copy, modify, and distribute this software,
 ****and to incorporate it, in whole or in part, into 
 ****other software,is hereby granted without fee, provided that
 ****  (1) the above copyright notice and this permission 
 ****      notice appear in all copies of the source code, and 
 ****      the above copyright notice appear in clearly visible 
 ****      form on all supporting documentation and distribution 
 ****      media, and
 ****     (2) any redistribution of the software, in original
 ****         or modified form, be without fee and subject to
 ****         these same conditions.
 ****   No guarantee, whatsoever, is offered that the code works as
 ****   advertised or is absent of any, even damaging,
 ****   side-effects. Use this code at your own personal risk.
 ****/
#include "smrg.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <limits.h>
#include <sys/time.h>
#define	ELMNTS 8
#define DEBUG 0
#define MODULO 100000
#define WRITELINE2  if (DEBUG) {\
	printf("%6d(%2d %2d)Out:\n",n,12345,12345);\
	for(i=0;i<ELMNTS;i++) printf("%d ",(int)ptr1[i]); printf("...");\
	for(i=n-ELMNTS;i<n;i++) printf("%d ",(int)ptr1[i]); printf("\n");\
	for(i=0;i<ELMNTS;i++) printf("%d ",(int)ptr2[i]); printf("...");\
	for(i=n-ELMNTS;i<n;i++) printf("%d ",(int)ptr2[i]); printf("\n");\
        }\
	printf("(%3d,%3d,%9d):",12345,34567,n);
#define CHECKLINE  for(i=0;i<n-1;i++) if (ptr1[i]>ptr1[i+1]) {printf("Not Sorted* %d :  %d %d\n",i,ptr1[i],ptr1[i+1]); }\
    if (ptr1[n-1]>ptr2[0]) {printf("NotSorted** %d : %d %d\n",0,ptr1[n-1],ptr2[0]);}\
    for(i=0;i<n-1;i++) if (ptr2[i]>ptr2[i+1]) {printf("Not Sorted*** %d : %d %d\n",i,ptr2[i],ptr2[i+1]); }
#define WRITELINE1   for(i=0;i<n;i++) ptr1[i] = bptr1[i];\
        for(i=0;i<n;i++) ptr2[i] = bptr2[i];\
	fflush(stdout);\
        if (DEBUG) {\
	printf("%6d(%2d %2d)In :\n",n,12345,12345);\
	for(i=0;i<ELMNTS;i++) printf("%d ",ptr1[i]); printf("...");\
	for(i=n-ELMNTS;i<n;i++) printf("%d ",ptr1[i]); printf("\n");\
	for(i=0;i<ELMNTS;i++) printf("%d ",ptr2[i]); printf("...");\
	for(i=n-ELMNTS;i<n;i++) printf("%d ",ptr2[i]); printf("\n");\
        }
#define WRITE1	elapsed=0.0; for(j=0;j<runs;j++){\
      for(i=0;i<n;i++) ptr1[i] = bptr1[i]; \
      for(i=0;i<n;i++) ptr2[i] = bptr2[i]; tstart();
#define WRITE2  tend(); elapsed += (treturn()); }

static struct timeval _tstart, _tend;
static struct timezone _tstruct;
void tstart(void) {
  gettimeofday(&_tstart, &_tstruct);
}
void tend(void) {
  gettimeofday(&_tend,&_tstruct);
}

double treturn() {
  double t1,t2;
  t1=(double)_tstart.tv_sec + (double)_tstart.tv_usec/(1000*1000);
  t2=(double)_tend.tv_sec + (double)_tend.tv_usec/(1000*1000);
  return(t2-t1);
}

extern clock_t clock();
int compare(const void *x,const void *y)
{
	return(* ((int*)x)-*((int*)y));
}

int main(int argc,char *argv[]) {
  int i,j,n,runs;
  int *ptr,*bptr, *ptr1,*ptr2, *bptr1,*bptr2;
  clock_t t1,t0;
  double elapsed;

  n=1000;runs=1;
  if (( argc <= 1 ) || (argc > 3)) {
    printf("Usage: %s size runs\nDEFAULTS= 12345=%d 34567=%d 56789=%d (0:left,1:middle,2:random)\n",argv[0],12345,34567,56789);
    return(1);
  } 
  else {
    n = atoi(argv[1]);
    runs=atoi(argv[2]);
   }

   ptr1 = (int*) malloc(n*sizeof(int));
   bptr1= (int*) malloc(n*sizeof(int));
   ptr2 = (int*) malloc(n*sizeof(int));
   bptr2= (int*) malloc(n*sizeof(int));

   for(i=0;i<n;i++) 
     bptr1[i]=ptr1[i]=(int) ((n)*(random()/((double)INT_MAX)));
   for(i=0;i<n;i++) 
     bptr2[i]=ptr2[i]=(int) ((n)*(random()/((double)INT_MAX)));
/*
     bptr[i]=ptr[i]=(int) random();
*/

/* generic qsort */
        qsort(bptr1,n,sizeof(int),compare); 
        qsort(bptr2,n,sizeof(int),compare); 

        WRITELINE1 ; WRITE1;
        gmerge1(ptr1,ptr2,n,n,sizeof(int),compare); 
        WRITE2; WRITELINE2; CHECKLINE;
        printf("gmerge1    generic:Elapsed time is %6.3f\n",elapsed/runs);

        WRITELINE1 ; WRITE1;
        gmerge2(ptr1,ptr2,n,n,sizeof(int),compare); 
        WRITE2; WRITELINE2; CHECKLINE;
        printf("gmerge2    generic:Elapsed time is %6.3f\n",elapsed/runs);

        WRITELINE1 ; WRITE1;
        gmerge3(ptr1,ptr2,n,n,sizeof(int),compare); 
        WRITE2; WRITELINE2; CHECKLINE;
        printf("gmerge3    generic:Elapsed time is %6.3f\n",elapsed/runs);

}
