// @(#)root/hist:$Id$
// Authors: L. Moneta, A. Flandi   08/2014
//
//
/**********************************************************************
 *                                                                    *
 * Copyright (c) 2015  ROOT  Team, CERN/PH-SFT                        *
 *                                                                    *
 *                                                                    *
 **********************************************************************/
//
//  TF1NormSum.cxx
//
//
//
#include "TROOT.h"
#include "TClass.h"
#include "TMath.h"
#include "TF1NormSum.h"
#include "Math/WrappedFunction.h"
#include "Math/WrappedTF1.h"





//ClassImp(TF1NormSum)


// function to find and rename duplicate parameters with the same name

template<class Iterator> 
void FixDuplicateNames(Iterator begin, Iterator end) { 


   // make a map of values 

   std::multimap<TString, int > parMap; 
   for (Iterator it = begin; it !=  end; ++it) { 
      parMap.insert( std::make_pair( *it, std::distance(begin,it) ) );
   }
   for ( auto & elem : parMap) { 
      TString name = elem.first; 
      int n = parMap.count( name); 
      if (n > 1 ) {
          std::pair <std::multimap<TString,int>::iterator, std::multimap<TString,int>::iterator> ret;
          ret = parMap.equal_range(name);
          int i = 0; 
          for (std::multimap<TString,int>::iterator it=ret.first; it!=ret.second; ++it) {
             *(begin+it->second) = TString::Format("%s%d",name.Data(),++i);
          }
      }
   }

   // for (Iterator it = begin; it !=  end; ++it) 
   //    std::cout << *it << "  ";
   // std::cout << std::endl;

}



void TF1NormSum::InitializeDataMembers(const std::vector <std::shared_ptr < TF1 >> &functions, const std::vector <Double_t> &coeffs, Double_t scale)
{

   fScale           = scale; 
   fFunctions       = functions;
   fCoeffs          = coeffs;
   fNOfFunctions    = functions.size();
   fCstIndexes      = std::vector < Int_t     > (fNOfFunctions);
   fParNames        = std::vector<TString> (fNOfFunctions);
   fParNames.reserve(3*fNOfFunctions);  // enlarge capacity for function parameters

   for (unsigned int n=0; n < fNOfFunctions; n++)
   {
      int npar = fFunctions[n] -> GetNpar();
      fCstIndexes[n]      = fFunctions[n] -> GetParNumber("Constant");//return -1 if there is no constant parameter
      //std::cout << " cst index of function " << n << " : " << fCstIndexes[n] << std::endl;
      //std::cout << "nofparam of function " << n <<" : " << fNOfParams[n] << std::endl;
      fParNames[n] = TString::Format("Coeff%d",n);
      //printf("examing function %s \n",fFunctions[n]->GetName() );
      if (fCstIndexes[n]!= -1)                                        //if there exists a constant parameter
      {
         fFunctions[n] -> FixParameter(fCstIndexes[n], 1.);          //fixes the parameters called "Constant" to 1
         int k = 0;                                                  //index for the temp arry, k wil go form 0 until fNofNonCstParameter
         for (int i=0; i<npar; i++)                         //go through all the parameter to
         {
            if (i==fCstIndexes[n])   continue;                      //go to next step if this is the constant parameter
            fParNames.push_back(  fFunctions[n] -> GetParName(i) ); 
            k++;
         }
      }
      else { 
         for (int i=0; i < npar; i++)                        //go through all the parameter to
         {
            fParNames.push_back( fFunctions[n] -> GetParName(i) ); 
         }
      }
      //normalize the functions if it is not already done (do at the end so constant parameter is not zero)
      if (!fFunctions[n] -> IsEvalNormalized())  fFunctions[n]  -> SetNormalized(true);
   }

   FixDuplicateNames(fParNames.begin()+fNOfFunctions, fParNames.end());

}
TF1NormSum::TF1NormSum()
{
   fNOfFunctions  = 0;
   fScale         = 1.;
   fFunctions     = std::vector< std::shared_ptr < TF1 >>(0) ;     // Vector of size fNOfFunctions containing TF1 functions
   fCoeffs        = std::vector < Double_t  >(0) ;        // Vector of size fNOfFunctions containing coefficients in front of each function
   fCstIndexes = std::vector < Int_t     > (0);   
}

//_________________________________________________________________
TF1NormSum::TF1NormSum(const std::vector <TF1*> &functions, const std::vector <Double_t> &coeffs, Double_t scale)
{
   std::vector <std::shared_ptr < TF1 > >f;
   for (unsigned int i = 0; i<functions.size(); i++)
   {
    f[i] = std::shared_ptr < TF1 >((TF1*)functions[i]->Clone());
   }
   
   InitializeDataMembers(f,coeffs,scale);
}

//______________________________________________________________________________
TF1NormSum::TF1NormSum(TF1* function1, TF1* function2, Double_t coeff1, Double_t coeff2, Double_t scale)
{
   // TF1NormSum constructor taking 2 functions, and 2 coefficients (if not equal to 1)
   
   std::vector < std::shared_ptr < TF1 > > functions(2);
   std::vector < Double_t > coeffs(2);
   TF1 * fnew1 = 0;
   TF1 * fnew2 = 0;
   // need to use Copy because clone does not work for functor-based functions
   if (function1) { 
      fnew1 = (TF1*) function1->IsA()->New();
      function1->Copy(*fnew1); 
   }
   if (function2) { 
      fnew2 = (TF1*) function2->IsA()->New();
      function2->Copy(*fnew2); 
   }
   if (fnew1 == nullptr || fnew2 == nullptr)
      Fatal("TF1NormSum","Invalid input functions - Abort");

   std::shared_ptr < TF1 > f1( fnew1);
   std::shared_ptr < TF1 > f2( fnew2);
   
   functions       = {f1, f2};
   coeffs          = {coeff1,    coeff2};
   
   InitializeDataMembers(functions, coeffs,scale);
}

//______________________________________________________________________________
TF1NormSum::TF1NormSum(TF1* function1, TF1* function2, TF1* function3, Double_t coeff1, Double_t coeff2, Double_t coeff3, Double_t scale)
{
   // TF1NormSum constructor taking 3 functions, and 3 coefficients (if not equal to 1)
   
   std::vector < std::shared_ptr < TF1 > > functions(3);
   std::vector < Double_t > coeffs(3);
   TF1 * fnew1 = 0;
   TF1 * fnew2 = 0;
   TF1 * fnew3 = 0;
   if (function1) { 
      fnew1 = (TF1*) function1->IsA()->New();
      function1->Copy(*fnew1); 
   }
   if (function2) { 
      fnew2 = (TF1*) function2->IsA()->New();
      function2->Copy(*fnew2); 
   }
   if (function3) { 
      fnew3 = (TF1*) function3->IsA()->New();
      function3->Copy(*fnew2); 
   }
   if (!fnew1 || !fnew2  || !fnew3 )
      Fatal("TF1NormSum","Invalid input functions - Abort");

   std::shared_ptr < TF1 > f1( fnew1);
   std::shared_ptr < TF1 > f2( fnew2);
   std::shared_ptr < TF1 > f3( fnew3);
   
   
   functions       = {f1, f2, f3};
   coeffs          = {coeff1,    coeff2,    coeff3};
   
   InitializeDataMembers(functions, coeffs,scale);
}

//_________________________________________________________________
TF1NormSum::TF1NormSum(const TString &formula, Double_t xmin, Double_t xmax)
{
   //  TF1NormSum constructortaking any addition of formulas with coefficient or not
   // example 1 : 2.*expo + gauss + 0.5* gauss
   // example 2 : expo + 0.3*f1 if f1 is defined in the list of fucntions
   
   TF1::InitStandardFunctions();
   
   TObjArray *arrayall    = formula.Tokenize("*+");
   TObjArray *arraytimes  = formula.Tokenize("*") ;
   Int_t noffunctions     = (formula.Tokenize("+")) -> GetEntries();
   Int_t nofobj           = arrayall  -> GetEntries();
   Int_t nofcoeffs        = nofobj - noffunctions;
   
   std::vector < std::shared_ptr < TF1 >     > functions(noffunctions);
   std::vector < Double_t > coeffs(noffunctions);
   std::vector < TString  > funcstringall(nofobj);
   std::vector < Int_t    > indexsizetimes(nofcoeffs+1);
   std::vector < Bool_t   > isacoeff(nofobj);//1 is it is a coeff, 0 if it is a functions
   
   for (int i=0; i<nofobj; i++)
   {
      funcstringall[i] = ((TObjString*)((*arrayall)[i])) -> GetString();
      funcstringall[i].ReplaceAll(" ","");
   }
   //algorithm to determine which object is a coefficient and which is a function
   //uses the fact that the last item of funcstringtimes[i].Tokenize("+") is always a coeff.
   Int_t j = 0;
   Int_t k = 1;
   for (int i=0; i<nofcoeffs+1; i++)
   {
      indexsizetimes[i] = ( ( ( (TObjString*)(*arraytimes)[i] ) -> GetString() ).Tokenize("+") ) -> GetEntries();
      while (k < indexsizetimes[i])
      {
         isacoeff[k+j-1] = 0;
         k++;
      }
      j = j+indexsizetimes[i];
      if (j==nofobj)    isacoeff[j-1] = 0;    //the last one is never a coeff
      else              isacoeff[j-1] = 1;
      k = 1;
   }
   k = 0;
   for (int i=0; i<noffunctions; i++)
   {
      if (isacoeff[k]==0)
      {
         coeffs[i]    = 1.;
         TF1* f = (TF1*)(gROOT -> GetListOfFunctions() -> FindObject(funcstringall[k]));
         if (!f)   Error("TF1NormSum", "Function %s does not exist", funcstringall[k].Data());
         functions[i] = std::shared_ptr < TF1 > ((TF1*)f->Clone(TString::Format("function_%s_%d",funcstringall[k].Data(), i)));
         functions[i]->SetRange(xmin,xmax);
         k++;
      }
      else
      {
         coeffs[i]    = funcstringall[k].Atof();
         TF1* f  = (TF1*)(gROOT -> GetListOfFunctions() -> FindObject(funcstringall[k+1]));
         if (!f)   Error("TF1NormSum", "Function %s does not exist", funcstringall[k+1].Data());
         functions[i] = std::shared_ptr < TF1 >((TF1*)f->Clone(TString::Format("function_%s_%d",funcstringall[k+1].Data(), i) ));
         functions[i]->SetRange(xmin,xmax);
         k=k+2;
      }
   }
   InitializeDataMembers(functions, coeffs,1.);
   
   /*for (auto f : functions)
    {
    f->Print();
    }
    for (auto c : coeffs)
    {
    std::cout << "coeff " << c << std::endl;
    }*/
}

//_________________________________________________________________
double TF1NormSum::operator()(double* x, double* p)
{
   // Overload the parenthesis to add the functions
   if (p!=0)   TF1NormSum::SetParameters(p);                           // first refresh the parameters
   
   Double_t sum = 0.;
   for (unsigned int n=0; n<fNOfFunctions; n++)
   {
      sum += fCoeffs[n]*(fFunctions[n] -> EvalPar(x,0));
   }
   // normalize by a scale parameter (typically the bin width)
   return fScale * sum;
}

//_________________________________________________________________   
std::vector<double>  TF1NormSum::GetParameters() const {
   // return array of parameters

   std::vector<double> params(GetNpar() );
   int offset = 0;
   int nOfNonCstParams = 0;
   for (unsigned int n=0; n<fNOfFunctions; n++)
   {
      params[n] = fCoeffs[n];   // copy the coefficients
      offset += nOfNonCstParams;           // offset to go along the list of parameters
      int k = 0;
      for (int j = 0; j < fFunctions[n]->GetNpar(); ++j) {
         if (j != fCstIndexes[n]) {
            params[k+fNOfFunctions+offset] = fFunctions[n]->GetParameter(j);
            k++;
         }
      }
      nOfNonCstParams = k; 
   }
   return params;
}
//_________________________________________________________________
void TF1NormSum::SetParameters(const double* params)//params should have the size [fNOfFunctions][fNOfNonCstParams]
{
   // Initialize array of all parameters.
   // double *params must contains first an array of the coefficients, then an array of the parameters.

   for (unsigned int n=0; n<fNOfFunctions; n++)                         //initialization of the coefficients
   {
      fCoeffs[n] = params[n];
   }
   Int_t    offset     = 0;
   int k = 0;  // k indicates the nnumber of non-constant parameter per function
   for (unsigned int n=0; n<fNOfFunctions; n++)
   {
      bool equalParams = true;
      Double_t * funcParams = fFunctions[n]->GetParameters();
      int npar = fFunctions[n]->GetNpar();
      offset += k;      // offset to go along the list of parameters
      k = 0; // reset k value for next function
      for (int i = 0; i < npar; ++i) {
         // constant parameters can be only one
         if (i != fCstIndexes[n])
         {
            // check if they are equal
            equalParams &= (funcParams[i] == params[k+fNOfFunctions+offset] );
            funcParams[i] = params[k+fNOfFunctions+offset];
            k++;
         }
      }
      // update function integral if not equal
      if (!equalParams) fFunctions[n]->Update(); 
            
   }
}

//______________________________________________________________________________
void TF1NormSum::SetParameters(Double_t p0, Double_t p1, Double_t p2, Double_t p3, Double_t p4,
                               Double_t p5, Double_t p6, Double_t p7, Double_t p8, Double_t p9, Double_t p10)
{
   // Initialize array of all parameters.
   // Overload the TF1::SetParameters() method.
   // A maximum of 10 parameters must be used, with first the coefficients, then the parameters
   
   const double params[] = {p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10};
   TF1NormSum::SetParameters(params);
   
}
//return the number of (non constant) paramters including the coefficients: for 2 functions: c1,c2,p0,p1,p2,p3...
Int_t TF1NormSum::GetNpar() const
{
   Int_t nofparams = 0;
   for (unsigned int n=0; n<fNOfFunctions; ++n)
   {
      nofparams += fFunctions[n]->GetNpar();
      if (fCstIndexes[n] >= 0) nofparams -= 1;
   }
   return nofparams + fNOfFunctions;                                   //fNOfFunctions for the  coefficientws
}
 TF1NormSum.cxx:1
 TF1NormSum.cxx:2
 TF1NormSum.cxx:3
 TF1NormSum.cxx:4
 TF1NormSum.cxx:5
 TF1NormSum.cxx:6
 TF1NormSum.cxx:7
 TF1NormSum.cxx:8
 TF1NormSum.cxx:9
 TF1NormSum.cxx:10
 TF1NormSum.cxx:11
 TF1NormSum.cxx:12
 TF1NormSum.cxx:13
 TF1NormSum.cxx:14
 TF1NormSum.cxx:15
 TF1NormSum.cxx:16
 TF1NormSum.cxx:17
 TF1NormSum.cxx:18
 TF1NormSum.cxx:19
 TF1NormSum.cxx:20
 TF1NormSum.cxx:21
 TF1NormSum.cxx:22
 TF1NormSum.cxx:23
 TF1NormSum.cxx:24
 TF1NormSum.cxx:25
 TF1NormSum.cxx:26
 TF1NormSum.cxx:27
 TF1NormSum.cxx:28
 TF1NormSum.cxx:29
 TF1NormSum.cxx:30
 TF1NormSum.cxx:31
 TF1NormSum.cxx:32
 TF1NormSum.cxx:33
 TF1NormSum.cxx:34
 TF1NormSum.cxx:35
 TF1NormSum.cxx:36
 TF1NormSum.cxx:37
 TF1NormSum.cxx:38
 TF1NormSum.cxx:39
 TF1NormSum.cxx:40
 TF1NormSum.cxx:41
 TF1NormSum.cxx:42
 TF1NormSum.cxx:43
 TF1NormSum.cxx:44
 TF1NormSum.cxx:45
 TF1NormSum.cxx:46
 TF1NormSum.cxx:47
 TF1NormSum.cxx:48
 TF1NormSum.cxx:49
 TF1NormSum.cxx:50
 TF1NormSum.cxx:51
 TF1NormSum.cxx:52
 TF1NormSum.cxx:53
 TF1NormSum.cxx:54
 TF1NormSum.cxx:55
 TF1NormSum.cxx:56
 TF1NormSum.cxx:57
 TF1NormSum.cxx:58
 TF1NormSum.cxx:59
 TF1NormSum.cxx:60
 TF1NormSum.cxx:61
 TF1NormSum.cxx:62
 TF1NormSum.cxx:63
 TF1NormSum.cxx:64
 TF1NormSum.cxx:65
 TF1NormSum.cxx:66
 TF1NormSum.cxx:67
 TF1NormSum.cxx:68
 TF1NormSum.cxx:69
 TF1NormSum.cxx:70
 TF1NormSum.cxx:71
 TF1NormSum.cxx:72
 TF1NormSum.cxx:73
 TF1NormSum.cxx:74
 TF1NormSum.cxx:75
 TF1NormSum.cxx:76
 TF1NormSum.cxx:77
 TF1NormSum.cxx:78
 TF1NormSum.cxx:79
 TF1NormSum.cxx:80
 TF1NormSum.cxx:81
 TF1NormSum.cxx:82
 TF1NormSum.cxx:83
 TF1NormSum.cxx:84
 TF1NormSum.cxx:85
 TF1NormSum.cxx:86
 TF1NormSum.cxx:87
 TF1NormSum.cxx:88
 TF1NormSum.cxx:89
 TF1NormSum.cxx:90
 TF1NormSum.cxx:91
 TF1NormSum.cxx:92
 TF1NormSum.cxx:93
 TF1NormSum.cxx:94
 TF1NormSum.cxx:95
 TF1NormSum.cxx:96
 TF1NormSum.cxx:97
 TF1NormSum.cxx:98
 TF1NormSum.cxx:99
 TF1NormSum.cxx:100
 TF1NormSum.cxx:101
 TF1NormSum.cxx:102
 TF1NormSum.cxx:103
 TF1NormSum.cxx:104
 TF1NormSum.cxx:105
 TF1NormSum.cxx:106
 TF1NormSum.cxx:107
 TF1NormSum.cxx:108
 TF1NormSum.cxx:109
 TF1NormSum.cxx:110
 TF1NormSum.cxx:111
 TF1NormSum.cxx:112
 TF1NormSum.cxx:113
 TF1NormSum.cxx:114
 TF1NormSum.cxx:115
 TF1NormSum.cxx:116
 TF1NormSum.cxx:117
 TF1NormSum.cxx:118
 TF1NormSum.cxx:119
 TF1NormSum.cxx:120
 TF1NormSum.cxx:121
 TF1NormSum.cxx:122
 TF1NormSum.cxx:123
 TF1NormSum.cxx:124
 TF1NormSum.cxx:125
 TF1NormSum.cxx:126
 TF1NormSum.cxx:127
 TF1NormSum.cxx:128
 TF1NormSum.cxx:129
 TF1NormSum.cxx:130
 TF1NormSum.cxx:131
 TF1NormSum.cxx:132
 TF1NormSum.cxx:133
 TF1NormSum.cxx:134
 TF1NormSum.cxx:135
 TF1NormSum.cxx:136
 TF1NormSum.cxx:137
 TF1NormSum.cxx:138
 TF1NormSum.cxx:139
 TF1NormSum.cxx:140
 TF1NormSum.cxx:141
 TF1NormSum.cxx:142
 TF1NormSum.cxx:143
 TF1NormSum.cxx:144
 TF1NormSum.cxx:145
 TF1NormSum.cxx:146
 TF1NormSum.cxx:147
 TF1NormSum.cxx:148
 TF1NormSum.cxx:149
 TF1NormSum.cxx:150
 TF1NormSum.cxx:151
 TF1NormSum.cxx:152
 TF1NormSum.cxx:153
 TF1NormSum.cxx:154
 TF1NormSum.cxx:155
 TF1NormSum.cxx:156
 TF1NormSum.cxx:157
 TF1NormSum.cxx:158
 TF1NormSum.cxx:159
 TF1NormSum.cxx:160
 TF1NormSum.cxx:161
 TF1NormSum.cxx:162
 TF1NormSum.cxx:163
 TF1NormSum.cxx:164
 TF1NormSum.cxx:165
 TF1NormSum.cxx:166
 TF1NormSum.cxx:167
 TF1NormSum.cxx:168
 TF1NormSum.cxx:169
 TF1NormSum.cxx:170
 TF1NormSum.cxx:171
 TF1NormSum.cxx:172
 TF1NormSum.cxx:173
 TF1NormSum.cxx:174
 TF1NormSum.cxx:175
 TF1NormSum.cxx:176
 TF1NormSum.cxx:177
 TF1NormSum.cxx:178
 TF1NormSum.cxx:179
 TF1NormSum.cxx:180
 TF1NormSum.cxx:181
 TF1NormSum.cxx:182
 TF1NormSum.cxx:183
 TF1NormSum.cxx:184
 TF1NormSum.cxx:185
 TF1NormSum.cxx:186
 TF1NormSum.cxx:187
 TF1NormSum.cxx:188
 TF1NormSum.cxx:189
 TF1NormSum.cxx:190
 TF1NormSum.cxx:191
 TF1NormSum.cxx:192
 TF1NormSum.cxx:193
 TF1NormSum.cxx:194
 TF1NormSum.cxx:195
 TF1NormSum.cxx:196
 TF1NormSum.cxx:197
 TF1NormSum.cxx:198
 TF1NormSum.cxx:199
 TF1NormSum.cxx:200
 TF1NormSum.cxx:201
 TF1NormSum.cxx:202
 TF1NormSum.cxx:203
 TF1NormSum.cxx:204
 TF1NormSum.cxx:205
 TF1NormSum.cxx:206
 TF1NormSum.cxx:207
 TF1NormSum.cxx:208
 TF1NormSum.cxx:209
 TF1NormSum.cxx:210
 TF1NormSum.cxx:211
 TF1NormSum.cxx:212
 TF1NormSum.cxx:213
 TF1NormSum.cxx:214
 TF1NormSum.cxx:215
 TF1NormSum.cxx:216
 TF1NormSum.cxx:217
 TF1NormSum.cxx:218
 TF1NormSum.cxx:219
 TF1NormSum.cxx:220
 TF1NormSum.cxx:221
 TF1NormSum.cxx:222
 TF1NormSum.cxx:223
 TF1NormSum.cxx:224
 TF1NormSum.cxx:225
 TF1NormSum.cxx:226
 TF1NormSum.cxx:227
 TF1NormSum.cxx:228
 TF1NormSum.cxx:229
 TF1NormSum.cxx:230
 TF1NormSum.cxx:231
 TF1NormSum.cxx:232
 TF1NormSum.cxx:233
 TF1NormSum.cxx:234
 TF1NormSum.cxx:235
 TF1NormSum.cxx:236
 TF1NormSum.cxx:237
 TF1NormSum.cxx:238
 TF1NormSum.cxx:239
 TF1NormSum.cxx:240
 TF1NormSum.cxx:241
 TF1NormSum.cxx:242
 TF1NormSum.cxx:243
 TF1NormSum.cxx:244
 TF1NormSum.cxx:245
 TF1NormSum.cxx:246
 TF1NormSum.cxx:247
 TF1NormSum.cxx:248
 TF1NormSum.cxx:249
 TF1NormSum.cxx:250
 TF1NormSum.cxx:251
 TF1NormSum.cxx:252
 TF1NormSum.cxx:253
 TF1NormSum.cxx:254
 TF1NormSum.cxx:255
 TF1NormSum.cxx:256
 TF1NormSum.cxx:257
 TF1NormSum.cxx:258
 TF1NormSum.cxx:259
 TF1NormSum.cxx:260
 TF1NormSum.cxx:261
 TF1NormSum.cxx:262
 TF1NormSum.cxx:263
 TF1NormSum.cxx:264
 TF1NormSum.cxx:265
 TF1NormSum.cxx:266
 TF1NormSum.cxx:267
 TF1NormSum.cxx:268
 TF1NormSum.cxx:269
 TF1NormSum.cxx:270
 TF1NormSum.cxx:271
 TF1NormSum.cxx:272
 TF1NormSum.cxx:273
 TF1NormSum.cxx:274
 TF1NormSum.cxx:275
 TF1NormSum.cxx:276
 TF1NormSum.cxx:277
 TF1NormSum.cxx:278
 TF1NormSum.cxx:279
 TF1NormSum.cxx:280
 TF1NormSum.cxx:281
 TF1NormSum.cxx:282
 TF1NormSum.cxx:283
 TF1NormSum.cxx:284
 TF1NormSum.cxx:285
 TF1NormSum.cxx:286
 TF1NormSum.cxx:287
 TF1NormSum.cxx:288
 TF1NormSum.cxx:289
 TF1NormSum.cxx:290
 TF1NormSum.cxx:291
 TF1NormSum.cxx:292
 TF1NormSum.cxx:293
 TF1NormSum.cxx:294
 TF1NormSum.cxx:295
 TF1NormSum.cxx:296
 TF1NormSum.cxx:297
 TF1NormSum.cxx:298
 TF1NormSum.cxx:299
 TF1NormSum.cxx:300
 TF1NormSum.cxx:301
 TF1NormSum.cxx:302
 TF1NormSum.cxx:303
 TF1NormSum.cxx:304
 TF1NormSum.cxx:305
 TF1NormSum.cxx:306
 TF1NormSum.cxx:307
 TF1NormSum.cxx:308
 TF1NormSum.cxx:309
 TF1NormSum.cxx:310
 TF1NormSum.cxx:311
 TF1NormSum.cxx:312
 TF1NormSum.cxx:313
 TF1NormSum.cxx:314
 TF1NormSum.cxx:315
 TF1NormSum.cxx:316
 TF1NormSum.cxx:317
 TF1NormSum.cxx:318
 TF1NormSum.cxx:319
 TF1NormSum.cxx:320
 TF1NormSum.cxx:321
 TF1NormSum.cxx:322
 TF1NormSum.cxx:323
 TF1NormSum.cxx:324
 TF1NormSum.cxx:325
 TF1NormSum.cxx:326
 TF1NormSum.cxx:327
 TF1NormSum.cxx:328
 TF1NormSum.cxx:329
 TF1NormSum.cxx:330
 TF1NormSum.cxx:331
 TF1NormSum.cxx:332
 TF1NormSum.cxx:333
 TF1NormSum.cxx:334
 TF1NormSum.cxx:335
 TF1NormSum.cxx:336
 TF1NormSum.cxx:337
 TF1NormSum.cxx:338
 TF1NormSum.cxx:339
 TF1NormSum.cxx:340
 TF1NormSum.cxx:341
 TF1NormSum.cxx:342
 TF1NormSum.cxx:343
 TF1NormSum.cxx:344
 TF1NormSum.cxx:345
 TF1NormSum.cxx:346
 TF1NormSum.cxx:347
 TF1NormSum.cxx:348
 TF1NormSum.cxx:349
 TF1NormSum.cxx:350
 TF1NormSum.cxx:351
 TF1NormSum.cxx:352
 TF1NormSum.cxx:353
 TF1NormSum.cxx:354
 TF1NormSum.cxx:355
 TF1NormSum.cxx:356
 TF1NormSum.cxx:357
 TF1NormSum.cxx:358
 TF1NormSum.cxx:359
 TF1NormSum.cxx:360
 TF1NormSum.cxx:361
 TF1NormSum.cxx:362
 TF1NormSum.cxx:363
 TF1NormSum.cxx:364