#include "AdvInsMEM.hh"

/*
       decombolution of resolution function by Maximum Entropy Method
         for high-resolution inelastic x-ray scattering spectra
             measured at SPring8 BL35XU
                  Copy right     Yukinobu KAWAKITA (Kyushu Univ.)
                  2002.9.13

       transfer insmem2.for (Fortran)  to Insmem.c (C) by AdvanceSoft. 2010.05.12

*/
    /*
     * global constant list
     * @param max_data_size maximum number of treated data
     * @param max_num_lorentzian_functions maximum number of Lorentzian functions used for initialization in MEM
     * @param pi pi
     * @param length_buffer length of buffer used for analysis of input sentence
     * @param length_filename length of filename
     * @param sect integration s[e] from e[0] to e[ndat-1]
     * @param rfac R-factor
    */

/*
int main()
{
//int LineDefParam[7]={2,2,3,4,1,2,3};
//double omegaInParam[]={1.0,1.1};
//double ene0InParam[]={1.0,1.1};
//double valInParam[]={1.0,1.1};

//AdvInsMEM::AdvInsMEM("sDET05","sV_5",1,1,LineDefParam,omegaInParam,ene0InParam,valInParam,10,1.0,"/usr/local/mlf/DNA/tmp/Mem/");


AdvInsMEM::AdvInsMEM();

}
*/
//////////////////////////////////////////////////////////

AdvInsMEM::
AdvInsMEM(char *DataFileName,char *ResFileName,int memData,int NumOfLor,int *LineDefParam,double *omegaInParam,double *ene0InParam,double valInParam[],int Itteration,double MemThreshold,char *savepath)
{


/*
    AdvInsMEM(char *DataFileName,char *ResFileName,int memData,int NumOfLor,int LineDefParam[],double omegaInParam[],
                                             double ene0InParam[],double valInParam[],int Itteration,double MemThreshold,char *savepath)

    * @param char *DataFileName   :: Experimental data File Name (ascii file)
    * @param char *ResFileName    :: Resolution data File Name (ascii file)
    * @param int   memData        :: MEM -- Initial Data
    *              1 = Conbination of Lorentzian functions / 2 = Observed data
    * @param int   NumOfLor       :: Number of Lorenzian function (fitting functions)
    * @param int   LineDefParam[] :: array ::
    *              line definition parameter
    *              LineDefParam[0]:: cmlineData :: Number of comment Line of Experimental-data-File
    *              LineDefParam[1]:: KcorEin    :: Column number of Energy Axis
    *              LineDefParam[2]:: KcorSin    :: Column number of Scattering Intensity
    *              LineDefParam[3]:: KcorRin    :: Column number of Statistic Error of Event
    *              LineDefParam[4]:: cmlineRes  :: Number of comment Line of Resolution-data-File
    *              LineDefParam[5]:: LcorEIn    :: Column number of Energy Axis
    *              LineDefParam[6]:: LcorNIn    :: Column number of Scattering Intensity
    * @param int   omegaInParam[] :: array :: Lorentian function initial parameter :: omega (meV)
    * @param int   ene0InParam[]  :: array :: Lorentian function initial parameter :: center energy (meV)
    * @param int   valInParam[]   :: array :: Lorentian function initial parameter :: relative intensity
    * @param int   Itteration     :: Maximum number of itteration
    * @param double MemThreshold  :: MEM threshold value
    * @param char  *savepath      :: temporary save file path
*/


    /** maximaum number of treated data */
    max_data_size=4096;
    /** maximum number of Lorentzian functions used for initialization in MEM */
    max_num_lorentzian_functions=10;
    /** pi */
    pi=3.14159265359;
    /** length of buffer used for analysis of input sentence */
    length_buffer=256;
    /** length of filename */
    length_filename=30;

    MessageTag = "Mem >> ";
    basepath = savepath;

    /* input parameter */

    manual=0;

    /* file name parameter */
    fname = DataFileName;
    fnameRes = ResFileName;

    /* line definition parameter */
    cmlineData = LineDefParam[0];
    KcorEin = LineDefParam[1];
    KcorSin = LineDefParam[2];
    KcorRin = LineDefParam[3];
    cmlineRes = LineDefParam[4];
    LcorEIn = LineDefParam[5];
    LcorNIn = LineDefParam[6];

    /*resolution function parameter */
    memDatain = memData;
    nlorin = NumOfLor;

    omegaIn=alloc_float(nlorin);
    ene0In=alloc_float(nlorin);
    valIn=alloc_float(nlorin);

    for (int i=0;i<nlorin;i++)
        {
            omegaIn[i] = omegaInParam[i];
            ene0In[i] = ene0InParam[i];
            valIn[i] = valInParam[i];
        }

    maxcIn = Itteration;
    constraintIn = MemThreshold;

    execute();
}

//////////////////////////////////////////////////////////

AdvInsMEM::
AdvInsMEM()
{

//Begin("sDET05","sV_5",1,2,2,2,3,4,1,2,3, 10 ,1.0,"/usr/local/mlf/DNA/tmp/Mem/");

}

//////////////////////////////////////////////////////////

AdvInsMEM::
~AdvInsMEM()
{
}
//////////////////////////////////////////////////////////


int AdvInsMEM::
Manual()
{
    /** maximaum number of treated data */
    max_data_size=4096;
    /** maximum number of Lorentzian functions used for initialization in MEM */
    max_num_lorentzian_functions=10;
    /** pi */
    pi=3.14159265359;
    /** length of buffer used for analysis of input sentence */
    length_buffer=256;
    /** length of filename */
    length_filename=30;

    MessageTag = "Mem >> ";

    /* input parameter */

    manual=1;

    execute();
    return 0;
}

//////////////////////////////////////////////////////////


/**
 * allocate memory of float type variable
 * @param size number of data size
*/
float* AdvInsMEM::alloc_float(int size){
  /* name of float pointer variable */
  float* val;
  val=(float* ) calloc(size, sizeof(float));
  return val;
}


int AdvInsMEM::Begin(char *DataFileName,char *ResFileName, int memData,int NumOfLor, int cmlineDataParam, int KcorEinParam,int KcorSinParam, int KcorRinParam,int cmlineResParam,int LcorEInParam, int LcorNInParam, int Itteration,double MemThreshold,char *savepath)
{

/*
int AdvInsMEM::Begin(char *DataFileName,char *ResFileName, int memData,int NumOfLor, int cmlineDataParam, int KcorEinParam,int KcorSinParam, int KcorRinParam,int cmlineResParam,int LcorEInParam, int LcorNInParam, int Itteration,double MemThreshold,char *savepath)

    * @param char *DataFileName   :: Experimental data File Name (ascii file)
    * @param char *ResFileName    :: Resolution data File Name (ascii file)
    * @param int   memData        :: MEM -- Initial Data
    *              1 = Conbination of Lorentzian functions / 2 = Observed data
    * @param int   NumOfLor       :: Number of Lorenzian function (fitting functions)
    * @param int
    *              line definition parameter
    * @param int   cmlineDataParam :: Number of comment Line of Experimental-data-File
    * @param int   KcorEinParam    :: Column number of Energy Axis
    * @param int   KcorSinParam    :: Column number of Scattering Intensity
    * @param int   KcorRinParam    :: Column number of Statistic Error of Event
    * @param int   cmlineResParam  :: Number of comment Line of Resolution-data-File
    * @param int   LcorEInParam    :: Column number of Energy Axis
    * @param int   LcorNInParam    :: Column number of Scattering Intensity
    * @param int   Itteration     :: Maximum number of itteration
    * @param double MemThreshold  :: MEM threshold value
    * @param char  *savepath      :: temporary save file path
*/


    /** maximaum number of treated data */
    max_data_size=4096;
    /** maximum number of Lorentzian functions used for initialization in MEM */
    max_num_lorentzian_functions=10;
    /** pi */
    pi=3.14159265359;
    /** length of buffer used for analysis of input sentence */
    length_buffer=256;
    /** length of filename */
    length_filename=30;

    MessageTag = "Mem >> ";
    basepath = savepath;

    /* input parameter */

    manual=0;


double a[20]={0};
double b[20]={0};
double c[20]={0};
FILE *iniFp;
//char s[256];
if ((iniFp = fopen("/usr/local/mlf/DNA/tmp/Mem/initParam.txt", "r")) == NULL) {
		std::printf("file open error!!\n");
		exit(EXIT_FAILURE);
	}
	int line =0;

while((fscanf(iniFp, "%lf", &a[line]) != EOF) && (fscanf(iniFp, " %lf", &b[line]) != EOF) && (fscanf(iniFp, " %lf", &c[line]) != EOF)) {
line++;
}

double omegaInParam[20];
double ene0InParam[20];
double valInParam[20];


for (int num=0;num<line;num++){
    omegaInParam[num] = a[num];
    ene0InParam[num] = b[num];
    valInParam[num] = c[num];
}

//int LineDefParam[7]={2,2,3,4,1,2,3};

//double omegaInParam[]={1.0,1.1};
//double ene0InParam[]={1.0,1.1};
//double valInParam[]={1.0,1.1};

    /* file name parameter */
    fname = DataFileName;
    fnameRes = ResFileName;

    /* line definition parameter */

    cmlineData = cmlineDataParam;
    KcorEin = KcorEinParam;
    KcorSin = KcorSinParam;
    KcorRin = KcorRinParam;
    cmlineRes = cmlineResParam;
    LcorEIn = LcorEInParam;
    LcorNIn = LcorNInParam;

    /*resolution function parameter */

    memDatain = memData;
    nlorin = NumOfLor;

    omegaIn=alloc_float(nlorin);
    ene0In=alloc_float(nlorin);
    valIn=alloc_float(nlorin);

    for (int i=0;i<nlorin;i++)
        {
            omegaIn[i] = omegaInParam[i];
            ene0In[i] = ene0InParam[i];
            valIn[i] = valInParam[i];
        }

    maxcIn = Itteration;
    constraintIn = MemThreshold;

    execute();
return 0;
}


int AdvInsMEM::execute(){
  /* enum Opetype :: specifying operation type */
  enum OpeType {Newdata=4, Initialize=2, MEM=3, OutputSqe=1} Operation;
  /* int imode :: specifying Mem operation mode*/
  int imode;
  /* int flag :: flag for input */
  int flag;
  /* loop_flag :: flag for loop */
  int loop_flag;

  int ret;

  loop_flag=0;
  Operation=Newdata;

  /*
     float *tmp_e :: temporary allocated memory for read observation data of energy
     float *tmp_s :: temporary allocated memory for read observation data of scattering intensity
     float *tmp_r :: temporary allocated memory for read statistical errors
     float *e :: allocated memory for read observation data of energy
     float *s :: allocated memory for read observation data of scattering intensity
     float *r :: allocated memory for read statistical errors
  */
  float *tmp_e, *tmp_s, *tmp_r, *e, *s, *r;
    e=0;
    s=0;
    r=0;
  float *er, *sr, *tmp_er, *tmp_sr;
    er=0;
    sr=0;
  /*
     float *th0 :: allocated memory for the initial S(q,e)
     float *th1 :: allocated memory for the present S(q,e)
     float *thcal :: alllocated memory for the S(q,e) times resolution
  */
  float *th0, *th1;
    th0=0;
    th1=0;
  //float thcal[max_data_size];
  float* thcal = new float[max_data_size];

  /*
     buffer :: sentence given by user by console input
     finam  :: filename of observation data
     fires  :: filename of resolution data
  */
  char* buffer = new char[length_buffer]; //char buffer[length_buffer];
  char* finam = new char[length_filename]; //char finam[length_filename];
  char* fires = new char[length_filename]; //char fires[length_filename];
  int endflag=0;

  while(loop_flag==0){
    int nmin = 0;
    int nmax = 0;
    switch(Operation){
      case Newdata:
      /* opening comment */
        std::printf("%s \n", MessageTag);
        std::printf("%s $*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$\n", MessageTag);
        std::printf("%s \n", MessageTag);
        std::printf("%s This program is for the analysis of high-resolution\n", MessageTag);
        std::printf("%s inelastic x-ray scattering spectra. \n", MessageTag);
        std::printf("%s Data format is the same as the output \n", MessageTag);
        std::printf("%s  from ICSCAN*.for which produced by Dr. A. Baron \n", MessageTag);
        std::printf("%s   and alternated by Dr. Y. Kawakita.\n", MessageTag);
        std::printf("%s   transfer insmem2.for (Fortran)  to Insmem.c (C)\n", MessageTag);
        std::printf("%s         by AdvanceSoft. 2012.06.12\n", MessageTag);
        std::printf("%s \n", MessageTag);
        std::printf("%s $*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$\n", MessageTag);
        std::printf("%s \n", MessageTag);

      /* data spectrum (open & read) */
        /*
          int ndat :: valid number of data of energies in observation data file
        */
        int ndat;
        tmp_e=alloc_float(max_data_size);
        tmp_s=alloc_float(max_data_size);
        tmp_r=alloc_float(max_data_size);

        ret = read_data_spectrum(&ndat, tmp_e, tmp_s, tmp_r, finam);
        if (ret==1)
        {
        return 1;
        }

        e=alloc_float(ndat);
        s=alloc_float(ndat);
        r=alloc_float(ndat);
        int i;
        for(i=0; i<ndat; i++){
          e[i]=tmp_e[i];
          s[i]=tmp_s[i];
          r[i]=tmp_r[i];
        }
        free(tmp_e);
        free(tmp_s);
        free(tmp_r);

      /* resolution function data (open & read) */
        /*
          int nres :: valid number of data of energies in resolution data file
        */
        int nres;
        tmp_er=alloc_float(max_data_size);
        tmp_sr=alloc_float(max_data_size);
        ret = read_data_resolution(&nres, tmp_er, tmp_sr, fires);
        if (ret==1)
        {
        return 1;
        }

        er=alloc_float(nres);
        sr=alloc_float(nres);
        for(i=0; i<nres; i++){
          er[i]=tmp_er[i];
          sr[i]=tmp_sr[i];
        }
        free(tmp_er);
        free(tmp_sr);

        /*
          float eedge :: half of the energy width treated in resolution data file
          float emin :: considered minimum energy for MEM treatment
          float emax :: considered maximum energy for MEM treatment
          int nmin   :: index for minimum energy treated in MEM procedure
          int nmax   :: index for maximum energy treated in MEM procedure
        *//*
         * @param nres valid number of data of energies in resolution data file
         * @param *er observation data of energy
         * @param *sr observation data of scattering intensity
        */

        float eedge, emin, emax;
        //int nmin;
        //int nmax;

        eedge=0.5*(er[nres-1]-er[0]);
        if(eedge<0.0) eedge=-eedge;
        emin=e[0]+eedge;
        emax=e[ndat-1]-eedge;
        nmin=0;
        nmax=0;
        //20120625 AS Miyashita comment out
        //        for(i=0; i<ndat; i++){
        //          if(e[i]<=emin) nmin++;
        //          if(e[i]<emax) nmax++;
        //        }
        //20120625 AS Miyashita comment out end
        //20120625 AS Miyashita replace L437-442
        for(i=0; i<ndat; i++){
          if(e[i]<emin) nmin++;
          if(e[i]<=emax) nmax++;
     //     std::printf("Debug >>  e[%d]=%f\n",i,e[i]);
        }
        //20120625 AS Miyashita replace L437-442 end
        //20120625 AS : Recomment adding a judgment,"nmin < nmax ?", "eimn < emax ?","ndat < nres?"
        //20120625 AS : In case "ndat < nres", what happens?, Unexpected input value ??
        //20120625 AS : In case "e[ndat]-e[0] < er[ndat]-er[0]", what happens?, Unexpected input value ??
        //20120625 AS : probably. eedge value is too large, emin > emax.

     //   for(i=0; i<nres; i++){
     //     std::printf("Debug >>  er[%d]=%f\n",i,er[i]);
      //  }


        nmin-=1;
        nmax-=1;
        std::printf("Debug >>  ndat=%d\n",ndat);
        std::printf("Debug >>  e[0]=%f\n",e[0]);
        std::printf("Debug >>  e[ndat-1]=%f\n",e[ndat-1]);
        std::printf("Debug >>  eedge=%f\n",eedge);

        std::printf("Debug >>  nres=%d\n",nres);
        std::printf("Debug >>  emin=%f\n",emin);
        std::printf("Debug >>  emax=%f\n",emax);

        std::printf("Debug >>  nmin=%d\n",nmin);
        std::printf("Debug >>  nmax=%d\n",nmax);


      /* graphics */
        graphics_treatment(ndat, nres, e, s, er, sr);

      case Initialize:
      /* MEM PROCEDURES */
        /* initialize */
        th0=alloc_float(ndat);
        th1=alloc_float(ndat);
        init_mem_proc(ndat, nres, e, s, er, sr, th0, thcal);
        for(i=0; i<ndat; i++) th1[i]=th0[i];

      case MEM:
if (manual == 1)
{
        flag=0;
        imode=1;
        while(flag==0){
          std::printf("%s MEM (1=step by step / 2=auto) ::", MessageTag);
          //fgets(buffer, length_buffer, stdin);
	  while((fgets(buffer, length_buffer, stdin) == NULL) || (buffer[0] == '\n')){
	    std::printf("Invalid :: ");
	  }
          std::sscanf(buffer, "%d", &imode);
          if(imode != 2) imode=1;
          flag=1;
        }
}
else if (manual==0)
{
imode =2;
}
        main_mem_proc(&imode, ndat, nres, th0, th1, thcal, e, s, r, er, sr, nmin, nmax);
        break;

      case OutputSqe:
        char fiout[256];
if (manual ==1)
{
        std::printf("%s output file name ? :: ", MessageTag);
        //fgets(buffer, length_buffer, stdin);
	while((fgets(buffer, length_buffer, stdin) == NULL) || (buffer[0] == '\n')){
	  std::printf("Invalid :: ");
	}
        /*
          length_file :: length of filename for outputfile of S(q,e)
          fiout       :: output file name for S(q,e)
          *fpout      :: file pointer for output file name for S(q,e)
        */
        //int length_file=std::strlen(buffer);
        //int length_file=256;
        std::sscanf(buffer, "%s", fiout);
}
else if (manual == 0)
{

  char *filenamesqe;
  char basepath_array7[256];
  std::strcpy(basepath_array7,basepath);
  filenamesqe=std::strcat(basepath_array7,"outputSqe.txt");

        std::snprintf(fiout, sizeof(fiout), "%s", filenamesqe);

        std::printf("%s output file name  = %s \n", MessageTag,"outputSqe.txt");
        std::snprintf(buffer, length_buffer, "%s", fiout);
}
        FILE* fpout;
        if( !(fpout=fopen(fiout, "w")) ){
          std::printf("%s fiout file cannot open. \n", MessageTag);
          std::printf("%s Program was exited abnormally.\n", MessageTag);
          exit(1);
        }
       std::fprintf(fpout, "MEM procedure   R-factor = %f\n", rfac);
       std::fprintf(fpout, "spectrum   : %s \n", finam);
       std::fprintf(fpout, "resolution : %s \n", fires);
        int j;
        for(j=0; j<ndat; j++){
         std::fprintf(fpout, "%10.5f\t%10.5f\t%10.5f\t%10.5f\t%14.7e\t%14.7e\t%14.7e\n",
                  e[j], s[j], th1[j], thcal[j], sect*s[j], sect*th1[j], sect*thcal[j]);
        }
        fclose(fpout);
    }

    if(Operation != OutputSqe){
      if(imode != 1){
        std::printf("%s PLOT DATA IN A GRAPH SOFTWARE (ex. NGRAPH)\n", MessageTag);
        std::printf("%s     TEMP5.DAT    :present S(q,e)\n", MessageTag);
        std::printf("%s     TEMP6.DAT    : -----*resolution\n", MessageTag);
      }
    }

    /*
      int nn :  1: outputSqe
                2: initialize
                3: MEM
                4: new data
                5: end
    */
    int nn = 0;

if (manual ==1)
{
    flag=0;
    while(flag==0) {
      std::printf("%s 1=outputSqe /2=initialize /3=MEM /4=new data /5=end :: ", MessageTag);
      //fgets(buffer, length_buffer, stdin);
      while((fgets(buffer, length_buffer, stdin) == NULL) || (buffer[0] == '\n')){
	std::printf("Invalid :: ");
      }
      std::sscanf(buffer, "%d", &nn);
      if(nn<1 || nn>5) continue;
      flag=1;
    }
}
else if (manual ==0)
{
if(endflag!=1)
  {
      nn = 1;
//      std::sprintf(buffer, "%d", &nn);
      std::snprintf(buffer, length_buffer, "%d", nn);
      endflag = 1;
  }
//else if (endflag==1)
else
  {
      nn = 5;
//      std::sprintf(buffer, "%d", &nn);
      std::snprintf(buffer, length_buffer, "%d", nn);
  }
}


    if(nn==5) break;
    Operation=(enum OpeType) nn;
    if(Operation == Newdata){
      free(er);
      free(sr);
      free(e);
      free(s);
      free(r);
      free(th0);
      free(th1);
    }
    if(Operation == Initialize){
      free(th0);
      free(th1);
    }
  }
  std::printf("%s program finish \n", MessageTag);
delete [] thcal;
delete [] buffer;
delete [] finam;
delete [] fires;
return 0;
}

/**
 * read observation data file and set data to variables
 * @param ndat valid number of data of energies in observation data file
 * @param *e observation data of energy
 * @param *s observation data of scattering intensity
 * @param *r statistical errors
 * @param finam filename of observation data
 */
int AdvInsMEM::read_data_spectrum(int* ndat, float* e, float* s, float* r, char* finam){
  /*
     KcorE :: data colum number for the value of energy in the observation data file
     KcorS :: data colum number for the value of scattering intensity in the observation data file
     KcorR :: data colum number for the value of statistical error in the observation data file
  */
  int KcorE, KcorS, KcorR;
  int ret = 0;
  KcorE=2;
  KcorS=3;
  KcorR=4;

  /*
     char buffer[] :: sentence given by user by console input
     FILE*   fp_in :: file pointer for observation data file
     int  check    :: flag for input
     float *address_s :: pointer for the varaiable "s"
           *address_r :: pointer for the varaiable "r"
           *address_e :: pointer for the varaibale "e"
  */
  char* buffer = new char[length_buffer]; //char buffer[length_buffer];
  FILE* fp_in;
  int check;
  float *address_s, *address_r, *address_e;

  address_s=s;
  address_r=r;
  address_e=e;

if (manual==1)
{
  check=0;
  std::printf("%s Input data file name :: ", MessageTag);
  while(check==0){
    //fgets(buffer, length_buffer, stdin);
    while((fgets(buffer, length_buffer, stdin) == NULL) || (buffer[0] == '\n')){
      std::printf("Invalid :: ");
    }
    std::sscanf(buffer, "%s", finam);
    if(!(fp_in=fopen(finam, "r"))){
      std::printf("%s Input file is not found :: input file name = %s.\n", MessageTag, finam);
      std::printf("%s Please input file name again", MessageTag);
    } else {
      check=1;
    }
  }
}

else if (manual==0)
{
  check=0;
  std::printf("%s Input data file name :: %s\n", MessageTag,fname);
  while(check==0){
//    fgets(buffer, length_buffer, stdin);
    finam = fname;
    std::snprintf(buffer, length_buffer, "%s", finam);

    if(!(fp_in=fopen(finam, "r"))){
      std::printf("%s Input file is not found :: input file name = %s.\n", MessageTag, finam);
      std::printf("%s Please input file name again", MessageTag);
      delete [] buffer;
      return 1;
    } else {
      check=1;
    }
  }

}
  /*
    int ncom :: number of lines for comment in the observation file
  */
  int ncom;
if (manual==1)
{

  std::printf("%s How many comment lines ? :: ", MessageTag);
  check=0;
  while(check==0){
    //fgets(buffer, length_buffer, stdin);
    while((fgets(buffer, length_buffer, stdin) == NULL) || (buffer[0] == '\n')){
      std::printf("Invalid :: ");
    }
    if( !(std::strlen(buffer)) || !(std::sscanf(buffer, "%d", &ncom)) ){
      std::printf("%s Input Error!!!\n", MessageTag);
      std::printf("%s Please input digital number again\n", MessageTag);
    } else {
      check=1;
    }
  }
}

if (manual==0)
{
  std::printf("%s comment lines :: %i\n", MessageTag,cmlineData);
  check=0;
  while(check==0){
//    fgets(buffer, length_buffer, stdin);
    ncom = cmlineData;
//    if( !(std::strlen(buffer)) || !(std::sprintf(buffer, "%d",&ncom)) ){
    if( !(std::strlen(buffer)) || !(std::snprintf(buffer, length_buffer, "%d",ncom)) ){
      std::printf("%s Input Error!!!\n", MessageTag);
      std::printf("%s Please input digital number again\n", MessageTag);
      delete [] buffer;
      return 1;
    } else {
      check=1;
    }
  }
}



  int i;
  for(i=0; i<ncom; i++){
    //fgets(buffer, length_buffer, fp_in);
    if (fgets(buffer, length_buffer, fp_in) != NULL)
      std::printf("%s %s", MessageTag, buffer);
  }

if( manual ==1)
{
  check=0;
  while (check==0) {
    std::printf("%s Column number of energy axis ? < default= %d > :: ", MessageTag, KcorE);
    ret = set_column_num(&KcorE, &check);
  }
  check=0;
  while (check==0){
    std::printf("%s Column number of scattering intensity ? < default = %d > :: ", MessageTag, KcorS);
    ret = set_column_num(&KcorS, &check);
  }
  check=0;
  while (check==0){
    std::printf("%s Column number of statistical error ? < default = %d > :: ", MessageTag, KcorR);
    ret = set_column_num(&KcorR, &check);
  }
}

if( manual ==0)
{
  KcorE = KcorEin;
  KcorS = KcorSin;
  KcorR = KcorRin;

  check=0;
  while (check==0) {
    std::printf("%s Column number of energy axis = %d :: \n", MessageTag, KcorE);
    ret = set_column_num(&KcorE, &check);
  }
  check=0;
  while (check==0){
    std::printf("%s Column number of scattering intensity = %d :: \n", MessageTag, KcorS);
    ret = set_column_num(&KcorS, &check);
  }
  check=0;
  while (check==0){
    std::printf("%s Column number of statistical error = %d :: \n", MessageTag, KcorR);
    ret = set_column_num(&KcorR, &check);
  }
}

  KcorE--;
  KcorS--;
  KcorR--;

  /*
    int maxd :: maximum number in KcorE, KcorS and KcorR
  */
  int maxd;
  maxd=0;
  if(KcorE>maxd) maxd=KcorE;
  if(KcorS>maxd) maxd=KcorS;
  if(KcorR>maxd) maxd=KcorR;

  /*
    float ek_threshold :: threshold value for energy
    float sk_threshold :: threshold value for scattering intensity
  */
  //float ek_threshold=-3.5;
  float sk_threshold=0.0;

  int k;
  k=0;

  while (fgets(buffer, length_buffer, fp_in)!=NULL) {
      int count;
      char* p;
      count=0;
      p=std::strtok(buffer, " ,:;/");
      if(KcorE==count) std::sscanf(p, "%f", e);
      if(KcorS==count) std::sscanf(p, "%f", s);
      if(KcorR==count) std::sscanf(p, "%f", r);
      while ( (p=std::strtok(NULL, " ,:;/")) != NULL){
        count++;
        if(count>maxd) break;
        if(KcorE==count) std::sscanf(p, "%f", e);
        if(KcorS==count) std::sscanf(p, "%f", s);
        if(KcorR==count) std::sscanf(p, "%f", r);
      }
     // 2012 07/03 AS Miyashita comment out
     // if(*e<ek_threshold ) continue;
      if(*s<sk_threshold ){
        *s=0.0;
        *r=0.0;
      }
      k++;
      if(k==max_data_size) break;
      e++;
      s++;
      r++;
  }
  fclose(fp_in);
  *ndat=k;

  s=address_s;
  r=address_r;
  e=address_e;

  trap(e, s, *ndat, &sect);
  std::printf("%s normalization of spectrum :: sect=%f\n", MessageTag, sect);

  for(i=0; i<*ndat; i++){
    *s/=sect;
    *r/=sect;
    s++;
    r++;
  }
  delete [] buffer;
  return 0;
}

/**
 * set column number to variable column
 * @param column_num column number for energy or intensity or stastical error
 * @param flag flag for input
*/
int AdvInsMEM::set_column_num(int* column_num, int* flag){
  /*
     char buffer[] :: sentence given by user by console input
  */
  char* buffer = new char[length_buffer]; //char buffer[length_buffer];

if (manual==1)
{
  *flag=0;
  while(*flag==0){
    //fgets(buffer, length_buffer, stdin);
    while((fgets(buffer, length_buffer, stdin) == NULL) || (buffer[0] == '\n')){
      std::printf("Invalid :: ");
    }
    std::printf("%s read %s", MessageTag, buffer);
    if(std::strlen(buffer)){
      if( !(std::sscanf(buffer, "%d", column_num)) ){
        std::printf("%s Input Error!!!\n", MessageTag);
        std::printf("%s Please input digital number again\n", MessageTag);
      } else {
        *flag=1;
      }
    } else {
      *flag=1;
    }
  }
}
else if (manual==0)
{
  *flag=0;
  while(*flag==0){
   // fgets(buffer, length_buffer, stdin);
    //std::printf("%s read %s\n", MessageTag, buffer);
    if(std::strlen(buffer)){
      //if( !(std::sprintf(buffer, "%d", column_num)) ){
      if( !(std::snprintf(buffer, length_buffer, "%d", *column_num)) ){
        std::printf("%s Input Error!!!\n", MessageTag);
        std::printf("%s Please input digital number again\n", MessageTag);
        delete [] buffer;
        return 1;
      } else {
        *flag=1;
      }
    } else {
      *flag=1;
    }
  }
}

  delete [] buffer;
  return 0;
}

/**
 * read resolution data file and set data to variables
 * @param nres valid number of data of energies in resolution data file
 * @param *er observation data of energy
 * @param *sr observation data of scattering intensity
 * @param fires filename of resolution data
 */
int AdvInsMEM::read_data_resolution(int* nres, float* er, float* sr, char* fires){
  /*
     LcorE :: data column number for the value of energy in the resolution data file
     LcorN :: data column number for the value of scattering intensity in the resolution data file
  */
  int LcorE, LcorN;
  LcorE=2;
  LcorN=3;
  int ret = 0;
  /*
     char buffer[] :: sentence given by user by console input
     FILE*   fp_in :: file pointer for resolution data file
     int  check    :: flag for input
     float *address_sr :: pointer for the varaiable "sr"
           *address_er :: pointer for the varaibale "er"
  */
  char* buffer = new char[length_buffer]; //char buffer[length_buffer];
  FILE* fp_in;
  int check;
  float *address_sr, *address_er;

  address_sr=sr;
  address_er=er;

if (manual==1)
{
  check=0;
  std::printf("%s Input file name for the resolution function :: ", MessageTag);
  while(check==0){
    //fgets(buffer, length_buffer, stdin);
    while((fgets(buffer, length_buffer, stdin) == NULL) || (buffer[0] == '\n')){
      std::printf("Invalid :: ");
    }
    std::sscanf(buffer, "%s", fires);
    if(!(fp_in=fopen(fires, "r"))){
      std::printf("%s Input file is not found :: input file name = %s.\n", MessageTag, fires);
      std::printf("%s Please input file name again\n", MessageTag);
    } else {
      check=1;
    }
  }
}
else if (manual==0)
{
  check=0;
  std::printf("%s Input file name for the resolution function :: %s\n", MessageTag,fnameRes);
  while(check==0){
    fires = fnameRes;
    //fgets(buffer, length_buffer, stdin);
    std::snprintf(buffer, length_buffer, "%s", fires);
    if(!(fp_in=fopen(fires, "r"))){
      std::printf("%s Input file is not found :: input file name = %s.\n", MessageTag, fires);
      std::printf("%s Please input file name again\n", MessageTag);
      delete [] buffer;
      return 1;
    } else {
      check=1;
    }
  }
}

  /*
    int ncom :: number of lines for comment in the observation file
  */
  int ncom = 0;
if (manual==1)
{
  check=0;
  std::printf("%s How many comment lines ? :: ", MessageTag);

  while(check==0){
    //fgets(buffer, length_buffer, stdin);
    while((fgets(buffer, length_buffer, stdin) == NULL) || (buffer[0] == '\n')){
      std::printf("Invalid :: ");
    }
    if( !(std::strlen(buffer)) || !(std::sscanf(buffer, "%d", &ncom)) ){
      std::printf("%s Input Error!!!\n", MessageTag);
      std::printf("%s Please input digital number again\n", MessageTag);
    } else {
      check=1;
    }
  }
}
else if (manual == 0)
{
  check=0;
  std::printf("%s How many comment lines = %d :: \n", MessageTag,cmlineRes);

  while(check==0){
//    fgets(buffer, length_buffer, stdin);
    ncom = cmlineRes;
    if( !(std::strlen(buffer)) || !(std::snprintf(buffer, length_buffer, "%d", ncom)) ){
      std::printf("%s Input Error!!!\n", MessageTag);
      std::printf("%s Please input digital number again\n", MessageTag);
      delete [] buffer;
      return 1;
    } else {
      check=1;
    }
  }
}

  int i;
  for(i=0; i<ncom; i++){
    //fgets(buffer, length_buffer, fp_in);
    if (fgets(buffer, length_buffer, fp_in) != NULL)
      std::printf("%s %s\n", MessageTag, buffer);
  }

if (manual==1)
{
  check=0;
  while (check==0) {
    std::printf("%s Column number of energy axis =  ? < default= %d > ::  ", MessageTag, LcorE);
    ret = set_column_num(&LcorE, &check);
  }
  check=0;
  while (check==0){
    std::printf("%s Column number of scattering intensity =  ? < default= %d > ::  ", MessageTag, LcorN);
    ret = set_column_num(&LcorN, &check);
  }
}
else if (manual==0)
{
  LcorE = LcorEIn;
  LcorN = LcorNIn;

  check=0;
  while (check==0) {
    std::printf("%s Column number of energy axis = :: %d\n", MessageTag, LcorE);
    ret = set_column_num(&LcorE, &check);
  }
  check=0;
  while (check==0){
    std::printf("%s Column number of scattering intensity = :: %d\n", MessageTag, LcorN);
    ret = set_column_num(&LcorN, &check);
  }
}

  LcorE--;
  LcorN--;

  /*
    int maxd :: maximum number in LcorE and LcorN
  */
  int maxd;
  maxd=0;
  if(LcorE>maxd) maxd=LcorE;
  if(LcorN>maxd) maxd=LcorN;

  /*
    float lcorn_threshold :: threshold value for *sr
  */
  float lcorn_threshold=0.0;
  int k;
  k=0;
  while (fgets(buffer, length_buffer, fp_in)!=NULL) {
    int count;
    char* p;
    count=0;
    p=std::strtok(buffer, " ,:;/");
    if(LcorE==count) std::sscanf(p, "%f", er);
    if(LcorN==count) {
      std::sscanf(p, "%f", sr);
      if(*sr==lcorn_threshold){
        *er=0.0;
        *sr=0.0;
        continue;
      }
    }
    while ((p=std::strtok(NULL, " ,:;/"))!=NULL){
      count++;
      if(count>maxd) break;
      if(LcorE==count) std::sscanf(p, "%f", er);
      if(LcorN==count) std::sscanf(p, "%f", sr);
    }
    if(*sr==lcorn_threshold){
      *er=0.0;
      *sr=0.0;
      continue;
    }
    k++;
    er++;
    sr++;
  }
  fclose(fp_in);
  *nres=k;
  std::printf("%s resolution data point =%i\n", MessageTag, k);
  sr=address_sr;
  er=address_er;

  /*
    float sres :: integration of sr(er) from er[0] to er[nres-1]
  */
  float sres;
  trap(er, sr, *nres, &sres);
  std::printf("%s normalization of resolution function :: sres=%f\n", MessageTag, sres);
  for(i=0; i<*nres; i++){
    *sr/=sres;
    sr++;
  }
  delete [] buffer;
  return 0;
}

/**
 * output observation data and resolution data for file
 * @param ndat valid number of data of energies in observation data file
 * @param nres valid number of data or energies in resolution data file
 * @param *e observation data of energy
 * @param *s observation data of scattering intensity
 * @param *er resolution data of energy
 * @param *sr resolution data of scattering intensity
*/
int AdvInsMEM::graphics_treatment(int ndat, int nres, float* e, float* s, float* er, float* sr){
  /*
    char filename1[] :: output filename for observation data
    char filename2[] :: output filename for resolution data
    FILE *fp1 :: file pointer for output filename for observation data
    FILE *fp2 :: file pointer for output filename for resolution data
  */

const char *filename1={0};
const char *filename2={0};
char basepath_array1[256];
char basepath_array2[256];
if (manual ==0)
{
  std::strcpy(basepath_array1,basepath);
  filename1=std::strcat(basepath_array1,"TEMP1.DAT");
  std::strcpy(basepath_array2,basepath);
  filename2=std::strcat(basepath_array2,"TEMP2.DAT");
}
else if (manual ==1)
{
  filename1="TEMP1.DAT";
  filename2="TEMP2.DAT";
}


  FILE* fp1, *fp2;

  if(!(fp1=fopen(filename1, "w")) || !(fp2=fopen(filename2, "w")) ){
    std::printf("%s TEMP1.DAT or TEMP2.DAT cannot open. \n", MessageTag);
    std::printf("%s Program was exited abnormally.\n", MessageTag);
  }

  int i;
  for(i=0; i<ndat; i++)std::fprintf(fp1, "%f\t%10.7e\n", e[i], s[i]);
  for(i=0; i<nres; i++)std::fprintf(fp2, "%f\t%10.7e\n", er[i], sr[i]);

  fclose(fp1);
  fclose(fp2);

  std::printf("%s PLOT DATA IN A GRAPH SOFTWARE (ex. NGRAPH)\n", MessageTag);
  std::printf("%s     TEMP1.DAT    :EXPERIMENTAL DATA FROM SAMPLE\n", MessageTag);
  std::printf("%s     TEMP2.DAT    :RESOLUTION FUNCTION\n", MessageTag);

  /*
    char buffer[] :: sentence given by user by console input
  */
  char* buffer = new char[length_buffer]; //char buffer[length_buffer];
if (manual==1)
   {
  std::printf("%s hit any key to continue...", MessageTag);
  //fgets(buffer, length_buffer, stdin);
  while((fgets(buffer, length_buffer, stdin) == NULL) || (buffer[0] == '\n')){
    std::printf("Invalid :: ");
  }
   }
else
{
std::printf("%s \n", MessageTag);
}
  delete [] buffer;
  return 0;
}


/**
 * initialize process for MEM procedure
 * @param ndat valid number of data of energies in observation data file
 * @param nres valid number of data or energies in resolution data file
 * @param *e observation data of energy
 * @param *s observation data of scattering intensity
 * @param *er resolution data of energy
 * @param *sr resolution data of scattering intensity
 * @param *th0 initial S(q,e)
 * @param *thcal S(q,e) times resolution
*/
int AdvInsMEM::init_mem_proc(int ndat, int nres, float* e, float* s, float* er, float* sr, float* th0, float* thcal){
  /*
    int flag_init0 :: flag for setting of initial function data
    char filename3[] :: output file name for the initial value of S(q,e)
    char filename4[] :: output file name for the initial value of S(q,e) times resolution
    FILE *fp3 :: file pointer for output file name for the initial value of S(q,e)
    FILE *fp4 :: file pointer for output file name for the initial value of S(q,e) times resolution
    char buffer[] :: sentence given by user by console input
    float address_e :: pointer for the varaiable "e"
    float address_th0 :: pointer for the varaiable "th0"
    float address_thcal :: pointer for the varaibale "thcal"
    int mem_data :: 1: made by the Lorentizan functions
                    2: made by the observed data
    int check :: flag for input
  */
  int i, flag_init0;

const char *filename3={0};
const char *filename4={0};
char basepath_array3[256];
char basepath_array4[256];
if (manual ==0)
{
  std::strcpy(basepath_array3,basepath);
  filename3=std::strcat(basepath_array3,"TEMP3.DAT");
  std::strcpy(basepath_array4,basepath);
  filename4=std::strcat(basepath_array4,"TEMP4.DAT");
}else if (manual ==1)
{
  filename3="TEMP3.DAT";
  filename4="TEMP4.DAT";
}

  FILE *fp3, *fp4;
  char* buffer = new char[length_buffer]; //char buffer[length_buffer];
  float *address_e, *address_th0, *address_thcal;
  int mem_data;
  int check;

  address_e=e;
  address_th0=th0;
  address_thcal=thcal;

if (manual==1)
{
  flag_init0=0;
  while(flag_init0==0){//864loop
    check=0;
    mem_data=0;
    while(check==0){//867loop
      std::printf("%s MEM :: Initial Data\n", MessageTag);
      std::printf("%s 1 = Conbination of Lorentzian functions / 2 = Observed data :: ", MessageTag);
      //fgets(buffer, length_buffer, stdin);
      while((fgets(buffer, length_buffer, stdin) == NULL)||(buffer[0] == '\n')){
	std::printf("%s 1 = Conbination of Lorentzian functions / 2 = Observed data :: ", MessageTag);
      }
      std::sscanf(buffer, "%d",  &mem_data);
      if(mem_data==1 || mem_data==2) check=1;
    }//867loop end

    if(mem_data==1){
      init0_Lorentzian(ndat, e, th0);
    } else {
      init0_ObservedData(ndat, s, th0);
    }

    convol(ndat, e, th0, nres, er, sr, thcal);
    if( !(fp3=fopen(filename3, "w")) || !(fp4=fopen(filename4, "w")) ){
      std::printf("%s Cannnot open file %s or %s\n", MessageTag, filename3, filename4);
      std::printf("%s Program was exited abnormally.^n", MessageTag);
      exit(1);
    }
    for(i=0; i<ndat; i++){
     std::fprintf(fp3, "%f\t%10.7e\n", *e, *th0);
     std::fprintf(fp4, "%f\t%10.7e\n", *e, *thcal);
      e++;
      th0++;
      thcal++;
    }
    e=address_e;
    th0=address_th0;
    thcal=address_thcal;

    fclose(fp4);
    fclose(fp3);

    /*
      int flag :: flag for input
      int ifunc :: 1: remake initial function
                   2: end initialization for MEM
    */
    int flag, ifunc;
    flag=0;
    while(flag==0){ //908loop
      std::printf("%s PLOT DATA IN A GRAPH SOFTWARE (ex. NGRAPH)\n", MessageTag);
      std::printf("%s     TEMP3.DAT    :initial Lorentzian\n", MessageTag);
      std::printf("%s     TEMP4.DAT    : -----*resolution\n", MessageTag);
      std::printf("%s Initial function again (1=yes, 2=no) :: ", MessageTag);

      //fgets(buffer, length_buffer, stdin);
      while((fgets(buffer, length_buffer, stdin) == NULL) || (buffer[0] == '\n')){
	std::printf("%s Initial function again (1=yes, 2=no) :: ", MessageTag);
      }
      if(!(std::sscanf(buffer, "%d", &ifunc))) continue;
      if(ifunc<1 || ifunc>2) continue;
      flag=1;
      if (ifunc==2) flag_init0=1; //864loop end condition
    }//908 loop end
  }//864 loop end
}
else if (manual==0)
{
    check=0;
    mem_data=0;
    while(check==0){//867loop
      mem_data=memDatain;
      std::printf("%s MEM :: Initial Data\n", MessageTag);
if (mem_data==1)
{
      std::printf("%s     Convination of Lorentzian functions\n", MessageTag);
}
else if (mem_data==2)
{
      std::printf("%s     Observed data \n", MessageTag);
}
      //fgets(buffer, length_buffer, stdin);
//      std::sprintf(buffer, "%d",  &mem_data);
      std::snprintf(buffer, length_buffer, "%d",  mem_data);

      if(mem_data==1 || mem_data==2) check=1;
    }//867loop end

    if(mem_data==1){
      init0_Lorentzian(ndat, e, th0);
    } else {
      init0_ObservedData(ndat, s, th0);
    }

    convol(ndat, e, th0, nres, er, sr, thcal);
    if( !(fp3=fopen(filename3, "w")) || !(fp4=fopen(filename4, "w")) ){
      std::printf("%s Cannnot open file %s or %s\n", MessageTag, filename3, filename4);
      std::printf("%s Program was exited abnormally.^n", MessageTag);
      exit(1);
    }
    for(i=0; i<ndat; i++){
     std::fprintf(fp3, "%f\t%10.7e\n", *e, *th0);
     std::fprintf(fp4, "%f\t%10.7e\n", *e, *thcal);
      e++;
      th0++;
      thcal++;
    }
    e=address_e;
    th0=address_th0;
    thcal=address_thcal;

    fclose(fp4);
    fclose(fp3);

      std::printf("%s PLOT DATA IN A GRAPH SOFTWARE (ex. NGRAPH)\n", MessageTag);
      std::printf("%s     TEMP3.DAT    :initial Lorentzian\n", MessageTag);
      std::printf("%s     TEMP4.DAT    : -----*resolution\n", MessageTag);

}
  delete [] buffer;
  return 0;
}



/**
 * set the observation data to initial S(q,e)
 * @param ndat valid number of data of energies in observation data file
 * @param *s observation data of scattering intensity
 * @param *th0 initial S(q,e)
 */
int AdvInsMEM::init0_ObservedData(int ndat, float* s, float* th0){
  int i;
  for(i=0; i<ndat; i++){
    *th0=*s;
    th0++;
    s++;
  }
  return 0;
}

/**
 * set the value of initial S(q,e)  by use of Lorentzian functions
 * @param ndat valid number of data of energies in observation data file
 * @param e[] observation data of energy
 * @param *th0 initial S(q,e)
 */
int AdvInsMEM::init0_Lorentzian(int ndat, float e[], float* th0){
  /*
    float pp[] :: relative intensity
    int nlor :: number of Lorentzian functions
    char buffer[] :: sentence given by user by console input
    int flag :: flag for input
    float pall :: summation of intensities pp[]
    float omega :: omega for Lorentzian function
    float ene0 :: center of energy for Lorentzian function
    float ee :: e[i]-ene0
    int check :: flag for input
    float* addres_th0 :: pointer for the variable "th0"
  */
  float* pp = new float[max_num_lorentzian_functions]; //float pp[max_num_lorentzian_functions];
  int i, j, nlor;
  char* buffer = new char[length_buffer]; //char buffer[length_buffer];
  int flag;
  float pall, omega, ene0, ee;
  int check;
  float* address_th0;

if (manual==1)
{
  address_th0=th0;
  flag=0;
  while(flag==0){//1017 loop
    std::printf("%s creation of an initial Lorentzian function\n", MessageTag);
    std::printf("%s how many Lorentzian ? (=< %d ) :: ", MessageTag, max_num_lorentzian_functions);
    check=0;
    while(check==0){//1021 loop
      //fgets(buffer, length_buffer, stdin);
      while((fgets(buffer, length_buffer, stdin) == NULL) || (buffer[0] == '\n')){
	std::printf("Invalid :: ");
      }
      if( !(std::strlen(buffer)) || !(std::sscanf(buffer, "%d", &nlor)) ){ // scanf
        std::printf("%s Input Error!!!\n", MessageTag);
        std::printf("%s Please input digital number again\n", MessageTag);
        continue;
      }
      if(nlor<0 || nlor> max_num_lorentzian_functions) {
        std::printf("%s Input Error!!!\n", MessageTag);
        std::printf("%s Please input digital number again\n", MessageTag);
        continue;
      }
      for(i=0; i<ndat; i++) {
        *th0=0.0;
        th0++;
      }
      th0=address_th0;
      check=1;
    }//1021 loop end
    pall=0.0;
    /*
      float val :: relative intensity input by user
    */
    float val;
    for(j=0; j<nlor; j++){//1045 loop
      std::printf("%s Lorentzian : %d\n", MessageTag,j+1);
      std::printf("%s input omega (meV) :: ", MessageTag);
      check=0;
      while(check==0){//1049 loop
        //fgets(buffer, length_buffer, stdin);
	while((fgets(buffer, length_buffer, stdin) == NULL) || (buffer[0] == '\n')){
	  std::printf("Invalid :: ");
	}
        if( !(std::strlen(buffer)) || !(std::sscanf(buffer, "%f", &omega)) ){ // std::sscanf
          std::printf("%s Input Error!!!\n", MessageTag);
          std::printf("%s Please input float number again(omega%d=%f)\n", MessageTag,j,omega);
          continue;
        }
        if(omega<=0.0) {
          std::printf("%s Input Error!!!\n", MessageTag);
          std::printf("%s Please input positive float number again(omega%d=%f)\n", MessageTag,j,omega);
          continue;
        }
        check=1;
      }//1049 loop

      std::printf("%s input center E (meV) :: ", MessageTag);
      check=0;
      while(check==0){//1066 loop
        //fgets(buffer, length_buffer, stdin);
	while((fgets(buffer, length_buffer, stdin) == NULL) || (buffer[0] == '\n')){
	  std::printf("Invalid :: ");
	}
        if( !(std::strlen(buffer)) || !(std::sscanf(buffer, "%f", &ene0)) ){ // std::sscanf
          std::printf("%s Input Error!!!\n", MessageTag);
          std::printf("%s Please input float number again(centerE%d=%f)\n", MessageTag,j,ene0);
          continue;
        }
        check=1;
      }//1066 loop

      std::printf("%s input relative intensity :: ", MessageTag);
      check=0;
      while(check==0){//1078 loop
        //fgets(buffer, length_buffer, stdin);
	while((fgets(buffer, length_buffer, stdin) == NULL) || (buffer[0] == '\n')){
	  std::printf("Invalid :: ");
	}
        if( !(std::strlen(buffer)) || !(std::sscanf(buffer, "%f", &val)) ){ // std::sscanf
          std::printf("%s Input Error!!!\n", MessageTag);
          std::printf("%s Please input float number again(val%d=%f)\n", MessageTag,j,val);
          continue;
        }
        if(val<=0.0) {
          std::printf("%s Input Error!!!\n", MessageTag);
          std::printf("%s Please input positive float number again(val%d=%f)\n", MessageTag,j,val);
          continue;
        }
        check=1;
        pp[j]=val;
        pall+=val;
      }//1078 loop end
      for(i=0; i<ndat; i++){
        ee=e[i]-ene0;
        *th0+=pp[j]*omega/(ee*ee+omega*omega)/pi;
        th0++;
      }
      th0=address_th0;
    }//1045 loop end

    if(pall <= 0.0){
      std::printf("%s invalid intensity\n", MessageTag);
    } else {
      for(i=0; i<ndat; i++) {
        *th0/=pall;
        th0++;
      }
      flag=1;
    }
  }//1017 loop end
}
else if (manual==0)
{
  address_th0=th0;
  flag=0;
  //while(flag==0){//1120 loop
    std::printf("%s creation of an initial Lorentzian function\n", MessageTag);
    std::printf("%s num of Lorentzian  = %d  \n", MessageTag, nlorin);
    check=0;
    while(check==0){//1124 loop
      nlor=nlorin;
      //fgets(buffer, length_buffer, stdin);
//      if( !(std::strlen(buffer)) || !(std::sprintf(buffer, "%d", &nlor)) ){
      if( !(std::strlen(buffer)) || !(std::snprintf(buffer, length_buffer, "%d", nlor)) ){
        std::printf("%s Input Error!!!\n", MessageTag);
        std::printf("%s Please input digital number again\n", MessageTag);
        continue;
      }
      if(nlor<0 || nlor> max_num_lorentzian_functions) {
        std::printf("%s Input Error!!!\n", MessageTag);
        std::printf("%s Please input digital number again\n", MessageTag);
        continue;
      }
      for(i=0; i<ndat; i++) {
        *th0=0.0;
        th0++;
      }
      th0=address_th0;
      check=1;
    }//1124 loop end
    pall=0.0;
    /*
      float val :: relative intensity input by user
    */
    float val;
    for(j=0; j<nlor; j++){//1149 loop
      std::printf("%s Lorentzian : %d\n", MessageTag,j+1);
      std::printf("%s input omega (meV) = %f \n", MessageTag,omegaIn[j]);
      check=0;
      //while(check==0){//1153 loop
        //fgets(buffer, length_buffer, stdin);
        omega = omegaIn[j];
        //if( !(std::strlen(buffer)) || !(std::sprintf(buffer, "%f", &omega)) ){ // std::sscanf
        if( !(std::strlen(buffer)) || !(std::snprintf(buffer, length_buffer, "%f", omega)) ){ // std::sscanf

          std::printf("%s Input Error!!!\n", MessageTag);
          std::printf("%s Please input float number again(omega%d=%f)\n", MessageTag,j,omega);
          //continue;
        }
        if(omega<0.0) {
          std::printf("%s Input Error!!!\n", MessageTag);
          std::printf("%s Please input positive float number again(omega%d=%f)\n", MessageTag,j,omega);
            omega=abs(omega);
         // continue;
        }
       else if(omega==0.0) {
          std::printf("%s Input Error!!!\n", MessageTag);
          std::printf("%s Please input positive float number again(omega%d=%f)\n", MessageTag,j,omega);
          std::printf("%s In this time, forcedly set 1.0 (omega%d=%f)\n", MessageTag,j,omega);
            omega=1.0;
         // continue;
        }
        check=1;
      //}//1153 loop end

      std::printf("%s input center E (meV) = %f\n", MessageTag,ene0In[j]);
      check=0;
      //while(check==0){//1170 loop
        //fgets(buffer, length_buffer, stdin);
        ene0 = ene0In[j];
        //if( !(std::strlen(buffer)) || !(std::sprintf(buffer, "%f", &ene0)) ){ // std::sscanf
        if( !(std::strlen(buffer)) || !(std::snprintf(buffer, length_buffer, "%f", ene0)) ){ // std::sscanf
          std::printf("%s Input Error!!!\n", MessageTag);
          std::printf("%s Please input float number again(ene0%d=%f)\n", MessageTag,j,ene0);
         // continue;
        }
        check=1;
      //}//1170 loop

      std::printf("%s input relative intensity = %f \n", MessageTag,valIn[j]);
      check=0;
      //while(check==0){//1182 loop
        //fgets(buffer, length_buffer, stdin);
        val = valIn[j];
        //if( !(std::strlen(buffer)) || !(std::sprintf(buffer, "%f", &val)) ){ // std::sscanf
        if( !(std::strlen(buffer)) || !(std::snprintf(buffer, length_buffer, "%f", val)) ){ // std::sscanf
          std::printf("%s Input Error!!!\n", MessageTag);
          std::printf("%s Please input float number again(val%d=%f)\n", MessageTag,j,val);
         // continue;
        }
        if(val<=0.0) {
          std::printf("%s Input Error!!!\n", MessageTag);
          std::printf("%s Please input positive float number again(val%d=%f)\n", MessageTag,j,val);
          val=abs(val);
        //  continue;
        }
        check=1;
        pp[j]=val;
        pall+=val;
     // }//1182 loop end
      for(i=0; i<ndat; i++){
        ee=e[i]-ene0;
        *th0+=pp[j]*omega/(ee*ee+omega*omega)/pi;
        th0++;
      }
      th0=address_th0;
    }//1124 loop end

    if(pall <= 0.0){
      std::printf("%s invalid intensity\n", MessageTag);
    } else {
      for(i=0; i<ndat; i++) {
        *th0/=pall;
        th0++;
      }
      flag=1;
    }
//  }//1120 loop end
}
  delete [] buffer;
  delete [] pp;
  return 0;
}

/**
 * calculation of convoiution integral
 * @param ndat valid number of data of energies in observation data file
 * @param e[] observation data of energy
 * @param th0[] initial S(q,e)
 * @param nres valid number of data of energies in resolution data file
 * @param er[] observation data of energy
 * @param sr[] observation data of scattering intensity
 * @param thcal S(q,e) times resolution
*/
int AdvInsMEM::convol(int ndat, float e[], float th0[], int nres, float er[], float sr[], float* thcal){
//  float er2[max_data_size], sr2[max_data_size],
  /*
    float s2[] :: interpolate value of resolution at energy point e2[]
    float e2[] :: energy value in unit of ediv
    int ie2[] :: e[i]/(e[1]-e[0])
    int nres2 :: valid number of data or energies in resolution data file
    float ediv :: unit of energy in this subroutine :: e[1]-e[0]
    float tmp_thcal[] :: S(q,e) times resolution
  */
  //float s2[max_data_size], e2[max_data_size];
  //int   ie2[max_data_size];
  float* s2 = new float[max_data_size];
  float* e2 = new float[max_data_size];
  int* ie2 = new int[max_data_size];
  int i, j, k, iflag, nres2;
  float ediv;
  float* tmp_thcal = new float[ndat]; //float tmp_thcal[ndat];

  for(i=0; i<ndat; i++) tmp_thcal[i]=0.0;
  iflag=0;
  k=-1;
  ediv=e[1]-e[0];
  for(i=0; i<ndat; i++){
    if(e[i]<er[0] || e[i]>er[nres-1]) continue;
    ie2[++k]=(int) (e[i]/ediv);
    e2[k]=(float) (ediv*ie2[k]);
    if(ie2[k]==0 && iflag==0){
      k--;
      iflag=1;
    }
  }
  nres2=k+1;

  /*
  CSIEZ(&nres, er, sr, &nres2, e2, s2);
  */
  spline3(nres, er, sr, nres2, e2, s2);
//AS Miyashita 2012/07/03(add) start
  float sres2;
  trap(e2, s2, nres2, &sres2);
  for (i=0; i<nres2; i++){
    s2[i]/=sres2;
  }
//AS Miyashita 2012/07/03(add) end

  int ii;
  for(i=0; i<ndat; i++){
    k=0;
    for(j=0; j< nres2; j++){
      ii=i+ie2[j];
      if(ii<0 || ii>ndat-1) continue;
      tmp_thcal[ii]+=th0[i]*s2[j]*ediv;
    }
  }
  for(i=0; i<ndat; i++){
    *thcal=tmp_thcal[i];
    thcal++;
  }
  delete [] s2;
  delete [] e2;
  delete [] ie2;
  delete [] tmp_thcal;
  return 0;
}

/**
  * renewal of S(q,e) by performing MEM procedure and convolution integral
  * @param *imode Mem operation mode
  * @param ndat valid number of data of energies in observation data file
  * @param nres valid number of data of energies in resolution data file
  * @param *th0 initial S(q,e)
  * @param *th1 present S(q,e)
  * @param *thcal convolution integral, S(q,e) times resolution
  * @param e[] energy of observation data
  * @param s[] scattering intensity of observation data
  * @param r[] statistical error of observation data
  * @param er[] energy of resolution data
  * @param sr[] resolution of resolution data
  * @param nmin index for data of start point of integral calculation
  * @param nmax index for data of end point of integral calculation
*/
int AdvInsMEM::main_mem_proc(int* imode, int ndat, int nres, float* th0, float* th1, float* thcal,
             float e[], float s[], float r[], float er[], float sr[], int nmin, int nmax){
  /*
    int maxc :: maximum iteration number for MEM procedure
    float constraint :: threshold value for MEM procedure
    char buffer :: sentence given by user by console input
    int flag :: flag for input
    float* address_th0 :: pointer for varaiable "th0"
           address_th1 :: pointer for varaiable "th1"
           address_thcal :: pointer for varaiable "thcal"
  */

  int maxc = 0;
  float constraint;
  char* buffer = new char[length_buffer]; //char buffer[length_buffer];
  int i, j, nn, flag;
  float *address_th0, *address_th1, *address_thcal;
  constraint = 1.0;

  address_th0=th0;
  address_th1=th1;
  address_thcal=thcal;
  flag=0;
  if(*imode==1){
    maxc=1000;
    constraint=1.0;
  } else {
if (manual==1)
{
    while(flag==0){
      std::printf("%s input max cycle", MessageTag);
      //fgets(buffer, length_buffer, stdin);
      while((fgets(buffer, length_buffer, stdin) == NULL) || (buffer[0] == '\n')){
	std::printf("Invalid :: ");
      }
      if( !(std::sscanf(buffer, "%d", &maxc)) ) continue;
      if(maxc<1) continue;
      flag=1;
    }
    std::printf("%s input constraint parameter", MessageTag);
    //fgets(buffer, length_buffer, stdin);
    while((fgets(buffer, length_buffer, stdin) == NULL) || (buffer[0] == '\n')){
      std::printf("Invalid :: ");
    }
    //std::sscanf(buffer, "%f", constraint);
    std::sscanf(buffer, "%f", &constraint);
}
else if (manual ==0)
{
          maxc= maxcIn;
          if (maxc < 1){
          delete [] buffer;
          return 1;
          }else{
          std::printf("%s input max cycle = %d\n", MessageTag,maxcIn);
          //fgets(buffer, length_buffer, stdin);
          //std::sprintf(buffer, "%d", &maxc);
          std::snprintf(buffer, length_buffer, "%d", maxc);
        constraint = constraintIn;
        std::printf("%s input constraint parameter\n", MessageTag);
        //fgets(buffer, length_buffer, stdin);
        std::snprintf(buffer, length_buffer, "%f", constraint);
     }
    }
  }


  /*
    int kk :: number of calculation energy points
    float aaa :: difference between observed S and calculated S at each energy point
    FILE *fp5 :: file pointer for output file of S(q,e)
    FILE *fp6 :: file pointer for output file of S(q,e) times resolution
    char filename5[] :: output file name for S(q,e)
    char filename6[] :: output file name for S(q,e) times resolution
  */
  int kk;
  float aaa;
  FILE *fp5, *fp6;

const char *filename5={0};
const char *filename6={0};
char basepath_array5[256];
char basepath_array6[256];
if (manual ==0)
{
  std::strcpy(basepath_array5,basepath);
  filename5=std::strcat(basepath_array5,"TEMP5.DAT");
  std::strcpy(basepath_array6,basepath);
  filename6=std::strcat(basepath_array6,"TEMP6.DAT");
}else if (manual ==1)
{
  filename5="TEMP5.DAT";
  filename6="TEMP6.DAT";
}
  for(i=0; i<maxc; i++){
    if(*imode==1){
      std::printf("%s MEM procedure : (1=yes /2=finish) :: ", MessageTag);
      //fgets(buffer, length_buffer, stdin);
      while((fgets(buffer, length_buffer, stdin) == NULL) || (buffer[0] == '\n')){
	std::printf("Invalid :: ");
      }
      std::sscanf(buffer, "%d", &nn);
      if(nn==2){
        *imode=3;
        delete [] buffer;
        return 0;
      }
    }

    th0=address_th0;
    th1=address_th1;
    thcal=address_thcal;

    for(j=0; j<ndat; j++){
      *th0=*th1;
      th0++;
      th1++;
    }
    th0=address_th0;
    th1=address_th1;

    memproc(ndat, e, s, r, th0, nres, er, sr, th1);
    convol(ndat, e, th1, nres, er, sr, thcal);

    /*
      float tmp_thcal[] :: S(q,e) times resolution
    */
    float* tmp_thcal = new float[ndat]; //float tmp_thcal[ndat];
    for(j=0; j<ndat; j++){
      tmp_thcal[j]=*thcal;
      thcal++;
    }
    thcal=address_thcal;

    kk=0;
    rfac=0.0;
    //std::printf("nmin=%d\n",nmin);
    //std::printf("nmax=%d\n",nmax);
    for(j=nmin; j<=nmax; j++){
      if(s[j]==0.0) continue;
      if(r[j]<=0.0) continue;
      aaa=(s[j]-tmp_thcal[j])/r[j];
      rfac+=aaa*aaa;
      kk++;
    }
    //std::printf("kk=%d\n",kk);
    rfac/=kk;
    std::printf("%s MEM : %d R-factor=%f\n", MessageTag, i+1, rfac);
    if( !(fp5=fopen(filename5, "w")) || !(fp6=fopen(filename6, "w")) ){
      std::printf("%s Cannot open file :: %s, %s\n", MessageTag, filename5, filename6);
      std::printf("%s Program was exited abnormally.\n", MessageTag);
    }
    for(j=0; j<ndat; j++){
     std::fprintf(fp5, "%f\t%10.7e\n", e[j], *th1);
     std::fprintf(fp6, "%f\t%10.7e\n", e[j], *thcal);
      th1++;
      thcal++;
    }
    fclose(fp5);
    fclose(fp6);
    if(rfac <= constraint){
      std::printf("%s CONGRATULATION !!!\n", MessageTag);
      delete [] buffer;
      delete [] tmp_thcal;
      return 0;
    }

/* should be removed in future */
/* TEMPORARY */
    char file5[256], file6[256];
    std::snprintf(file5, sizeof(file5), "%s_%d", filename5, i+1);
    std::snprintf(file6, sizeof(file6), "%s_%d", filename6, i+1);
    char cmd[512];
    std::snprintf(cmd, sizeof(cmd), "cp %s %s", filename5, file5);
    int ret_system;
    ret_system = system(cmd);
    std::snprintf(cmd, sizeof(cmd), "cp %s %s", filename6, file6);
    ret_system = system(cmd);
/* TEMPORARY END */

    if(*imode != 2){
      std::printf("%s PLOT DATA IN A GRAPH SOFTWARE (ex. NGRAPH)\n", MessageTag);
      std::printf("%s     TEMP5.DAT    :present S(q,e)\n", MessageTag);
      std::printf("%s     TEMP6.DAT    : -----*resolution\n", MessageTag);
    }
  }
  delete [] buffer;
  return 0;
}

/**
 * perfome MEM procedure
 * @param ndat valid number of data of energies of observation data
 * @param e[] observation data of energy
 * @param s[] observation data of scattering intensity
 * @param r[] statistical error
 * @param *th0 S(q,e) before MEM procedure
 * @param nres valid number of data of energies of resolution data
 * @param er[] energy of resolution data
 * @param sr[] resolution of resolution data
 * @param *th1 S(q,e) after MEM procedure
*/
int AdvInsMEM::memproc(int ndat, float e[], float s[], float r[], float* th0,
            int nres, float er[], float sr[], float* th1){

  /*
    float w1[] :: temporally value for work space
    float w2[] :: temporally value for work space
    float w3[] :: temporally value for work space
    float w4[] :: temporally value for work space
    float coef :: coefficient of th0 to calculate th1
    float threshold :: threshold value fo w2[]
    float tmp_th0[] :: S(q,e) before MEM
    float tmp_th1[] :: S(q,e) after MEM
    float* address_th0 :: pointer for the variable "th0"
  */
  //float w1[max_data_size], w2[max_data_size], w3[max_data_size], w4[max_data_size];
  float* w1 = new float[max_data_size];
  float* w2 = new float[max_data_size];
  float* w3 = new float[max_data_size];
  float* w4 = new float[max_data_size];

  int i; // , iflag;
  float a, b, c, a1, c1, bb2;
  float coef;
  float threshold=1.e-20;

  //float tmp_th0[ndat], tmp_th1[ndat];
  float *tmp_th0 = new float[ndat];
  float *tmp_th1 = new float[ndat];
  float *address_th0;

  address_th0=th0;

  convol(ndat, e, th0, nres, er, sr, w1);
  for(i=0; i<ndat; i++)
    if(r[i]!=0.0) w2[i]=(w1[i]-s[i])/r[i]/r[i]/ndat;
  convol(ndat, e, w2, nres, er, sr, w3);

  for(i=0; i<ndat; i++){
    tmp_th0[i]=*th0;
    th0++;
  }
  th0=address_th0;
  for(i=0; i<ndat; i++) w4[i]=tmp_th0[i]*w3[i];
  convol(ndat, e, w4, nres, er, sr, w2);
  a=b=c=0.0;
  for(i=0; i<ndat; i++){
    if(r[i]!=0.0){
      a1=w2[i]/r[i];
      a+=a1*a1;
      b+=w2[i]*(w1[i]-s[i])/r[i]/r[i];
      c1=(w1[i]-s[i])/r[i];
      c+=c1*c1;
    }
  }

  bb2=b*(b-a/b*c);
  // iflag=0;
  if(bb2<0.0){
    // iflag=10000;
    bb2=0.0;
  }
  coef=(-b+sqrt(bb2))/a;
  for(i=0; i<ndat; i++){
    if(w2[i]> -threshold && w2[i]<threshold) continue;
    tmp_th1[i]=tmp_th0[i]+tmp_th0[i]*w3[i]*coef;
    if(tmp_th1[i] < threshold) tmp_th1[i]=0.0;
  }

  /*
    float area :: integrated value of th1[e]
  */
  float area;
  trap(e, tmp_th1, ndat, &area);
  for(i=0; i<ndat; i++) tmp_th1[i]/=area;
  for(i=0; i<ndat; i++){
     *th1=tmp_th1[i];
     th1++;
  }
  delete [] w1;
  delete [] w2;
  delete [] w3;
  delete [] w4;
  delete [] tmp_th0;
  delete [] tmp_th1;
  return 0;
}


/**
 * integration by use of trapezoid formula
 * @param x[] :: value of x[i], 0 <= i < n
 * @param y[] :: value of y[i], 0 <= i < n
 * @param n :: number of x points
 * @param *s :: the value of integration of y[x]
 */
int AdvInsMEM::trap(float* x, float* y, int n, float* s){
  int nn, nn1;
  *s=0.0;
  nn=n-1;
  nn1=nn-1;
  if(nn <= 0) {
    std::printf("%s Cannot execute integral (nn<=0)\n", MessageTag);
    std::printf("%s Program was exited abnormally.\n", MessageTag);
    exit(1);
  }
  int i;
  for(i=0; i<nn; i++){
  //    std::printf("%s x[%d] -- %f.\n",MessageTag,i,x[i]);
  //    if(x[i] >= x[i+1]){
    if(x[i] > x[i+1]){
      std::printf("%s Cannot execute integral (x[i]>=x[i+1]) i=%d, x[i]=%f, x[i+1]=%f\n", MessageTag, i, x[i], x[i+1]);
      std::printf("%s Program was exited abnormally.\n", MessageTag);
      exit(1);
    }
  }
  if(nn1==0){
    *s=(x[1]-x[0])*(y[1]+y[0])*0.5;
  } else {
    float s1, s2;
    s1=(x[1]-x[0])*y[0];
    s2=(x[n-1]-x[nn-1])*y[n-1];
    for(i=0; i<nn1; i++) *s+=(x[i+2]-x[i])*y[i+1];
    *s=(*s+s1+s2)*0.5;
  }
  return 0;
}

/**
 * interpolation by use of third spline function /br
 * see http://www.cannula.jp/hokan.html
 * @param ndata number of defined data
 * @param x[] x value of defined data
 * @param y[] y(x) value of defined data
 * @param N_xvec number of interpolation data
 * @param xvec[] x value for interpolation
 * @param *fvec interpolated value of y
 */
int AdvInsMEM::spline3(int ndata, float x[], float y[], int n_xvec, float xvec[], float* fvec){
  /*
   3ji spline method ::
     given data points :: x[0], x[1], ..., x[n]

     for x[i] <= x <= x[i+1]
        y[i](x)=c1[i]*(x-x[i])^3+c2[i]*(x-x[i])^2+c3[i]*(x-x[i])+c4[i]

     y[i](x[i])=y[i-1](x[i])
     y[i]'(x[i])=y[i-1]'(x[i])
     y[i]''(x[i])=y[i-1]''(x[i])
     y[0]''(x[0])=y[n-1]''(x[n])=0

     In the above-mentioned condition, we solve the following equation

       m[i][j]*u[j] = v[j], 1 <= i, j <= n-1,

     where
       u[i] = y[i]''
       m[i][i] = 2*(h[i-1]+h[i]),
       m[i+1][i]=m[i][i+1]=h[i+1],
       other wise m[i][j]=0,
       v[i]=6*( ( (y[i+1]-y[i])/h[i] ) - ( (y[i]-y[i-1])/h[i-1] ) )
     Here,
       h[i]=x[i+1]-x[i].


   vp[n-1] :: same as v[0], ... , v[n-2]
   up[n-1] :: same as u[0], ... , u[n-2]
   are used for solve the above-mentioned Matrix*std::vector=std::vector equation.

   Then,
     c1[i]=(u[i+1]-u[i])/6/(x[i+1]-x[i])
     c2[i]=0.5*u[i]
     c4[i]=y[i]
    and c3 is obtained by use of c1, c2, c4.

  */
  int n=ndata-1;
  //float h[n], v[n], up[n-1], u[n], vp[n-1];
  float* h = new float[n];
  float* v = new float[n];
  float* up = new float[n-1];
  float* u = new float[n];
  float* vp = new float[n-1];
  int i;

  for(i=0; i<n; i++) h[i]=x[i+1]-x[i];
  for(i=1; i<n; i++) v[i]=6.0*((y[i+1]-y[i])/h[i]-(y[i]-y[i-1])/h[i-1]);
  for(i=1; i<n; i++) vp[i-1]=v[i];

  /*
   m1[n-1] :: m[i+1][i] of triangular matrix m
   m2[n-1] :: m[i][i] of triangular matrix m
   m3[n-1] :: [i][i+1] of triangular matrix m
  */
  //float m1[n-1], m2[n-1], m3[n-1];
  float* m1 = new float[n-1];
  float* m2 = new float[n-1];
  float* m3 = new float[n-1];
  for(i=0; i<n-1; i++){
    m1[i]=m2[i]=m3[i]=0.0;
    m2[i]=2.0*(h[i]+h[i+1]);
    m3[i]=h[i+1];
    m1[i]=h[i];
  }
  Thomas(n-1, m1, m2, m3, vp, up);
  delete [] m1;
  delete [] m2;
  delete [] m3;
  for(i=0; i<n-1; i++) u[i+1]=up[i];
  u[0]=u[n]=0.0;

  /*
    float c1 :: coefficient of x*x*x
    float c2 :: coefficient of x*x
    float c3 :: coefficient of x
    float c4 :: constant
  */
  //float c1[n], c2[n], c3[n], c4[n];
  float* c1 = new float[n];
  float* c2 = new float[n];
  float* c3 = new float[n];
  float* c4 = new float[n];
  for(i=0; i<n; i++) c1[i]=(u[i+1]-u[i])/6.0/(x[i+1]-x[i]);
  for(i=0; i<n; i++) c2[i]=0.5*u[i];
  for(i=0; i<n; i++) c4[i]=y[i];
  for(i=0; i<n; i++) {
    c3[i]=(1.0/(x[i+1]-x[i]))*(y[i+1]-c1[i]*(x[i+1]-x[i])*(x[i+1]-x[i])*(x[i+1]-x[i])
                                     -c2[i]*(x[i+1]-x[i])*(x[i+1]-x[i])
                                     -c4[i]);
  }

  /*
    int knot :: knot number
    float xval :: x value from knot point
  */
  int j, knot;
  float xval;
  for(i=0; i<n_xvec; i++){
    knot=-1;
    for(j=0; j<ndata; j++) if(xvec[i]>=x[j]) knot++;
    if(knot>n-1) knot=n-1;
    xval=xvec[i]-x[knot];
    fvec[i]=c1[knot]*xval*xval*xval+c2[knot]*xval*xval+c3[knot]*xval+c4[knot];
  }
  delete [] h;
  delete [] v;
  delete [] up;
  delete [] u;
  delete [] vp;
  delete [] c1;
  delete [] c2;
  delete [] c3;
  delete [] c4;

  return 0;
}

/**
 * execution of Thomas method
 * Mx = b
 * @param n dimension of matrix
 * @param m1[] M[i+1][i]  of triangluar matrix M
 * @param m2[] M[i][i]  of triangluar matrix M
 * @param m3[] M[i][i+1]  of triangluar matrix M
 * @param b[] n dimensional std::vector b
 * @param *x  n dimensional vectro x
 */
int AdvInsMEM::Thomas(int n, float m1[], float m2[], float m3[], float b[], float* x){
  //float p[n], q[n], x_tmp[n];
  float* p = new float[n];
  float* q = new float[n];
  float* x_tmp = new float[n];
  int i;
  p[0]=m3[0]/m2[0];
  q[0]=b[0]/m2[0];
  for(i=1; i<n-1; i++) p[i]=m3[i]/(m2[i]-m1[i]*p[i-1]);
  for(i=1; i<n; i++) q[i]=(b[i]-m1[i]*q[i-1])/(m2[i]-m1[i]*p[i-1]);
  x_tmp[n-1]=q[n-1];
  for(i=n-2; i>=0; i--) x_tmp[i]=q[i]-p[i]*x_tmp[i+1];
  for(i=0; i<n; i++){
    *x=x_tmp[i];
    x++;
  }
  delete [] p;
  delete [] q;
  delete [] x_tmp;
  return 0;
}

