#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#define GADGET           2
#define BYTESWAP         1
#define GADGETlength2Mpc 1E-3
#define GADGET_MUNIT     1E10

int ReadInt       (FILE *fptr,int *n,int swap);
int ReadFloat     (FILE *fptr,float *n, int swap);
int ReadDouble    (FILE *fptr,double *n,int swap);
int ReadLong      (FILE *fptr,long *n,int swap);
int ReadUInt      (FILE *fptr,unsigned int *n,int swap);
int ReadLongLong  (FILE *fptr,long long *n,int swap);

unsigned int blklen;
#define GADGET_SKIP  ReadUInt     (fd,&blklen,SWAPBYTES);

#define TRUE    1
#define FALSE   0
#define NFILL   (256- 6*4- 6*8- 2*8- 2*4- 6*4- 2*4 - 4*8)

struct io_header_1
{
  int      npart[6];
  double   mass[6];
  double   time;
  double   redshift;
  int      flag_sfr;
  int      flag_feedback;
  int      npartTotal[6];
  int      flag_cooling;
  int      num_files;
  double   BoxSize;
  double   Omega0;
  double   OmegaLambda;
  double   HubbleParam; 
  char     fill[NFILL];  /* fills to 256 Bytes */
} header1;



int     NumPart, Ngas;

struct particle_data 
{
  float  Pos[3];
  float  Vel[3];
  float  Mass;
  int    Type;
  
  float  Rho, U, Temp, Ne;
} *P;

int *Id;

double  Time, Redshift;

int load_snapshot(char *fname, int files);
int write_ascii(char *file_name);
int allocate_memory(void);

/* Here we load a snapshot file. It can be distributed
 * onto several files (for files>1).
 * The particles are brought back into the order
 * implied by their ID's.
 * A unit conversion routine is called to do unit
 * conversion, and to evaluate the gas temperature.
 */
int main(int argc, char **argv)
{
  // Argument:
  //             file to convert.
  //
  // Works only with one file.
  //
  
  int  files;
  
  if(argc!=3)
  {
    printf("Usage: gadget2ascii input_file output_file\n");
    exit(0);
  }
  
  files=1;                               /* number of files per snapshot */
  
  // Reads snapshot (already converts (x, v, m) to (Mpc/h, km/sec, Msun/h) ).
  load_snapshot(argv[1], files);
  
  // Reorder (does not work for state-of-the-art simulations ... too slow!).
  //reordering();  /* call this routine only if your ID's are set properly */
  
  // Units convertion (only relevant for gas quantities).
  //gas_unit_conversion();  /* optional stuff */
  
  // Writes info.
  write_ascii(argv[2]);

  return 0;

}

//-------------------------------
//  write_ascii
//-------------------------------
int write_ascii(char *file_name)
{
  int i;
  FILE *fd;
  
  printf("Writing %s.\n", file_name);
  if(!(fd=fopen(file_name,"w")))
  {
    printf("can't open file `%s`\n",file_name);
    exit(0);
  }
  
  fprintf(fd, "# npart         = %d  %d  %d  %d  %d  %d\n", header1.npart[0], header1.npart[1], header1.npart[2], header1.npart[3], header1.npart[4], header1.npart[5]);
  fprintf(fd, "# mass          = %lf  %lf  %lf  %lf  %lf  %lf\n", header1.mass[0], header1.mass[1], header1.mass[2], header1.mass[3], header1.mass[4],header1. mass[5]);
  fprintf(fd, "# time          = %lf\n", header1.time);
  fprintf(fd, "# redshift      = %lf\n", header1.redshift);
  fprintf(fd, "# fralg_str     = %d\n", header1.flag_sfr);
  fprintf(fd, "# flag_feedback = %d\n", header1.flag_feedback);
  fprintf(fd, "# npartTotal    = %d  %d  %d  %d  %d  %d\n", header1.npartTotal[0], header1.npartTotal[1], header1.npartTotal[2], header1.npartTotal[3], header1.npartTotal[4], header1.npartTotal[5]);
  fprintf(fd, "# flag_cooling  = %d\n", header1.flag_cooling);
  fprintf(fd, "# num_files     = %d\n", header1.num_files);
  fprintf(fd, "# BoxSize       = %lf\n", header1.BoxSize);
  fprintf(fd, "# Omega0        = %lf\n", header1.Omega0);
  fprintf(fd, "# OmegaLambda   = %lf\n", header1.OmegaLambda);
  fprintf(fd, "# HubbleParam   = %lf\n", header1.HubbleParam);
  
  for(i=1; i<=NumPart; i++)
  {
    fprintf(fd, "%f  %f  %f  %f  %f  %f  %f  %d\n", P[i].Pos[0], P[i].Pos[1], P[i].Pos[2], P[i].Vel[0], P[i].Vel[1], P[i].Vel[2], P[i].Mass, Id[i]);
  }
  
  fclose(fd);

  return 0;
  
}

/* this template shows how one may convert the gas particles
 * from Gadget's units to cgs units.
 * In this example, the temperate of the gas is computed.
 * (assuming that the electron density in units of the hydrogen density
 * was computed by the code. This is done if cooling is enabled.)
 */
int gas_unit_conversion(void)
{
  double GRAVITY, BOLTZMANN, PROTONMASS;
  double UnitLength_in_cm, UnitMass_in_g, UnitVelocity_in_cm_per_s;
  double UnitTime_in_s, UnitDensity_in_cgs, UnitPressure_in_cgs, UnitEnergy_in_cgs;  
  double G, Xh, HubbleParam;
  
  int i;
  double MeanWeight, u, gamma;
  
  /* physical constants in cgs units */
  GRAVITY   = 6.672e-8;
  BOLTZMANN = 1.3806e-16;
  PROTONMASS = 1.6726e-24;
  
  /* internal unit system of the code */
  UnitLength_in_cm= 3.085678e21;   /*  code length unit in cm/h */
  UnitMass_in_g= 1.989e43;         /*  code mass unit in g/h */
  UnitVelocity_in_cm_per_s= 1.0e5;
  
  UnitTime_in_s= UnitLength_in_cm / UnitVelocity_in_cm_per_s;
  UnitDensity_in_cgs= UnitMass_in_g/ pow(UnitLength_in_cm,3);
  UnitPressure_in_cgs= UnitMass_in_g/ UnitLength_in_cm/ pow(UnitTime_in_s,2);
  UnitEnergy_in_cgs= UnitMass_in_g * pow(UnitLength_in_cm,2) / pow(UnitTime_in_s,2);
  
  G=GRAVITY/ pow(UnitLength_in_cm,3) * UnitMass_in_g * pow(UnitTime_in_s,2);
  
  
  Xh= 0.76;  /* mass fraction of hydrogen */
  HubbleParam= header1.HubbleParam;
  
  
  for(i=1; i<=NumPart; i++)
  {
    if(P[i].Type==0)  /* gas particle */
    {
      MeanWeight= 4.0/(3*Xh+1+4*Xh*P[i].Ne) * PROTONMASS;
      
	  /* convert internal energy to cgs units */
      
      u  = P[i].U * UnitEnergy_in_cgs/ UnitMass_in_g;
      
      gamma= 5.0/3;
      
	  /* get temperature in Kelvin */
      
      P[i].Temp= MeanWeight/BOLTZMANN * (gamma-1) * u;
    }
  }
  
  return 0;

}





/* this routine loads particle data from Gadget's default
 * binary file format. (A snapshot may be distributed
 * into multiple files.
 */
int load_snapshot(char *fname, int files)
{
  FILE *fd;
  char   buf[200], DATA[512];
  int    i,j,k,ntot_withmasses;
  int    t,n,off,pc,pc_new,pc_sph;
  int    ic,c,SWAPBYTES;
  float  x_min=1E40, x_max=-1E40, y_min=1E40, y_max=-1E40, z_min=1E40, z_max=-1E40;
  
  for(i=0, pc=1; i<files; i++, pc=pc_new)
  {
    if(files>1)
      sprintf(buf,"%s.%d",fname,i);
    else
      sprintf(buf,"%s",fname);
    
    if(!(fd=fopen(buf,"r")))
    {
      printf("can't open file `%s`\n",buf);
      exit(0);
    }
    
#if (BYTESWAP==1)
    SWAPBYTES = TRUE;
    printf("reading BYTESWAPed `%s' ...\n\n",buf); fflush(stdout);
#else
    SWAPBYTES = FALSE;
    printf("reading `%s' ...\n\n",buf); fflush(stdout);
#endif
    
    /*================= read in GADGET IO header =================*/
#if (GADGET==2)
    GADGET_SKIP;
    fread(DATA,sizeof(char),4,fd);
    DATA[4] = '\0';
    fprintf(stderr,"\n o reading %s\n",DATA);
    GADGET_SKIP;
    GADGET_SKIP;
#endif
    
    GADGET_SKIP;
    ReadInt(fd, &(header1.npart[0]), SWAPBYTES);
    ReadInt(fd, &(header1.npart[1]), SWAPBYTES);
    ReadInt(fd, &(header1.npart[2]), SWAPBYTES);
    ReadInt(fd, &(header1.npart[3]), SWAPBYTES);
    ReadInt(fd, &(header1.npart[4]), SWAPBYTES);
    ReadInt(fd, &(header1.npart[5]), SWAPBYTES);
    ReadDouble(fd, &(header1.mass[0]), SWAPBYTES);
    ReadDouble(fd, &(header1.mass[1]), SWAPBYTES);
    ReadDouble(fd, &(header1.mass[2]), SWAPBYTES);
    ReadDouble(fd, &(header1.mass[3]), SWAPBYTES);
    ReadDouble(fd, &(header1.mass[4]), SWAPBYTES);
    ReadDouble(fd, &(header1.mass[5]), SWAPBYTES);
    ReadDouble(fd, &(header1.time), SWAPBYTES);
    ReadDouble(fd, &(header1.redshift), SWAPBYTES);
    ReadInt(fd, &(header1.flag_sfr), SWAPBYTES);
    ReadInt(fd, &(header1.flag_feedback), SWAPBYTES);
    ReadInt(fd, &(header1.npartTotal[0]), SWAPBYTES);
    ReadInt(fd, &(header1.npartTotal[1]), SWAPBYTES);
    ReadInt(fd, &(header1.npartTotal[2]), SWAPBYTES);
    ReadInt(fd, &(header1.npartTotal[3]), SWAPBYTES);
    ReadInt(fd, &(header1.npartTotal[4]), SWAPBYTES);
    ReadInt(fd, &(header1.npartTotal[5]), SWAPBYTES);
    ReadInt(fd, &(header1.flag_cooling), SWAPBYTES);
    ReadInt(fd, &(header1.num_files), SWAPBYTES);
    ReadDouble(fd, &(header1.BoxSize), SWAPBYTES);
    ReadDouble(fd, &(header1.Omega0), SWAPBYTES);
    ReadDouble(fd, &(header1.OmegaLambda), SWAPBYTES);
    ReadDouble(fd, &(header1.HubbleParam), SWAPBYTES);
    for(ic=0; ic<NFILL; ic++)
      {
       c = fgetc(fd);
       if (c == EOF)
          return(FALSE);
       header1.fill[ic]   = c;
       header1.fill[ic+1] = '\0';
      }
    GADGET_SKIP;
    
    /* convert to Mpc/h */
    header1.BoxSize      *= GADGETlength2Mpc;
    
    printf("Header:\n");
    printf("npart         = %d  %d  %d  %d  %d  %d\n", header1.npart[0], header1.npart[1], header1.npart[2], header1.npart[3], header1.npart[4], header1.npart[5]);
    printf("mass          = %lf  %lf  %lf  %lf  %lf  %lf\n", header1.mass[0], header1.mass[1], header1.mass[2], header1.mass[3], header1.mass[4],header1. mass[5]);
    printf("time          = %lf\n", header1.time);
    printf("redshift      = %lf\n", header1.redshift);
    printf("fralg_str     = %d\n", header1.flag_sfr);
    printf("flag_feedback = %d\n", header1.flag_feedback);
    printf("npartTotal    = %d  %d  %d  %d  %d  %d\n", header1.npartTotal[0], header1.npartTotal[1], header1.npartTotal[2], header1.npartTotal[3], header1.npartTotal[4], header1.npartTotal[5]);
    printf("flag_cooling  = %d\n", header1.flag_cooling);
    printf("num_files     = %d\n", header1.num_files);
    printf("BoxSize       = %lf\n", header1.BoxSize);
    printf("Omega0        = %lf\n", header1.Omega0);
    printf("OmegaLambda   = %lf\n", header1.OmegaLambda);
    printf("HubbleParam   = %lf\n", header1.HubbleParam);
    
    if(files==1)
    {
      for(k=0, NumPart=0, ntot_withmasses=0; k<5; k++)
        NumPart+= header1.npart[k];
      Ngas= header1.npart[0];
    }
    else
    {
      for(k=0, NumPart=0, ntot_withmasses=0; k<5; k++)
        NumPart+= header1.npartTotal[k];
      Ngas= header1.npartTotal[0];
    }
    
    for(k=0, ntot_withmasses=0; k<5; k++)
    {
      if(header1.mass[k]==0)
        ntot_withmasses+= header1.npart[k];
    }
    
    if(i==0)
      allocate_memory();
    
    
    /*================= read in GADGET particles =================*/
#if (GADGET==2)
    GADGET_SKIP;
    fread(DATA,sizeof(char),4,fd);
    DATA[4] = '\0';
    fprintf(stderr,"\n o reading %s\n",DATA);
    GADGET_SKIP;
    GADGET_SKIP;
#endif
    GADGET_SKIP;
    for(k=0,pc_new=pc;k<6;k++)
    {
      for(n=0;n<header1.npart[k];n++)
      {
        ReadFloat(fd, &(P[pc_new].Pos[0]), SWAPBYTES);
        ReadFloat(fd, &(P[pc_new].Pos[1]), SWAPBYTES);
        ReadFloat(fd, &(P[pc_new].Pos[2]), SWAPBYTES);
        
        /* convert to Mpc/h */
        P[pc_new].Pos[0] *= GADGETlength2Mpc;
        P[pc_new].Pos[1] *= GADGETlength2Mpc;
        P[pc_new].Pos[2] *= GADGETlength2Mpc;
        
        if(P[pc_new].Pos[0] > x_max) x_max=P[pc_new].Pos[0];
        if(P[pc_new].Pos[1] > y_max) y_max=P[pc_new].Pos[1];
        if(P[pc_new].Pos[2] > z_max) z_max=P[pc_new].Pos[2];
        if(P[pc_new].Pos[0] < x_min) x_min=P[pc_new].Pos[0];
        if(P[pc_new].Pos[1] < y_min) y_min=P[pc_new].Pos[1];
        if(P[pc_new].Pos[2] < z_min) z_min=P[pc_new].Pos[2];
        
        
        if(n==0)
          printf("P[%d].Pos = %f  %f  %f\n", pc_new, P[pc_new].Pos[0], P[pc_new].Pos[1], P[pc_new].Pos[2]);
        pc_new++;
      }
    }
    GADGET_SKIP;
    printf("ranges:\n");
    printf("x = %g  %g\n",x_min,x_max);
    printf("y = %g  %g\n",y_min,y_max);
    printf("z = %g  %g\n",z_min,z_max);
 
    /*================= read in GADGET velocities =================*/
#if (GADGET==2)
    GADGET_SKIP;
    fread(DATA,sizeof(char),4,fd);
    DATA[4] = '\0';
    fprintf(stderr,"\n o reading %s\n",DATA);
    GADGET_SKIP;
    GADGET_SKIP;
#endif
    GADGET_SKIP;
    for(k=0,pc_new=pc;k<6;k++)
    {
      for(n=0;n<header1.npart[k];n++)
      {
        ReadFloat(fd, &(P[pc_new].Vel[0]), SWAPBYTES);
        ReadFloat(fd, &(P[pc_new].Vel[1]), SWAPBYTES);
        ReadFloat(fd, &(P[pc_new].Vel[2]), SWAPBYTES);
        
        /* convert to peculiar velocities in km/sec */
        P[pc_new].Vel[0] *= sqrt(header1.time);
        P[pc_new].Vel[1] *= sqrt(header1.time);
        P[pc_new].Vel[2] *= sqrt(header1.time);
        
        if(n==0)
          printf("P[%d].Vel = %f  %f  %f\n", pc_new, P[pc_new].Vel[0], P[pc_new].Vel[1], P[pc_new].Vel[2]);
        pc_new++;
      }
    }
    GADGET_SKIP;
    
    /*================= read in GADGET id's =================*/   
#if (GADGET==2)
    GADGET_SKIP;
    fread(DATA,sizeof(char),4,fd);
    DATA[4] = '\0';
    fprintf(stderr,"\n o reading %s\n",DATA);
    GADGET_SKIP;
    GADGET_SKIP;
#endif
    GADGET_SKIP;
    for(k=0,pc_new=pc;k<6;k++)
    {
      for(n=0;n<header1.npart[k];n++)
      {
        ReadInt(fd, &(Id[pc_new]), SWAPBYTES);
        if(n==0)
          printf("Id[%d] = %d\n", pc_new, Id[pc_new]);
        pc_new++;
      }
    }
    GADGET_SKIP;
    
    if(ntot_withmasses>0)
    {
#if (GADGET==2)
       GADGET_SKIP;
       fread(DATA,sizeof(char),4,fd);
       DATA[4] = '\0';
       fprintf(stderr,"\n o reading %s\n",DATA);
       GADGET_SKIP;
       GADGET_SKIP;
#endif
       GADGET_SKIP;
    }
    for(k=0, pc_new=pc; k<6; k++)
    {
      for(n=0;n<header1.npart[k];n++)
      {
        P[pc_new].Type=k;
        
        if(header1.mass[k]==0)
        {
          ReadFloat(fd, &(P[pc_new].Mass), SWAPBYTES);
          if(n==0)
            printf("P[%d].Mass = %f", pc_new, P[pc_new].Mass);
        }
        else
        {
          P[pc_new].Mass= header1.mass[k];
        }
        
        /* convert to Msun */
        P[pc_new].Mass *= GADGET_MUNIT; 
        
        pc_new++;
      }
    }
    if(ntot_withmasses>0)
    {
#if (GADGET==2)
       GADGET_SKIP;
       fread(DATA,sizeof(char),4,fd);
       DATA[4] = '\0';
       fprintf(stderr,"\n o reading %s\n",DATA);
       GADGET_SKIP;
       GADGET_SKIP;
#endif
       GADGET_SKIP;
    }
    
    if(header1.npart[0]>0)
    {
#if (GADGET==2)
       GADGET_SKIP;
       fread(DATA,sizeof(char),4,fd);
       DATA[4] = '\0';
       fprintf(stderr,"\n o reading %s\n",DATA);
       GADGET_SKIP;
       GADGET_SKIP;
#endif
       GADGET_SKIP;
      for(n=0, pc_sph=pc; n<header1.npart[0];n++)
      {
        ReadFloat(fd, &(P[pc_sph].U), SWAPBYTES);
        if(n==0)
          printf("P[%d].U = %f\n", pc_sph, P[pc_sph].U);
        pc_sph++;
      }
      GADGET_SKIP;
      
#if (GADGET==2)
      GADGET_SKIP;
      fread(DATA,sizeof(char),4,fd);
      DATA[4] = '\0';
      fprintf(stderr,"\n o reading %s\n",DATA);
      GADGET_SKIP;
      GADGET_SKIP;
#endif
      GADGET_SKIP;
      for(n=0, pc_sph=pc; n<header1.npart[0];n++)
      {
        ReadFloat(fd, &(P[pc_sph].Rho), SWAPBYTES);
        if(n==0)
          printf("P[%d].Rho = %f\n", pc_sph, P[pc_sph].Rho);
        pc_sph++;
      }
      GADGET_SKIP;
      
      if(header1.flag_cooling)
      {
#if (GADGET==2)
         GADGET_SKIP;
         fread(DATA,sizeof(char),4,fd);
         DATA[4] = '\0';
         fprintf(stderr,"\n o reading %s\n",DATA);
         GADGET_SKIP;
         GADGET_SKIP;
#endif
         GADGET_SKIP;
        for(n=0, pc_sph=pc; n<header1.npart[0];n++)
        {
          ReadFloat(fd, &(P[pc_sph].Ne), SWAPBYTES);
          if(n==0)
            printf("P[%d].Ne = %f\n", pc_sph, P[pc_sph].Ne);
          pc_sph++;
        }
        GADGET_SKIP;
      }
      else
        for(n=0, pc_sph=pc; n<header1.npart[0];n++)
        {
          P[pc_sph].Ne= 1.0;
          if(n==0)
            printf("P[%d].Ne = %f\n", pc_sph, P[pc_sph].Ne);
          pc_sph++;
        }
    }
    
    fclose(fd);
  }
  
  
  Time= header1.time;
  Redshift= header1.time;

  return 0;

}




/* this routine allocates the memory for the 
 * particle data.
 */
int allocate_memory(void)
{
  printf("allocating memory...\n");
  
  printf("numpart = %d\n", NumPart);
  
  if(!(P=malloc(NumPart*sizeof(struct particle_data))))
  {
    fprintf(stderr,"failed to allocate memory.\n");
    exit(0);
  }
  
  P--;   /* start with offset 1 */
  
  
  if(!(Id=malloc(NumPart*sizeof(int))))
  {
    fprintf(stderr,"failed to allocate memory.\n");
    exit(0);
  }
  
  Id--;   /* start with offset 1 */
  
  printf("allocating memory...done\n");
}




/* This routine brings the particles back into
 * the order of their ID's.
 * NOTE: The routine only works if the ID's cover
 * the range from 1 to NumPart !
 * In other cases, one has to use more general
 * sorting routines.
 */
int reordering(void)
{
  int i,j;
  int idsource, idsave, dest;
  struct particle_data psave, psource;
  
  
  printf("reordering....\n");
  
  for(i=1; i<=NumPart; i++)
  {
    if(Id[i] != i)
    {
      psource= P[i];
      idsource=Id[i];
      dest=Id[i];
      
      do
      {
        psave= P[dest];
        idsave=Id[dest];
        
        P[dest]= psource;
        Id[dest]= idsource;
        
        if(dest == i) 
          break;
        
        psource= psave;
        idsource=idsave;
        
        dest=idsource;
      }
      while(1);
    }
  }
  
  printf("done.\n");
  
  Id++;   
  free(Id);
  
  printf("space for particle ID freed\n");
}




/*
 Read a string of n characters
 */
int ReadString(FILE *fptr,char *s,int n)
{
   int i,c;
   
   if(sizeof(char) != 1)
     {
      fprintf(stderr,"ReadString: sizeof(char)=%ld and not 1\n",sizeof(char));
      exit(0);
     }
   
   s[0] = '\0';
   for (i=0;i<n;i++) {
      c = fgetc(fptr);
      if (c == EOF)
         return(FALSE);
      s[i] = c;
      s[i+1] = '\0';
   }
   return(TRUE);
}

/*
 Read a possibly byte swapped integer
 */
int ReadInt(FILE *fptr,int *n,int swap)
{
   unsigned char *cptr,tmp;
   
   if(sizeof(int) != 4)
     {
      fprintf(stderr,"ReadInt: sizeof(int)=%ld and not 4\n",sizeof(int));
      exit(0);
     }
   
   if (fread(n,4,1,fptr) != 1)
      return(FALSE);
   if (swap) {
      cptr = (unsigned char *)n;
      tmp     = cptr[0];
      cptr[0] = cptr[3];
      cptr[3] = tmp;
      tmp     = cptr[1];
      cptr[1] = cptr[2];
      cptr[2] = tmp;
   }
   return(TRUE);
}

/*
 Read a possibly byte swapped unsigned integer
 */
int ReadUInt(FILE *fptr,unsigned int *n,int swap)
{
   unsigned char *cptr,tmp;
   
   if(sizeof(int) != 4)
     {
      fprintf(stderr,"ReadInt: sizeof(int)=%ld and not 4\n",sizeof(int));
      exit(0);
     }
   
   if (fread(n,4,1,fptr) != 1)
      return(FALSE);
   if (swap) {
      cptr = (unsigned char *)n;
      tmp     = cptr[0];
      cptr[0] = cptr[3];
      cptr[3] = tmp;
      tmp     = cptr[1];
      cptr[1] = cptr[2];
      cptr[2] = tmp;
   }
   return(TRUE);
}

/*
 Read a possibly byte swapped long integer
 */
int ReadLong(FILE *fptr,long *n,int swap)
{
   unsigned char *cptr,tmp;
   
   if(sizeof(long) == 4)
     {
      if (fread(n,4,1,fptr) != 1)
         return(FALSE);
      if (swap) {
         cptr = (unsigned char *)n;
         tmp     = cptr[0];
         cptr[0] = cptr[3];
         cptr[3] = tmp;
         tmp     = cptr[1];
         cptr[1] = cptr[2];
         cptr[2] = tmp;
      }
     }
   else if(sizeof(long) == 8)
     {
      if (fread(n,8,1,fptr) != 1)
         return(FALSE);
      if (swap) {
         cptr = (unsigned char *)n;
         tmp     = cptr[0];
         cptr[0] = cptr[7];
         cptr[7] = tmp;
         tmp     = cptr[1];
         cptr[1] = cptr[6];
         cptr[6] = tmp;
         tmp     = cptr[2];
         cptr[2] = cptr[5];
         cptr[5] = tmp;
         tmp     = cptr[3];
         cptr[3] = cptr[4];
         cptr[4] = tmp;
      }
     }
   else
     {
      fprintf(stderr,"ReadLong: something wrong...cannot read long\n");
      exit(0);
     }
   
   
   
   return(TRUE);
}

/*
 Read a possibly byte swapped long long integer
 */
int ReadLongLong(FILE *fptr,long long *n,int swap)
{
   unsigned char *cptr,tmp;
   
   if (fread(n,8,1,fptr) != 1)
      return(FALSE);
   if (swap) {
      cptr = (unsigned char *)n;
      tmp     = cptr[0];
      cptr[0] = cptr[7];
      cptr[7] = tmp;
      tmp     = cptr[1];
      cptr[1] = cptr[6];
      cptr[6] = tmp;
      tmp     = cptr[2];
      cptr[2] = cptr[5];
      cptr[5] = tmp;
      tmp     = cptr[3];
      cptr[3] = cptr[4];
      cptr[4] = tmp;
   }
   return(TRUE);
}

/*
 Read a possibly byte swapped double precision number
 Assume IEEE
 */
int ReadDouble(FILE *fptr,double *n,int swap)
{
   unsigned char *cptr,tmp;
   
   if(sizeof(double) != 8)
     {
      fprintf(stderr,"ReadDouble: sizeof(double)=%ld and not 8\n",sizeof(double));
      exit(0);
     }
   
   if (fread(n,8,1,fptr) != 1)
      return(FALSE);
   if (swap) {
      cptr = (unsigned char *)n;
      tmp     = cptr[0];
      cptr[0] = cptr[7];
      cptr[7] = tmp;
      tmp     = cptr[1];
      cptr[1] = cptr[6];
      cptr[6] = tmp;
      tmp     = cptr[2];
      cptr[2] = cptr[5];
      cptr[5] = tmp;
      tmp     = cptr[3];
      cptr[3] = cptr[4];
      cptr[4] = tmp;
   }
   
   return(TRUE);
}

/*
 Read a possibly byte swapped floating point number
 Assume IEEE format
 */
int ReadFloat(FILE *fptr,float *n, int swap)
{
   unsigned char *cptr,tmp;
   
   if(sizeof(float) != 4)
     {
      fprintf(stderr,"ReadFloat: sizeof(float)=%ld and not 4\n",sizeof(float));
      exit(0);
     }
   
   if (fread(n,4,1,fptr) != 1)
      return(FALSE);
   if (swap) 
     {
      cptr = (unsigned char *)n;
      tmp     = cptr[0];
      cptr[0] = cptr[3];
      cptr[3] = tmp;
      tmp     = cptr[1];
      cptr[1] = cptr[2];
      cptr[2] = tmp;
     }
   return(TRUE);
}
















