#include "ShamotoDymPDF.hh"

ShamotoMagFormFact::ShamotoMagFormFact(){
    // Mn2+ magnetic form factor
    A1=0.4220;
    a2=17.684;
    B1=0.5948;
    b2=6.005;
    C1=0.0043;
    c2=-0.609;
    D=-0.0219;
}
ShamotoMagFormFact::~ShamotoMagFormFact(){

}
Double ShamotoMagFormFact::Calc(Double Q){
    Double s=Q/4.0/M_PI;
    Double mgf=A1*exp(-a2*s*s)+B1*exp(-b2*s*s)+C1*exp(-c2*s*s)+D;
    return mgf;
}


ShamotoDymPDF::ShamotoDymPDF(bool useMF){
    _ecm = NULL;
    _sArray = NULL;
    _is_inner_ecm = true;
    _st = new StringTools();
    _dHW = 0.0;
    _minHW = 0.0;
    _maxHW = 0.0;
    _Cf = 74.84;
    _dR = 0.1;
    _maxR = 40.0;
    //_useMF = useMF;
    SetMode(useMF);
    _mfg = new ShamotoMagFormFact();
    _nav = 5;
    _DEBUG = UtsusemiEnvGetDebugMode();
}
ShamotoDymPDF::~ShamotoDymPDF(){
    delete _st;
    delete _mfg;
    if ((_is_inner_ecm) && (_ecm!=NULL)) delete _ecm;
}
void ShamotoDymPDF::SetData( ElementContainerMatrix* ecm ){
     _ecm=ecm;
     _is_inner_ecm = false;
}
void ShamotoDymPDF::SetMode(bool useMF){
    _useMF = useMF;
    if (useMF) _MessageTag = "ShamotoDymPDF::";
    else _MessageTag = "ShamotoDyPDF::";
}
void ShamotoDymPDF::SetData( ElementContainerArray* eca ){
    if ((_is_inner_ecm) && (_ecm!=NULL)) delete _ecm;
    _ecm = new ElementContainerMatrix( eca->PutHeader() );
    _is_inner_ecm = true;
    _ecm->Add( *eca );
}
void ShamotoDymPDF::SetSlicedData( ElementContainerArray* eca ){
    if (_sArray != NULL) delete _sArray;
    _sArray = eca;
}
void ShamotoDymPDF::SetSliceWidth( Double delta_hw, Double min_hw, Double max_hw ){
    _dHW = fabs( delta_hw );
    _minHW = min_hw;
    _maxHW = max_hw;
    if (_minHW > _maxHW){
        Double tmp = _minHW;
        _minHW = _maxHW;
        _maxHW = tmp;
    }
}
void ShamotoDymPDF::SetMagFormFact(Double _A1, Double _a2, Double _B1, Double _b2, Double _C1, Double _c2, Double _D){
    _mfg->A1 = _A1;
    _mfg->a2 = _a2;
    _mfg->B1 = _B1;
    _mfg->b2 = _b2;
    _mfg->C1 = _C1;
    _mfg->c2 = _c2;
    _mfg->D = _D;
}
bool ShamotoDymPDF::SetRRange( Double dR, Double maxR ){
    if ( (dR<0.0)&&(maxR<0.0) ) return false;
    _dR = dR;
    _maxR = maxR;
    return true;
}
bool ShamotoDymPDF::Slice( ElementContainerMatrix* ecm, ElementContainerArray* eca, Double dHW, Double min_hw, Double max_hw){
    if (min_hw==max_hw){
        std::vector<Double> hw = ecm->PutPointer(0)->PutPointer(0)->PutX();
        min_hw = hw[0];
        max_hw = hw.back();
    }
    if (min_hw>max_hw){
        Double tmp = min_hw;
        min_hw = max_hw;
        max_hw = tmp;
    }
    std::vector<Double> r_hw = CalcRangeAsBinCenterZero( min_hw, max_hw , dHW, true );
    min_hw = r_hw[0];
    max_hw = r_hw[1];
    UInt4 num_hw = UInt4( r_hw[2] );

    MlfArraySlicer* AS = new MlfArraySlicer( ecm );
    Double cur_hw = min_hw;
    for (UInt4 i=0; i<num_hw; i++){
        ElementContainer* _ec = new ElementContainer();
        if ( AS->CutAlongX( _ec, cur_hw, cur_hw+dHW, true ) ){
            _ec->AddToHeader(UTSUSEMI_KEY_HW, cur_hw + dHW/2.0 );
            std::vector<Double> hws;
            hws.push_back( cur_hw );
            hws.push_back( cur_hw+dHW );
            _ec->AddToHeader(UTSUSEMI_KEY_HW+"s", hws );
            eca->Add( *_ec );
        }
        delete _ec;
        cur_hw += dHW;
    }
    delete AS;
    return true;
}
bool ShamotoDymPDF::Execute( bool doSlice ){
    if (_useMF)
        return _ExecuteDymPDF(doSlice);
    else
        return _ExecuteDyPDF(doSlice);
}
bool ShamotoDymPDF::_ExecuteDymPDF( bool doSlice ){

    UInt4 j, j0;
    Double Pi, dr, Qmax, SSsum, Smax, Smaxerr;
    Double b, b1, b2;
    Pi = M_PI;

    if (doSlice){
        if (_sArray!=NULL) delete _sArray;
        _sArray = new ElementContainerArray();
        if (!(Slice( _ecm, _sArray, _dHW, _minHW, _maxHW))){
            UtsusemiError(_MessageTag + " Execute>> Slice Error");
            return false;
        }
    }
    if (_sArray==NULL){
        UtsusemiError(_MessageTag + "");
        return false;
    }else{
        for (UInt4 i1=0; i1<(_sArray->PutSize()); i1++){
            ElementContainer* ec = _sArray->PutPointer(i1);
            std::vector<Double> Qo = ec->PutX();
            std::vector<Double> I = ec->PutY();
            std::vector<Double> E = ec->PutE();
            std::vector<Double> Q;
            UInt4 Size = (UInt4)I.size();
            if ((UInt4)Qo.size()==Size){
                Q.resize(Size);
                copy(Qo.begin(),Qo.end(),Q.begin());
            }else{
                for (UInt4 i2=0; i2<Size; i2++)
                    Q.push_back( (Qo[i2]+Qo[i2+1])/2.0 );
            }

            j=3;
            //dr=0.1;
            dr = _dR;
            j0=0;
            SSsum=0;
            Smax=0;
            Qmax = ( Q[ Size-3 ] + Q[ Size-2 ] + Q[ Size-1 ] )/3.0;
            Smax = ( I[ Size-3 ] + I[ Size-2 ] + I[ Size-1 ] )/3.0;
            Smaxerr = sqrt( Q[ Size-3 ]*Q[ Size-3 ] + Q[ Size-2 ]*Q[ Size-2 ] + Q[ Size-1 ]*Q[ Size-1 ] )/3.0;
            UtsusemiMessage(_MessageTag + "ExecuteDymPDF >> N_data="+_st->UInt4ToString( Size ));
            UtsusemiMessage(_MessageTag + "ExecuteDymPDF >> Q_max, Smax="+_st->DoubleToString( Qmax )+","+_st->DoubleToString( Smax ) );

            // Least squre fit of S(Q,E) by b*(Q-Qmax)(Q+Qmax)
            b1=0;
            b2=0;
            std::vector<Double> X(Size,0.0);
            std::vector<Double> Y(Size,0.0);
            for (UInt4 M=0; M<Size; M++){
                X[M] = (Q[M]-Qmax)*(Q[M]-Qmax);
                Y[M] = I[M]-Smax;
                b1 = b1+X[M]*Y[M];
                b2 = b2+X[M]*X[M];
                //std::cout<< X[M] << ","<<Y[M]<<std::endl;
            }
            b = b1/b2;
            //std::cout << b << std::endl;

            std::vector<Double> Q_av(Q.size(),0.0);
            std::vector<Double> I_av(Size,0.0);
            std::vector<Double> E_av(E.size(),0.0);
            for (UInt4 M=0; M<Size; M++){
                if (Q[M]==0.0) Q[M] = 0.001;
                Double WF = Qmax*sin(Pi*Q[M]/Qmax)/Pi/Q[M];
                Q_av[M] = Q[M];
                if (_useMF){
                    I_av[M] = _Cf*Q[M]*(I[M]-Smax-b*(Q[M]-Qmax)*(Q[M]-Qmax))*WF/_mfg->Calc(Q[M])/_mfg->Calc(Q[M]);
                    E_av[M] = _Cf*Q[M]*E[M]*WF/_mfg->Calc(Q[M])/_mfg->Calc(Q[M]);
                }else{
                    I_av[M] = _Cf*Q[M]*(I[M]-Smax-b*(Q[M]-Qmax)*(Q[M]-Qmax))*WF;
                    E_av[M] = _Cf*Q[M]*E[M]*WF;
                }
                SSsum = SSsum+I_av[M];
                //if (M==(Size-1)){
                //    std::cout << Q[M] << "," << I[M] << "," << E[M] << std::endl;
                //    std::cout << _Cf << std::endl;
                //    std::cout << WF << std::endl;
                //    std::cout << _mfg->Calc(Q[M]) << std::endl;
                //    std::cout << Q_av[M] << "," << I_av[M] << "," << E_av[M] << std::endl;
                //}
            }
            UtsusemiMessage(_MessageTag + "ExecuteDymPDF >> SUM of S(Q,E)="+_st->DoubleToString( SSsum ));

            // DyPDF G(r,E)/n(E) calculation ***************
            //UInt4 SizeOfG = 400;
            UInt4 SizeOfG = (UInt4)(_maxR/_dR);
            std::vector<Double> Q_rho(SizeOfG,0.0);
            std::vector<Double> I_rho(SizeOfG,0.0);
            std::vector<Double> E_rho(SizeOfG,0.0);
            for (UInt4 N=0; N<SizeOfG; N++){
                Q_rho[N] = (Double)N*dr;
                for (UInt4 M=0;M<(Size-1);M++){
                    I_rho[N]=I_rho[N]+I_av[M]*sin( Q_av[M]*Q_rho[N] )*Q_av[M]*(Q_av[M+1]-Q_av[M]);
                    if (I_av[M] < 0.001){
                        E_rho[N] = E_rho[N]+((E_av[M]/0.1)*(E_av[M]/0.1))*Q_av[M]*Q_av[M]*(Q_av[M+1]-Q_av[M]);
                    }else{
                        E_rho[N] = E_rho[N]+((E_av[M]/I_av[M])*(E_av[M]/I_av[M]))*Q_av[M]*Q_av[M]*(Q_av[M+1]-Q_av[M]);
                    }
                }
                I_rho[N] = 2.0*I_rho[N]/Pi;
                E_rho[N] = sqrt( E_rho[N])*sqrt(2.0)/Pi;
            }
            ec->Add(UTSUSEMI_KEY_MOMENTTRANSFER+"_RHO",Q_rho,UTSUSEMI_KEY_MOMENTTRANSFER_UNIT);
            ec->Add(UTSUSEMI_KEY_INTENSITY+"_RHO",I_rho,UTSUSEMI_KEY_ARB_UNIT);
            ec->Add(UTSUSEMI_KEY_ERROR+"_RHO",E_rho,UTSUSEMI_KEY_ARB_UNIT);
            ec->SetKeys(UTSUSEMI_KEY_MOMENTTRANSFER+"_RHO",UTSUSEMI_KEY_INTENSITY+"_RHO",UTSUSEMI_KEY_ERROR+"_RHO");
         }
    }
    return true;
}
bool ShamotoDymPDF::ExecuteWideDymPDF(Double Qmin_phononBG, Double Qmax_DymPDF,  bool doSlice){
    Double Pi = M_PI;

    bool ret = false;
    if (doSlice){
        if (_sArray!=NULL) delete _sArray;
        _sArray = new ElementContainerArray();
        if (!(Slice( _ecm, _sArray, _dHW, _minHW, _maxHW))){
            UtsusemiError(_MessageTag + "_ExecuteWideDymPDF>> Slice Error");
            return false;
        }
    }
    if (_sArray==NULL){
        UtsusemiError("");
        return false;
    }else{
        for (UInt4 i1=0; i1<(_sArray->PutSize()); i1++){
            if (_DEBUG) {
                std::cout << "============================================" << std::endl;
                std::cout << "              " << i1 << " / " << (_sArray->PutSize()) << std::endl;
            }
            ElementContainer* ec = _sArray->PutPointer(i1);
            std::vector<Double> Qo = ec->PutX();
            std::vector<Double> I = ec->PutY();
            std::vector<Double> E = ec->PutE();
            std::vector<Double> Q;
            UInt4 Size = (UInt4)I.size();
            if ((UInt4)Qo.size()==Size){
                Q.resize(Size);
                copy(Qo.begin(),Qo.end(),Q.begin());
            }else{
                for (UInt4 i2=0; i2<Size; i2++)
                    Q.push_back( (Qo[i2]+Qo[i2+1])/2.0 );
            }

            UInt4 SizeOfG = (UInt4)(_maxR/_dR);
            std::vector<Double> Q_rho(SizeOfG,0.0);
            std::vector<Double> I_rho(SizeOfG,0.0);
            std::vector<Double> E_rho(SizeOfG,0.0);

            std::vector<Double> params;
            params.push_back(Qmin_phononBG);
            params.push_back(Qmax_DymPDF);

            ret = _ExecuteWideDymPDFBase(Q_rho, I_rho, E_rho, Q, I, E, params);

            ec->Add(UTSUSEMI_KEY_MOMENTTRANSFER+"_RHO",Q_rho,UTSUSEMI_KEY_MOMENTTRANSFER_UNIT);
            ec->Add(UTSUSEMI_KEY_INTENSITY+"_RHO",I_rho,UTSUSEMI_KEY_ARB_UNIT);
            ec->Add(UTSUSEMI_KEY_ERROR+"_RHO",E_rho,UTSUSEMI_KEY_ARB_UNIT);
            ec->SetKeys(UTSUSEMI_KEY_MOMENTTRANSFER+"_RHO",UTSUSEMI_KEY_INTENSITY+"_RHO",UTSUSEMI_KEY_ERROR+"_RHO");
         }
    }
    return true;
}
bool ShamotoDymPDF::_ExecuteWideDymPDFBase(std::vector<Double>& r_RHO, std::vector<Double>& g_RHO, std::vector<Double>& e_RHO, std::vector<Double>& q_FQ, std::vector<Double>& s_FQ, std::vector<Double>& e_FQ, const std::vector<Double>& params){
    Double in_Qmin = params[0]; // Qmin_phononBG
    Double in_Qmax = params[1]; // Qmax_DymPDF
    UInt4 j1 = 0;
    UInt4 j2 = 0;
    for (UInt4 i = 0; i < (q_FQ.size()); i++){
        if ((q_FQ[i] >= (in_Qmax - 0.1)) && (q_FQ[i] <= (in_Qmax + 0.1))) j2 = i;
        if ((q_FQ[i] >= (in_Qmin - 0.1)) && (q_FQ[i - 1] <= (in_Qmin + 0.1))) j1 = i;
    }
    UInt4 j = (UInt4)(q_FQ.size() - 1);
    Double Qmax = q_FQ[j];
    Double Qmax2 = q_FQ[j2];
    Double Qmin = q_FQ[j1];
    Double Smax = (s_FQ[j - 2] + s_FQ[j - 1] + s_FQ[j]) / 3.0;
    Double Smaxerr = sqrt(e_FQ[j - 2] * e_FQ[j - 2] + e_FQ[j - 1] * e_FQ[j - 1] + e_FQ[j] * e_FQ[j]);
    if (_DEBUG){
        std::cout << "Qmax, Qmin, Qmax2, Smax=" << q_FQ[j] << ", " << q_FQ[j1] << ", " << q_FQ[j2] << ", " << Smax << std::endl;
        std::cout << "N_data, J_Qmin, J_Qmax2=" << q_FQ.size() << ", " << j1 << ", " << j2 << std::endl;
    }

    // ************* make a Phonon intensity file for BG determination **********
    std::vector<Double> q_BG;
    std::vector<Double> s_BG;
    std::vector<Double> e_BG;
    q_BG.clear();
    s_BG.clear();
    e_BG.clear();
    for (UInt4 M0=0; M0<(q_FQ.size()); M0++){
        if (M0 >= j1){
            q_BG.push_back(q_FQ[M0]);
            s_BG.push_back(s_FQ[M0]);
            e_BG.push_back(e_FQ[M0]);
        }
    }
    // ************Least squre fit of S(Q,E) for a*(Q-Qmax)^2-b*(Q-Qmax)^4+Smax ***********
    /*
        S(Q,E)_BG=Smax(Qmax)+a0*(Q-Qmax)*(Q+Qmax)-b0*(Q-Qmax)^2*(Q+Qmax)^2
        S(Q,E)_BG=Smax+a0*X(M)-b0*X(M)**2
    */

    gsl_matrix* A = gsl_matrix_alloc(j, 3);
    gsl_matrix* At = gsl_matrix_alloc(3, j);
    gsl_matrix* AtA = gsl_matrix_alloc(3, 3);
    gsl_vector* AtY = gsl_vector_alloc(3);
    gsl_vector* coefficients = gsl_vector_alloc(3);
    gsl_vector* FQ2 = gsl_vector_alloc(j);
    //gsl_vector* X = gsl_vector_alloc(j);

    // Initialize (matrix elements must be zero)
    gsl_matrix_set_zero(A);
    gsl_matrix_set_zero(At);
    gsl_matrix_set_zero(AtA);

    if (_DEBUG) std::cout << "------------------------" << std::endl;
    UInt4 numQ = j - j1 + 1;
    std::vector<Double> X(j, 0.0);
    for (UInt4 M=0; M<numQ; M++){
        X[M] = (q_BG[M] - Qmax) * (q_BG[M] + Qmax);
        gsl_vector_set(FQ2, M, (s_BG[M] - Smax));
        gsl_matrix_set(A, M, 0, X[M]);
        gsl_matrix_set(A, M, 1, (X[M] * X[M] * (-1.0)));
        gsl_matrix_set(A, M, 2, 1.0);
    }
    //for (UInt4 i=0; i<(q_BG.size()); i++) std::cout << "A[i][0] = " << gsl_matrix_get(A, i, 1) << std::endl;
    if (_DEBUG) for (UInt4 i=0; i<j; i++) std::cout << "A[" + _st->UInt4ToString(i) + "][1] = " << gsl_matrix_get(A, i, 1) << std::endl;

    // Compute transpose of A (At)
    UInt4 ret = gsl_matrix_transpose_memcpy(At, A);
    if (_DEBUG) for (UInt4 i=0; i<j; i++)std::cout << "At[0][" + _st->UInt4ToString(i) + "] = " << gsl_matrix_get(At, 0, i) << std::endl;

    // Compute AtA = At * A
    ret = gsl_blas_dgemm( CblasNoTrans, CblasNoTrans, 1.0, At, A, 0.0, AtA); // AtA = At*A
    if (_DEBUG){
        std::cout << "=== AtA ====" << std::endl;
        for (UInt4 i=0; i<3; i++)
            std::cout << gsl_matrix_get(AtA, i, 0) << "," << gsl_matrix_get(AtA, i, 1) << "," << gsl_matrix_get(AtA, i, 2) << std::endl;
        std::cout << std::endl;
    }

    // Compute AtY = At * FQ
    ret = gsl_blas_dgemv(CblasNoTrans, 1.0, At, FQ2, 0.0, AtY); // AtA = At*FQ2
    if (_DEBUG){
        std::cout << "=== AtY ====" << std::endl;
        std::cout << gsl_vector_get(AtY, 0) << "," << gsl_vector_get(AtY, 1) << "," << gsl_vector_get(AtY, 2) << std::endl;
        std::cout << std::endl;
    }

    UInt4 n = 3;
    UInt4 n2 = 3;
    gsl_vector_memcpy(coefficients, AtY); // coefficients <- AtY

    // Solve AtA * coefficients = AtY using Gauss-Jordan elimination
    for (UInt4 k=0; k < n; k++){
       Double pivot = gsl_matrix_get(AtA, k, k);
       if (_DEBUG) std::cout << "k = " << k << ", pivot = " << pivot << std::endl;
       if (pivot == 0.0){
           UtsusemiError(_MessageTag + "Pivot is zero, system is singular!");
           return false;
       }
       // Normalize the pivot row
       for (UInt4 k2 = 0; k2 < n2; k2++){
           Double p = gsl_matrix_get(AtA, k, k2);
           gsl_matrix_set(AtA, k, k2, p/pivot);
       }
       Double p2 = gsl_vector_get(coefficients, k);
       gsl_vector_set(coefficients, k, p2/pivot);

       // Eliminate other rows
       for (UInt4 M = 0; M < n; M++){
           if (M != k){
              Double temp = gsl_matrix_get(AtA, M, k);
              for (UInt4 i=0; i<n2; i++){
                  Double t2 = gsl_matrix_get(AtA, M, i) - gsl_matrix_get(AtA, k, i) * temp;
                  gsl_matrix_set(AtA, M ,i, t2);
              }
              Double t3 = gsl_vector_get(coefficients, M) - gsl_vector_get(coefficients, k) * temp;
              gsl_vector_set(coefficients, M, t3);
           }
       }
    }

    // Extract fitted parameters a0 and b0
    Double a0 = gsl_vector_get(coefficients, 0);
    Double b0 = gsl_vector_get(coefficients, 1);
    Double c0 = gsl_vector_get(coefficients, 2);
    UtsusemiMessage(_MessageTag + "ExecuteWideDymPDF >>> a0, b0, Smax = " + _st->DoubleToString(a0) + ", " + _st->DoubleToString(b0) + ", " + _st->DoubleToString(Smax + c0));

    gsl_matrix_free(A);
    gsl_matrix_free(At);
    gsl_matrix_free(AtA);
    gsl_vector_free(AtY);
    gsl_vector_free(coefficients);
    gsl_vector_free(FQ2);

    //************* S(Q,E) corrections by S(Q,E)_BG ***************
    // Window function WF(Q) calculation
    // write(*,'(a60)') 'Window function'

    std::vector<Double> q_FQA(j, 0.0);
    std::vector<Double> s_FQA(j, 0.0);
    std::vector<Double> e_FQA(j, 0.0);
    Double SSsum = 0;
    for (UInt4 M1 = 0; M1 < (j - 1); M1++){
        if (q_FQ[M1] == 0.0) q_FQ[M1] = 0.001;
        if (X[M1] == 0.0) X[M1] = 0.0000000000001;
        // Normalization by S(Q,E)_BG(=Smax+c0+a0*X(M1)-b0*X(M1)**2)
        q_FQA[M1] = q_FQ[M1];
        s_FQA[M1] = s_FQ[M1] - Smax - c0 - (a0 * X[M1]) + (b0 * X[M1] * X[M1]);
        e_FQA[M1] = e_FQ[M1];
        if (_DEBUG) std::cout << s_FQ[M1] << ", " << s_FQA[M1] << std::endl;
    }
    Double Smax2 = s_FQA[j2];
    if (_DEBUG){
        std::cout << "SUM of CfQ[S(Q,E)-1]WF(Q)=" << SSsum << std::endl;
        std::cout << "S(Qmax,E)=" << s_FQA[j-1] << std::endl;
    }
    // ************Least squre fit of S(Q,E) by b*(Q-Qmax)(Q-Qmax)***********
    Double d1 = 0.0;
    Double d2 = 0.0;
    Double b = 0.0;
    std::vector<Double> X1(j, 0.0);
    std::vector<Double> Y(j, 0.0);
    for (UInt4 M2 = 1; M2 < (j2 + 1); M2++){
        X1[M2] = (q_FQA[M2] - Qmax2) * (q_FQA[M2] - Qmax2);
        Y[M2] = s_FQA[M2] - s_FQA[j2];
        d1 = d1 + X1[M2] * Y[M2];
        d2 = d2 + X1[M2] * X1[M2];
    }
    b = d1 / d2;
    if (_DEBUG)
        std::cout << "b of b*(Q-Qmax)(Q-Qmax), Smax2=" << b << ", " << Smax2 << std::endl;

    /* ************* S(Q,E)/n(E) correction ***************
        Window function WF(Q)=Q[S_M(Q)-1] calculation
        write(*,'(a60)') 'Window function and Magnetic form factor normalization'
    */

    std::vector<Double> WF(j, 0.0);
    std::vector<Double> q_FQAV(j, 0.0);
    std::vector<Double> s_FQAV(j, 0.0);
    std::vector<Double> e_FQAV(j, 0.0);

    for (UInt4 M = 1; M < (j2 + 1); M++){
        if (q_FQA[M] == 0.0) q_FQA[M] = 0.001;
        WF[M] = Qmax2 * sin(MLF_PI * q_FQA[M] / Qmax2) / MLF_PI / q_FQA[M];
        q_FQAV[M] = q_FQA[M];
        // FQAV(2, M)=Cf*WF(M)*FQA(1, M)*(FQA(2, M)-Smax2-b*(FQA(1, M)-Qmax2)**2)/mgf(FQA(1, M))/mgf(FQA(1, M))
        s_FQAV[M] = _Cf * WF[M] * q_FQA[M] * (s_FQA[M] - Smax2 - b * (q_FQA[M] - Qmax2) * (q_FQA[M] - Qmax2)) / _mfg->Calc(q_FQA[M]) / _mfg->Calc(q_FQA[M]);
        e_FQAV[M] = _Cf * WF[M] * q_FQA[M] * e_FQA[M] / _mfg->Calc(q_FQA[M]) / _mfg->Calc(q_FQA[M]);
        SSsum += s_FQAV[M];
    }
    if (_DEBUG) std::cout << "SUM of S(Q,E)=" << SSsum << std::endl;

    // ************* DymPDF Gm(r,E)/n(E) calculation ***************
    // wideDymPDF Gm(r,E) calculation r=0~20 AA, Error of wideDymPDF: RHOAV(3,N)
    // r=RHOAV(1,N)=N*dr, Q=FQAV(1,M), chi"(Q)=FQAV(2,M), rho(r)=RHOAV(2,N),dQ=FQAV(1,M+1)-FQAV(1,M)
    UInt4 numN = r_RHO.size();
    Double dr = 0.1;
    for (UInt4 N = 0; N < numN; N++){
       r_RHO[N] = N * dr;
       for (UInt4 M = 1; M < j2; M++){
           //RHOAV(2,N) = RHOAV(2,N) + FQAV(2,M) * sin(FQAV(1,M) * RHOAV(1,N)) * FQAV(1,M) * (FQAV(1,M+1)-FQAV(1,M))
           g_RHO[N] = g_RHO[N] + s_FQAV[M] * sin(q_FQAV[M] * r_RHO[N]) * q_FQAV[M] * (q_FQAV[M + 1] - q_FQAV[M]);
           if (s_FQAV[M] < 0.001)
              e_RHO[N] = e_RHO[N] + ((e_FQAV[M] / 0.1) * (e_FQAV[M] / 0.1)) * q_FQAV[M] * q_FQAV[M] * (q_FQAV[M + 1] - q_FQAV[M]);
           else
              e_RHO[N] = e_RHO[N] + ((e_FQAV[M] / s_FQAV[M]) * (e_FQAV[M] / s_FQAV[M])) * q_FQAV[M] * q_FQAV[M] * (q_FQAV[M + 1] - q_FQAV[M]);
       }
       g_RHO[N] = 2.0 * g_RHO[N] / MLF_PI;
       e_RHO[N] = sqrt(e_RHO[N]) * sqrt(2.0) / MLF_PI;
    }
    return true;
}
bool ShamotoDymPDF::_ExecuteDyPDFBase(std::vector<Double>* r_RHO, std::vector<Double>* g_RHO, std::vector<Double>* e_RHO, std::vector<Double>* q_FQ, std::vector<Double>* s_FQ, std::vector<Double>* e_FQ, UInt4 nav){
    UInt4 j = (UInt4)(q_FQ->size());
    UInt4 numQ = j - nav + 1;
    std::vector<Double> q_FQA(numQ, 0.0);
    std::vector<Double> s_FQA(numQ, 0.0);
    std::vector<Double> e_FQA(numQ, 0.0);
    Double Qmax = 0.0;
    Double Smax = 0.0;
    for (UInt4 nm = 0; nm < (numQ); nm++){
        for (UInt4 na = 0; na < nav; na++){
            q_FQA[nm] = q_FQA[nm] + q_FQ->at(nm + na);
            s_FQA[nm] = s_FQA[nm] + s_FQ->at(nm + na);
            e_FQA[nm] = (e_FQA[nm] * e_FQA[nm]) + (e_FQ->at(nm + na) * e_FQ->at(nm + na));
        }
        q_FQA[nm] = q_FQA[nm] / nav;
        s_FQA[nm] = s_FQA[nm] / nav;
        e_FQA[nm] = sqrt(e_FQA[nm]) / nav;
        //std::cout << q_FQA[nm] << ", " << s_FQA[nm] << ", " << e_FQA[nm] << std::endl;
    }
    Qmax = q_FQA.back();
    Smax = s_FQA.back();

    if (_DEBUG) std::cout << "Qmax = " << Qmax << ", Smax = " << Smax << std::endl;
    //std::cout << q_FQA[j] << "," <<q_FQA[q_FQA.size() +1] << std::endl;

    /* ************Least squre fit of S(Q,E) for a*(Q-Qmax)^2-b*(Q-Qmax)^4+Smax ***********
       S(Q,E)_BG=Smax(Qmax)+a0*(Q-Qmax)*(Q+Qmax)-b0*(Q-Qmax)^2*(Q+Qmax)^2
       S(Q,E)_BG=Smax+a0*X(M)-b0*X(M)**2
    */
    // j = q_FQ.size()

    gsl_matrix* A = gsl_matrix_alloc(j, 3);
    gsl_matrix* At = gsl_matrix_alloc(3, j);
    gsl_matrix* AtA = gsl_matrix_alloc(3, 3);
    gsl_vector* AtY = gsl_vector_alloc(3);
    gsl_vector* coefficients = gsl_vector_alloc(3);
    //gsl_vector* FQ2 = gsl_vector_alloc(j);
    gsl_vector* FQ2 = gsl_vector_alloc(j);

    // Initialize (matrix elements must be zero)
    gsl_matrix_set_zero(A);
    gsl_matrix_set_zero(At);
    gsl_matrix_set_zero(AtA);

    std::cout << "------------------------" << std::endl;
    std::vector<Double> X(numQ, 0.0);
    for (UInt4 M = 0; M < numQ; M++){
        X[M] = (q_FQA[M] - Qmax) * (q_FQA[M] + Qmax);
        gsl_vector_set(FQ2, M, (s_FQA[M] - Smax));
        gsl_matrix_set(A, M, 0, X[M]);
        gsl_matrix_set(A, M, 1, X[M]*X[M]*(-1.0));
        gsl_matrix_set(A, M, 2, 1.0);
    }
    //for (UInt4 i=0; i<(q_FQA.size()); i++) std::cout << "A[i][0] = " << gsl_matrix_get(A, i, 1) << std::endl;

    // Compute transpose of A (At)
    UInt4 ret = gsl_matrix_transpose_memcpy(At, A);
    // for (UInt4 i=0; i<j; i++)std::cout << "At[0][i] = " << gsl_matrix_get(At, 0, i) << std::endl;

    // Compute AtA = At * A
    ret = gsl_blas_dgemm( CblasNoTrans, CblasNoTrans, 1.0, At, A, 0.0, AtA); // AtA = At*A
    // Compute AtY = At * FQ
    ret = gsl_blas_dgemv(CblasNoTrans, 1.0, At, FQ2, 0.0, AtY); // AtA = At*FQ2

    UInt4 n = 3;
    UInt4 n2 = 3;
    gsl_vector_memcpy(coefficients, AtY); // coefficients <- AtY

    // Forward elimination
    for (UInt4 k=0; k < n; k++){
        Double pivot = gsl_matrix_get(AtA, k, k);
        std::cout << "k = " << k << ", pivot = " << pivot << std::endl;
        if (pivot == 0.0){
            std::cout << "Pivot is zero, system is singular!" << std::endl;
            return false;
        }
        // Normalize the pivot row
        for (UInt4 k2 = 0; k2 < n2; k2++){
            Double p = gsl_matrix_get(AtA, k, k2);
            gsl_matrix_set(AtA, k, k2, p/pivot);
        }
        Double p2 = gsl_vector_get(coefficients, k);
        gsl_vector_set(coefficients, k, p2/pivot);

        // Eliminate other rows
        for (UInt4 M = 0; M < n; M++){
            if (M != k){
                Double temp = gsl_matrix_get(AtA, M, k);
                for (UInt4 i=0; i<n2; i++){
                    Double t2 = gsl_matrix_get(AtA, M, i) - gsl_matrix_get(AtA, k, i) * temp;
                    gsl_matrix_set(AtA, M ,i, t2);
                }
                Double t3 = gsl_vector_get(coefficients, M) - gsl_vector_get(coefficients, k) * temp;
                gsl_vector_set(coefficients, M, t3);
            }
        }
    }

    // Extract fitted parameters a0 and b0
    Double a0 = gsl_vector_get(coefficients, 0);
    Double b0 = gsl_vector_get(coefficients, 1);
    Double c0 = gsl_vector_get(coefficients, 2);
    std::cout << "a0, b0, c0 = " << std::scientific << std::setprecision(16) << a0 << ", " << b0 << ", " << c0 << std::endl;

    gsl_matrix_free(A);
    gsl_matrix_free(At);
    gsl_matrix_free(AtA);
    gsl_vector_free(AtY);
    gsl_vector_free(coefficients);
    gsl_vector_free(FQ2);

    //************* S(Q,E) corrections by WF(M) and S(Q,E)_BG ***************
    // Window function WF(Q) calculation
    // write(*,'(a60)') 'Window function'

    std::vector<Double> WF((numQ), 0.0);
    //std::vector<std::vector<Double>> FQAV;
    std::vector<Double> q_FQAV(numQ, 0.0);
    std::vector<Double> s_FQAV(numQ, 0.0);
    std::vector<Double> e_FQAV(numQ, 0.0);
    Double SSsum = 0;
    for (UInt4 M = 0; M < (numQ); M++){
        if (q_FQA[M] == 0.0) q_FQA[M] = 0.001;
        if (X[M] == 0.0) X[M] = 0.0000000000001;
        WF[M] = Qmax * sin(MLF_PI * q_FQA[M] / Qmax) / MLF_PI / q_FQA[M];
        q_FQAV[M] = q_FQA[M];
        s_FQAV[M] = _Cf * q_FQA[M] * (s_FQA[M] - Smax - c0 - (a0 * X[M]) + (b0 * X[M] * X[M])) * WF[M] / (Smax + c0 + (a0*X[M]) - (b0 * X[M] * X[M]));
        e_FQAV[M] = _Cf * q_FQA[M] * e_FQA[M] * WF[M];

        SSsum += s_FQAV[M];
    }
    std::cout << "SUM of CfQ[S(Q,E)-1]WF(Q)=" << SSsum << std::endl;

    // ************* DyPDF G(r,E) calculation ***************
    // DyPDF G(r,E) calculation r=0~20 AA-1, Error of DyPDF: RHOAV(3,N)
    // r=RHOAV(1,N)=N*dr, Q=FQAV(1,M), chi"(Q)=FQAV(2,M), rho(r)=RHOAV(2,N),dQ=FQAV(1,M+1)-FQAV(1,M)
    Double dr = 0.1;
    for (UInt4 N = 0; N < (r_RHO->size()); N++){
        (*r_RHO)[N] = N * dr;
        for (UInt4 M = 0; M < (numQ); M++){
            (*g_RHO)[N] = (*g_RHO)[N] + s_FQAV[M] * sin(q_FQAV[M] * (*r_RHO)[N]) * q_FQAV[M] * (q_FQAV[M + 1] - q_FQAV[M]);
            if (s_FQAV[M] < 0.001)
                (*e_RHO)[N] = (*e_RHO)[N] + ((e_FQAV[M] / 0.1) * (e_FQAV[M] / 0.1)) * q_FQAV[M] * q_FQAV[M] * (q_FQAV[M + 1] - q_FQAV[M]);
            else
                (*e_RHO)[N] = (*e_RHO)[N] + ((e_FQAV[M] / s_FQAV[M]) * (e_FQAV[M] / s_FQAV[M])) * q_FQAV[M] * q_FQAV[M] * (q_FQAV[M + 1] - q_FQAV[M]);
        }
        (*g_RHO)[N] = 2.0 * (*g_RHO)[N] / MLF_PI;
        (*e_RHO)[N] = sqrt((*e_RHO)[N]) * sqrt(2.0) / MLF_PI;
    }
    return true;
}
bool ShamotoDymPDF::_ExecuteDyPDF( bool doSlice ){
    Double Pi = M_PI;

    bool ret = false;
    if (doSlice){
        if (_sArray!=NULL) delete _sArray;
        _sArray = new ElementContainerArray();
        if (!(Slice( _ecm, _sArray, _dHW, _minHW, _maxHW))){
            UtsusemiError(_MessageTag + "_ExecuteDyPDF>> Slice Error");
            return false;
        }
    }
    if (_sArray==NULL){
        UtsusemiError("");
        return false;
    }else{
        for (UInt4 i1=0; i1<(_sArray->PutSize()); i1++){
            ElementContainer* ec = _sArray->PutPointer(i1);
            std::vector<Double> Qo = ec->PutX();
            std::vector<Double> I = ec->PutY();
            std::vector<Double> E = ec->PutE();
            std::vector<Double> Q;
            UInt4 Size = (UInt4)I.size();
            if ((UInt4)Qo.size()==Size){
                Q.resize(Size);
                copy(Qo.begin(),Qo.end(),Q.begin());
            }else{
                for (UInt4 i2=0; i2<Size; i2++)
                    Q.push_back( (Qo[i2]+Qo[i2+1])/2.0 );
            }

            UInt4 SizeOfG = (UInt4)(_maxR/_dR);
            std::vector<Double> Q_rho(SizeOfG,0.0);
            std::vector<Double> I_rho(SizeOfG,0.0);
            std::vector<Double> E_rho(SizeOfG,0.0);

            ret = _ExecuteDyPDFBase(&Q_rho, &I_rho, &E_rho, &Q, &I, &E, _nav);

            ec->Add(UTSUSEMI_KEY_MOMENTTRANSFER+"_RHO",Q_rho,UTSUSEMI_KEY_MOMENTTRANSFER_UNIT);
            ec->Add(UTSUSEMI_KEY_INTENSITY+"_RHO",I_rho,UTSUSEMI_KEY_ARB_UNIT);
            ec->Add(UTSUSEMI_KEY_ERROR+"_RHO",E_rho,UTSUSEMI_KEY_ARB_UNIT);
            ec->SetKeys(UTSUSEMI_KEY_MOMENTTRANSFER+"_RHO",UTSUSEMI_KEY_INTENSITY+"_RHO",UTSUSEMI_KEY_ERROR+"_RHO");
         }
    }
    return true;
}
ElementContainerArray ShamotoDymPDF::PutResult( bool isXaxisR ){
    ElementContainerArray ret;
    PutResult(&ret, isXaxisR);
    return ret;
}
void ShamotoDymPDF::PutResult( ElementContainerArray* eca, bool isXaxisR ){
    //if (!isXaxisR) return *_sArray;
    if (!isXaxisR){
        eca->InputHeader(_sArray->PutHeader());
        for (UInt4 i = 0; i < (_sArray->PutSize()); i++) eca->Add(_sArray->Put(i));
        return;
    }
    std::vector<Double> vr = _sArray->PutPointer(0)->PutX();
    UInt4 num_hw = (UInt4)(_sArray->PutSize());
    eca->Allocate((UInt4)vr.size());
    for (UInt4 i = 0; i<(UInt4)(vr.size()); i++){
        ElementContainer* ec = new ElementContainer();
        ec->AddToHeader( "R", vr[i] );
        ec->AddToHeader( "_UNIT_R", UTSUSEMI_KEY_LAMBDA_UNIT );
        std::vector<Double> hw(num_hw);
        std::vector<Double> II(num_hw);
        std::vector<Double> EE(num_hw);
        for (UInt4 j=0; j<num_hw; j++){
            hw[j] = _sArray->PutPointer(j)->PutHeaderPointer()->PutDouble(UTSUSEMI_KEY_HW);
            ElementContainer* _ec = _sArray->PutPointer(j);
            std::vector<Double>* ii = _ec->PutP( _ec->PutYKey() );
            std::vector<Double>* ee = _ec->PutP( _ec->PutEKey() );
            II[j] = ii->at(i);
            EE[j] = ee->at(i);
        }

        ec->Add( UTSUSEMI_KEY_ENERGYTRANSFER, hw, UTSUSEMI_KEY_ENERGY_UNIT); // hw, "EnergyTransfer", "meV"
        ec->Add( UTSUSEMI_KEY_INTENSITY, II, UTSUSEMI_KEY_ARB_UNIT );       // II, "Intensity", "arb. unit"
        ec->Add( UTSUSEMI_KEY_ERROR, EE, UTSUSEMI_KEY_ARB_UNIT );           // II, "Error", "arb. unit"
        ec->SetKeys(UTSUSEMI_KEY_ENERGYTRANSFER, UTSUSEMI_KEY_INTENSITY, UTSUSEMI_KEY_ERROR );
        eca->Set( i, ec );
    }
}
bool ShamotoDymPDF::Test( std::string _inputfile, std::string _outputfile, ElementContainerArray* _eca ){
    std::vector<Double> X;
    std::vector<Double> I;
    std::vector<Double> E;
    X.clear();
    I.clear();
    E.clear();

    FILE* fi;
    if ((fi=fopen(_inputfile.c_str(),"r"))==NULL){
        UtsusemiError(_MessageTag + "Test file open error "+_inputfile);
        return false;
    }
    char s[2000];
    if (fgets( s, 2000, fi )==NULL){ // Read Title line to be ignored
        UtsusemiError(_MessageTag + "Test file read error "+_inputfile);
        return false;
    }
    while( fgets( s, 2000, fi )!=NULL ){
        std::string a_line(s);
        std::vector<std::string> v = _st->SplitString( a_line);
        std::vector<Double> s;
        for (UInt4 i=0; i<v.size(); i++){
            if (v[i]!=""){
                s.push_back( _st->StringToDouble( v[i] ) );
            }
        }
        if ((UInt4)s.size() != 3){
            UtsusemiError(_MessageTag + "Test >>> file format is invalid : line = "+a_line+", size= "+_st->UInt4ToString((UInt4)(s.size())));
            return false;
        }
        X.push_back(s[0]);
        I.push_back(s[1]);
        E.push_back(s[2]);
    }
    fclose(fi);

    if (_sArray!=NULL) delete _sArray;
    _sArray = new ElementContainerArray();
    ElementContainer EC;

    EC.Add(UTSUSEMI_KEY_MOMENTTRANSFER,X,UTSUSEMI_KEY_MOMENTTRANSFER_UNIT);
    EC.Add(UTSUSEMI_KEY_INTENSITY,I,UTSUSEMI_KEY_ARB_UNIT);
    EC.Add(UTSUSEMI_KEY_ERROR,E,UTSUSEMI_KEY_ARB_UNIT);
    EC.SetKeys(UTSUSEMI_KEY_MOMENTTRANSFER,UTSUSEMI_KEY_INTENSITY,UTSUSEMI_KEY_ERROR);
    _sArray->Add(EC);

    Execute(false);
    ElementContainer ec_result = _sArray->Put(0);

    X.clear();
    I.clear();
    E.clear();

    FILE* fo;
    if ((fo=fopen(_outputfile.c_str(),"r"))==NULL){
        UtsusemiError(_MessageTag + "Test file error "+_outputfile);
        return false;
    }
    while( fgets( s, 2000, fo )!=NULL ){
        std::string a_line(s);
        std::vector<std::string> v = _st->SplitString( a_line," ",true );
        std::vector<Double> v2;
        for (UInt4 i=0; i<v.size(); i++){
            if (v[i]!=""){
                v2.push_back( _st->StringToDouble( v[i] ) );
            }
        }
        if ((UInt4)v2.size() != 3){
            UtsusemiError(_MessageTag + "Test >>> file format is invalid : line = "+a_line+", size= "+_st->UInt4ToString((UInt4)(v2.size())));
            return false;
        }
        X.push_back(v2[0]);
        I.push_back(v2[1]);
        E.push_back(v2[2]);
    }
    fclose(fo);

    ElementContainer ec_comp;
    ec_comp.Add(UTSUSEMI_KEY_MOMENTTRANSFER,X,UTSUSEMI_KEY_MOMENTTRANSFER_UNIT);
    ec_comp.Add(UTSUSEMI_KEY_INTENSITY,I,UTSUSEMI_KEY_ARB_UNIT);
    ec_comp.Add(UTSUSEMI_KEY_ERROR,E,UTSUSEMI_KEY_ARB_UNIT);
    ec_comp.SetKeys(UTSUSEMI_KEY_MOMENTTRANSFER,UTSUSEMI_KEY_INTENSITY,UTSUSEMI_KEY_ERROR);


    _eca->Add(EC);
    _eca->Add(ec_result);
    _eca->Add(ec_comp);

    return true;
}
bool ShamotoDymPDF::TestDyPDF( std::string _inputfile, UInt4 nav ){
    if (_useMF){
        UtsusemiError(_MessageTag + "TestDyPDF must be used on DyPDF mode only");
        return false;
    }

    _Cf = 1.0;
    //_inputfile = ;
    std::string ofn = "G2_" + _inputfile;
    std::string ofnq = "S2_" + _inputfile;
    std::cout << "Input file" + _inputfile << ", Output File = " + ofn + ", " + ofnq << std::endl;

    FILE* fp;
    if ((fp = fopen(_inputfile.c_str(), "r")) == NULL){
        UtsusemiError(_MessageTag + "TestDyPDF");
        std::cout << "ERROR : file not found (" + _inputfile + ")" << std::endl;
        return false;
    }
    UInt4 fret;
    Double q, s, e;
    std::vector<Double> q_FQ, s_FQ, e_FQ;
    while((fret = fscanf(fp, "%lf %lf %lf", &q, &s, &e)) != EOF){
        q_FQ.push_back(q);
        s_FQ.push_back(s);
        e_FQ.push_back(e);
    }
    fclose(fp);

    std::cout << "N_data=" << q_FQ.size() << std::endl;

    UInt4 numN = 1000;
    std::vector<Double> r_RHO(numN, 0.0);
    std::vector<Double> g_RHO(numN, 0.0);
    std::vector<Double> e_RHO(numN, 0.0);

    if (_ExecuteDyPDFBase(&r_RHO, &g_RHO, &e_RHO, &q_FQ, &s_FQ, &e_FQ, nav)){
        if ((fp = fopen(ofn.c_str(), "w")) == NULL){
            std::cout << "ERROR : Failed open file (" + ofn + ")" << std::endl;
            return false;
        }else{
            std::string mtitle = "# r(A) G(r,E) error";
           std::fprintf(fp, "%s\n", mtitle.c_str());
            char line_c[200];
            //for (UInt4 i = 0; i < (numN); i++){
            for (UInt4 i = 0; i < 400; i++){
                std::snprintf(line_c, sizeof(line_c), "%16.12f %16.12f %16.12f", r_RHO[i], g_RHO[i], e_RHO[i]);
                std::string a_line(line_c);
               std::fprintf(fp, "%s\n", a_line.c_str());
            }
            fclose(fp);
        }
    }else{
        std::cout << "ERROR!!  Failed execute calculation" << std::endl;
        return false;
    }
    return true;
}
bool ShamotoDymPDF::TestWideDymPDF( std::string _inputfile, Double Qmin, Double Qmax){
    _DEBUG = true;
    _Cf = 1.0;
    //_inputfile = ;
    std::string ofn = "Dm_" + _inputfile;
    std::string ofnq = "Sm_" + _inputfile;
    std::cout << "Input file" + _inputfile << ", Output File = " + ofn + ", " + ofnq << std::endl;

    FILE* fp;
    if ((fp = fopen(_inputfile.c_str(), "r")) == NULL){
        UtsusemiError(_MessageTag + "TestDyPDF");
        std::cout << "ERROR : file not found (" + _inputfile + ")" << std::endl;
        return false;
    }
    UInt4 fret;
    Double q, s, e;
    std::vector<Double> q_FQ, s_FQ, e_FQ;
    while((fret = fscanf(fp, "%lf %lf %lf", &q, &s, &e)) != EOF){
        q_FQ.push_back(q);
        s_FQ.push_back(s);
        e_FQ.push_back(e);
    }
    fclose(fp);

    std::cout << "N_data=" << q_FQ.size() << std::endl;
    UInt4 numN = 1000;
    std::vector<Double> r_RHO(numN, 0.0);
    std::vector<Double> g_RHO(numN, 0.0);
    std::vector<Double> e_RHO(numN, 0.0);

    std::vector<Double> params;
    params.push_back(Qmin);
    params.push_back(Qmax);

    if (_ExecuteWideDymPDFBase(r_RHO, g_RHO, e_RHO, q_FQ, s_FQ, e_FQ, params)){
        if ((fp = fopen(ofn.c_str(), "w")) == NULL){
            std::cout << "ERROR : Failed open file (" + ofn + ")" << std::endl;
            return false;
        }else{
            std::string mtitle = "# r(A) G(r,E) error";
           std::fprintf(fp, "%s\n", mtitle.c_str());
            char line_c[200];
            //for (UInt4 i = 0; i < (numN); i++){
            for (UInt4 i = 0; i < 400; i++){
                std::snprintf(line_c, sizeof(line_c), "%16.12f %16.12f %16.12f", r_RHO[i], g_RHO[i], e_RHO[i]);
                std::string a_line(line_c);
               std::fprintf(fp, "%s\n", a_line.c_str());
            }
            fclose(fp);
        }
    }else{
        std::cout << "ERROR!!  Failed execute calculation" << std::endl;
        return false;
    }
    _DEBUG = UtsusemiEnvGetDebugMode();
    return true;
}