/* Module To Interface C I/O to Fortran */
#include <stdio.h>

#if(SIZEOF_SHORT==4)
#define fint4 short
#elif(SIZEOF_INT==4)
#define fint4 int
#elif(SIZEOF_LONG==4)
#define fint4 long
#else
#define fint4 int
#endif

#ifdef FORTRANCAPS
#define read_binary_field READ_BINARY_FIELD
#define in_to_im          IN_TO_IM
#endif

#ifdef UNDERSCORE
#define read_binary_field read_binary_field_
#define in_to_im          in_to_im_
#endif

#ifdef DOUBLEUNDERSCORE
#define read_binary_field read_binary_field__
#define in_to_im          in_to_im__
#endif

#define swap2(x) ((((x)>>8)&255)|(((x)&255)<<8))


int read_binary_field(char *data, fint4 *in_size, fint4 *out_size, fint4 *nitems,
                      char *fname, fint4 *len)
{
  FILE *fp;
  int cnt;

 
  fname[*len]='\0';
  fp = fopen(fname,"rb");
  cnt = fread(data,(*in_size),(*nitems),fp);
  fclose(fp);

  if(cnt != (*nitems)){
    fprintf(stderr,"Failed to read number of expected items in read_binary_field %d %d\n",
            *nitems,cnt);
    return -1;
  }
  cnt = in_to_im(in_size,out_size,data,nitems);

  return(cnt);
  
 
}  
  
/* translates a field of integer*n to a field of integer*m given that
   m>= n
*/

int in_to_im(fint4 *insize, fint4 *outsize,char *data, fint4 *nitems)
{
  int i,n,m;
  int *j;
  short *k;  

  if(*insize == *outsize)
    return 0;
  if(*insize > *outsize)
    return -1;

  n = (*insize);
  m = (*outsize);

  if(n==sizeof(short) && m==sizeof(fint4)){
    j = (fint4 *) data;
    k = (short *) data;
    for(i=(*nitems)-1;i>=0;i--)
#ifdef WORDS_BIGENDIAN
      j[i]=(fint4) k[i];
#else
      j[i]=(fint4) swap2(k[i]);
#endif
    return 0;
  }
  if(n==sizeof(char) && m==sizeof(fint4)){
    j = (fint4 *) data;
    for(i=(*nitems)-1;i>=0;i--)
      j[i]=(fint4) data[i];
    return 0;
  }
  fprintf(stderr,"Failed to find type match in in_to_im %d %d\n",m,n);
  return -1;
}

int in_to_fm(fint4 *insize, fint4 *outsize,char *data, fint4 *nitems)
{
  int j,n,m;
  short *s;
  int *i;
  float *f;  
  double *d;

  if(*insize == *outsize)
    return 0;
  if(*insize > *outsize)
    return -1;

  n = (*insize);
  m = (*outsize);

  if(n==sizeof(short) && m==sizeof(float)){
    s = (short *) data;
    f = (float *) data;
    for(j=(*nitems)-1;j>=0;j--)
      f[j]=(float) s[j];
    return 0;
  }
  if(n==sizeof(char) && m==sizeof(float)){
    f = (float *) data;
    for(j=(*nitems)-1;j>=0;j--)
      f[j]=(float) data[j];
    return 0;
  }
  if(n==sizeof(short) && m==sizeof(double)){
    s = (short *) data;
    d = (double *) data;
    for(j=(*nitems)-1;j>=0;j--)
      d[j]=(double) s[j];
    return 0;
  }
  if(n==sizeof(char) && m==sizeof(double)){
    d = (double *) data;
    for(j=(*nitems)-1;j>=0;j--)
      d[j]=(double) data[j];
    return 0;
  }
  fprintf(stderr,"Failed to find type match in in_to_fm %d %d\n",m,n);
  return -1;
}