/****Copyright (c) 1997-2009 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 "avgmrgmain.h"
#define DEBUG 0

#define N_MERGE_ALGS 9

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

int main(int argc,char *argv[]) {
  int i,j,k,n,runs,type;
  data *ptr,*bptr, *ptr1,*ptr2, *bptr1,*bptr2;
  double elapsed;
void (*gfunc[N_MERGE_ALGS])() = {  
	gmerge,gmerge1, gmerge11, gmerge21, gmerge2, gmerge12, gmerge3, gmerge13, gmerge23
  };
  char *labels[N_MERGE_ALGS]   = {
       "gmerge","gmerge1", "gmerge11","gmerge21", "gmerge2", "gmerge12", "gmerge3","gmerge13","gmerge23"
  };
    int doalg[N_MERGE_ALGS] = {
    1,1,1,1,1,1,1,1,1 };

  void (*GTYPEMERGE)(void *,void *,int,int,int,int (*) (const void *,const void *));

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


   ptr1 = (data*) Malloc(n*sizeof(data),"ptr1");
   bptr1= (data*) Malloc(n*sizeof(data),"bptr1");
   ptr2 = (data*) Malloc(n*sizeof(data),"ptr2");
   bptr2= (data*) Malloc(n*sizeof(data),"bptr2");
   memset( ptr1,0,n*sizeof(data ));
   memset(bptr1,0,n*sizeof(data ));
   memset( ptr2,0,n*sizeof(data ));
   memset(bptr2,0,n*sizeof(data ));


   srandom(21+1001*11);
   for(i=0;i<n;i++)  {
    if  ( type==1 ) {
     bptr1[i]=ptr1[i]=(data) (random()&MODULO_UINT);
    }
    if  ( type==2 ) {
     bptr1[i]=ptr1[i]=(data) ((n)*(random()/((double)INT_MAX)));
    }
    if  ( type==3 ) {
     bptr1[i]=ptr1[i]=(data) 10;
    }
    if  ( type==4 ) {
     bptr1[i]=ptr1[i]=(data) i;
    }
    if  ( type>=5 ) {
     bptr1[i]=ptr1[i]=(data) n-i+1;
    }
   }
   for(i=0;i<n;i++)  {
    if  ( type==1 ) {
     bptr2[i]=ptr2[i]=(data) (random()&MODULO_UINT);
    }
    if  ( type==2 ) {
     bptr2[i]=ptr2[i]=(data) ((n)*(random()/((double)INT_MAX)));
    }
    if  ( type==3 ) {
     bptr2[i]=ptr2[i]=(data) 10;
    }
    if  ( type==4 ) {
     bptr2[i]=ptr2[i]=(data) i;
    }
    if  ( type>=5 ) {
     bptr2[i]=ptr2[i]=(data) n-i+1;
    }
   }



/* generic qsort */
        qsort(bptr1,n,sizeof(data),compare); 
        qsort(bptr2,n,sizeof(data),compare); 
 if (DEBUG) { 
        printf("BP1: %6d(%2d %2d)Out:",n, 1     ,1      );
        for(i=0;i<ELMNTS;i++) printf("%d ",(int)bptr1[i]); printf("...");
        for(i=n-ELMNTS;i<n;i++) printf("%d ",(int)bptr1[i]); printf("\n");
        printf("BP2: %6d(%2d %2d)Out:",n, 1     ,1      );
        for(i=0;i<ELMNTS;i++) printf("%d ",(int)bptr2[i]); printf("...");
        for(i=n-ELMNTS;i<n;i++) printf("%d ",(int)bptr2[i]); printf("\n");
        }


   for(k=0;k<N_MERGE_ALGS;k++) {
    if (doalg[k]==1) {
     GTYPEMERGE=gfunc[k];
     WRITELINE1; WRITE1;
     GTYPEMERGE(ptr1,ptr2,n,n,sizeof(data ),compare);
     WRITE2; WRITELINE2; CHECKLINE;
     printf("%12s generic: Elapsed time is: %10.8f\n",labels[k],elapsed/runs);
    }
   }

   Free((void *) bptr2,n*sizeof(data),"bptr");
   Free((void *) ptr2,n*sizeof(data),"ptr");
   Free((void *) bptr1,n*sizeof(data),"bptr");
   Free((void *) ptr1,n*sizeof(data),"ptr");


 return(0);
}
