/* Alexander Shabarshin - 26 Apr 2008 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define POOLSIZE 8*1024*1024
#define POOLSTEP 128*1024
#define A16MASK 0xFFFFFFF0
#define NTRIES 10
#define MTRIES 1000000

unsigned char* gpool;
int rt[NTRIES];
int pt[NTRIES];
int tt[NTRIES];

int main()
{
 FILE *f;
 double d1,d2;
 clock_t t1,t2;
 unsigned char *pool,*p1,*p2;
 int i,j,k,r,s,b1,b2,e1,e2;
 printf("TEST G4\n");
 if(RAND_MAX < POOLSIZE) 
 {
   printf("too short random generator - RAND_MAX=%i\n",RAND_MAX);
   return -1;
 }  
 gpool = (unsigned char*)malloc(POOLSIZE+512);
 if(gpool==NULL) return -2;
 pool = gpool;
 while((int)pool&511) pool++;
 printf("pool = 0x%8.8X\n",(int)pool);
 srand(time(NULL));
 for(i=0;i<POOLSIZE;i++)
 {
   do { r = rand()&255; } while(!r);
   pool[i] = r;
 }
 printf("randomized %i bytes\n",POOLSIZE);
 f = fopen("memcpy.csv","wt");
 if(f==NULL)
 {
   free(gpool);
   return -3;
 }
 fprintf(f,"size,nal,al\n");
 for(i=0;i<NTRIES;i++)
 {
   rt[i] = rand()%(POOLSIZE-(POOLSTEP<<1));
   pt[i] = POOLSTEP + (rand()%POOLSTEP);
 }
 for(j=3;j<100000;j<<=1)
 {
   printf("size %i\n",j);
   s = 0;
   for(k=0;k<NTRIES;k++)
   {
     p1 = &pool[rt[k]];
     p2 = &p1[pt[k]];
     t1 = clock();
     for(i=0;i<MTRIES;i+=10) 
     {
        memcpy(p1,p2,j);
        memcpy(p1,p2,j);
        memcpy(p1,p2,j);
        memcpy(p1,p2,j);
        memcpy(p1,p2,j);
        memcpy(p1,p2,j);
        memcpy(p1,p2,j);
        memcpy(p1,p2,j);
        memcpy(p1,p2,j);
        memcpy(p1,p2,j);
     }	
     t2 = clock();
     tt[k] = (int)((t2-t1)/(CLOCKS_PER_SEC/1000.0));
//     printf("t[%i]=%i ms\n",k,tt[k]);
     s += tt[k];
   }
   s /= NTRIES;
   d1 = MTRIES/1.024*j/1024.0/s;
   printf("nal : %i ms -> %4.2f MB/s\n",s,d1);
   s = 0;
   for(k=0;k<NTRIES;k++)
   {
     p1 = &pool[rt[k]&A16MASK];
     p2 = &p1[pt[k]&A16MASK];
     t1 = clock();
     for(i=0;i<MTRIES;i+=10) 
     {
        memcpy(p1,p2,j);
        memcpy(p1,p2,j);
        memcpy(p1,p2,j);
        memcpy(p1,p2,j);
        memcpy(p1,p2,j);
        memcpy(p1,p2,j);
        memcpy(p1,p2,j);
        memcpy(p1,p2,j);
        memcpy(p1,p2,j);
        memcpy(p1,p2,j);
     }	
     t2 = clock();
     tt[k] = (int)((t2-t1)/(CLOCKS_PER_SEC/1000.0));
//     printf("t[%i]=%i ms\n",k,tt[k]);
     s += tt[k];
   }
   s /= NTRIES;
   d2 = MTRIES/1.024*j/1024.0/s;
   printf(" al : %i ms -> %4.2lf MB/s\n",s,d2);
   fprintf(f,"%i,%4.2f,%4.2f\n",j,d1,d2);
 }
 fclose(f);
 



 free(gpool);
 return 0;
}

