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

//int main(int argc, char *argv[]) {
//void * memcpy ( void * destination, const void * source, size_t num );

#include "bandwidth.h"
//#include "250.h"

void membandwidth(){
        //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));
	//int output;
	void * retval;
        struct timeval starttime,endtime;
        double te, test1, test2, test3;
        register long t, t2;
	//pthread_mutex_lock (&mutex1); 
	//double memtotal = meminfo();
	//double memtotal = 
	//memtotal = memtotal / 1024 / 20;
	//memtotal = .5;
	int long_size=sizeof(long);
	//printf("long size: %d\n", long_size);
	register long asize = memtotal * 1024 * 1024 / long_size;
	register long array_bytes=asize*long_size;
        register long block_size;
	register long *a;
	register long *b;
	//a=calloc(1610612736, 4);
	memtotal /= 2;
	printf ("Running Memory Bandwidth Tests:\n\n");
	//allocate 1200MB a peice (2.4GB total) two zero-initialized memory blocks
	printf ( "\tallocating %lfMB a peice (%lfMB total) two zero-initialized memory blocks\n\n", memtotal, memtotal*2); 
	//gettimeofday(&starttime, NULL);
	a=calloc(asize, long_size);
	b=calloc(asize, long_size);
	//memset ((void*) a, '\0', sizeof (a));
	//memset ((void*) b, '\0', sizeof (b));
	//gettimeofday(&endtime, NULL);
	//te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
	//printf ( "\tTime: %lfMB/s\n", memtotal*2/te);

	printf ( "\tcopying array a to array b in progessive steps of %lfMB\n", memtotal/64);
	block_size= memtotal/64 * 1024 * 1024 / long_size;
	gettimeofday(&starttime, NULL);
	for(t=0; t<array_bytes; t+=block_size) {
        	retval = memcpy(b,a,t);
        }
	gettimeofday(&endtime, NULL);
        te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
        
	t2 = 0;
        for(t=0; t<array_bytes; t+=block_size) {
               t2+=t; 
        }
	
	test1 = (t2/1024/1024)/te;
	printf ( "\t\tResult: %lfMB/s\n\n", test1*2);

//system("free -m");
	//32MB block size
	printf ( "\tcopying array a to array b in progressive steps of %lfMB\n", memtotal/18);
        block_size=memtotal/18 * 1024 * 1024 / long_size;
	gettimeofday(&starttime, NULL);
        for(t=0; t<array_bytes; t+=block_size) {
                retval = memcpy(b,a,t);
        }
        gettimeofday(&endtime, NULL); 
        te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
        t2 = 0;
        for(t=0; t<array_bytes; t+=block_size) {
               t2+=t;
        }
	test2 = (t2/1024/1024)/te;
        printf ( "\t\tResult: %lfMB/s\n\n", test2*2);




        printf ( "\tcopying array a to array b in progressive steps of %lfMB\n", memtotal/4);
        block_size=memtotal/4 * 1024 * 1024 / long_size;
        gettimeofday(&starttime, NULL);
        for(t=0; t<array_bytes; t+=block_size) {
                retval = memcpy(b,a,t);
        }
        gettimeofday(&endtime, NULL);
        te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
        t2 = 0;
        for(t=0; t<array_bytes; t+=block_size) {
               t2+=t;
        }
        test3 = (t2/1024/1024)/te;
        printf ( "\t\tResult: %lfMB/s\n\n", test3*2);





	//free arrays
	printf ( "\tfreeing arrays\n\n");
	//gettimeofday(&starttime, NULL);
	free (a);
	free (b);
        //gettimeofday(&endtime, NULL);
        //te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
        //printf ( "\tTime: %lf\n", te);
//system("free -m");


	printf ("\taverage read+write mem bandwidth %lfMB/s\n\n", ((test1*2)+(test2*2)+(test3*2))/3);
	printf ( "\tdone.\n\n");

	//size2 = 1024 / 4; 
	//int array1[(size1*1024)/sizeof(int)];

	//int array1[268435456];
	//size2 = sizeof(array1);
	//printf ( "array1: %lf\n", sizeof(array1));
	//sleep (240);

//return 0;	
}
