#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include "cpuinfo.h"

int main(int argc, char *argv[]) {

        //printf ( "argv[1] = %s\n", argv[1] );
        //printf ( "argv[2] = %s\n", argv[2] );
	//int empty1;
	//int size1;
	//int size2;
	//size1 = atoi (argv[1]);
	//printf ( "size1: %d\n", size1);
        //printf ( "sizeof int: %d\n", sizeof(int));
        struct timeval starttime,endtime;
        double te;
        long t, t2; 
	double mhz = cpuinfo();
		
/*
Array  4 Byte 64 Byte
 Size  stride  stride
 (kb) (ticks) (ticks)
   1     2.0     2.0
   2     2.0     2.0
   3     2.0     2.0
   4     2.0     2.0
   6     2.0     2.0
   8     2.1     2.2
  10     2.9    18.4
  12     2.6    16.6
  14     2.6    17.2
*/

printf("cpuinfo: %lf\n", mhz);

int long_size=sizeof(long);
//printf("long size: %d\n", long_size);
long asize = 24 * 1024 * 1024 / long_size;
long array_bytes;
//=asize*long_size;
        long block_size;
	long *a;
//	long *b;
//b=calloc(asize, long_size);

/*        for(t=0; t<asize; t++) {
                a[t]=0xaa;
		//b[t]=0xab;
        }
*/
	printf ( "Block size(KB):\t4 Byte Time:\t64 Byte Time:\n\n");

	//asize=2 * 1024 / long_size;
	long max_bytes = 24 * 1024 * 1024;

	for(block_size=1024; block_size<max_bytes; block_size=block_size+1024) {
        	//for(t2=0; t2<block_size; t2++) {
                	//a[t]=0xaa;
                	//b[t]=0xab;
			if(block_size >= 5120 && block_size < 32768) {
				block_size = block_size+1024;
			}
                        if(block_size >= 32768 && block_size < 65536) {
                                block_size = block_size+3072;
                        }
                        if(block_size >= 65536 && block_size < 131072) {
                                block_size = block_size+7168;
                        }
                        if(block_size >= 131072 && block_size < 262144) {
                                block_size = block_size+15360;
                        }
                        if(block_size >= 262144 && block_size < 786432) {
                                block_size = block_size+31744;
                        }
                        if(block_size >= 786432 && block_size < 1048576) {
                                block_size = block_size+64512;
                        }
                        if(block_size >= 1048576 && block_size < 16777216) {
                                block_size = block_size+523264;
                        }
                        if(block_size >= 16777216) {
                                block_size = block_size+2096128;
                        }


 

		asize =  block_size / long_size;
array_bytes=asize*long_size;
gettimeofday(&starttime, NULL);
		a=calloc(asize, long_size);
		memcpy (a,a,array_bytes);
gettimeofday(&endtime, NULL);
te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec));
printf ( "%ld\t%lf\t\n", block_size/1024, (te/(mhz*1000))*1000000);
free(a);
		//array_bytes=asize*long_size;
/*
			//memmove (a,a,block_size);

			gettimeofday(&starttime, NULL);
			for(t2=0; t2<array_bytes; t2+=4) {
				memcpy (a,a,t2);
				//memmove (a,a,block_size);
				//memcpy (a,a,block_size);
				//memmove (a,a,block_size);
			}
			gettimeofday(&endtime, NULL);	
			te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec));

			printf ( "%ld\t%lf\t", block_size/1024, (te/(mhz*1000))*1000000);

                        gettimeofday(&starttime, NULL);
                        for(t2=0; t2<array_bytes; t2+=64) {
                                memcpy (a,a,t2);        
                                //memmove (a,a,block_size);
                                //memcpy (a,a,block_size);
                                //memmove (a,a,block_size);
                        }
                        gettimeofday(&endtime, NULL);
                        te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec));
                        printf ( "%lf\n", (te/(mhz*1000))*1000000);
			free(a);
*/
	}

//memmove (str+t2,str+t2,t2);

	printf ( "Done.\n");
//free(b);
	return 0;
}
