#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>

#define data_t double

void heat(int iterations, int x, int y, const char* filename)
{
    int i,j,k;
    data_t **curr_t, **next_t, ** temp;
    FILE* fd;
    struct timeval start_time,stop_time;
    double running_time,processing_rate;

    curr_t=(data_t**)malloc(x*sizeof(data_t*));
    next_t=(data_t**)malloc(x*sizeof(data_t*));
    for(i=0;i<x;i++)
    {
	curr_t[i]=(data_t*)malloc(y*sizeof(data_t));
	next_t[i]=(data_t*)malloc(y*sizeof(data_t));
    }

    for(i=0;i<x;i++)
	for(j=0;j<y;j++)
	{
	    curr_t[i][j]=20.0;
	    if(i==0||j==0||i==x-1||j==y-1)
		curr_t[i][j]=20.0;
	    if(j==0&&i>x/4&&i<3*x/4)
		curr_t[i][j]=100.0;
	    next_t[i][j]=curr_t[i][j];
	}

    gettimeofday(&start_time,NULL);
    for(k=0;k<iterations;k++)
    {
	for(i=1;i<x-1;i++)
	    for(j=1;j<y-1;j++)
		next_t[i][j]=0.25*(curr_t[i-1][j]+curr_t[i][j-1]
			      +curr_t[i+1][j]+curr_t[i][j+1]);
        /*barrier(n);*/
        /* if (id==0) */
        {temp=next_t; next_t=curr_t;curr_t=temp;}
        /*barrier(n);*/
    }

    gettimeofday(&stop_time,NULL);
    running_time = stop_time.tv_sec-start_time.tv_sec
                          + (stop_time.tv_usec-start_time.tv_usec)/1000000.0;
    processing_rate=1.0*iterations*(x-2)*(y-2)/running_time;

    printf("%d iterations on %dx%d grids,\n",iterations,x-2,y-2);
    printf("Running time: %.2f,  execution rate: %.3e\n",running_time,processing_rate);
    fd=fopen(filename,"w");
    if(fd<0)
    {
	printf("[error] Can't open the file '%s' for writing. \n",filename);
	return;
    }

    fprintf(fd,"%d %d\n",x,y);
    for(i=0;i<x;i++)
    {
	for(j=0;j<y;j++)
	    fprintf(fd,"%f\n",curr_t[i][j]);
    }
    fclose(fd);

    for(i=0;i<x;i++)
    {
	free(curr_t[i]);
	free(next_t[i]);
    }
    free(curr_t);
    free(next_t);
}
int main(int argc, char* argv[])
{
    int iterations=1024;
    int x=120;
    int y=120;
    char filename[100];

    strcpy(filename,"heat-seq.map");
    if(argc>=2) iterations=atoi(argv[1]);
    if(argc>=3) x=atoi(argv[2]);
    if(argc>=4) y=atoi(argv[3]);
    if(argc>=5) strcpy(filename,argv[4]);
    
    heat(iterations,x+2,y+2,filename);

    return 0;
}
