/*
Set of subroutines for I/O of dem matrix files

CREATED BY Anirudha Shimpi
   for     Dr. David Tarboton

Parameters :
	arr = array[nx,ny] of data_type;
	*nx,*ny = array bounds;
	*dx,*dy = column spacing;
	*igy = max y dimension in original array;
	*fname = filname 80 chars;
	2 character filetype as extension of filename :-
		b1 : binary 1 byte;
		b2 : binary 2 byte - integers;
		b4 : binary 4 byte - double integers;
		r4 : float 4 byte - real numbers;
		r8 : float 8 byte - double precision float;
		i1 : 1 byte integer	|
		i2 : 2 byte integer	|
		i4 : 4 byte integer	 > ASCII files 
		a4 : 4 byte float	|
		a8 : 8 byte float	|
	i,a extensions result in an ascii file of that type;
*/

#define SIZE 80

#include <stdio.h>
#include <string.h>
#include <ctype.h>

/* 
	demwrite_

	parameters :
		arr 	the array to be written to the file
		fname 	the file name
		nx,ny	the number of rows and columns
		dx,dy	the difference in the rows and columns
		igy 	the actual number of rows (for FORTRAN compatibility)

Functions performed :
	1. open file 
	2. write to file after necessary type casting

Assumptions : 
	1. integers are 2 byte, long 4 byte 
	2. filename follow pattern given in header above
*/

demwrite_ (arr,fname,nx,ny,igy,dx,dy)

char *arr;
char *fname;
int *nx,*ny,*igy;
float *dx,*dy;

{
FILE *opfile;
int size,i,j,binary;
short *iarr;
char *where,*first;
int *larr;
float *rarr;
double *darr;
int nrow=40;

makecompat(fname);
/* lowcaseit(fname);  */
printf("Writing to file %s\n",fname);
where=strrchr(fname,'.');
first=where+1;
opfile=fopen(fname,"w+");
if (opfile==NULL)
	{
	fprintf(stderr,"Unable to open file %s for writing\n",fname);
	return(0);
	}
if (*first == 'b' || *first == 'r')
	binary =1;
else 
	binary =0;
size=atoi(where+2);
/*********array type casting***********/
iarr=(short *)arr;
larr=(int *)arr;
rarr=(float *)arr;
darr=(double *)arr;
/**************************************/
if (!binary) {
	fprintf(opfile,"%d %d %f %f\n",*nx,*ny,*dx,*dy);
	if (*igy == 0)
		*igy = *ny;
	switch (*first) {
		case 'i' : {
			if (size == 1)
			{ 
			for (i=0;i<(*ny);i++) {
			  for (j=0;j<(*nx)-1;j++)
                            if((j+1)%nrow != 0)
				fprintf(opfile,"%d ",arr[(*igy)*j+i]);
                            else
				fprintf(opfile,"%d\n",arr[(*igy)*j+i]);
		            fprintf(opfile,"%d\n",arr[(*igy)*(*nx-1)+i]);
			 }
                        }
		        else if (size == 2)
			{
			for (i=0;i<(*ny);i++) {
	 		  for (j=0;j<(*nx)-1;j++)
                            if((j+1)%nrow != 0)
			      fprintf(opfile,"%hd ",iarr[(*igy)*j+i]);
                            else
			      fprintf(opfile,"%hd\n",iarr[(*igy)*j+i]);
			    fprintf(opfile,"%hd\n",iarr[(*igy)*(*nx-1)+i]);
			 }
			}
			else
			{
			for (i=0;i<(*ny);i++) {
			  for (j=0;j<(*nx)-1;j++)
                            if((j+1)%nrow != 0)
			      fprintf(opfile,"%d ",larr[(*igy)*j+i]);
                            else
			      fprintf(opfile,"%d\n",larr[(*igy)*j+i]);
			    fprintf(opfile,"%d\n",larr[(*igy)*(*nx-1)+i]);
			 }
			}
		        break;
		}
		case 'a' : {
			if (size == 4)
			{
			for (i=0;i<(*ny);i++) {
			  for (j=0;j<(*nx)-1;j++)
                            if((j+1)%nrow != 0)
			      fprintf(opfile,"%g ",rarr[(*igy)*j+i]);
                            else
			      fprintf(opfile,"%g\n",rarr[(*igy)*j+i]);
			    fprintf(opfile,"%g\n",rarr[(*igy)*(*nx-1)+i]);
			 }
			}
		        else 
			{
			for (i=0;i<(*ny);i++) {
			  for (j=0;j<(*nx)-1;j++)
                            if((j+1)%nrow != 0)
			      fprintf(opfile,"%g ",darr[(*igy)*j+i]);
                            else
			      fprintf(opfile,"%g\n",darr[(*igy)*j+i]);
			    fprintf(opfile,"%g\n",darr[(*igy)*(*nx-1)+i]);
			 }
			}
		} 
	}
}
else
{
	fwrite(nx,sizeof(nx),1,opfile);
	fwrite(ny,sizeof(ny),1,opfile);
	fwrite(dx,sizeof(dx),1,opfile);
	fwrite(dy,sizeof(dy),1,opfile);
	if (*igy == 0)
		*igy = *ny;
	for (i=0;i<(*ny);i++)
		for (j=0;j<(*nx);j++)
		{
		  switch (*first) {
		    case 'b' : {
		      if (size == 1)
			fwrite(arr+(*igy)*j+i,size,1,opfile);
		      else if (size == 2)
			fwrite(iarr+(*igy)*j+i,size,1,opfile);
		      else
			fwrite(larr+(*igy)*j+i,size,1,opfile);
		      break;
		    }
		    case 'r' : {
		      if (size == 4)
			fwrite(rarr+(*igy)*j+i,size,1,opfile);
		      else 
			fwrite(darr+(*igy)*j+i,size,1,opfile);
		      break;
		    }
		  }
		}
}
fclose(opfile);
return(1);
}	/* demwrite_ */

/*
	demread_

	parameters :
		arr 	the array in which to read into
		fname	the file name
		nx,ny	number of rows and columns
		dx,dy 	difference in rows and columns
		igy	actual number of rows

Functions performed :
	1. Allocation of memory
	2. Reading from the opened file

Assumptions :
	1. Memory allocation done by calling program
	2. integers 2 byte, long 4 byte
	3. filenames follow pattern in header above
*/

demread_ (arr,fname,nx,ny,igy,dx,dy)

char *arr;
char *fname;
int *nx,*ny,*igy;
float *dx,*dy;

{
FILE *ipfile;
int size,i,j,binary;
short *iarr;
char *where,*first;
int *larr;
float *rarr;
double *darr;

makecompat(fname);
/*  lowcaseit(fname); */
printf("Reading from file %s ",fname);
where=strrchr(fname,'.');
first=where+1;
ipfile=fopen(fname,"r");
if (ipfile==NULL)
	{
	fprintf(stderr,"Unable to open file %s for reading\n",fname);
	return(0);
	}
if (*first == 'b' || *first == 'r')
	binary =1;
else 
	binary =0;
size=atoi(where+2);
/*********array type casting***********/
iarr=(short *)arr;
larr=(int *)arr;
rarr=(float *)arr;
darr=(double *)arr;
/**************************************/
if (!binary) {
	fscanf(ipfile,"%d %d %f %f\n",nx,ny,dx,dy);
	if (*igy == 0)
		*igy = *ny;
	switch (*first) {
		case 'i' : {
			if (size == 1)
			{ 
			for (i=0;i<(*ny);i++) {
			  for (j=0;j<(*nx);j++)
		            fscanf(ipfile,"%d ",(arr+(*igy)*j+i));
			 }
                        }
		        else if (size == 2)
			{
			for (i=0;i<(*ny);i++) {
	 		  for (j=0;j<(*nx);j++)
			    fscanf(ipfile,"%hd ",(iarr+(*igy)*j+i));
			  }
			}
			else
			{
			for (i=0;i<(*ny);i++) {
			  for (j=0;j<(*nx);j++)
			    fscanf(ipfile,"%d ",(larr+(*igy)*j+i));
			 }
			}
		        break;
		}
		case 'a' : {
			if (size == 4)
			{
			for (i=0;i<(*ny);i++) {
			  for (j=0;j<(*nx);j++)
			    fscanf(ipfile,"%f ",(rarr+(*igy)*j+i));
			 }
			}
		        else 
			{
			for (i=0;i<(*ny);i++) {
			  for (j=0;j<(*nx);j++)
			    fscanf(ipfile,"%g ",(darr+(*igy)*j+i));
			 }
			}
		} 
	}
}
else
{
	fread(nx,sizeof(nx),1,ipfile);
	fread(ny,sizeof(ny),1,ipfile);
	fread(dx,sizeof(dx),1,ipfile);
	fread(dy,sizeof(dy),1,ipfile);
	if (*igy == 0)
		*igy = *ny;
	for (i=0;i<(*ny);i++)
		for (j=0;j<(*nx);j++)
		{
		  switch (*first) {
		    case 'b' : {
		      if (size == 1)
			fread(arr+(*igy)*j+i,size,1,ipfile);
		      else if (size == 2)
			fread(iarr+(*igy)*j+i,size,1,ipfile);
		      else
			fread(larr+(*igy)*j+i,size,1,ipfile);
		      break;
		    }
		    case 'r' : {
		      if (size == 4)
			fread(rarr+(*igy)*j+i,size,1,ipfile);
		      else 
			fread(darr+(*igy)*j+i,size,1,ipfile);
		      break;
		    }
		  }
		}
}
fclose(ipfile);
printf("done\n");
return(1);
}

/* lowcaseit  */

lowcaseit(name)

char name[80];

{
int i=0;

while (name[i]!=NULL)
	{
	if (isupper(name[i]))name[i]=tolower(name[i]);
/*		name[i]=name[i]+40;  */
/* printf('%s\n',name[i]); */
	i++;
	}
}

makecompat(name)

char *name;

{
char *temp;

temp=name;
while(*temp > 32 && *temp <123)
	temp++;
*temp='\0';
}

/*
	getfileinfo

	parameters :
		ipfilename	file name
		nx,ny,dx,dy	the dimensions

Functions performed :
	1. get the dimensions for the array to be read in
	2. get `type' of data in file

Purposes :
	1. for C programs to allocate memory before reading the array.
	2. Serves no purpose for FORTRAN programs, hence no _ after name for
		compatibilty with FORTRAN unlike demread_ and demwrite_
*/

getfileinfo (ipfilename,size,datatype)

char *ipfilename;
int  *size;
char *datatype;

{
FILE *ipfile;
char *where, *first;
int nx,ny;
float dx,dy;

makecompat(ipfilename);
/*   lowcaseit(ipfilename);  */
printf("Reading dimensions from file %s",ipfilename);
where=strrchr(ipfilename,'.');
first=where+1;
ipfile=fopen(ipfilename,"r");
if (ipfile==NULL) {
	fprintf(stderr,"Unable to open file %s for reading\n",ipfilename);
	return(0);
	}
if (*first == 'i' || *first == 'a')
	fscanf(ipfile,"%d %d %f %f\n",&nx,&ny,&dx,&dy);
else {
	fread(&nx,sizeof(nx),1,ipfile);
	fread(&ny,sizeof(ny),1,ipfile);
	fread(&dx,sizeof(dx),1,ipfile);
	fread(&dy,sizeof(dy),1,ipfile);
	}
fclose (ipfile);
switch (*first) {
	case 'b' : case 'i' : switch (*(first+1)) {
			case '1' : *datatype = 'c'; break;
			case '2' : *datatype = 'i'; break;
			case '4' : *datatype = 'l'; 
		} /* of switch (2) */
		break;
	case 'r' : case 'a' : switch (*(first+1)) {
			case '4' : *datatype = 'f'; break;
			case '8' : *datatype = 'd'; 
		} /* of switch (2) */
	} /* of switch (1) */
*size = nx*ny;
printf ("\n");
return(1);
}
