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


typedef struct{
  int atoms;
  int step;
  double a, b, c;
  double alpha, beta, gamma;
  double x_low, x_hi, xy;
  double y_low, y_hi, xz;
  double z_low, z_hi, yz;
  double A[3][3]; /* 並進行列 */
  double B[3][3]; /* 並進逆行列 */
}HEAD;

typedef struct{
  int atoms;   /* 原子数 */
  char **elem; /* 元素名 */
  int *type;     /* 元素type */
  int *id;     /* 0から始まるid */
  double *x, *y, *z; /* 絶対座標 */
  double *vx, *vy, *vz; /* 速度 */
  double *fx, *fy, *fz; /* 速度 */
}ATOMS;

/* 引数解析用 */
typedef struct{
  int atoms; /* 原子数 */
  int steps; /* トータルステップ数 */
  char infile[1024];
  char outfile[1024];
  char mode[1024];   /* grかmsd */
  int *Aid;     /* 原子数, id1, id2, id3... */
  int *Bid;     /* 原子数, id1, id2, id3... */
  int *Cid;     /* 原子数, id1, id2, id3... */
  char Aelem[256];   /* 引数で与える中心元素名 */
  char Belem[256];   /* 引数で与えるカウンター元素名 */  
  char Celem[256];   /* 引数で与えるカウンター元素名 */  
  int  Atype;        /* 引数で与える原子タイプ */
  int  Btype;        /* 引数で与える原子タイプ */
  int  Ctype;        /* 引数で与える原子タイプ */
}PARAM; 

void Error();
int SetArgment(int, char**, PARAM*);
void Allocate(ATOMS*, int);
void Deallocate(ATOMS *a, int n);
void GetData(FILE *f, PARAM* para, HEAD *head, ATOMS *a, ATOMS *b, ATOMS *c);
void GetAllData(FILE *f, PARAM* p, HEAD *head, ATOMS *a);
void EstimateGr(PARAM *param);
void EstimateDistance(PARAM *param);
void EstimateAngle(PARAM *param);
int CheckArgAtomSelect(PARAM *p);
void GetDataFixID(FILE *f, PARAM* p, HEAD *head, ATOMS *a);
void EstimateMSD(PARAM *param);
void GetOneStepData(FILE *f, HEAD *head, ATOMS *a);
void SetIDfromElemTtype(PARAM *param);
void EstimateCube(PARAM *param);
int Eleme2AtomicNumber(char *elem);
void SetAtomsSteps(PARAM *param);
void ArgCheck(PARAM *arg);
int ArgCheckInputOutput(PARAM *arg);
void EstimateVelocityCorr(PARAM *param);
void EstimateCube_Jump(PARAM *param);
void EstimateCube_Radius(PARAM *param);
void OutputCube(PARAM *p, double ***rho);
int* SetIDfromMolecules(int *Aid, int n);
void EstimateRotationCorr(PARAM *param);
void EstimateVanHove(PARAM *param);
void Unwrap(int steps, int atoms, double **x, double **y, double **z);
  
extern double DT;
extern int TAU;
extern int TAU_SHIFT;
extern double DR;
extern double RMAX;
extern double RMIN;
extern double RCUT;
extern double RCUT_AB;
extern double RCUT_BC;
extern double DA;
extern int NX, NY, NZ, CUBE_TYPE;
extern double RADIUS;
