double ECHARM_distribution::GenerateNumberGauss(double Mean, double Sigma)
{
    double GaussValue = 0.0;
    double GaussTemp = 0.0;
    double GaussTempX1 = 0.0;
    double GaussTempX2 = 0.0;

    
    if (fGaussFirstOk)		       
    {
        GaussValue = fGaussSecondValue;
        fGaussFirstOk = 0;
    }
    else
    {
        do {
            GaussTempX1 = 2.0 * drand48() - 1.0;
            GaussTempX2 = 2.0 * drand48() - 1.0;
            GaussTemp = GaussTempX1 * GaussTempX1 + GaussTempX2 * GaussTempX2;
        } while ( GaussTemp >= 1.0 );
        
        GaussTemp = fSquareRoot( (-2.0*log(GaussTemp))/GaussTemp);
        GaussValue = GaussTempX1 * GaussTemp;
        fGaussSecondValue = GaussTempX2 * GaussTemp;
        fGaussFirstOk = 1;
    }
    return (Mean + GaussValue * Sigma);
}
double ECHARM_cell::FindPeriodReciprocal(int vIndex[3])
{
    double double_temp = 0.0;
    int i;
    for(i=0;i<3;i++) double_temp += fSquare(vIndex[i]/fSize->GetComponent(i));
    double_temp = fSquareRoot(double_temp)*2*M_PI;
    return double_temp;
}
double ECHARM_cell::FindPeriodDirect(int vIndex[3])
{
    double double_temp = 0.0;
    int i;
    for(i=0;i<3;i++) double_temp += fSquare(vIndex[i]/fSize->GetComponent(i));
    double_temp = fSquareRoot(1/double_temp);
    return double_temp;
}
void ECHARM_process_bethe_bloch::DoOnParticle(ECHARM_strip* strip,ECHARM_particle* part,ECHARM_info_save*){
    fStdDev = fSquareRoot(ComputeMeanEnergyLoss(strip,part) * part->GetStepLength() * cElectronMass) * ComputeAvgElD(strip,part);

    fDistr->SetPar(1,fStdDev);
    
    double vMomVar = part->GetMom()->GetModule() - fDistr->GenerateNumber();

    part->GetMom()->ScaleModule(vMomVar);
}
double ECHARM_distribution::GetValueGauss(double vX, double Mean, double Sigma)
{
    double vValue = exp(-0.5*fSquare((vX-Mean)/(Sigma)))/(fSquareRoot(2.*M_PI)*Sigma);
    return vValue;
}
double ECHARM_simulation_integration_averaged::GetAveragedDechannelingProbability()
{
    double vDechannelingEnergy = 0.0;
    double vValueATD = 0.;
    double vValueELD = 0.;
    double vDechProb = 0.0;
    
#ifdef ROOT_
    std::string vHistoName = "hDechProb_prf" + GetStrip()->GetRadiusValueAsStringText() + "_" + GetStrip()->GetLengthValueAsStringText();
    std::string vHistoNameATD = "hDechProbATD_prf" + GetStrip()->GetRadiusValueAsStringText() + "_" + GetStrip()->GetLengthValueAsStringText();
    std::string vHistoNameELD = "hDechProbELD_prf" + GetStrip()->GetRadiusValueAsStringText() + "_" + GetStrip()->GetLengthValueAsStringText();
    
    TH1F *hDechProb = new TH1F( vHistoName.c_str(),"hDechProb;Interplanar Distance [#AA]",GetIntegrationStepNumberPlanar(),0.,GetStrip()->GetCrystal()->GetDirectPeriodPlanar()/AA);
    TH1F *hDechProbATD = new TH1F( vHistoNameATD.c_str(),"hDechProb;Interplanar Distance [#AA]",GetIntegrationStepNumberPlanar(),0.,GetStrip()->GetCrystal()->GetDirectPeriodPlanar()/AA);
    TH1F *hDechProbELD = new TH1F( vHistoNameELD.c_str(),"hDechProb;Interplanar Distance [#AA]",GetIntegrationStepNumberPlanar(),0.,GetStrip()->GetCrystal()->GetDirectPeriodPlanar()/AA);
#endif
    
    std::vector<double> vVectEff;
    vVectEff.clear();
    
    for(unsigned int i = 0; i < GetIntegrationStepNumberPlanar(); i++)
    {
 
        if(fPlanarEnergyToDechannel.at(i)==0.){
            vValueELD = 1.;
            vValueATD = 1.;
        }
        else{
            if(fPlanarElectronDensity.at(i)!=0.0){
                fMultipleScattering->SetCrossedMaterialLength( fPlanarElectronDensity.at(i) * GetStrip()->GetDimension()->GetZ() );
                fMultipleScattering->UpdateElectronScatteringOutgoingDistribution();
                vValueELD = (erfc(vDechannelingEnergy/(fSquareRoot(2.)*(fMultipleScattering->GetElectronScatteringOutgoingDistribution()->GetDistributionParameters().at(1)))));
            }
            if(fPlanarEnergyToDechannel.at(i)!=0.){
                fMultipleScattering->SetCrossedMaterialLength( fPlanarAtomicDensity.at(i) * GetStrip()->GetDimension()->GetZ() );
                fMultipleScattering->UpdateNuclearScatteringOutgoingDistribution();
                vValueATD = (erfc(vDechannelingEnergy/(fSquareRoot(2.)*(fMultipleScattering->GetNuclearScatteringOutgoingDistribution()->GetDistributionParameters().at(1)))));
            }
        
            vDechannelingEnergy = fSquareRoot(2. * fPlanarEnergyToDechannel.at(i) * GetParticle()->GetMomentumVector()->GetZ() );
        }
        
        vVectEff.push_back(fSquareRoot(fSquare(vValueATD)+fSquare(vValueELD)) / fSquareRoot(2.));
        vDechProb += vVectEff.at(i);
        
#ifdef ROOT_
        hDechProbATD->SetBinContent(i+1,vValueATD);
        hDechProbELD->SetBinContent(i+1,vValueELD);
        hDechProb->SetBinContent(i+1,vVectEff.at(i));
#endif
    }

//    unsigned int vNumberOfResample = 3;
//    unsigned int iTot = GetIntegrationStepNumberPlanar() * vNumberOfResample;
//
//    double vValue = 0.;
//    double x = 0.;
//    
//    for(unsigned int j = 0;j < iTot - 2 ;j++)
//    {
//        x = GetStrip()->GetDirectPeriodPlanar() / iTot * j;
//        vValue = fInterpolationFunction->FindInterpolate1D(vVectEff.at(j),vVectEff.at(j+1),vVectEff.at(j+2),vVectEff.at(j+3),x);
//        vDechProb += vValue;
//    }
//        
//    x = GetStrip()->GetDirectPeriodPlanar() / iTot * (iTot - 2);
//    vDechProb += fInterpolationFunction->FindInterpolate1D(vVectEff.at(iTot - 2),vVectEff.at(iTot - 1),vVectEff.at(iTot),vVectEff.at(0),x)
//    
//    x = GetStrip()->GetDirectPeriodPlanar() / iTot * (iTot - 1);
//    vDechProb += fInterpolationFunction->FindInterpolate1D(vVectEff.at(iTot - 1),vVectEff.at(iTot),vVectEff.at(0),vVectEff.at(1),x)
    
    
    vDechProb /= GetIntegrationStepNumberPlanar();
    vDechProb -= 1.;
    vDechProb *= (-1);
    
    //std::cout << "ECHARM_simulation_integration_averaged: Efficiency = " << vDechProb*100 << " [%]" << std::endl;
    return vDechProb;
}
double ComputeDistanceThreeVectors(ECHARM_threevector* X1,ECHARM_threevector* X2){
    return fSquareRoot( (X1->GetX()-X2->GetX()) + (X1->GetY()-X2->GetY()) + (X1->GetZ()-X2->GetZ()));
}