TF1.cxx

Go to the documentation of this file.
00001 // @(#)root/hist:$Id: TF1.cxx 38124 2011-02-17 17:19:13Z moneta $
00002 // Author: Rene Brun   18/08/95
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "Riostream.h"
00013 #include "TROOT.h"
00014 #include "TMath.h"
00015 #include "TF1.h"
00016 #include "TH1.h"
00017 #include "TGraph.h"
00018 #include "TVirtualPad.h"
00019 #include "TStyle.h"
00020 #include "TRandom.h"
00021 #include "TInterpreter.h"
00022 #include "TPluginManager.h"
00023 #include "TBrowser.h"
00024 #include "TColor.h"
00025 #include "TClass.h"
00026 #include "TMethodCall.h"
00027 #include "TF1Helper.h"
00028 #include "Math/WrappedFunction.h"
00029 #include "Math/WrappedTF1.h"
00030 #include "Math/BrentRootFinder.h"
00031 #include "Math/BrentMinimizer1D.h"
00032 #include "Math/BrentMethods.h"
00033 #include "Math/Integrator.h"
00034 #include "Math/GaussIntegrator.h"
00035 #include "Math/GaussLegendreIntegrator.h"
00036 #include "Math/AdaptiveIntegratorMultiDim.h"
00037 #include "Math/RichardsonDerivator.h"
00038 #include "Math/Functor.h"
00039 #include "Fit/FitResult.h"
00040 
00041 //#include <iostream>
00042 
00043 Bool_t TF1::fgAbsValue    = kFALSE;
00044 Bool_t TF1::fgRejectPoint = kFALSE;
00045 static Double_t gErrorTF1 = 0;
00046 
00047 
00048 ClassImp(TF1)
00049 
00050 // class wrapping evaluation of TF1(x) - y0
00051 class GFunc {
00052    const TF1* fFunction;
00053    const double fY0;
00054 public:
00055    GFunc(const TF1* function , double y ):fFunction(function), fY0(y) {}
00056    double operator()(double x) const {
00057       return fFunction->Eval(x) - fY0;
00058    }
00059 };
00060 
00061 // class wrapping evaluation of -TF1(x)
00062 class GInverseFunc {
00063    const TF1* fFunction;
00064 public:
00065    GInverseFunc(const TF1* function):fFunction(function) {}
00066    double operator()(double x) const {
00067       return - fFunction->Eval(x);
00068    }
00069 };
00070 
00071 // class wrapping function evaluation directly in 1D interface (used for integration) 
00072 // and implementing the methods for the momentum calculations
00073 
00074 class  TF1_EvalWrapper : public ROOT::Math::IGenFunction { 
00075 public: 
00076    TF1_EvalWrapper(TF1 * f, const Double_t * par, bool useAbsVal, Double_t n = 1, Double_t x0 = 0) : 
00077       fFunc(f), 
00078       fPar( ( (par) ? par : f->GetParameters() ) ),
00079       fAbsVal(useAbsVal),
00080       fN(n), 
00081       fX0(x0)   
00082    {
00083       fFunc->InitArgs(fX, fPar); 
00084    }
00085 
00086    ROOT::Math::IGenFunction * Clone()  const { 
00087       // use default copy constructor
00088       TF1_EvalWrapper * f =  new TF1_EvalWrapper( *this);
00089       f->fFunc->InitArgs(f->fX, f->fPar); 
00090       return f;
00091    }
00092    // evaluate |f(x)|
00093    Double_t DoEval( Double_t x) const { 
00094       fX[0] = x; 
00095       Double_t fval = fFunc->EvalPar( fX, fPar);
00096       if (fAbsVal && fval < 0)  return -fval;
00097       return fval; 
00098    } 
00099    // evaluate x * |f(x)|
00100    Double_t EvalFirstMom( Double_t x) { 
00101       fX[0] = x; 
00102       return fX[0] * TMath::Abs( fFunc->EvalPar( fX, fPar) ); 
00103    } 
00104    // evaluate (x - x0) ^n * f(x)
00105    Double_t EvalNMom( Double_t x) const  { 
00106       fX[0] = x; 
00107       return TMath::Power( fX[0] - fX0, fN) * TMath::Abs( fFunc->EvalPar( fX, fPar) ); 
00108    }
00109 
00110    TF1 * fFunc; 
00111    mutable Double_t fX[1]; 
00112    const double * fPar; 
00113    Bool_t fAbsVal;
00114    Double_t fN; 
00115    Double_t fX0;
00116 };
00117 
00118 
00119 
00120 //______________________________________________________________________________
00121 /* Begin_Html
00122 <center><h2>TF1: 1-Dim function class</h2></center>
00123 A TF1 object is a 1-Dim function defined between a lower and upper limit.
00124 <br>The function may be a simple function (see <tt>TFormula</tt>) or a
00125 precompiled user function.
00126 <br>The function may have associated parameters.
00127 <br>TF1 graphics function is via the <tt>TH1/TGraph</tt> drawing functions.
00128 <p>
00129 The following types of functions can be created:
00130 <ul>
00131 <li><a href="#F1">A - Expression using variable x and no parameters</a></li>
00132 <li><a href="#F2">B - Expression using variable x with parameters</a></li>
00133 <li><a href="#F3">C - A general C function with parameters</a></li>
00134 <li><a href="#F4">D - A general C++ function object (functor) with parameters</a></li>
00135 <li><a href="#F5">E - A member function with parameters of a general C++ class</a></li>
00136 </ul>
00137 
00138 <a name="F1"></a><h3>A - Expression using variable x and no parameters</h3>
00139 <h4>Case 1: inline expression using standard C++ functions/operators</h4>
00140 <div class="code"><pre>
00141    TF1 *fa1 = new TF1("fa1","sin(x)/x",0,10);
00142    fa1->Draw();
00143 </pre></div><div class="clear" />
00144 End_Html
00145 Begin_Macro
00146 {
00147    TCanvas *c = new TCanvas("c","c",0,0,500,300);
00148    TF1 *fa1 = new TF1("fa1","sin(x)/x",0,10);
00149    fa1->Draw();
00150    return c;
00151 }
00152 End_Macro
00153 Begin_Html
00154 <h4>Case 2: inline expression using TMath functions without parameters</h4>
00155 <div class="code"><pre>
00156    TF1 *fa2 = new TF1("fa2","TMath::DiLog(x)",0,10);
00157    fa2->Draw();
00158 </pre></div><div class="clear" />
00159 End_Html
00160 Begin_Macro
00161 {
00162    TCanvas *c = new TCanvas("c","c",0,0,500,300);
00163    TF1 *fa2 = new TF1("fa2","TMath::DiLog(x)",0,10);
00164    fa2->Draw();
00165    return c;
00166 }
00167 End_Macro
00168 Begin_Html
00169 <h4>Case 3: inline expression using a CINT function by name</h4>
00170 <div class="code"><pre>
00171    Double_t myFunc(x) {
00172       return x+sin(x);
00173    }
00174    TF1 *fa3 = new TF1("fa3","myFunc(x)",-3,5);
00175    fa3->Draw();
00176 </pre></div><div class="clear" />
00177 
00178 <a name="F2"></a><h3>B - Expression using variable x with parameters</h3>
00179 <h4>Case 1: inline expression using standard C++ functions/operators</h4>
00180 <ul>
00181 <li>Example a:
00182 <div class="code"><pre>
00183    TF1 *fa = new TF1("fa","[0]*x*sin([1]*x)",-3,3);
00184 </pre></div><div class="clear" />
00185 This creates a function of variable x with 2 parameters.
00186 The parameters must be initialized via:
00187 <pre>
00188    fa->SetParameter(0,value_first_parameter);
00189    fa->SetParameter(1,value_second_parameter);
00190 </pre>
00191 Parameters may be given a name:
00192 <pre>
00193    fa->SetParName(0,"Constant");
00194 </pre>
00195 </li>
00196 <li> Example b:
00197 <div class="code"><pre>
00198    TF1 *fb = new TF1("fb","gaus(0)*expo(3)",0,10);
00199 </pre></div><div class="clear" />
00200 <tt>gaus(0)</tt> is a substitute for <tt>[0]*exp(-0.5*((x-[1])/[2])**2)</tt>
00201 and <tt>(0)</tt> means start numbering parameters at <tt>0</tt>.
00202 <tt>expo(3)</tt> is a substitute for <tt>exp([3]+[4]*x)</tt>.
00203 </li>
00204 </ul>
00205 
00206 <h4>Case 2: inline expression using TMath functions with parameters</h4>
00207 <div class="code"><pre>
00208    TF1 *fb2 = new TF1("fa3","TMath::Landau(x,[0],[1],0)",-5,10);
00209    fb2->SetParameters(0.2,1.3);
00210    fb2->Draw();
00211 </pre></div><div class="clear" />
00212 End_Html
00213 Begin_Macro
00214 {
00215    TCanvas *c = new TCanvas("c","c",0,0,500,300);
00216    TF1 *fb2 = new TF1("fa3","TMath::Landau(x,[0],[1],0)",-5,10);
00217    fb2->SetParameters(0.2,1.3);
00218    fb2->Draw();
00219    return c;
00220 }
00221 End_Macro
00222 Begin_Html
00223 
00224 <a name="F3"></a><h3>C - A general C function with parameters</h3>
00225 Consider the macro myfunc.C below:
00226 <div class="code"><pre>
00227    // Macro myfunc.C
00228    Double_t myfunction(Double_t *x, Double_t *par)
00229    {
00230       Float_t xx =x[0];
00231       Double_t f = TMath::Abs(par[0]*sin(par[1]*xx)/xx);
00232       return f;
00233    }
00234    void myfunc()
00235    {
00236       TF1 *f1 = new TF1("myfunc",myfunction,0,10,2);
00237       f1->SetParameters(2,1);
00238       f1->SetParNames("constant","coefficient");
00239       f1->Draw();
00240    }
00241    void myfit()
00242    {
00243       TH1F *h1=new TH1F("h1","test",100,0,10);
00244       h1->FillRandom("myfunc",20000);
00245       TF1 *f1=gROOT->GetFunction("myfunc");
00246       f1->SetParameters(800,1);
00247       h1->Fit("myfunc");
00248    }
00249 </pre></div><div class="clear" />
00250 
00251 End_Html
00252 Begin_Html
00253 
00254 <p>
00255 In an interactive session you can do:
00256 <div class="code"><pre>
00257    Root > .L myfunc.C
00258    Root > myfunc();
00259    Root > myfit();
00260 </pre></div>
00261 <div class="clear" />
00262 
00263 End_Html
00264 Begin_Html
00265 
00266 <tt>TF1</tt> objects can reference other <tt>TF1</tt> objects (thanks John
00267 Odonnell) of type A or B defined above. This excludes CINT interpreted functions
00268 and compiled functions. However, there is a restriction. A function cannot
00269 reference a basic function if the basic function is a polynomial polN.
00270 <p>Example:
00271 <div class="code"><pre>
00272    {
00273       TF1 *fcos = new TF1 ("fcos", "[0]*cos(x)", 0., 10.);
00274       fcos->SetParNames( "cos");
00275       fcos->SetParameter( 0, 1.1);
00276 
00277       TF1 *fsin = new TF1 ("fsin", "[0]*sin(x)", 0., 10.);
00278       fsin->SetParNames( "sin");
00279       fsin->SetParameter( 0, 2.1);
00280 
00281       TF1 *fsincos = new TF1 ("fsc", "fcos+fsin");
00282 
00283       TF1 *fs2 = new TF1 ("fs2", "fsc+fsc");
00284    }
00285 </pre></div><div class="clear" />
00286 
00287 End_Html
00288 Begin_Html
00289 
00290 
00291 <a name="F4"></a><h3>D - A general C++ function object (functor) with parameters</h3>
00292 A TF1 can be created from any C++ class implementing the operator()(double *x, double *p).
00293 The advantage of the function object is that he can have a state and reference therefore what-ever other object.
00294 In this way the user can customize his function.
00295 <p>Example:
00296 <div class="code"><pre>
00297 class  MyFunctionObject {
00298  public:
00299    // use constructor to customize your function object
00300 
00301    double operator() (double *x, double *p) {
00302       // function implementation using class data members
00303    }
00304 };
00305 {
00306     ....
00307    MyFunctionObject * fobj = new MyFunctionObject(....);       // create the function object
00308    TF1 * f = new TF1("f",fobj,0,1,npar,"MyFunctionObject");    // create TF1 class.
00309    .....
00310 }
00311 </pre></div><div class="clear" />
00312 When constructing the TF1 class, the name of the function object class is required only if running in CINT
00313 and it is not needed in compiled C++ mode. In addition in compiled mode the cfnution object can be passed to TF1
00314 by value.
00315 See also the tutorial math/exampleFunctor.C for a running example.
00316 
00317 End_Html
00318 Begin_Html
00319 
00320 <a name="F5"></a><h3>E - A member function with parameters of a general C++ class</h3>
00321 A TF1 can be created in this case from any member function of a class which has the signature of
00322 (double * , double *) and returning a double.
00323 <p>Example:
00324 <div class="code"><pre>
00325 class  MyFunction {
00326  public:
00327    ...
00328    double Evaluate() (double *x, double *p) {
00329       // function implementation
00330    }
00331 };
00332 {
00333     ....
00334    MyFunction * fptr = new MyFunction(....);  // create the user function class
00335    TF1 * f = new TF1("f",fptr,&MyFunction::Evaluate,0,1,npar,"MyFunction","Evaluate");   // create TF1 class.
00336 
00337    .....
00338 }
00339 </pre></div><div class="clear" />
00340 When constructing the TF1 class, the name of the function class and of the member function are required only
00341 if running in CINT and they are not need in compiled C++ mode.
00342 See also the tutorial math/exampleFunctor.C for a running example.
00343 
00344 End_Html */
00345 
00346 TF1 *TF1::fgCurrent = 0;
00347 
00348 
00349 //______________________________________________________________________________
00350 TF1::TF1(): TFormula(), TAttLine(), TAttFill(), TAttMarker()
00351 {
00352    // F1 default constructor.
00353 
00354    fXmin      = 0;
00355    fXmax      = 0;
00356    fNpx       = 100;
00357    fType      = 0;
00358    fNpfits    = 0;
00359    fNDF       = 0;
00360    fNsave     = 0;
00361    fChisquare = 0;
00362    fIntegral  = 0;
00363    fParErrors = 0;
00364    fParMin    = 0;
00365    fParMax    = 0;
00366    fAlpha     = 0;
00367    fBeta      = 0;
00368    fGamma     = 0;
00369    fParent    = 0;
00370    fSave      = 0;
00371    fHistogram = 0;
00372    fMinimum   = -1111;
00373    fMaximum   = -1111;
00374    fMethodCall = 0;
00375    fCintFunc   = 0;
00376    SetFillStyle(0);
00377 }
00378 
00379 
00380 //______________________________________________________________________________
00381 TF1::TF1(const char *name,const char *formula, Double_t xmin, Double_t xmax)
00382       :TFormula(name,formula), TAttLine(), TAttFill(), TAttMarker()
00383 {
00384    // F1 constructor using a formula definition
00385    //
00386    //  See TFormula constructor for explanation of the formula syntax.
00387    //
00388    //  See tutorials: fillrandom, first, fit1, formula1, multifit
00389    //  for real examples.
00390    //
00391    //  Creates a function of type A or B between xmin and xmax
00392    //
00393    //  if formula has the form "fffffff;xxxx;yyyy", it is assumed that
00394    //  the formula string is "fffffff" and "xxxx" and "yyyy" are the
00395    //  titles for the X and Y axis respectively.
00396 
00397    if (xmin < xmax ) {
00398       fXmin      = xmin;
00399       fXmax      = xmax;
00400    } else {
00401       fXmin = xmax; //when called from TF2,TF3
00402       fXmax = xmin;
00403    }
00404    fNpx       = 100;
00405    fType      = 0;
00406    if (fNpar) {
00407       fParErrors = new Double_t[fNpar];
00408       fParMin    = new Double_t[fNpar];
00409       fParMax    = new Double_t[fNpar];
00410       for (int i = 0; i < fNpar; i++) {
00411          fParErrors[i]  = 0;
00412          fParMin[i]     = 0;
00413          fParMax[i]     = 0;
00414       }
00415    } else {
00416       fParErrors = 0;
00417       fParMin    = 0;
00418       fParMax    = 0;
00419    }
00420    fChisquare  = 0;
00421    fIntegral   = 0;
00422    fAlpha      = 0;
00423    fBeta       = 0;
00424    fGamma      = 0;
00425    fParent     = 0;
00426    fNpfits     = 0;
00427    fNDF        = 0;
00428    fNsave      = 0;
00429    fSave       = 0;
00430    fHistogram  = 0;
00431    fMinimum    = -1111;
00432    fMaximum    = -1111;
00433    fMethodCall = 0;
00434    fCintFunc   = 0;
00435 
00436    if (fNdim != 1 && xmin < xmax) {
00437       Error("TF1","function: %s/%s has %d parameters instead of 1",name,formula,fNdim);
00438       MakeZombie();
00439    }
00440 
00441    if (!gStyle) return;
00442    SetLineColor(gStyle->GetFuncColor());
00443    SetLineWidth(gStyle->GetFuncWidth());
00444    SetLineStyle(gStyle->GetFuncStyle());
00445    SetFillStyle(0);
00446 }
00447 
00448 
00449 //______________________________________________________________________________
00450 TF1::TF1(const char *name, Double_t xmin, Double_t xmax, Int_t npar)
00451       :TFormula(), TAttLine(), TAttFill(), TAttMarker()
00452 {
00453    // F1 constructor using name of an interpreted function.
00454    //
00455    //  Creates a function of type C between xmin and xmax.
00456    //  name is the name of an interpreted CINT cunction.
00457    //  The function is defined with npar parameters
00458    //  fcn must be a function of type:
00459    //     Double_t fcn(Double_t *x, Double_t *params)
00460    //
00461    //  This constructor is called for functions of type C by CINT.
00462    //
00463    // WARNING! A function created with this constructor cannot be Cloned.
00464 
00465    fXmin       = xmin;
00466    fXmax       = xmax;
00467    fNpx        = 100;
00468    fType       = 2;
00469    if (npar > 0 ) fNpar = npar;
00470    if (fNpar) {
00471       fNames      = new TString[fNpar];
00472       fParams     = new Double_t[fNpar];
00473       fParErrors  = new Double_t[fNpar];
00474       fParMin     = new Double_t[fNpar];
00475       fParMax     = new Double_t[fNpar];
00476       for (int i = 0; i < fNpar; i++) {
00477          fParams[i]     = 0;
00478          fParErrors[i]  = 0;
00479          fParMin[i]     = 0;
00480          fParMax[i]     = 0;
00481       }
00482    } else {
00483       fParErrors = 0;
00484       fParMin    = 0;
00485       fParMax    = 0;
00486    }
00487    fChisquare  = 0;
00488    fIntegral   = 0;
00489    fAlpha      = 0;
00490    fBeta       = 0;
00491    fGamma      = 0;
00492    fParent     = 0;
00493    fNpfits     = 0;
00494    fNDF        = 0;
00495    fNsave      = 0;
00496    fSave       = 0;
00497    fHistogram  = 0;
00498    fMinimum    = -1111;
00499    fMaximum    = -1111;
00500    fMethodCall = 0;
00501    fCintFunc   = 0;
00502    fNdim       = 1;
00503 
00504    TF1 *f1old = (TF1*)gROOT->GetListOfFunctions()->FindObject(name);
00505    gROOT->GetListOfFunctions()->Remove(f1old);
00506    SetName(name);
00507 
00508    if (gStyle) {
00509       SetLineColor(gStyle->GetFuncColor());
00510       SetLineWidth(gStyle->GetFuncWidth());
00511       SetLineStyle(gStyle->GetFuncStyle());
00512    }
00513    SetFillStyle(0);
00514 
00515    SetTitle(name);
00516    if (name) {
00517       if (*name == '*') return; //case happens via SavePrimitive
00518       fMethodCall = new TMethodCall();
00519       fMethodCall->InitWithPrototype(name,"Double_t*,Double_t*");
00520       fNumber = -1;
00521       gROOT->GetListOfFunctions()->Add(this);
00522       if (! fMethodCall->IsValid() ) {
00523          Error("TF1","No function found with the signature %s(Double_t*,Double_t*)",name);
00524       }
00525    } else {
00526       Error("TF1","requires a proper function name!");
00527    }
00528 }
00529 
00530 
00531 //______________________________________________________________________________
00532 TF1::TF1(const char *name,void *fcn, Double_t xmin, Double_t xmax, Int_t npar)
00533       :TFormula(), TAttLine(), TAttFill(), TAttMarker()
00534 {
00535    // F1 constructor using pointer to an interpreted function.
00536    //
00537    //  See TFormula constructor for explanation of the formula syntax.
00538    //
00539    //  Creates a function of type C between xmin and xmax.
00540    //  The function is defined with npar parameters
00541    //  fcn must be a function of type:
00542    //     Double_t fcn(Double_t *x, Double_t *params)
00543    //
00544    //  see tutorial; myfit for an example of use
00545    //  also test/stress.cxx (see function stress1)
00546    //
00547    //
00548    //  This constructor is called for functions of type C by CINT.
00549    //
00550    //  WARNING! A function created with this constructor cannot be Cloned.
00551 
00552 
00553    fXmin       = xmin;
00554    fXmax       = xmax;
00555    fNpx        = 100;
00556    fType       = 2;
00557    //fFunction   = 0;
00558    if (npar > 0 ) fNpar = npar;
00559    if (fNpar) {
00560       fNames      = new TString[fNpar];
00561       fParams     = new Double_t[fNpar];
00562       fParErrors  = new Double_t[fNpar];
00563       fParMin     = new Double_t[fNpar];
00564       fParMax     = new Double_t[fNpar];
00565       for (int i = 0; i < fNpar; i++) {
00566          fParams[i]     = 0;
00567          fParErrors[i]  = 0;
00568          fParMin[i]     = 0;
00569          fParMax[i]     = 0;
00570       }
00571    } else {
00572       fParErrors = 0;
00573       fParMin    = 0;
00574       fParMax    = 0;
00575    }
00576    fChisquare  = 0;
00577    fIntegral   = 0;
00578    fAlpha      = 0;
00579    fBeta       = 0;
00580    fGamma      = 0;
00581    fParent     = 0;
00582    fNpfits     = 0;
00583    fNDF        = 0;
00584    fNsave      = 0;
00585    fSave       = 0;
00586    fHistogram  = 0;
00587    fMinimum    = -1111;
00588    fMaximum    = -1111;
00589    fMethodCall = 0;
00590    fCintFunc   = 0;
00591    fNdim       = 1;
00592 
00593    TF1 *f1old = (TF1*)gROOT->GetListOfFunctions()->FindObject(name);
00594    gROOT->GetListOfFunctions()->Remove(f1old);
00595    SetName(name);
00596 
00597    if (gStyle) {
00598       SetLineColor(gStyle->GetFuncColor());
00599       SetLineWidth(gStyle->GetFuncWidth());
00600       SetLineStyle(gStyle->GetFuncStyle());
00601    }
00602    SetFillStyle(0);
00603 
00604    if (!fcn) return;
00605    const char *funcname = gCint->Getp2f2funcname(fcn);
00606    SetTitle(funcname);
00607    if (funcname) {
00608       fMethodCall = new TMethodCall();
00609       fMethodCall->InitWithPrototype(funcname,"Double_t*,Double_t*");
00610       fNumber = -1;
00611       gROOT->GetListOfFunctions()->Add(this);
00612       if (! fMethodCall->IsValid() ) {
00613          Error("TF1","No function found with the signature %s(Double_t*,Double_t*)",funcname);
00614       }
00615    } else {
00616       Error("TF1","can not find any function at the address 0x%lx. This function requested for %s",(Long_t)fcn,name);
00617    }
00618 
00619 
00620 }
00621 
00622 
00623 //______________________________________________________________________________
00624 TF1::TF1(const char *name,Double_t (*fcn)(Double_t *, Double_t *), Double_t xmin, Double_t xmax, Int_t npar)
00625       :TFormula(), TAttLine(), TAttFill(), TAttMarker()
00626 {
00627    // F1 constructor using a pointer to a real function.
00628    //
00629    //   npar is the number of free parameters used by the function
00630    //
00631    //   This constructor creates a function of type C when invoked
00632    //   with the normal C++ compiler.
00633    //
00634    //   see test program test/stress.cxx (function stress1) for an example.
00635    //   note the interface with an intermediate pointer.
00636    //
00637    // WARNING! A function created with this constructor cannot be Cloned.
00638 
00639    fXmin       = xmin;
00640    fXmax       = xmax;
00641    fNpx        = 100;
00642 
00643    fType       = 1;
00644    fMethodCall = 0;
00645    fCintFunc   = 0;
00646    fFunctor = ROOT::Math::ParamFunctor(fcn);
00647 
00648    if (npar > 0 ) fNpar = npar;
00649    if (fNpar) {
00650       fNames      = new TString[fNpar];
00651       fParams     = new Double_t[fNpar];
00652       fParErrors  = new Double_t[fNpar];
00653       fParMin     = new Double_t[fNpar];
00654       fParMax     = new Double_t[fNpar];
00655       for (int i = 0; i < fNpar; i++) {
00656          fParams[i]     = 0;
00657          fParErrors[i]  = 0;
00658          fParMin[i]     = 0;
00659          fParMax[i]     = 0;
00660       }
00661    } else {
00662       fParErrors = 0;
00663       fParMin    = 0;
00664       fParMax    = 0;
00665    }
00666    fChisquare  = 0;
00667    fIntegral   = 0;
00668    fAlpha      = 0;
00669    fBeta       = 0;
00670    fGamma      = 0;
00671    fNsave      = 0;
00672    fSave       = 0;
00673    fParent     = 0;
00674    fNpfits     = 0;
00675    fNDF        = 0;
00676    fHistogram  = 0;
00677    fMinimum    = -1111;
00678    fMaximum    = -1111;
00679    fNdim       = 1;
00680 
00681    // Store formula in linked list of formula in ROOT
00682    TF1 *f1old = (TF1*)gROOT->GetListOfFunctions()->FindObject(name);
00683    gROOT->GetListOfFunctions()->Remove(f1old);
00684    SetName(name);
00685    gROOT->GetListOfFunctions()->Add(this);
00686 
00687    if (!gStyle) return;
00688    SetLineColor(gStyle->GetFuncColor());
00689    SetLineWidth(gStyle->GetFuncWidth());
00690    SetLineStyle(gStyle->GetFuncStyle());
00691    SetFillStyle(0);
00692 
00693 }
00694 
00695 //______________________________________________________________________________
00696 TF1::TF1(const char *name,Double_t (*fcn)(const Double_t *, const Double_t *), Double_t xmin, Double_t xmax, Int_t npar)
00697       :TFormula(), TAttLine(), TAttFill(), TAttMarker()
00698 {
00699    // F1 constructor using a pointer to real function.
00700    //
00701    //   npar is the number of free parameters used by the function
00702    //
00703    //   This constructor creates a function of type C when invoked
00704    //   with the normal C++ compiler.
00705    //
00706    //   see test program test/stress.cxx (function stress1) for an example.
00707    //   note the interface with an intermediate pointer.
00708    //
00709    // WARNING! A function created with this constructor cannot be Cloned.
00710 
00711    fXmin       = xmin;
00712    fXmax       = xmax;
00713    fNpx        = 100;
00714 
00715    fType       = 1;
00716    fMethodCall = 0;
00717    fCintFunc   = 0;
00718    fFunctor = ROOT::Math::ParamFunctor(fcn);
00719 
00720    if (npar > 0 ) fNpar = npar;
00721    if (fNpar) {
00722       fNames      = new TString[fNpar];
00723       fParams     = new Double_t[fNpar];
00724       fParErrors  = new Double_t[fNpar];
00725       fParMin     = new Double_t[fNpar];
00726       fParMax     = new Double_t[fNpar];
00727       for (int i = 0; i < fNpar; i++) {
00728          fParams[i]     = 0;
00729          fParErrors[i]  = 0;
00730          fParMin[i]     = 0;
00731          fParMax[i]     = 0;
00732       }
00733    } else {
00734       fParErrors = 0;
00735       fParMin    = 0;
00736       fParMax    = 0;
00737    }
00738    fChisquare  = 0;
00739    fIntegral   = 0;
00740    fAlpha      = 0;
00741    fBeta       = 0;
00742    fGamma      = 0;
00743    fNsave      = 0;
00744    fSave       = 0;
00745    fParent     = 0;
00746    fNpfits     = 0;
00747    fNDF        = 0;
00748    fHistogram  = 0;
00749    fMinimum    = -1111;
00750    fMaximum    = -1111;
00751    fNdim       = 1;
00752 
00753    // Store formula in linked list of formula in ROOT
00754    TF1 *f1old = (TF1*)gROOT->GetListOfFunctions()->FindObject(name);
00755    gROOT->GetListOfFunctions()->Remove(f1old);
00756    SetName(name);
00757    gROOT->GetListOfFunctions()->Add(this);
00758 
00759    if (!gStyle) return;
00760    SetLineColor(gStyle->GetFuncColor());
00761    SetLineWidth(gStyle->GetFuncWidth());
00762    SetLineStyle(gStyle->GetFuncStyle());
00763    SetFillStyle(0);
00764 
00765 }
00766 
00767 
00768 //______________________________________________________________________________
00769 TF1::TF1(const char *name, ROOT::Math::ParamFunctor f, Double_t xmin, Double_t xmax, Int_t npar ) :
00770    TFormula(),
00771    TAttLine(),
00772    TAttFill(),
00773    TAttMarker(),
00774    fXmin      ( xmin ),
00775    fXmax      ( xmax ),
00776    fNpx       ( 100 ),
00777    fType      ( 1 ),
00778    fNpfits    ( 0 ),
00779    fNDF       ( 0 ),
00780    fNsave     ( 0 ),
00781    fChisquare ( 0 ),
00782    fIntegral  ( 0 ),
00783    fParErrors ( 0 ),
00784    fParMin    ( 0 ),
00785    fParMax    ( 0 ),
00786    fSave      ( 0 ),
00787    fAlpha     ( 0 ),
00788    fBeta      ( 0 ),
00789    fGamma     ( 0 ),
00790    fParent    ( 0 ),
00791    fHistogram ( 0 ),
00792    fMaximum   ( -1111 ),
00793    fMinimum   ( -1111 ),
00794    fMethodCall( 0 ),
00795    fCintFunc  ( 0 ),
00796    fFunctor   ( ROOT::Math::ParamFunctor(f) )
00797 {
00798    // F1 constructor using the Functor class.
00799    //
00800    //   xmin and xmax define the plotting range of the function
00801    //   npar is the number of free parameters used by the function
00802    //
00803    //   This constructor can be used only in compiled code
00804    //
00805    // WARNING! A function created with this constructor cannot be Cloned.
00806 
00807    CreateFromFunctor(name, npar);
00808 }
00809 
00810 
00811 //______________________________________________________________________________
00812 void TF1::CreateFromFunctor(const char *name, Int_t npar)
00813 {
00814    // Internal Function to Create a TF1  using a Functor.
00815    //
00816    //          Used by the template constructors
00817 
00818    fNdim       = 1;
00819 
00820    if (npar > 0 ) fNpar = npar;
00821    if (fNpar) {
00822       fNames      = new TString[fNpar];
00823       fParams     = new Double_t[fNpar];
00824       fParErrors  = new Double_t[fNpar];
00825       fParMin     = new Double_t[fNpar];
00826       fParMax     = new Double_t[fNpar];
00827       for (int i = 0; i < fNpar; i++) {
00828          fParams[i]     = 0;
00829          fParErrors[i]  = 0;
00830          fParMin[i]     = 0;
00831          fParMax[i]     = 0;
00832       }
00833    } else {
00834       fParErrors = 0;
00835       fParMin    = 0;
00836       fParMax    = 0;
00837    }
00838 
00839    // Store formula in linked list of formula in ROOT
00840    TF1 *f1old = (TF1*)gROOT->GetListOfFunctions()->FindObject(name);
00841    gROOT->GetListOfFunctions()->Remove(f1old);
00842    SetName(name);
00843    gROOT->GetListOfFunctions()->Add(this);
00844 
00845    if (!gStyle) return;
00846    SetLineColor(gStyle->GetFuncColor());
00847    SetLineWidth(gStyle->GetFuncWidth());
00848    SetLineStyle(gStyle->GetFuncStyle());
00849    SetFillStyle(0);
00850 
00851 }
00852 
00853 //______________________________________________________________________________
00854 TF1::TF1(const char *name,void *ptr, Double_t xmin, Double_t xmax, Int_t npar, const char * className )
00855       :TFormula(), TAttLine(), TAttFill(), TAttMarker()
00856 {
00857    // F1 constructor from an interpreted class defining the operator() or Eval().
00858    // This constructor emulate the syntax of the template constructor using a C++ callable object (functor)
00859    // which can be used only in C++ compiled mode.
00860    // The class name is required to get the type of class given the void pointer ptr.
00861    // For the method name is used the operator() (double *, double * ).
00862    // Use the other constructor taking the method name for different method names.
00863    //
00864    //  xmin and xmax specify the function plotting range
00865    //  npar are the number of function parameters
00866    //
00867    //  see tutorial  math.exampleFunctor.C for an example of using this constructor
00868    //
00869    //  This constructor is used only when using CINT.
00870    //  In compiled mode the template constructor is used and in that case className is not needed
00871 
00872    CreateFromCintClass(name, ptr, xmin, xmax, npar, className, 0 );
00873 }
00874 
00875 //______________________________________________________________________________
00876 TF1::TF1(const char *name,void *ptr, void * , Double_t xmin, Double_t xmax, Int_t npar, const char * className, const char * methodName)
00877       :TFormula(), TAttLine(), TAttFill(), TAttMarker()
00878 {
00879    // F1 constructor from an interpreter class using a specidied member function.
00880    // This constructor emulate the syntax of the template constructor using a C++ class and a given
00881    // member function pointer, which can be used only in C++ compiled mode.
00882    // The class name is required to get the type of class given the void pointer ptr.
00883    // The second void * is not needed for the CINT case, but is kept for emulating the API of the
00884    // template constructor.
00885    // The method name is optional. By default is looked for operator() (double *, double *) or
00886    // Eval(double *, double*)
00887    //
00888    //  xmin and xmax specify the function plotting range
00889    //  npar are the number of function parameters.
00890    //
00891    //
00892    //  see tutorial  math.exampleFunctor.C for an example of using this constructor
00893    //
00894    //  This constructor is used only when using CINT.
00895    //  In compiled mode the template constructor is used and in that case className is not needed
00896 
00897    CreateFromCintClass(name, ptr, xmin, xmax, npar, className, methodName);
00898 }
00899 
00900 //______________________________________________________________________________
00901 void TF1::CreateFromCintClass(const char *name,void *ptr, Double_t xmin, Double_t xmax, Int_t npar, const char * className, const char * methodName)
00902 {
00903    // Internal function used to create from TF1 from an interpreter CINT class
00904    // with the specified type (className) and member function name (methodName).
00905    //
00906 
00907 
00908    fXmin       = xmin;
00909    fXmax       = xmax;
00910    fNpx        = 100;
00911    fType       = 3;
00912    if (npar > 0 ) fNpar = npar;
00913    if (fNpar) {
00914       fNames      = new TString[fNpar];
00915       fParams     = new Double_t[fNpar];
00916       fParErrors  = new Double_t[fNpar];
00917       fParMin     = new Double_t[fNpar];
00918       fParMax     = new Double_t[fNpar];
00919       for (int i = 0; i < fNpar; i++) {
00920          fParams[i]     = 0;
00921          fParErrors[i]  = 0;
00922          fParMin[i]     = 0;
00923          fParMax[i]     = 0;
00924       }
00925    } else {
00926       fParErrors = 0;
00927       fParMin    = 0;
00928       fParMax    = 0;
00929    }
00930    fChisquare  = 0;
00931    fIntegral   = 0;
00932    fAlpha      = 0;
00933    fBeta       = 0;
00934    fGamma      = 0;
00935    fParent     = 0;
00936    fNpfits     = 0;
00937    fNDF        = 0;
00938    fNsave      = 0;
00939    fSave       = 0;
00940    fHistogram  = 0;
00941    fMinimum    = -1111;
00942    fMaximum    = -1111;
00943    fMethodCall = 0;
00944    fNdim       = 1;
00945 
00946    TF1 *f1old = (TF1*)gROOT->GetListOfFunctions()->FindObject(name);
00947    gROOT->GetListOfFunctions()->Remove(f1old);
00948    SetName(name);
00949 
00950    if (gStyle) {
00951       SetLineColor(gStyle->GetFuncColor());
00952       SetLineWidth(gStyle->GetFuncWidth());
00953       SetLineStyle(gStyle->GetFuncStyle());
00954    }
00955    SetFillStyle(0);
00956 
00957    if (!ptr) return;
00958    fCintFunc = ptr;
00959 
00960    if (!className) return;
00961 
00962    TClass *cl = TClass::GetClass(className);
00963 
00964    if (cl) {
00965       fMethodCall = new TMethodCall();
00966 
00967 
00968       if (methodName)
00969          fMethodCall->InitWithPrototype(cl,methodName,"Double_t*,Double_t*");
00970       else {
00971          fMethodCall->InitWithPrototype(cl,"operator()","Double_t*,Double_t*");
00972          if (! fMethodCall->IsValid() )
00973             // try with Eval if operator() is not found
00974             fMethodCall->InitWithPrototype(cl,"Eval","Double_t*,Double_t*");
00975       }
00976 
00977       fNumber = -1;
00978       gROOT->GetListOfFunctions()->Add(this);
00979       if (! fMethodCall->IsValid() ) {
00980          if (methodName)
00981             Error("TF1","No function found in class %s with the signature %s(Double_t*,Double_t*)",className,methodName);
00982          else
00983             Error("TF1","No function found in class %s with the signature operator() (Double_t*,Double_t*) or Eval(Double_t*,Double_t*)",className);
00984       }
00985    } else {
00986       Error("TF1","can not find any class with name %s at the address 0x%lx",className,(Long_t)ptr);
00987    }
00988 
00989 
00990 }
00991 
00992 
00993 
00994 //______________________________________________________________________________
00995 TF1& TF1::operator=(const TF1 &rhs)
00996 {
00997    // Operator =
00998 
00999    if (this != &rhs) {
01000       rhs.Copy(*this);
01001    }
01002    return *this;
01003 }
01004 
01005 
01006 //______________________________________________________________________________
01007 TF1::~TF1()
01008 {
01009    // TF1 default destructor.
01010 
01011    if (fParMin)    delete [] fParMin;
01012    if (fParMax)    delete [] fParMax;
01013    if (fParErrors) delete [] fParErrors;
01014    if (fIntegral)  delete [] fIntegral;
01015    if (fAlpha)     delete [] fAlpha;
01016    if (fBeta)      delete [] fBeta;
01017    if (fGamma)     delete [] fGamma;
01018    if (fSave)      delete [] fSave;
01019    delete fHistogram;
01020    delete fMethodCall;
01021 
01022    if (fParent) fParent->RecursiveRemove(this);
01023 }
01024 
01025 
01026 //______________________________________________________________________________
01027 TF1::TF1(const TF1 &f1) : TFormula(), TAttLine(f1), TAttFill(f1), TAttMarker(f1)
01028 {
01029    // Constuctor.
01030 
01031    fXmin      = 0;
01032    fXmax      = 0;
01033    fNpx       = 100;
01034    fType      = 0;
01035    fNpfits    = 0;
01036    fNDF       = 0;
01037    fNsave     = 0;
01038    fChisquare = 0;
01039    fIntegral  = 0;
01040    fParErrors = 0;
01041    fParMin    = 0;
01042    fParMax    = 0;
01043    fAlpha     = 0;
01044    fBeta      = 0;
01045    fGamma     = 0;
01046    fParent    = 0;
01047    fSave      = 0;
01048    fHistogram = 0;
01049    fMinimum   = -1111;
01050    fMaximum   = -1111;
01051    fMethodCall = 0;
01052    fCintFunc   = 0;
01053    SetFillStyle(0);
01054 
01055    ((TF1&)f1).Copy(*this);
01056 }
01057 
01058 
01059 //______________________________________________________________________________
01060 void TF1::AbsValue(Bool_t flag)
01061 {
01062    // Static function: set the fgAbsValue flag.
01063    // By default TF1::Integral uses the original function value to compute the integral
01064    // However, TF1::Moment, CentralMoment require to compute the integral
01065    // using the absolute value of the function.
01066 
01067    fgAbsValue = flag;
01068 }
01069 
01070 
01071 //______________________________________________________________________________
01072 void TF1::Browse(TBrowser *b)
01073 {
01074    // Browse.
01075 
01076    Draw(b ? b->GetDrawOption() : "");
01077    gPad->Update();
01078 }
01079 
01080 
01081 //______________________________________________________________________________
01082 void TF1::Copy(TObject &obj) const
01083 {
01084    // Copy this F1 to a new F1.
01085 
01086    if (((TF1&)obj).fParMin)    delete [] ((TF1&)obj).fParMin;
01087    if (((TF1&)obj).fParMax)    delete [] ((TF1&)obj).fParMax;
01088    if (((TF1&)obj).fParErrors) delete [] ((TF1&)obj).fParErrors;
01089    if (((TF1&)obj).fIntegral)  delete [] ((TF1&)obj).fIntegral;
01090    if (((TF1&)obj).fAlpha)     delete [] ((TF1&)obj).fAlpha;
01091    if (((TF1&)obj).fBeta)      delete [] ((TF1&)obj).fBeta;
01092    if (((TF1&)obj).fGamma)     delete [] ((TF1&)obj).fGamma;
01093    if (((TF1&)obj).fSave)      delete [] ((TF1&)obj).fSave;
01094    delete ((TF1&)obj).fHistogram;
01095    delete ((TF1&)obj).fMethodCall;
01096 
01097    TFormula::Copy(obj);
01098    TAttLine::Copy((TF1&)obj);
01099    TAttFill::Copy((TF1&)obj);
01100    TAttMarker::Copy((TF1&)obj);
01101    ((TF1&)obj).fXmin = fXmin;
01102    ((TF1&)obj).fXmax = fXmax;
01103    ((TF1&)obj).fNpx  = fNpx;
01104    ((TF1&)obj).fType = fType;
01105    ((TF1&)obj).fCintFunc  = fCintFunc;
01106    ((TF1&)obj).fFunctor   = fFunctor;
01107    ((TF1&)obj).fChisquare = fChisquare;
01108    ((TF1&)obj).fNpfits  = fNpfits;
01109    ((TF1&)obj).fNDF     = fNDF;
01110    ((TF1&)obj).fMinimum = fMinimum;
01111    ((TF1&)obj).fMaximum = fMaximum;
01112 
01113    ((TF1&)obj).fParErrors = 0;
01114    ((TF1&)obj).fParMin    = 0;
01115    ((TF1&)obj).fParMax    = 0;
01116    ((TF1&)obj).fIntegral  = 0;
01117    ((TF1&)obj).fAlpha     = 0;
01118    ((TF1&)obj).fBeta      = 0;
01119    ((TF1&)obj).fGamma     = 0;
01120    ((TF1&)obj).fParent    = fParent;
01121    ((TF1&)obj).fNsave     = fNsave;
01122    ((TF1&)obj).fSave      = 0;
01123    ((TF1&)obj).fHistogram = 0;
01124    ((TF1&)obj).fMethodCall = 0;
01125    if (fNsave) {
01126       ((TF1&)obj).fSave = new Double_t[fNsave];
01127       for (Int_t j=0;j<fNsave;j++) ((TF1&)obj).fSave[j] = fSave[j];
01128    }
01129    if (fNpar) {
01130       ((TF1&)obj).fParErrors = new Double_t[fNpar];
01131       ((TF1&)obj).fParMin    = new Double_t[fNpar];
01132       ((TF1&)obj).fParMax    = new Double_t[fNpar];
01133       Int_t i;
01134       for (i=0;i<fNpar;i++)   ((TF1&)obj).fParErrors[i] = fParErrors[i];
01135       for (i=0;i<fNpar;i++)   ((TF1&)obj).fParMin[i]    = fParMin[i];
01136       for (i=0;i<fNpar;i++)   ((TF1&)obj).fParMax[i]    = fParMax[i];
01137    }
01138    if (fMethodCall) {
01139       // use copy-constructor of TMethodCall 
01140       TMethodCall *m = new TMethodCall(*fMethodCall);
01141 //       m->InitWithPrototype(fMethodCall->GetMethodName(),fMethodCall->GetProto());
01142       ((TF1&)obj).fMethodCall  = m;
01143    }
01144 }
01145 
01146 
01147 //______________________________________________________________________________
01148 Double_t TF1::Derivative(Double_t x, Double_t *params, Double_t eps) const
01149 {
01150    // Returns the first derivative of the function at point x,
01151    // computed by Richardson's extrapolation method (use 2 derivative estimates
01152    // to compute a third, more accurate estimation)
01153    // first, derivatives with steps h and h/2 are computed by central difference formulas
01154    //Begin_Latex
01155    // D(h) = #frac{f(x+h) - f(x-h)}{2h}
01156    //End_Latex
01157    // the final estimate Begin_Latex D = #frac{4D(h/2) - D(h)}{3} End_Latex
01158    //  "Numerical Methods for Scientists and Engineers", H.M.Antia, 2nd edition"
01159    //
01160    // if the argument params is null, the current function parameters are used,
01161    // otherwise the parameters in params are used.
01162    //
01163    // the argument eps may be specified to control the step size (precision).
01164    // the step size is taken as eps*(xmax-xmin).
01165    // the default value (0.001) should be good enough for the vast majority
01166    // of functions. Give a smaller value if your function has many changes
01167    // of the second derivative in the function range.
01168    //
01169    // Getting the error via TF1::DerivativeError:
01170    //   (total error = roundoff error + interpolation error)
01171    // the estimate of the roundoff error is taken as follows:
01172    //Begin_Latex
01173    //    err = k#sqrt{f(x)^{2} + x^{2}deriv^{2}}#sqrt{#sum ai^{2}},
01174    //End_Latex
01175    // where k is the double precision, ai are coefficients used in
01176    // central difference formulas
01177    // interpolation error is decreased by making the step size h smaller.
01178    //
01179    // Author: Anna Kreshuk
01180    
01181    if (GetNdim() > 1) { 
01182       Warning("Derivative","Function dimension is larger than one");
01183    }
01184 
01185    ROOT::Math::RichardsonDerivator rd;
01186    double xmin, xmax;
01187    GetRange(xmin, xmax);
01188    // this is not optimal (should be used the average x instead of the range) 
01189    double h = eps* std::abs(xmax-xmin);
01190    if ( h <= 0 ) h = 0.001;  
01191    double der = 0; 
01192    if (params) { 
01193       ROOT::Math::WrappedTF1 wtf(*( const_cast<TF1 *> (this) )); 
01194       wtf.SetParameters(params);
01195       der = rd.Derivative1(wtf,x,h);   
01196    }                                            
01197    else { 
01198       // no need to set parameters used a non-parametric wrapper to avoid allocating 
01199       // an array with parameter values
01200       ROOT::Math::WrappedFunction<const TF1 & > wf( *this);
01201       der = rd.Derivative1(wf,x,h);   
01202    }
01203 
01204    gErrorTF1 = rd.Error();
01205    return der;
01206 
01207 }
01208 
01209 
01210 //______________________________________________________________________________
01211 Double_t TF1::Derivative2(Double_t x, Double_t *params, Double_t eps) const
01212 {
01213    // Returns the second derivative of the function at point x,
01214    // computed by Richardson's extrapolation method (use 2 derivative estimates
01215    // to compute a third, more accurate estimation)
01216    // first, derivatives with steps h and h/2 are computed by central difference formulas
01217    //Begin_Latex
01218    //    D(h) = #frac{f(x+h) - 2f(x) + f(x-h)}{h^{2}}
01219    //End_Latex
01220    // the final estimate Begin_Latex D = #frac{4D(h/2) - D(h)}{3} End_Latex
01221    //  "Numerical Methods for Scientists and Engineers", H.M.Antia, 2nd edition"
01222    //
01223    // if the argument params is null, the current function parameters are used,
01224    // otherwise the parameters in params are used.
01225    //
01226    // the argument eps may be specified to control the step size (precision).
01227    // the step size is taken as eps*(xmax-xmin).
01228    // the default value (0.001) should be good enough for the vast majority
01229    // of functions. Give a smaller value if your function has many changes
01230    // of the second derivative in the function range.
01231    //
01232    // Getting the error via TF1::DerivativeError:
01233    //   (total error = roundoff error + interpolation error)
01234    // the estimate of the roundoff error is taken as follows:
01235    //Begin_Latex
01236    //    err = k#sqrt{f(x)^{2} + x^{2}deriv^{2}}#sqrt{#sum ai^{2}},
01237    //End_Latex
01238    // where k is the double precision, ai are coefficients used in
01239    // central difference formulas
01240    // interpolation error is decreased by making the step size h smaller.
01241    //
01242    // Author: Anna Kreshuk
01243 
01244    if (GetNdim() > 1) { 
01245       Warning("Derivative2","Function dimension is larger than one");
01246    }
01247 
01248    ROOT::Math::RichardsonDerivator rd;
01249    double xmin, xmax;
01250    GetRange(xmin, xmax);
01251    // this is not optimal (should be used the average x instead of the range) 
01252    double h = eps* std::abs(xmax-xmin);
01253    if ( h <= 0 ) h = 0.001;  
01254    double der = 0; 
01255    if (params) { 
01256       ROOT::Math::WrappedTF1 wtf(*( const_cast<TF1 *> (this) )); 
01257       wtf.SetParameters(params);
01258       der = rd.Derivative2(wtf,x,h);   
01259    }                                            
01260    else { 
01261       // no need to set parameters used a non-parametric wrapper to avoid allocating 
01262       // an array with parameter values
01263       ROOT::Math::WrappedFunction<const TF1 & > wf( *this);
01264       der = rd.Derivative2(wf,x,h);   
01265    }
01266 
01267    gErrorTF1 = rd.Error();
01268 
01269    return der;
01270 }
01271 
01272 
01273 //______________________________________________________________________________
01274 Double_t TF1::Derivative3(Double_t x, Double_t *params, Double_t eps) const
01275 {
01276    // Returns the third derivative of the function at point x,
01277    // computed by Richardson's extrapolation method (use 2 derivative estimates
01278    // to compute a third, more accurate estimation)
01279    // first, derivatives with steps h and h/2 are computed by central difference formulas
01280    //Begin_Latex
01281    //    D(h) = #frac{f(x+2h) - 2f(x+h) + 2f(x-h) - f(x-2h)}{2h^{3}}
01282    //End_Latex
01283    // the final estimate Begin_Latex D = #frac{4D(h/2) - D(h)}{3} End_Latex
01284    //  "Numerical Methods for Scientists and Engineers", H.M.Antia, 2nd edition"
01285    //
01286    // if the argument params is null, the current function parameters are used,
01287    // otherwise the parameters in params are used.
01288    //
01289    // the argument eps may be specified to control the step size (precision).
01290    // the step size is taken as eps*(xmax-xmin).
01291    // the default value (0.001) should be good enough for the vast majority
01292    // of functions. Give a smaller value if your function has many changes
01293    // of the second derivative in the function range.
01294    //
01295    // Getting the error via TF1::DerivativeError:
01296    //   (total error = roundoff error + interpolation error)
01297    // the estimate of the roundoff error is taken as follows:
01298    //Begin_Latex
01299    //    err = k#sqrt{f(x)^{2} + x^{2}deriv^{2}}#sqrt{#sum ai^{2}},
01300    //End_Latex
01301    // where k is the double precision, ai are coefficients used in
01302    // central difference formulas
01303    // interpolation error is decreased by making the step size h smaller.
01304    //
01305    // Author: Anna Kreshuk
01306 
01307    if (GetNdim() > 1) { 
01308       Warning("Derivative3","Function dimension is larger than one");
01309    }
01310 
01311    ROOT::Math::RichardsonDerivator rd;
01312    double xmin, xmax;
01313    GetRange(xmin, xmax);
01314    // this is not optimal (should be used the average x instead of the range) 
01315    double h = eps* std::abs(xmax-xmin);
01316    if ( h <= 0 ) h = 0.001;  
01317    double der = 0; 
01318    if (params) { 
01319       ROOT::Math::WrappedTF1 wtf(*( const_cast<TF1 *> (this) )); 
01320       wtf.SetParameters(params);
01321       der = rd.Derivative3(wtf,x,h);   
01322    }                                            
01323    else { 
01324       // no need to set parameters used a non-parametric wrapper to avoid allocating 
01325       // an array with parameter values
01326       ROOT::Math::WrappedFunction<const TF1 & > wf( *this);
01327       der = rd.Derivative3(wf,x,h);   
01328    }
01329 
01330    gErrorTF1 = rd.Error();
01331    return der; 
01332 
01333 }
01334 
01335 
01336 //______________________________________________________________________________
01337 Double_t TF1::DerivativeError()
01338 {
01339    // Static function returning the error of the last call to the of Derivative's
01340    // functions
01341 
01342    return gErrorTF1;
01343 }
01344 
01345 
01346 //______________________________________________________________________________
01347 Int_t TF1::DistancetoPrimitive(Int_t px, Int_t py)
01348 {
01349    // Compute distance from point px,py to a function.
01350    //
01351    //  Compute the closest distance of approach from point px,py to this
01352    //  function. The distance is computed in pixels units.
01353    //
01354    //  Note that px is called with a negative value when the TF1 is in
01355    //  TGraph or TH1 list of functions. In this case there is no point
01356    //  looking at the histogram axis.
01357 
01358    if (!fHistogram) return 9999;
01359    Int_t distance = 9999;
01360    if (px >= 0) {
01361       distance = fHistogram->DistancetoPrimitive(px,py);
01362       if (distance <= 1) return distance;
01363    } else {
01364       px = -px;
01365    }
01366 
01367    Double_t xx[1];
01368    Double_t x    = gPad->AbsPixeltoX(px);
01369    xx[0]         = gPad->PadtoX(x);
01370    if (xx[0] < fXmin || xx[0] > fXmax) return distance;
01371    Double_t fval = Eval(xx[0]);
01372    Double_t y    = gPad->YtoPad(fval);
01373    Int_t pybin   = gPad->YtoAbsPixel(y);
01374    return TMath::Abs(py - pybin);
01375 }
01376 
01377 
01378 //______________________________________________________________________________
01379 void TF1::Draw(Option_t *option)
01380 {
01381    // Draw this function with its current attributes.
01382    //
01383    // Possible option values are:
01384    //   "SAME"  superimpose on top of existing picture
01385    //   "L"     connect all computed points with a straight line
01386    //   "C"     connect all computed points with a smooth curve
01387    //   "FC"    draw a fill area below a smooth curve
01388    //
01389    // Note that the default value is "L". Therefore to draw on top
01390    // of an existing picture, specify option "LSAME"
01391    //
01392    // NB. You must use DrawCopy if you want to draw several times the same
01393    //     function in the current canvas.
01394 
01395    TString opt = option;
01396    opt.ToLower();
01397    if (gPad && !opt.Contains("same")) gPad->Clear();
01398 
01399    AppendPad(option);
01400 }
01401 
01402 
01403 //______________________________________________________________________________
01404 TF1 *TF1::DrawCopy(Option_t *option) const
01405 {
01406    // Draw a copy of this function with its current attributes.
01407    //
01408    //  This function MUST be used instead of Draw when you want to draw
01409    //  the same function with different parameters settings in the same canvas.
01410    //
01411    // Possible option values are:
01412    //   "SAME"  superimpose on top of existing picture
01413    //   "L"     connect all computed points with a straight line
01414    //   "C"     connect all computed points with a smooth curve
01415    //   "FC"    draw a fill area below a smooth curve
01416    //
01417    // Note that the default value is "L". Therefore to draw on top
01418    // of an existing picture, specify option "LSAME"
01419 
01420    TF1 *newf1 = (TF1*)this->IsA()->New();
01421    Copy(*newf1);
01422    newf1->AppendPad(option);
01423    newf1->SetBit(kCanDelete);
01424    return newf1;
01425 }
01426 
01427 
01428 //______________________________________________________________________________
01429 TObject *TF1::DrawDerivative(Option_t *option)
01430 {
01431    // Draw derivative of this function
01432    //
01433    // An intermediate TGraph object is built and drawn with option.
01434    // The function returns a pointer to the TGraph object. Do:
01435    //    TGraph *g = (TGraph*)myfunc.DrawDerivative(option);
01436    //
01437    // The resulting graph will be drawn into the current pad.
01438    // If this function is used via the context menu, it recommended
01439    // to create a new canvas/pad before invoking this function.
01440 
01441    TVirtualPad *pad = gROOT->GetSelectedPad();
01442    TVirtualPad *padsav = gPad;
01443    if (pad) pad->cd();
01444 
01445    TGraph *gr = new TGraph(this,"d");
01446    gr->Draw(option);
01447    if (padsav) padsav->cd();
01448    return gr;
01449 }
01450 
01451 
01452 //______________________________________________________________________________
01453 TObject *TF1::DrawIntegral(Option_t *option)
01454 {
01455    // Draw integral of this function
01456    //
01457    // An intermediate TGraph object is built and drawn with option.
01458    // The function returns a pointer to the TGraph object. Do:
01459    //    TGraph *g = (TGraph*)myfunc.DrawIntegral(option);
01460    //
01461    // The resulting graph will be drawn into the current pad.
01462    // If this function is used via the context menu, it recommended
01463    // to create a new canvas/pad before invoking this function.
01464 
01465    TVirtualPad *pad = gROOT->GetSelectedPad();
01466    TVirtualPad *padsav = gPad;
01467    if (pad) pad->cd();
01468 
01469    TGraph *gr = new TGraph(this,"i");
01470    gr->Draw(option);
01471    if (padsav) padsav->cd();
01472    return gr;
01473 }
01474 
01475 
01476 //______________________________________________________________________________
01477 void TF1::DrawF1(const char *formula, Double_t xmin, Double_t xmax, Option_t *option)
01478 {
01479    // Draw formula between xmin and xmax.
01480 
01481    if (Compile(formula)) return;
01482 
01483    SetRange(xmin, xmax);
01484 
01485    Draw(option);
01486 }
01487 
01488 
01489 //______________________________________________________________________________
01490 Double_t TF1::Eval(Double_t x, Double_t y, Double_t z, Double_t t) const
01491 {
01492    // Evaluate this formula.
01493    //
01494    //   Computes the value of this function (general case for a 3-d function)
01495    //   at point x,y,z.
01496    //   For a 1-d function give y=0 and z=0
01497    //   The current value of variables x,y,z is passed through x, y and z.
01498    //   The parameters used will be the ones in the array params if params is given
01499    //    otherwise parameters will be taken from the stored data members fParams
01500 
01501    Double_t xx[4];
01502    xx[0] = x;
01503    xx[1] = y;
01504    xx[2] = z;
01505    xx[3] = t;
01506 
01507    ((TF1*)this)->InitArgs(xx,fParams);
01508 
01509    return ((TF1*)this)->EvalPar(xx,fParams);
01510 }
01511 
01512 
01513 //______________________________________________________________________________
01514 Double_t TF1::EvalPar(const Double_t *x, const Double_t *params)
01515 {
01516    // Evaluate function with given coordinates and parameters.
01517    //
01518    // Compute the value of this function at point defined by array x
01519    // and current values of parameters in array params.
01520    // If argument params is omitted or equal 0, the internal values
01521    // of parameters (array fParams) will be used instead.
01522    // For a 1-D function only x[0] must be given.
01523    // In case of a multi-dimemsional function, the arrays x must be
01524    // filled with the corresponding number of dimensions.
01525    //
01526    // WARNING. In case of an interpreted function (fType=2), it is the
01527    // user's responsability to initialize the parameters via InitArgs
01528    // before calling this function.
01529    // InitArgs should be called at least once to specify the addresses
01530    // of the arguments x and params.
01531    // InitArgs should be called everytime these addresses change.
01532 
01533    fgCurrent = this;
01534 
01535    if (fType == 0) return TFormula::EvalPar(x,params);
01536    Double_t result = 0;
01537    if (fType == 1)  {
01538 //       if (fFunction) {
01539 //          if (params) result = (*fFunction)((Double_t*)x,(Double_t*)params);
01540 //          else        result = (*fFunction)((Double_t*)x,fParams);
01541       if (!fFunctor.Empty()) {
01542          if (params) result = fFunctor((Double_t*)x,(Double_t*)params);
01543          else        result = fFunctor((Double_t*)x,fParams);
01544 
01545       }else          result = GetSave(x);
01546       return result;
01547    }
01548    if (fType == 2) {
01549       if (fMethodCall) fMethodCall->Execute(result);
01550       else             result = GetSave(x);
01551       return result;
01552    }
01553    if (fType == 3) {
01554       //std::cout << "Eval interp function object  " << fCintFunc << " result = " << result << std::endl;
01555       if (fMethodCall) fMethodCall->Execute(fCintFunc,result);
01556       else             result = GetSave(x);
01557       return result;
01558    }
01559    return result;
01560 }
01561 
01562 
01563 //______________________________________________________________________________
01564 void TF1::ExecuteEvent(Int_t event, Int_t px, Int_t py)
01565 {
01566    // Execute action corresponding to one event.
01567    //
01568    //  This member function is called when a F1 is clicked with the locator
01569 
01570    if (fHistogram) fHistogram->ExecuteEvent(event,px,py);
01571 
01572    if (!gPad->GetView()) {
01573       if (event == kMouseMotion)  gPad->SetCursor(kHand);
01574    }
01575 }
01576 
01577 
01578 //______________________________________________________________________________
01579 void TF1::FixParameter(Int_t ipar, Double_t value)
01580 {
01581    // Fix the value of a parameter
01582    // The specified value will be used in a fit operation
01583 
01584    if (ipar < 0 || ipar > fNpar-1) return;
01585    SetParameter(ipar,value);
01586    if (value != 0) SetParLimits(ipar,value,value);
01587    else            SetParLimits(ipar,1,1);
01588 }
01589 
01590 
01591 //______________________________________________________________________________
01592 TF1 *TF1::GetCurrent()
01593 {
01594    // Static function returning the current function being processed
01595 
01596    return fgCurrent;
01597 }
01598 
01599 
01600 //______________________________________________________________________________
01601 TH1 *TF1::GetHistogram() const
01602 {
01603    // Return a pointer to the histogram used to vusualize the function
01604 
01605    if (fHistogram) return fHistogram;
01606 
01607    // May be function has not yet be painted. force a pad update
01608    ((TF1*)this)->Paint();
01609    return fHistogram;
01610 }
01611 
01612 
01613 //______________________________________________________________________________
01614 Double_t TF1::GetMaximum(Double_t xmin, Double_t xmax, Double_t epsilon, Int_t maxiter,Bool_t logx) const
01615 {
01616    // Return the maximum value of the function
01617    // Method:
01618    //  First, the grid search is used to bracket the maximum
01619    //  with the step size = (xmax-xmin)/fNpx.
01620    //  This way, the step size can be controlled via the SetNpx() function.
01621    //  If the function is unimodal or if its extrema are far apart, setting
01622    //  the fNpx to a small value speeds the algorithm up many times.
01623    //  Then, Brent's method is applied on the bracketed interval
01624    //  epsilon (default = 1.E-10) controls the relative accuracy (if |x| > 1 ) 
01625    //  and absolute (if |x| < 1)  and maxiter (default = 100) controls the maximum number 
01626    //  of iteration of the Brent algorithm
01627    //  If the flag logx is set the grid search is done in log step size
01628    //  This is done automatically if the log scale is set in the current Pad
01629    //
01630    // NOTE: see also TF1::GetMaximumX and TF1::GetX
01631 
01632    if (xmin >= xmax) {xmin = fXmin; xmax = fXmax;}
01633 
01634    if (!logx && gPad != 0) logx = gPad->GetLogx(); 
01635 
01636    ROOT::Math::BrentMinimizer1D bm;
01637    GInverseFunc g(this);
01638    ROOT::Math::WrappedFunction<GInverseFunc> wf1(g);
01639    bm.SetFunction( wf1, xmin, xmax );
01640    bm.SetNpx(fNpx);
01641    bm.SetLogScan(logx);
01642    bm.Minimize(maxiter, epsilon, epsilon );
01643    Double_t x;
01644    x = - bm.FValMinimum();
01645 
01646    return x;
01647 }
01648 
01649 
01650 //______________________________________________________________________________
01651 Double_t TF1::GetMaximumX(Double_t xmin, Double_t xmax, Double_t epsilon, Int_t maxiter,Bool_t logx) const
01652 {
01653    // Return the X value corresponding to the maximum value of the function
01654    // Method:
01655    //  First, the grid search is used to bracket the maximum
01656    //  with the step size = (xmax-xmin)/fNpx.
01657    //  This way, the step size can be controlled via the SetNpx() function.
01658    //  If the function is unimodal or if its extrema are far apart, setting
01659    //  the fNpx to a small value speeds the algorithm up many times.
01660    //  Then, Brent's method is applied on the bracketed interval
01661    //  epsilon (default = 1.E-10) controls the relative accuracy (if |x| > 1 ) 
01662    //  and absolute (if |x| < 1)  and maxiter (default = 100) controls the maximum number 
01663    //  of iteration of the Brent algorithm
01664    //  If the flag logx is set the grid search is done in log step size
01665    //  This is done automatically if the log scale is set in the current Pad
01666     //
01667    // NOTE: see also TF1::GetX
01668    
01669    if (xmin >= xmax) {xmin = fXmin; xmax = fXmax;}
01670 
01671    if (!logx && gPad != 0) logx = gPad->GetLogx(); 
01672 
01673    ROOT::Math::BrentMinimizer1D bm;
01674    GInverseFunc g(this);
01675    ROOT::Math::WrappedFunction<GInverseFunc> wf1(g);
01676    bm.SetFunction( wf1, xmin, xmax );
01677    bm.SetNpx(fNpx);
01678    bm.SetLogScan(logx);
01679    bm.Minimize(maxiter, epsilon, epsilon );
01680    Double_t x;
01681    x = bm.XMinimum();
01682 
01683    return x;
01684 }
01685 
01686 
01687 //______________________________________________________________________________
01688 Double_t TF1::GetMinimum(Double_t xmin, Double_t xmax, Double_t epsilon, Int_t maxiter, Bool_t logx) const
01689 {
01690    // Returns the minimum value of the function on the (xmin, xmax) interval
01691    // Method:
01692    //  First, the grid search is used to bracket the maximum
01693    //  with the step size = (xmax-xmin)/fNpx. This way, the step size
01694    //  can be controlled via the SetNpx() function. If the function is
01695    //  unimodal or if its extrema are far apart, setting the fNpx to
01696    //  a small value speeds the algorithm up many times.
01697    //  Then, Brent's method is applied on the bracketed interval
01698    //  epsilon (default = 1.E-10) controls the relative accuracy (if |x| > 1 ) 
01699    //  and absolute (if |x| < 1)  and maxiter (default = 100) controls the maximum number 
01700    //  of iteration of the Brent algorithm
01701    //  If the flag logx is set the grid search is done in log step size
01702    //  This is done automatically if the log scale is set in the current Pad
01703    //
01704    // NOTE: see also TF1::GetMaximumX and TF1::GetX
01705 
01706    if (xmin >= xmax) {xmin = fXmin; xmax = fXmax;}
01707 
01708    if (!logx && gPad != 0) logx = gPad->GetLogx(); 
01709 
01710    ROOT::Math::BrentMinimizer1D bm;
01711    ROOT::Math::WrappedFunction<const TF1&> wf1(*this);
01712    bm.SetFunction( wf1, xmin, xmax );
01713    bm.SetNpx(fNpx);
01714    bm.SetLogScan(logx);
01715    bm.Minimize(maxiter, epsilon, epsilon );
01716    Double_t x;
01717    x = bm.FValMinimum();
01718 
01719    return x;
01720 }
01721 
01722 
01723 //______________________________________________________________________________
01724 Double_t TF1::GetMinimumX(Double_t xmin, Double_t xmax, Double_t epsilon, Int_t maxiter, Bool_t logx) const
01725 {
01726    // Returns the X value corresponding to the minimum value of the function
01727    // on the (xmin, xmax) interval
01728    // Method:
01729    //  First, the grid search is used to bracket the maximum
01730    //  with the step size = (xmax-xmin)/fNpx. This way, the step size
01731    //  can be controlled via the SetNpx() function. If the function is
01732    //  unimodal or if its extrema are far apart, setting the fNpx to
01733    //  a small value speeds the algorithm up many times.
01734    //  Then, Brent's method is applied on the bracketed interval
01735    //  epsilon (default = 1.E-10) controls the relative accuracy (if |x| > 1 ) 
01736    //  and absolute (if |x| < 1)  and maxiter (default = 100) controls the maximum number 
01737    //  of iteration of the Brent algorithm
01738    //  If the flag logx is set the grid search is done in log step size
01739    //  This is done automatically if the log scale is set in the current Pad
01740    //
01741    // NOTE: see also TF1::GetX
01742 
01743    if (xmin >= xmax) {xmin = fXmin; xmax = fXmax;}
01744 
01745    ROOT::Math::BrentMinimizer1D bm;
01746    ROOT::Math::WrappedFunction<const TF1&> wf1(*this);
01747    bm.SetFunction( wf1, xmin, xmax );
01748    bm.SetNpx(fNpx);
01749    bm.SetLogScan(logx);
01750    bm.Minimize(maxiter, epsilon, epsilon );
01751    Double_t x;
01752    x = bm.XMinimum();
01753 
01754    return x;
01755 }
01756 
01757 
01758 //______________________________________________________________________________
01759 Double_t TF1::GetX(Double_t fy, Double_t xmin, Double_t xmax, Double_t epsilon, Int_t maxiter, Bool_t logx) const
01760 {
01761    // Returns the X value corresponding to the function value fy for (xmin<x<xmax).
01762    // in other words it can find the roots of the function when fy=0 and successive calls
01763    // by changing the next call to [xmin+eps,xmax] where xmin is the previous root.
01764    // Method:
01765    //  First, the grid search is used to bracket the maximum
01766    //  with the step size = (xmax-xmin)/fNpx. This way, the step size
01767    //  can be controlled via the SetNpx() function. If the function is
01768    //  unimodal or if its extrema are far apart, setting the fNpx to
01769    //  a small value speeds the algorithm up many times.
01770    //  Then, Brent's method is applied on the bracketed interval
01771    //  epsilon (default = 1.E-10) controls the relative accuracy (if |x| > 1 ) 
01772    //  and absolute (if |x| < 1)  and maxiter (default = 100) controls the maximum number 
01773    //  of iteration of the Brent algorithm
01774    //  If the flag logx is set the grid search is done in log step size
01775    //  This is done automatically if the log scale is set in the current Pad
01776    //
01777    // NOTE: see also TF1::GetMaximumX, TF1::GetMinimumX
01778 
01779    if (xmin >= xmax) {xmin = fXmin; xmax = fXmax;}
01780 
01781    if (!logx && gPad != 0) logx = gPad->GetLogx(); 
01782 
01783    GFunc g(this, fy);
01784    ROOT::Math::WrappedFunction<GFunc> wf1(g);
01785    ROOT::Math::BrentRootFinder brf;
01786    brf.SetFunction(wf1,xmin,xmax);
01787    brf.SetNpx(fNpx);
01788    brf.SetLogScan(logx);
01789    brf.Solve(maxiter, epsilon, epsilon);
01790    return brf.Root();
01791 
01792 }
01793 
01794 //______________________________________________________________________________
01795 Int_t TF1::GetNDF() const
01796 {
01797    // Return the number of degrees of freedom in the fit
01798    // the fNDF parameter has been previously computed during a fit.
01799    // The number of degrees of freedom corresponds to the number of points
01800    // used in the fit minus the number of free parameters.
01801 
01802    if (fNDF == 0 && (fNpfits > fNpar) ) return fNpfits-fNpar;
01803    return fNDF;
01804 }
01805 
01806 
01807 //______________________________________________________________________________
01808 Int_t TF1::GetNumberFreeParameters() const
01809 {
01810    // Return the number of free parameters
01811 
01812    Int_t nfree = fNpar;
01813    Double_t al,bl;
01814    for (Int_t i=0;i<fNpar;i++) {
01815       ((TF1*)this)->GetParLimits(i,al,bl);
01816       if (al*bl != 0 && al >= bl) nfree--;
01817    }
01818    return nfree;
01819 }
01820 
01821 
01822 //______________________________________________________________________________
01823 char *TF1::GetObjectInfo(Int_t px, Int_t /* py */) const
01824 {
01825    // Redefines TObject::GetObjectInfo.
01826    // Displays the function info (x, function value)
01827    // corresponding to cursor position px,py
01828 
01829    static char info[64];
01830    Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
01831    snprintf(info,64,"(x=%g, f=%g)",x,((TF1*)this)->Eval(x));
01832    return info;
01833 }
01834 
01835 
01836 //______________________________________________________________________________
01837 Double_t TF1::GetParError(Int_t ipar) const
01838 {
01839    // Return value of parameter number ipar
01840 
01841    if (ipar < 0 || ipar > fNpar-1) return 0;
01842    return fParErrors[ipar];
01843 }
01844 
01845 
01846 //______________________________________________________________________________
01847 void TF1::GetParLimits(Int_t ipar, Double_t &parmin, Double_t &parmax) const
01848 {
01849    // Return limits for parameter ipar.
01850 
01851    parmin = 0;
01852    parmax = 0;
01853    if (ipar < 0 || ipar > fNpar-1) return;
01854    if (fParMin) parmin = fParMin[ipar];
01855    if (fParMax) parmax = fParMax[ipar];
01856 }
01857 
01858 
01859 //______________________________________________________________________________
01860 Double_t TF1::GetProb() const
01861 {
01862    // Return the fit probability
01863 
01864    if (fNDF <= 0) return 0;
01865    return TMath::Prob(fChisquare,fNDF);
01866 }
01867 
01868 
01869 //______________________________________________________________________________
01870 Int_t TF1::GetQuantiles(Int_t nprobSum, Double_t *q, const Double_t *probSum)
01871 {
01872    //  Compute Quantiles for density distribution of this function
01873    //     Quantile x_q of a probability distribution Function F is defined as
01874    //Begin_Latex
01875    //        F(x_{q}) = #int_{xmin}^{x_{q}} f dx = q with 0 <= q <= 1.
01876    //End_Latex
01877    //     For instance the median Begin_Latex x_{#frac{1}{2}} End_Latex of a distribution is defined as that value
01878    //     of the random variable for which the distribution function equals 0.5:
01879    //Begin_Latex
01880    //        F(x_{#frac{1}{2}}) = #prod(x < x_{#frac{1}{2}}) = #frac{1}{2}
01881    //End_Latex
01882    //  code from Eddy Offermann, Renaissance
01883    //
01884    // input parameters
01885    //   - this TF1 function
01886    //   - nprobSum maximum size of array q and size of array probSum
01887    //   - probSum array of positions where quantiles will be computed.
01888    //     It is assumed to contain at least nprobSum values.
01889    //  output
01890    //   - return value nq (<=nprobSum) with the number of quantiles computed
01891    //   - array q filled with nq quantiles
01892    //
01893    //  Getting quantiles from two histograms and storing results in a TGraph,
01894    //   a so-called QQ-plot
01895    //
01896    //     TGraph *gr = new TGraph(nprob);
01897    //     f1->GetQuantiles(nprob,gr->GetX());
01898    //     f2->GetQuantiles(nprob,gr->GetY());
01899    //     gr->Draw("alp");
01900 
01901    // LM: change to use fNpx 
01902    // should we change code to use a root finder ? 
01903    // It should be more precise and more efficient
01904    const Int_t npx     = TMath::Max(fNpx, 2*nprobSum);
01905    const Double_t xMin = GetXmin();
01906    const Double_t xMax = GetXmax();
01907    const Double_t dx   = (xMax-xMin)/npx;
01908 
01909    TArrayD integral(npx+1);
01910    TArrayD alpha(npx);
01911    TArrayD beta(npx);
01912    TArrayD gamma(npx);
01913 
01914    integral[0] = 0;
01915    Int_t intNegative = 0;
01916    Int_t i;
01917    for (i = 0; i < npx; i++) {
01918       const Double_t *params = 0;
01919       Double_t integ = Integral(Double_t(xMin+i*dx),Double_t(xMin+i*dx+dx),params);
01920       if (integ < 0) {intNegative++; integ = -integ;}
01921       integral[i+1] = integral[i] + integ;
01922    }
01923 
01924    if (intNegative > 0)
01925       Warning("GetQuantiles","function:%s has %d negative values: abs assumed",
01926       GetName(),intNegative);
01927    if (integral[npx] == 0) {
01928       Error("GetQuantiles","Integral of function is zero");
01929       return 0;
01930    }
01931 
01932    const Double_t total = integral[npx];
01933    for (i = 1; i <= npx; i++) integral[i] /= total;
01934    //the integral r for each bin is approximated by a parabola
01935    //  x = alpha + beta*r +gamma*r**2
01936    // compute the coefficients alpha, beta, gamma for each bin
01937    for (i = 0; i < npx; i++) {
01938       const Double_t x0 = xMin+dx*i;
01939       const Double_t r2 = integral[i+1]-integral[i];
01940       const Double_t r1 = Integral(x0,x0+0.5*dx)/total;
01941       gamma[i] = (2*r2-4*r1)/(dx*dx);
01942       beta[i]  = r2/dx-gamma[i]*dx;
01943       alpha[i] = x0;
01944       gamma[i] *= 2;
01945    }
01946 
01947    // Be careful because of finite precision in the integral; Use the fact that the integral
01948    // is monotone increasing
01949    for (i = 0; i < nprobSum; i++) {
01950       const Double_t r = probSum[i];
01951       Int_t bin  = TMath::Max(TMath::BinarySearch(npx+1,integral.GetArray(),r),(Long64_t)0);
01952       // LM use a tolerance 1.E-12 (integral precision)
01953       while (bin < npx-1 && TMath::AreEqualRel(integral[bin+1], r, 1E-12) ) {
01954          if (TMath::AreEqualRel(integral[bin+2], r, 1E-12) ) bin++;
01955          else break;
01956       }
01957 
01958       const Double_t rr = r-integral[bin];
01959       if (rr != 0.0) {
01960          Double_t xx = 0.0;
01961          const Double_t fac = -2.*gamma[bin]*rr/beta[bin]/beta[bin];
01962          if (fac != 0 && fac <= 1)
01963             xx = (-beta[bin]+TMath::Sqrt(beta[bin]*beta[bin]+2*gamma[bin]*rr))/gamma[bin];
01964          else if (beta[bin] != 0.)
01965             xx = rr/beta[bin];
01966          q[i] = alpha[bin]+xx;
01967       } else {
01968          q[i] = alpha[bin];
01969          if (integral[bin+1] == r) q[i] += dx;
01970       }
01971    }
01972 
01973    return nprobSum;
01974 }
01975 
01976 
01977 //______________________________________________________________________________
01978 Double_t TF1::GetRandom()
01979 {
01980    // Return a random number following this function shape
01981    //
01982    //   The distribution contained in the function fname (TF1) is integrated
01983    //   over the channel contents.
01984    //   It is normalized to 1.
01985    //   For each bin the integral is approximated by a parabola.
01986    //   The parabola coefficients are stored as non persistent data members
01987    //   Getting one random number implies:
01988    //     - Generating a random number between 0 and 1 (say r1)
01989    //     - Look in which bin in the normalized integral r1 corresponds to
01990    //     - Evaluate the parabolic curve in the selected bin to find
01991    //       the corresponding X value.
01992    //   if the ratio fXmax/fXmin > fNpx the integral is tabulated in log scale in x
01993    //   The parabolic approximation is very good as soon as the number
01994    //   of bins is greater than 50.
01995 
01996    //  Check if integral array must be build
01997    if (fIntegral == 0) {
01998       fIntegral = new Double_t[fNpx+1];
01999       fAlpha    = new Double_t[fNpx+1];
02000       fBeta     = new Double_t[fNpx];
02001       fGamma    = new Double_t[fNpx];
02002       fIntegral[0] = 0;
02003       fAlpha[fNpx] = 0;
02004       Double_t integ;
02005       Int_t intNegative = 0;
02006       Int_t i;
02007       Bool_t logbin = kFALSE;
02008       Double_t dx;
02009       Double_t xmin = fXmin;
02010       Double_t xmax = fXmax;
02011       if (xmin > 0 && xmax/xmin> fNpx) {
02012          logbin =  kTRUE;
02013          fAlpha[fNpx] = 1;
02014          xmin = TMath::Log10(fXmin);
02015          xmax = TMath::Log10(fXmax);
02016       }
02017       dx = (xmax-xmin)/fNpx;
02018          
02019       Double_t *xx = new Double_t[fNpx+1];
02020       for (i=0;i<fNpx;i++) {
02021             xx[i] = xmin +i*dx;
02022       }
02023       xx[fNpx] = xmax;
02024       for (i=0;i<fNpx;i++) {
02025          if (logbin) {
02026             integ = Integral(TMath::Power(10,xx[i]), TMath::Power(10,xx[i+1]));
02027          } else {
02028             integ = Integral(xx[i],xx[i+1]);
02029          }
02030          if (integ < 0) {intNegative++; integ = -integ;}
02031          fIntegral[i+1] = fIntegral[i] + integ;
02032       }
02033       if (intNegative > 0) {
02034          Warning("GetRandom","function:%s has %d negative values: abs assumed",GetName(),intNegative);
02035       }
02036       if (fIntegral[fNpx] == 0) {
02037          delete [] xx;
02038          Error("GetRandom","Integral of function is zero");
02039          return 0;
02040       }
02041       Double_t total = fIntegral[fNpx];
02042       for (i=1;i<=fNpx;i++) {  // normalize integral to 1
02043          fIntegral[i] /= total;
02044       }
02045       //the integral r for each bin is approximated by a parabola
02046       //  x = alpha + beta*r +gamma*r**2
02047       // compute the coefficients alpha, beta, gamma for each bin
02048       Double_t x0,r1,r2,r3;
02049       for (i=0;i<fNpx;i++) {
02050          x0 = xx[i];
02051          r2 = fIntegral[i+1] - fIntegral[i];
02052          if (logbin) r1 = Integral(TMath::Power(10,x0),TMath::Power(10,x0+0.5*dx))/total;
02053          else        r1 = Integral(x0,x0+0.5*dx)/total;
02054          r3 = 2*r2 - 4*r1;
02055          if (TMath::Abs(r3) > 1e-8) fGamma[i] = r3/(dx*dx);
02056          else           fGamma[i] = 0;
02057          fBeta[i]  = r2/dx - fGamma[i]*dx;
02058          fAlpha[i] = x0;
02059          fGamma[i] *= 2;
02060       }
02061       delete [] xx;
02062    }
02063 
02064    // return random number
02065    Double_t r  = gRandom->Rndm();
02066    Int_t bin  = TMath::BinarySearch(fNpx,fIntegral,r);
02067    Double_t rr = r - fIntegral[bin];
02068 
02069    Double_t yy;
02070    if(fGamma[bin] != 0)
02071       yy = (-fBeta[bin] + TMath::Sqrt(fBeta[bin]*fBeta[bin]+2*fGamma[bin]*rr))/fGamma[bin];
02072    else
02073       yy = rr/fBeta[bin];
02074    Double_t x = fAlpha[bin] + yy;
02075    if (fAlpha[fNpx] > 0) return TMath::Power(10,x);
02076    return x;
02077 }
02078 
02079 
02080 //______________________________________________________________________________
02081 Double_t TF1::GetRandom(Double_t xmin, Double_t xmax)
02082 {
02083    // Return a random number following this function shape in [xmin,xmax]
02084    //
02085    //   The distribution contained in the function fname (TF1) is integrated
02086    //   over the channel contents.
02087    //   It is normalized to 1.
02088    //   For each bin the integral is approximated by a parabola.
02089    //   The parabola coefficients are stored as non persistent data members
02090    //   Getting one random number implies:
02091    //     - Generating a random number between 0 and 1 (say r1)
02092    //     - Look in which bin in the normalized integral r1 corresponds to
02093    //     - Evaluate the parabolic curve in the selected bin to find
02094    //       the corresponding X value.
02095    //   The parabolic approximation is very good as soon as the number
02096    //   of bins is greater than 50.
02097    //
02098    //  IMPORTANT NOTE
02099    //  The integral of the function is computed at fNpx points. If the function
02100    //  has sharp peaks, you should increase the number of points (SetNpx)
02101    //  such that the peak is correctly tabulated at several points.
02102 
02103    //  Check if integral array must be build
02104    if (fIntegral == 0) {
02105       Double_t dx = (fXmax-fXmin)/fNpx;
02106       fIntegral = new Double_t[fNpx+1];
02107       fAlpha    = new Double_t[fNpx];
02108       fBeta     = new Double_t[fNpx];
02109       fGamma    = new Double_t[fNpx];
02110       fIntegral[0] = 0;
02111       Double_t integ;
02112       Int_t intNegative = 0;
02113       Int_t i;
02114       for (i=0;i<fNpx;i++) {
02115          integ = Integral(Double_t(fXmin+i*dx), Double_t(fXmin+i*dx+dx));
02116          if (integ < 0) {intNegative++; integ = -integ;}
02117          fIntegral[i+1] = fIntegral[i] + integ;
02118       }
02119       if (intNegative > 0) {
02120          Warning("GetRandom","function:%s has %d negative values: abs assumed",GetName(),intNegative);
02121       }
02122       if (fIntegral[fNpx] == 0) {
02123          Error("GetRandom","Integral of function is zero");
02124          return 0;
02125       }
02126       Double_t total = fIntegral[fNpx];
02127       for (i=1;i<=fNpx;i++) {  // normalize integral to 1
02128          fIntegral[i] /= total;
02129       }
02130       //the integral r for each bin is approximated by a parabola
02131       //  x = alpha + beta*r +gamma*r**2
02132       // compute the coefficients alpha, beta, gamma for each bin
02133       Double_t x0,r1,r2,r3;
02134       for (i=0;i<fNpx;i++) {
02135          x0 = fXmin+i*dx;
02136          r2 = fIntegral[i+1] - fIntegral[i];
02137          r1 = Integral(x0,x0+0.5*dx)/total;
02138          r3 = 2*r2 - 4*r1;
02139          if (TMath::Abs(r3) > 1e-8) fGamma[i] = r3/(dx*dx);
02140          else           fGamma[i] = 0;
02141          fBeta[i]  = r2/dx - fGamma[i]*dx;
02142          fAlpha[i] = x0;
02143          fGamma[i] *= 2;
02144       }
02145    }
02146 
02147    // return random number
02148    Double_t dx   = (fXmax-fXmin)/fNpx;
02149    Int_t nbinmin = (Int_t)((xmin-fXmin)/dx);
02150    Int_t nbinmax = (Int_t)((xmax-fXmin)/dx)+2;
02151    if(nbinmax>fNpx) nbinmax=fNpx;
02152 
02153    Double_t pmin=fIntegral[nbinmin];
02154    Double_t pmax=fIntegral[nbinmax];
02155 
02156    Double_t r,x,xx,rr;
02157    do {
02158       r  = gRandom->Uniform(pmin,pmax);
02159 
02160       Int_t bin  = TMath::BinarySearch(fNpx,fIntegral,r);
02161       rr = r - fIntegral[bin];
02162 
02163       if(fGamma[bin] != 0)
02164          xx = (-fBeta[bin] + TMath::Sqrt(fBeta[bin]*fBeta[bin]+2*fGamma[bin]*rr))/fGamma[bin];
02165       else
02166          xx = rr/fBeta[bin];
02167       x = fAlpha[bin] + xx;
02168    } while(x<xmin || x>xmax);
02169    return x;
02170 }
02171 
02172 
02173 //______________________________________________________________________________
02174 void TF1::GetRange(Double_t &xmin, Double_t &xmax) const
02175 {
02176    // Return range of a 1-D function.
02177 
02178    xmin = fXmin;
02179    xmax = fXmax;
02180 }
02181 
02182 
02183 //______________________________________________________________________________
02184 void TF1::GetRange(Double_t &xmin, Double_t &ymin,  Double_t &xmax, Double_t &ymax) const
02185 {
02186    // Return range of a 2-D function.
02187 
02188    xmin = fXmin;
02189    xmax = fXmax;
02190    ymin = 0;
02191    ymax = 0;
02192 }
02193 
02194 
02195 //______________________________________________________________________________
02196 void TF1::GetRange(Double_t &xmin, Double_t &ymin, Double_t &zmin, Double_t &xmax, Double_t &ymax, Double_t &zmax) const
02197 {
02198    // Return range of function.
02199 
02200    xmin = fXmin;
02201    xmax = fXmax;
02202    ymin = 0;
02203    ymax = 0;
02204    zmin = 0;
02205    zmax = 0;
02206 }
02207 
02208 
02209 //______________________________________________________________________________
02210 Double_t TF1::GetSave(const Double_t *xx)
02211 {
02212     // Get value corresponding to X in array of fSave values
02213 
02214    if (fNsave <= 0) return 0;
02215    if (fSave == 0) return 0;
02216    Double_t x    = Double_t(xx[0]);
02217    Double_t y,dx,xmin,xmax,xlow,xup,ylow,yup;
02218    if (fParent && fParent->InheritsFrom(TH1::Class())) {
02219       //if parent is a histogram the function had been savedat the center of the bins
02220       //we make a linear interpolation between the saved values
02221       xmin = fSave[fNsave-3];
02222       xmax = fSave[fNsave-2];
02223       if (fSave[fNsave-1] == xmax) {
02224          TH1 *h = (TH1*)fParent;
02225          TAxis *xaxis = h->GetXaxis();
02226          Int_t bin1  = xaxis->FindBin(xmin);
02227          Int_t binup = xaxis->FindBin(xmax);
02228          Int_t bin   = xaxis->FindBin(x);
02229          if (bin < binup) {
02230             xlow = xaxis->GetBinCenter(bin);
02231             xup  = xaxis->GetBinCenter(bin+1);
02232             ylow = fSave[bin-bin1];
02233             yup  = fSave[bin-bin1+1];
02234          } else {
02235             xlow = xaxis->GetBinCenter(bin-1);
02236             xup  = xaxis->GetBinCenter(bin);
02237             ylow = fSave[bin-bin1-1];
02238             yup  = fSave[bin-bin1];
02239          }
02240          dx = xup-xlow;
02241          y  = ((xup*ylow-xlow*yup) + x*(yup-ylow))/dx;
02242          return y;
02243       }
02244    }
02245    Int_t np = fNsave - 3;
02246    xmin = Double_t(fSave[np+1]);
02247    xmax = Double_t(fSave[np+2]);
02248    dx   = (xmax-xmin)/np;
02249    if (x < xmin || x > xmax) return 0;
02250    // return a Nan in case of x=nan, otherwise will crash later
02251    if (TMath::IsNaN(x) ) return x; 
02252    if (dx <= 0) return 0;
02253 
02254    Int_t bin     = Int_t((x-xmin)/dx);
02255    xlow = xmin + bin*dx;
02256    xup  = xlow + dx;
02257    ylow = fSave[bin];
02258    yup  = fSave[bin+1];
02259    y    = ((xup*ylow-xlow*yup) + x*(yup-ylow))/dx;
02260    return y;
02261 }
02262 
02263 
02264 //______________________________________________________________________________
02265 TAxis *TF1::GetXaxis() const
02266 {
02267    // Get x axis of the function.
02268 
02269    TH1 *h = GetHistogram();
02270    if (!h) return 0;
02271    return h->GetXaxis();
02272 }
02273 
02274 
02275 //______________________________________________________________________________
02276 TAxis *TF1::GetYaxis() const
02277 {
02278    // Get y axis of the function.
02279 
02280    TH1 *h = GetHistogram();
02281    if (!h) return 0;
02282    return h->GetYaxis();
02283 }
02284 
02285 
02286 //______________________________________________________________________________
02287 TAxis *TF1::GetZaxis() const
02288 {
02289    // Get z axis of the function. (In case this object is a TF2 or TF3)
02290 
02291    TH1 *h = GetHistogram();
02292    if (!h) return 0;
02293    return h->GetZaxis();
02294 }
02295 
02296 
02297 
02298 //______________________________________________________________________________
02299 Double_t TF1::GradientPar(Int_t ipar, const Double_t *x, Double_t eps)
02300 {
02301    // Compute the gradient (derivative) wrt a parameter ipar
02302    // Parameters:
02303    // ipar - index of parameter for which the derivative is computed
02304    // x - point, where the derivative is computed
02305    // eps - if the errors of parameters have been computed, the step used in
02306    // numerical differentiation is eps*parameter_error.
02307    // if the errors have not been computed, step=eps is used
02308    // default value of eps = 0.01
02309    // Method is the same as in Derivative() function
02310    //
02311    // If a paramter is fixed, the gradient on this parameter = 0
02312 
02313    if (fNpar == 0) return 0; 
02314 
02315    if(eps< 1e-10 || eps > 1) {
02316       Warning("Derivative","parameter esp=%g out of allowed range[1e-10,1], reset to 0.01",eps);
02317       eps = 0.01;
02318    }
02319    Double_t h;
02320    TF1 *func = (TF1*)this;
02321    //save original parameters
02322    Double_t par0 = fParams[ipar];
02323 
02324 
02325    func->InitArgs(x, fParams);
02326 
02327    Double_t al, bl;
02328    Double_t f1, f2, g1, g2, h2, d0, d2;
02329 
02330    ((TF1*)this)->GetParLimits(ipar,al,bl);
02331    if (al*bl != 0 && al >= bl) {
02332       //this parameter is fixed
02333       return 0;
02334    }
02335 
02336    // check if error has been computer (is not zero)
02337    if (func->GetParError(ipar)!=0)
02338       h = eps*func->GetParError(ipar);
02339    else
02340       h=eps;
02341 
02342 
02343 
02344    fParams[ipar] = par0 + h;     f1 = func->EvalPar(x,fParams);
02345    fParams[ipar] = par0 - h;     f2 = func->EvalPar(x,fParams);
02346    fParams[ipar] = par0 + h/2;   g1 = func->EvalPar(x,fParams);
02347    fParams[ipar] = par0 - h/2;   g2 = func->EvalPar(x,fParams);
02348 
02349    //compute the central differences
02350    h2    = 1/(2.*h);
02351    d0    = f1 - f2;
02352    d2    = 2*(g1 - g2);
02353 
02354    Double_t  grad = h2*(4*d2 - d0)/3.;
02355 
02356    // restore original value
02357    fParams[ipar] = par0;
02358 
02359    return grad;
02360 }
02361 
02362 //______________________________________________________________________________
02363 void TF1::GradientPar(const Double_t *x, Double_t *grad, Double_t eps)
02364 {
02365    // Compute the gradient wrt parameters
02366    // Parameters:
02367    // x - point, were the gradient is computed
02368    // grad - used to return the computed gradient, assumed to be of at least fNpar size
02369    // eps - if the errors of parameters have been computed, the step used in
02370    // numerical differentiation is eps*parameter_error.
02371    // if the errors have not been computed, step=eps is used
02372    // default value of eps = 0.01
02373    // Method is the same as in Derivative() function
02374    //
02375    // If a paramter is fixed, the gradient on this parameter = 0
02376 
02377    if(eps< 1e-10 || eps > 1) {
02378       Warning("Derivative","parameter esp=%g out of allowed range[1e-10,1], reset to 0.01",eps);
02379       eps = 0.01;
02380    }
02381 
02382    for (Int_t ipar=0; ipar<fNpar; ipar++){
02383       grad[ipar] = GradientPar(ipar,x,eps);
02384    }
02385 }
02386 
02387 //______________________________________________________________________________
02388 void TF1::InitArgs(const Double_t *x, const Double_t *params)
02389 {
02390    // Initialize parameters addresses.
02391 
02392    if (fMethodCall) {
02393       Long_t args[2];
02394       args[0] = (Long_t)x;
02395       if (params) args[1] = (Long_t)params;
02396       else        args[1] = (Long_t)fParams;
02397       fMethodCall->SetParamPtrs(args);
02398    }
02399 }
02400 
02401 
02402 //______________________________________________________________________________
02403 void TF1::InitStandardFunctions()
02404 {
02405    // Create the basic function objects
02406 
02407    TF1 *f1;
02408    if (!gROOT->GetListOfFunctions()->FindObject("gaus")) {
02409       f1 = new TF1("gaus","gaus",-1,1);       f1->SetParameters(1,0,1);
02410       f1 = new TF1("gausn","gausn",-1,1);     f1->SetParameters(1,0,1);
02411       f1 = new TF1("landau","landau",-1,1);   f1->SetParameters(1,0,1);
02412       f1 = new TF1("landaun","landaun",-1,1); f1->SetParameters(1,0,1);
02413       f1 = new TF1("expo","expo",-1,1);       f1->SetParameters(1,1);
02414       for (Int_t i=0;i<10;i++) {
02415          f1 = new TF1(Form("pol%d",i),Form("pol%d",i),-1,1);
02416          f1->SetParameters(1,1,1,1,1,1,1,1,1,1);
02417       }
02418    }
02419 }
02420 
02421 
02422 //______________________________________________________________________________
02423 Double_t TF1::Integral(Double_t a, Double_t b, const Double_t *params, Double_t epsilon)
02424 {
02425    // Return Integral of function between a and b.
02426    //
02427    //   based on original CERNLIB routine DGAUSS by Sigfried Kolbig
02428    //   converted to C++ by Rene Brun
02429    //
02430    // This function computes, to an attempted specified accuracy, the value
02431    // of the integral.
02432    //Begin_Latex
02433    //   I = #int^{B}_{A} f(x)dx
02434    //End_Latex
02435    // Usage:
02436    //   In any arithmetic expression, this function has the approximate value
02437    //   of the integral I.
02438    //   - A, B: End-points of integration interval. Note that B may be less
02439    //           than A.
02440    //   - params: Array of function parameters. If 0, use current parameters.
02441    //   - epsilon: Accuracy parameter (see Accuracy).
02442    //
02443    //Method:
02444    //   For any interval [a,b] we define g8(a,b) and g16(a,b) to be the 8-point
02445    //   and 16-point Gaussian quadrature approximations to
02446    //Begin_Latex
02447    //   I = #int^{b}_{a} f(x)dx
02448    //End_Latex
02449    //   and define
02450    //Begin_Latex
02451    //   r(a,b) = #frac{#||{g_{16}(a,b)-g_{8}(a,b)}}{1+#||{g_{16}(a,b)}}
02452    //End_Latex
02453    //   Then,
02454    //Begin_Latex
02455    //   G = #sum_{i=1}^{k}g_{16}(x_{i-1},x_{i})
02456    //End_Latex
02457    //   where, starting with x0 = A and finishing with xk = B,
02458    //   the subdivision points xi(i=1,2,...) are given by
02459    //Begin_Latex
02460    //   x_{i} = x_{i-1} + #lambda(B-x_{i-1})
02461    //End_Latex
02462    //   Begin_Latex #lambdaEnd_Latex is equal to the first member of the
02463    //   sequence 1,1/2,1/4,... for which r(xi-1, xi) < EPS.
02464    //   If, at any stage in the process of subdivision, the ratio
02465    //Begin_Latex
02466    //   q = #||{#frac{x_{i}-x_{i-1}}{B-A}}
02467    //End_Latex
02468    //   is so small that 1+0.005q is indistinguishable from 1 to
02469    //   machine accuracy, an error exit occurs with the function value
02470    //   set equal to zero.
02471    //
02472    // Accuracy:
02473    //   Unless there is severe cancellation of positive and negative values of
02474    //   f(x) over the interval [A,B], the argument EPS may be considered as
02475    //   specifying a bound on the <I>relative</I> error of I in the case
02476    //   |I|&gt;1, and a bound on the absolute error in the case |I|&lt;1. More
02477    //   precisely, if k is the number of sub-intervals contributing to the
02478    //   approximation (see Method), and if
02479    //Begin_Latex
02480    //   I_{abs} = #int^{B}_{A} #||{f(x)}dx
02481    //End_Latex
02482    //   then the relation
02483    //Begin_Latex
02484    //   #frac{#||{G-I}}{I_{abs}+k} < EPS
02485    //End_Latex
02486    //   will nearly always be true, provided the routine terminates without
02487    //   printing an error message. For functions f having no singularities in
02488    //   the closed interval [A,B] the accuracy will usually be much higher than
02489    //   this.
02490    //
02491    // Error handling:
02492    //   The requested accuracy cannot be obtained (see Method).
02493    //   The function value is set equal to zero.
02494    //
02495    // Note 1:
02496    //   Values of the function f(x) at the interval end-points A and B are not
02497    //   required. The subprogram may therefore be used when these values are
02498    //   undefined.
02499    //
02500    // Note 2:
02501    //   Instead of TF1::Integral, you may want to use the combination of
02502    //   TF1::CalcGaussLegendreSamplingPoints and TF1::IntegralFast.
02503    //   See an example with the following script:
02504    //
02505    //   void gint() {
02506    //      TF1 *g = new TF1("g","gaus",-5,5);
02507    //      g->SetParameters(1,0,1);
02508    //      //default gaus integration method uses 6 points
02509    //      //not suitable to integrate on a large domain
02510    //      double r1 = g->Integral(0,5);
02511    //      double r2 = g->Integral(0,1000);
02512    //
02513    //      //try with user directives computing more points
02514    //      Int_t np = 1000;
02515    //      double *x=new double[np];
02516    //      double *w=new double[np];
02517    //      g->CalcGaussLegendreSamplingPoints(np,x,w,1e-15);
02518    //      double r3 = g->IntegralFast(np,x,w,0,5);
02519    //      double r4 = g->IntegralFast(np,x,w,0,1000);
02520    //      double r5 = g->IntegralFast(np,x,w,0,10000);
02521    //      double r6 = g->IntegralFast(np,x,w,0,100000);
02522    //      printf("g->Integral(0,5)               = %g\n",r1);
02523    //      printf("g->Integral(0,1000)            = %g\n",r2);
02524    //      printf("g->IntegralFast(n,x,w,0,5)     = %g\n",r3);
02525    //      printf("g->IntegralFast(n,x,w,0,1000)  = %g\n",r4);
02526    //      printf("g->IntegralFast(n,x,w,0,10000) = %g\n",r5);
02527    //      printf("g->IntegralFast(n,x,w,0,100000)= %g\n",r6);
02528    //      delete [] x;
02529    //      delete [] w;
02530    //   }
02531    //
02532    //   This example produces the following results:
02533    //
02534    //      g->Integral(0,5)               = 1.25331
02535    //      g->Integral(0,1000)            = 1.25319
02536    //      g->IntegralFast(n,x,w,0,5)     = 1.25331
02537    //      g->IntegralFast(n,x,w,0,1000)  = 1.25331
02538    //      g->IntegralFast(n,x,w,0,10000) = 1.25331
02539    //      g->IntegralFast(n,x,w,0,100000)= 1.253
02540 
02541 
02542    TF1_EvalWrapper wf1( this, params, fgAbsValue ); 
02543 
02544    ROOT::Math::GaussIntegrator giod;
02545    //ROOT::Math::Integrator giod;
02546    giod.SetFunction(wf1);
02547    giod.SetRelTolerance(epsilon);
02548    //giod.SetAbsTolerance(epsilon);
02549 
02550    return giod.Integral(a, b);
02551 }
02552 
02553 
02554 //______________________________________________________________________________
02555 Double_t TF1::Integral(Double_t, Double_t, Double_t, Double_t, Double_t)
02556 {
02557    // Return Integral of a 2d function in range [ax,bx],[ay,by]
02558 
02559    Error("Integral","Must be called with a TF2 only");
02560    return 0;
02561 }
02562 
02563 
02564 //______________________________________________________________________________
02565 Double_t TF1::Integral(Double_t, Double_t, Double_t, Double_t, Double_t, Double_t, Double_t)
02566 {
02567    // Return Integral of a 3d function in range [ax,bx],[ay,by],[az,bz]
02568 
02569    Error("Integral","Must be called with a TF3 only");
02570    return 0;
02571 }
02572 
02573 //______________________________________________________________________________
02574 Double_t TF1::IntegralError(Double_t a, Double_t b, const Double_t * params, const Double_t * covmat, Double_t epsilon )
02575 {
02576    // Return Error on Integral of a parameteric function between a and b 
02577    // due to the parameter uncertainties.
02578    // A pointer to a vector of parameter values and to the elements of the covariance matrix (covmat)
02579    // can be optionally passed.  By default (i.e. when a zero pointer is passed) the current stored 
02580    // parameter values are used to estimate the integral error together with the covariance matrix
02581    // from the last fit (retrieved from the global fitter instance) 
02582    //
02583    // IMPORTANT NOTE1: When no covariance matrix is passed and in the meantime a fit is done 
02584    // using another function, the routine will signal an error and it will return zero only 
02585    // when the number of fit parameter is different than the values stored in TF1 (TF1::GetNpar() ). 
02586    // In the case that npar is the same, an incorrect result is returned. 
02587    //
02588    // IMPORTANT NOTE2: The user must pass a pointer to the elements of the full covariance matrix 
02589    // dimensioned with the right size (npar*npar), where npar is the total number of parameters (TF1::GetNpar()), 
02590    // including also the fixed parameters. When there are fixed parameters, the pointer returned from 
02591    // TVirtualFitter::GetCovarianceMatrix() cannot be used. 
02592    // One should use the TFitResult class, as shown in the example below.   
02593    // 
02594    // To get the matrix and values from an old fit do for example:  
02595    // TFitResultPtr r = histo->Fit(func, "S");
02596    // ..... after performing other fits on the same function do 
02597    // func->IntegralError(x1,x2,r->GetParams(), r->GetCovarianceMatrix()->GetMatrixArray() );
02598 
02599    Double_t x1[1]; 
02600    Double_t x2[1]; 
02601    x1[0] = a, x2[0] = b;
02602    return ROOT::TF1Helper::IntegralError(this,1,x1,x2,params,covmat,epsilon);
02603 }
02604 
02605 //______________________________________________________________________________
02606 Double_t TF1::IntegralError(Int_t n, const Double_t * a, const Double_t * b, const Double_t * params, const  Double_t * covmat, Double_t epsilon )
02607 {
02608    // Return Error on Integral of a parameteric function with dimension larger tan one 
02609    // between a[] and b[]  due to the parameters uncertainties.
02610    // For a TF1 with dimension larger than 1 (for example a TF2 or TF3) 
02611    // TF1::IntegralMultiple is used for the integral calculation
02612    //
02613    // A pointer to a vector of parameter values and to the elements of the covariance matrix (covmat) can be optionally passed.
02614    // By default (i.e. when a zero pointer is passed) the current stored parameter values are used to estimate the integral error 
02615    // together with the covariance matrix from the last fit (retrieved from the global fitter instance).
02616    //
02617    // IMPORTANT NOTE1: When no covariance matrix is passed and in the meantime a fit is done 
02618    // using another function, the routine will signal an error and it will return zero only 
02619    // when the number of fit parameter is different than the values stored in TF1 (TF1::GetNpar() ). 
02620    // In the case that npar is the same, an incorrect result is returned. 
02621    //
02622    // IMPORTANT NOTE2: The user must pass a pointer to the elements of the full covariance matrix 
02623    // dimensioned with the right size (npar*npar), where npar is the total number of parameters (TF1::GetNpar()), 
02624    // including also the fixed parameters. When there are fixed parameters, the pointer returned from 
02625    // TVirtualFitter::GetCovarianceMatrix() cannot be used. 
02626    // One should use the TFitResult class, as shown in the example below.   
02627    // 
02628    // To get the matrix and values from an old fit do for example:  
02629    // TFitResultPtr r = histo->Fit(func, "S");
02630    // ..... after performing other fits on the same function do 
02631    // func->IntegralError(x1,x2,r->GetParams(), r->GetCovarianceMatrix()->GetMatrixArray() );
02632 
02633    return ROOT::TF1Helper::IntegralError(this,n,a,b,params,covmat,epsilon);
02634 }
02635 
02636 #ifdef INTHEFUTURE
02637 //______________________________________________________________________________
02638 Double_t TF1::IntegralFast(const TGraph *g, Double_t a, Double_t b, Double_t *params)
02639 {
02640    // Gauss-Legendre integral, see CalcGaussLegendreSamplingPoints
02641 
02642    if (!g) return 0;
02643    return IntegralFast(g->GetN(), g->GetX(), g->GetY(), a, b, params);
02644 }
02645 #endif
02646 
02647 
02648 //______________________________________________________________________________
02649 Double_t TF1::IntegralFast(Int_t num, Double_t * /* x */, Double_t * /* w */, Double_t a, Double_t b, Double_t *params, Double_t epsilon)
02650 {
02651    // Gauss-Legendre integral, see CalcGaussLegendreSamplingPoints
02652 
02653    // Now x and w are not used!
02654 
02655    ROOT::Math::WrappedTF1 wf1(*this);
02656    if ( params )
02657       wf1.SetParameters( params );
02658    ROOT::Math::GaussLegendreIntegrator gli(num,epsilon);
02659    gli.SetFunction( wf1 );
02660    return gli.Integral(a, b);
02661 
02662 }
02663 
02664 
02665 //______________________________________________________________________________
02666 Double_t TF1::IntegralMultiple(Int_t n, const Double_t *a, const Double_t *b, Double_t eps, Double_t &relerr)
02667 {
02668    //  See more general prototype below.
02669    //  This interface kept for back compatibility
02670 
02671    Int_t nfnevl,ifail;
02672    Int_t minpts = 2+2*n*(n+1)+1; //ie 7 for n=1
02673    Int_t maxpts = 1000;
02674    Double_t result = IntegralMultiple(n,a,b,minpts, maxpts,eps,relerr,nfnevl,ifail);
02675    if (ifail > 0) {
02676       Warning("IntegralMultiple","failed code=%d, ",ifail);
02677    }
02678    return result;
02679 }
02680 
02681 
02682 //______________________________________________________________________________
02683 Double_t TF1::IntegralMultiple(Int_t n, const Double_t *a, const Double_t *b, Int_t minpts, Int_t maxpts, Double_t eps, Double_t &relerr,Int_t &nfnevl, Int_t &ifail)
02684 {
02685    //  Adaptive Quadrature for Multiple Integrals over N-Dimensional
02686    //  Rectangular Regions
02687    //
02688    //Begin_Latex
02689    // I_{n} = #int_{a_{n}}^{b_{n}} #int_{a_{n-1}}^{b_{n-1}} ... #int_{a_{1}}^{b_{1}} f(x_{1}, x_{2},...,x_{n}) dx_{1}dx_{2}...dx_{n}
02690    //End_Latex
02691    //
02692    // Author(s): A.C. Genz, A.A. Malik
02693    // converted/adapted by R.Brun to C++ from Fortran CERNLIB routine RADMUL (D120)
02694    // The new code features many changes compared to the Fortran version.
02695    // Note that this function is currently called only by TF2::Integral (n=2)
02696    // and TF3::Integral (n=3).
02697    //
02698    // This function computes, to an attempted specified accuracy, the value of
02699    // the integral over an n-dimensional rectangular region.
02700    //
02701    // Input parameters:
02702    //
02703    //    n     : Number of dimensions [2,15]
02704    //    a,b   : One-dimensional arrays of length >= N . On entry A[i],  and  B[i],
02705    //            contain the lower and upper limits of integration, respectively.
02706    //    minpts: Minimum number of function evaluations requested. Must not exceed maxpts.
02707    //            if minpts < 1 minpts is set to 2^n +2*n*(n+1) +1
02708    //    maxpts: Maximum number of function evaluations to be allowed.
02709    //            maxpts >= 2^n +2*n*(n+1) +1
02710    //            if maxpts<minpts, maxpts is set to 10*minpts
02711    //    eps   : Specified relative accuracy.
02712    //
02713    // Output parameters:
02714    //
02715    //    relerr : Contains, on exit, an estimation of the relative accuracy of the result.
02716    //    nfnevl : number of function evaluations performed.
02717    //    ifail  :
02718    //        0 Normal exit.  . At least minpts and at most maxpts calls to the function were performed.
02719    //        1 maxpts is too small for the specified accuracy eps.
02720    //          The result and relerr contain the values obtainable for the
02721    //          specified value of maxpts.
02722    //        3 n<2 or n>15
02723    //
02724    // Method:
02725    //
02726    //    An integration rule of degree seven is used together with a certain
02727    //    strategy of subdivision.
02728    //    For a more detailed description of the method see References.
02729    //
02730    // Notes:
02731    //
02732    //   1.Multi-dimensional integration is time-consuming. For each rectangular
02733    //     subregion, the routine requires function evaluations.
02734    //     Careful programming of the integrand might result in substantial saving
02735    //     of time.
02736    //   2.Numerical integration usually works best for smooth functions.
02737    //     Some analysis or suitable transformations of the integral prior to
02738    //     numerical work may contribute to numerical efficiency.
02739    //
02740    // References:
02741    //
02742    //   1.A.C. Genz and A.A. Malik, Remarks on algorithm 006:
02743    //     An adaptive algorithm for numerical integration over
02744    //     an N-dimensional rectangular region, J. Comput. Appl. Math. 6 (1980) 295-302.
02745    //   2.A. van Doren and L. de Ridder, An adaptive algorithm for numerical
02746    //     integration over an n-dimensional cube, J.Comput. Appl. Math. 2 (1976) 207-217.
02747 
02748    ROOT::Math::WrappedMultiFunction<TF1&> wf1(*this, n);
02749 
02750    ROOT::Math::AdaptiveIntegratorMultiDim aimd(wf1, eps, eps, maxpts);
02751    aimd.SetMinPts(minpts);
02752    double result = aimd.Integral(a,b);
02753    relerr = aimd.RelError();
02754    nfnevl = aimd.NEval();
02755    ifail = 0;
02756 
02757    return result;
02758 }
02759 
02760 
02761 //______________________________________________________________________________
02762 Bool_t TF1::IsInside(const Double_t *x) const
02763 {
02764    // Return kTRUE if the point is inside the function range
02765 
02766    if (x[0] < fXmin || x[0] > fXmax) return kFALSE;
02767    return kTRUE;
02768 }
02769 
02770 
02771 //______________________________________________________________________________
02772 void TF1::Paint(Option_t *option)
02773 {
02774    // Paint this function with its current attributes.
02775 
02776    Int_t i;
02777    Double_t xv[1];
02778 
02779    fgCurrent = this;
02780 
02781    TString opt = option;
02782    opt.ToLower();
02783    Bool_t optSAME = kFALSE;
02784    if (opt.Contains("same")) optSAME = kTRUE;
02785 
02786    Double_t xmin=fXmin, xmax=fXmax, pmin=fXmin, pmax=fXmax;
02787    if (gPad) {
02788       pmin = gPad->PadtoX(gPad->GetUxmin());
02789       pmax = gPad->PadtoX(gPad->GetUxmax());
02790    }
02791    if (optSAME) {
02792       if (xmax < pmin) return;  // Completely outside.
02793       if (xmin > pmax) return;
02794       if (xmin < pmin) xmin = pmin;
02795       if (xmax > pmax) xmax = pmax;
02796    }
02797 
02798    //  Create a temporary histogram and fill each channel with the function value
02799    //  Preserve axis titles
02800    TString xtitle = "";
02801    TString ytitle = "";
02802    char *semicol = (char*)strstr(GetTitle(),";");
02803    if (semicol) {
02804       Int_t nxt = strlen(semicol);
02805       char *ctemp = new char[nxt];
02806       strlcpy(ctemp,semicol+1,nxt);
02807       semicol = (char*)strstr(ctemp,";");
02808       if (semicol) {
02809          *semicol = 0;
02810          ytitle = semicol+1;
02811       }
02812       xtitle = ctemp;
02813       delete [] ctemp;
02814    }
02815    if (fHistogram) {
02816       xtitle = fHistogram->GetXaxis()->GetTitle();
02817       ytitle = fHistogram->GetYaxis()->GetTitle();
02818       if (!gPad->GetLogx()  &&  fHistogram->TestBit(TH1::kLogX)) { delete fHistogram; fHistogram = 0;}
02819       if ( gPad->GetLogx()  && !fHistogram->TestBit(TH1::kLogX)) { delete fHistogram; fHistogram = 0;}
02820    }
02821 
02822    if (fHistogram) {
02823       fHistogram->GetXaxis()->SetLimits(xmin,xmax);
02824    } else {
02825       // If logx, we must bin in logx and not in x
02826       // otherwise in case of several decades, one gets wrong results.
02827       if (xmin > 0 && gPad && gPad->GetLogx()) {
02828          Double_t *xbins    = new Double_t[fNpx+1];
02829          Double_t xlogmin = TMath::Log10(xmin);
02830          Double_t xlogmax = TMath::Log10(xmax);
02831          Double_t dlogx   = (xlogmax-xlogmin)/((Double_t)fNpx);
02832          for (i=0;i<=fNpx;i++) {
02833             xbins[i] = gPad->PadtoX(xlogmin+ i*dlogx);
02834          }
02835          fHistogram = new TH1D("Func",GetTitle(),fNpx,xbins);
02836          fHistogram->SetBit(TH1::kLogX);
02837          delete [] xbins;
02838       } else {
02839          fHistogram = new TH1D("Func",GetTitle(),fNpx,xmin,xmax);
02840       }
02841       if (!fHistogram) return;
02842       if (fMinimum != -1111) fHistogram->SetMinimum(fMinimum);
02843       if (fMaximum != -1111) fHistogram->SetMaximum(fMaximum);
02844       fHistogram->SetDirectory(0);
02845    }
02846    // Restore axis titles.
02847    fHistogram->GetXaxis()->SetTitle(xtitle.Data());
02848    fHistogram->GetYaxis()->SetTitle(ytitle.Data());
02849 
02850    InitArgs(xv,fParams);
02851    for (i=1;i<=fNpx;i++) {
02852       xv[0] = fHistogram->GetBinCenter(i);
02853       fHistogram->SetBinContent(i,EvalPar(xv,fParams));
02854    }
02855 
02856    // Copy Function attributes to histogram attributes.
02857    Double_t minimum   = fHistogram->GetMinimumStored();
02858    Double_t maximum   = fHistogram->GetMaximumStored();
02859    if (minimum <= 0 && gPad && gPad->GetLogy()) minimum = -1111; // This can happen when switching from lin to log scale.
02860    if (gPad && gPad->GetUymin() < fHistogram->GetMinimum() &&
02861        !fHistogram->TestBit(TH1::kIsZoomed)) minimum = -1111; // This can happen after unzooming a fit.
02862    if (minimum == -1111) { // This can happen after unzooming.
02863       if (fHistogram->TestBit(TH1::kIsZoomed)) {
02864          minimum = fHistogram->GetYaxis()->GetXmin();
02865       } else {
02866          minimum = fMinimum;
02867          // Optimize the computation of the scale in Y in case the min/max of the 
02868          // function oscillate around a constant value
02869          if (minimum == -1111) {
02870             Double_t hmin;
02871             if (optSAME) hmin = gPad->GetUymin();
02872             else         hmin = fHistogram->GetMinimum();
02873             if (hmin > 0) {
02874                Double_t hmax;
02875                Double_t hminpos = hmin;
02876                if (optSAME) hmax = gPad->GetUymax();
02877                else         hmax = fHistogram->GetMaximum();
02878                hmin -= 0.05*(hmax-hmin);
02879                if (hmin < 0) hmin = 0;
02880                if (hmin <= 0 && gPad && gPad->GetLogy()) hmin = hminpos;
02881                minimum = hmin;
02882             }
02883          }
02884       }
02885       fHistogram->SetMinimum(minimum);
02886    }
02887    if (maximum == -1111) {
02888       if (fHistogram->TestBit(TH1::kIsZoomed)) {
02889          maximum = fHistogram->GetYaxis()->GetXmax();
02890       } else {
02891          maximum = fMaximum;
02892       }
02893       fHistogram->SetMaximum(maximum);
02894    }
02895    fHistogram->SetBit(TH1::kNoStats);
02896    fHistogram->SetLineColor(GetLineColor());
02897    fHistogram->SetLineStyle(GetLineStyle());
02898    fHistogram->SetLineWidth(GetLineWidth());
02899    fHistogram->SetFillColor(GetFillColor());
02900    fHistogram->SetFillStyle(GetFillStyle());
02901    fHistogram->SetMarkerColor(GetMarkerColor());
02902    fHistogram->SetMarkerStyle(GetMarkerStyle());
02903    fHistogram->SetMarkerSize(GetMarkerSize());
02904 
02905    // Draw the histogram.
02906    if (!gPad) return;
02907    if (opt.Length() == 0) fHistogram->Paint("lf");
02908    else if (optSAME)      fHistogram->Paint("lfsame");
02909    else                   fHistogram->Paint(option);
02910 }
02911 
02912 
02913 //______________________________________________________________________________
02914 void TF1::Print(Option_t *option) const
02915 {
02916    // Dump this function with its attributes.
02917 
02918    TFormula::Print(option);
02919    if (fHistogram) fHistogram->Print(option);
02920 }
02921 
02922 
02923 //______________________________________________________________________________
02924 void TF1::ReleaseParameter(Int_t ipar)
02925 {
02926    // Release parameter number ipar If used in a fit, the parameter
02927    // can vary freely. The parameter limits are reset to 0,0.
02928 
02929    if (ipar < 0 || ipar > fNpar-1) return;
02930    SetParLimits(ipar,0,0);
02931 }
02932 
02933 
02934 //______________________________________________________________________________
02935 void TF1::Save(Double_t xmin, Double_t xmax, Double_t, Double_t, Double_t, Double_t)
02936 {
02937    // Save values of function in array fSave
02938 
02939    if (fSave != 0) {delete [] fSave; fSave = 0;}
02940    if (fParent && fParent->InheritsFrom(TH1::Class())) {
02941       //if parent is a histogram save the function at the center of the bins
02942       if ((xmin >0 && xmax > 0) && TMath::Abs(TMath::Log10(xmax/xmin) > TMath::Log10(fNpx))) {
02943          TH1 *h = (TH1*)fParent;
02944          Int_t bin1 = h->GetXaxis()->FindBin(xmin);
02945          Int_t bin2 = h->GetXaxis()->FindBin(xmax);
02946          fNsave = bin2-bin1+4;
02947          fSave  = new Double_t[fNsave];
02948          Double_t xv[1];
02949          InitArgs(xv,fParams);
02950          for (Int_t i=bin1;i<=bin2;i++) {
02951             xv[0]    = h->GetXaxis()->GetBinCenter(i);
02952             fSave[i-bin1] = EvalPar(xv,fParams);
02953          }
02954          fSave[fNsave-3] = xmin;
02955          fSave[fNsave-2] = xmax;
02956          fSave[fNsave-1] = xmax;
02957          return;
02958       }
02959    }
02960    fNsave = fNpx+3;
02961    if (fNsave <= 3) {fNsave=0; return;}
02962    fSave  = new Double_t[fNsave];
02963    Double_t dx = (xmax-xmin)/fNpx;
02964    if (dx <= 0) {
02965       dx = (fXmax-fXmin)/fNpx;
02966       fNsave--;
02967       xmin = fXmin +0.5*dx;
02968       xmax = fXmax -0.5*dx;
02969    }
02970    Double_t xv[1];
02971    InitArgs(xv,fParams);
02972    for (Int_t i=0;i<=fNpx;i++) {
02973       xv[0]    = xmin + dx*i;
02974       fSave[i] = EvalPar(xv,fParams);
02975    }
02976    fSave[fNpx+1] = xmin;
02977    fSave[fNpx+2] = xmax;
02978 }
02979 
02980 
02981 //______________________________________________________________________________
02982 void TF1::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
02983 {
02984    // Save primitive as a C++ statement(s) on output stream out
02985 
02986    Int_t i;
02987    char quote = '"';
02988    out<<"   "<<endl;
02989    //if (!fMethodCall) {
02990    if (!fType) {
02991       out<<"   TF1 *"<<GetName()<<" = new TF1("<<quote<<GetName()<<quote<<","<<quote<<GetTitle()<<quote<<","<<fXmin<<","<<fXmax<<");"<<endl;
02992       if (fNpx != 100) {
02993          out<<"   "<<GetName()<<"->SetNpx("<<fNpx<<");"<<endl;
02994       }
02995    } else {
02996       out<<"   TF1 *"<<GetName()<<" = new TF1("<<quote<<"*"<<GetName()<<quote<<","<<fXmin<<","<<fXmax<<","<<GetNpar()<<");"<<endl;
02997       out<<"    //The original function : "<<GetTitle()<<" had originally been created by:" <<endl;
02998       out<<"    //TF1 *"<<GetName()<<" = new TF1("<<quote<<GetName()<<quote<<","<<GetTitle()<<","<<fXmin<<","<<fXmax<<","<<GetNpar()<<");"<<endl;
02999       out<<"   "<<GetName()<<"->SetRange("<<fXmin<<","<<fXmax<<");"<<endl;
03000       out<<"   "<<GetName()<<"->SetName("<<quote<<GetName()<<quote<<");"<<endl;
03001       out<<"   "<<GetName()<<"->SetTitle("<<quote<<GetTitle()<<quote<<");"<<endl;
03002       if (fNpx != 100) {
03003          out<<"   "<<GetName()<<"->SetNpx("<<fNpx<<");"<<endl;
03004       }
03005       Double_t dx = (fXmax-fXmin)/fNpx;
03006       Double_t xv[1];
03007       InitArgs(xv,fParams);
03008       for (i=0;i<=fNpx;i++) {
03009          xv[0]    = fXmin + dx*i;
03010          Double_t save = EvalPar(xv,fParams);
03011          out<<"   "<<GetName()<<"->SetSavedPoint("<<i<<","<<save<<");"<<endl;
03012       }
03013       out<<"   "<<GetName()<<"->SetSavedPoint("<<fNpx+1<<","<<fXmin<<");"<<endl;
03014       out<<"   "<<GetName()<<"->SetSavedPoint("<<fNpx+2<<","<<fXmax<<");"<<endl;
03015    }
03016 
03017    if (TestBit(kNotDraw)) {
03018       out<<"   "<<GetName()<<"->SetBit(TF1::kNotDraw);"<<endl;
03019    }
03020    if (GetFillColor() != 0) {
03021       if (GetFillColor() > 228) {
03022          TColor::SaveColor(out, GetFillColor());
03023          out<<"   "<<GetName()<<"->SetFillColor(ci);" << endl;
03024       } else
03025          out<<"   "<<GetName()<<"->SetFillColor("<<GetFillColor()<<");"<<endl;
03026    }
03027    if (GetFillStyle() != 1001) {
03028       out<<"   "<<GetName()<<"->SetFillStyle("<<GetFillStyle()<<");"<<endl;
03029    }
03030    if (GetMarkerColor() != 1) {
03031       if (GetMarkerColor() > 228) {
03032          TColor::SaveColor(out, GetMarkerColor());
03033          out<<"   "<<GetName()<<"->SetMarkerColor(ci);" << endl;
03034       } else
03035          out<<"   "<<GetName()<<"->SetMarkerColor("<<GetMarkerColor()<<");"<<endl;
03036    }
03037    if (GetMarkerStyle() != 1) {
03038       out<<"   "<<GetName()<<"->SetMarkerStyle("<<GetMarkerStyle()<<");"<<endl;
03039    }
03040    if (GetMarkerSize() != 1) {
03041       out<<"   "<<GetName()<<"->SetMarkerSize("<<GetMarkerSize()<<");"<<endl;
03042    }
03043    if (GetLineColor() != 1) {
03044       if (GetLineColor() > 228) {
03045          TColor::SaveColor(out, GetLineColor());
03046          out<<"   "<<GetName()<<"->SetLineColor(ci);" << endl;
03047       } else
03048          out<<"   "<<GetName()<<"->SetLineColor("<<GetLineColor()<<");"<<endl;
03049    }
03050    if (GetLineWidth() != 4) {
03051       out<<"   "<<GetName()<<"->SetLineWidth("<<GetLineWidth()<<");"<<endl;
03052    }
03053    if (GetLineStyle() != 1) {
03054       out<<"   "<<GetName()<<"->SetLineStyle("<<GetLineStyle()<<");"<<endl;
03055    }
03056    if (GetChisquare() != 0) {
03057       out<<"   "<<GetName()<<"->SetChisquare("<<GetChisquare()<<");"<<endl;
03058       out<<"   "<<GetName()<<"->SetNDF("<<GetNDF()<<");"<<endl;
03059    }
03060 
03061    GetXaxis()->SaveAttributes(out,GetName(),"->GetXaxis()");
03062    GetYaxis()->SaveAttributes(out,GetName(),"->GetYaxis()");
03063 
03064    Double_t parmin, parmax;
03065    for (i=0;i<fNpar;i++) {
03066       out<<"   "<<GetName()<<"->SetParameter("<<i<<","<<GetParameter(i)<<");"<<endl;
03067       out<<"   "<<GetName()<<"->SetParError("<<i<<","<<GetParError(i)<<");"<<endl;
03068       GetParLimits(i,parmin,parmax);
03069       out<<"   "<<GetName()<<"->SetParLimits("<<i<<","<<parmin<<","<<parmax<<");"<<endl;
03070    }
03071    if (!strstr(option,"nodraw")) {
03072       out<<"   "<<GetName()<<"->Draw("
03073          <<quote<<option<<quote<<");"<<endl;
03074    }
03075 }
03076 
03077 
03078 //______________________________________________________________________________
03079 void TF1::SetCurrent(TF1 *f1)
03080 {
03081    // Static function setting the current function.
03082    // the current function may be accessed in static C-like functions
03083    // when fitting or painting a function.
03084 
03085    fgCurrent = f1;
03086 }
03087 
03088 //______________________________________________________________________________
03089 void TF1::SetFitResult(const ROOT::Fit::FitResult & result, const Int_t* indpar )
03090 {
03091    // Set the result from the fit  
03092    // parameter values, errors, chi2, etc...
03093    // Optionally a pointer to a vector (with size fNpar) of the parameter indices in the FitResult can be passed
03094    // This is useful in the case of a combined fit with different functions, and the FitResult contains the global result 
03095    // By default it is assume that indpar = {0,1,2,....,fNpar-1}. 
03096 
03097    if (result.IsEmpty()) { 
03098       Warning("SetFitResult","Empty Fit result - nathing is set in TF1");
03099       return;      
03100    }
03101    if (indpar == 0 && fNpar != (int) result.NPar() ) { 
03102       Error("SetFitResult","Invalid Fit result passed - number of parameter is %d , different than TF1::GetNpar() = %d",fNpar,result.NPar());
03103       return;
03104    }
03105    if (result.Chi2() > 0) 
03106       SetChisquare(result.Chi2() );
03107    else 
03108       SetChisquare(result.MinFcnValue() );
03109 
03110    SetNDF(result.Ndf() );
03111    SetNumberFitPoints(result.Ndf() + result.NFreeParameters() );
03112 
03113 
03114    for (Int_t i = 0; i < fNpar; ++i) { 
03115       Int_t ipar = (indpar != 0) ? indpar[i] : i;  
03116       if (ipar < 0) continue;
03117       fParams[i] = result.Parameter(ipar);
03118       // in case errors are not present do not set them
03119       if (ipar < (int) result.Errors().size() )
03120          fParErrors[i] = result.Error(ipar);
03121    }
03122    //invalidate cached integral since parameters have changed
03123    Update();   
03124          
03125 }
03126 
03127 
03128 //______________________________________________________________________________
03129 void TF1::SetMaximum(Double_t maximum)
03130 {
03131    // Set the maximum value along Y for this function
03132    // In case the function is already drawn, set also the maximum in the
03133    // helper histogram
03134 
03135    fMaximum = maximum;
03136    if (fHistogram) fHistogram->SetMaximum(maximum);
03137    if (gPad) gPad->Modified();
03138 }
03139 
03140 
03141 //______________________________________________________________________________
03142 void TF1::SetMinimum(Double_t minimum)
03143 {
03144    // Set the minimum value along Y for this function
03145    // In case the function is already drawn, set also the minimum in the
03146    // helper histogram
03147 
03148    fMinimum = minimum;
03149    if (fHistogram) fHistogram->SetMinimum(minimum);
03150    if (gPad) gPad->Modified();
03151 }
03152 
03153 
03154 //______________________________________________________________________________
03155 void TF1::SetNDF(Int_t ndf)
03156 {
03157    // Set the number of degrees of freedom
03158    // ndf should be the number of points used in a fit - the number of free parameters
03159 
03160    fNDF = ndf;
03161 }
03162 
03163 
03164 //______________________________________________________________________________
03165 void TF1::SetNpx(Int_t npx)
03166 {
03167    // Set the number of points used to draw the function
03168    //
03169    // The default number of points along x is 100 for 1-d functions and 30 for 2-d/3-d functions
03170    // You can increase this value to get a better resolution when drawing
03171    // pictures with sharp peaks or to get a better result when using TF1::GetRandom
03172    // the minimum number of points is 4, the maximum is 100000 for 1-d and 10000 for 2-d/3-d functions
03173 
03174    if (npx < 4) {
03175       Warning("SetNpx","Number of points must be >4 && < 100000, fNpx set to 4");
03176       fNpx = 4;
03177    } else if(npx > 100000) {
03178       Warning("SetNpx","Number of points must be >4 && < 100000, fNpx set to 100000");
03179       fNpx = 100000;
03180    } else {
03181       fNpx = npx;
03182    }
03183    Update();
03184 }
03185 
03186 
03187 //______________________________________________________________________________
03188 void TF1::SetParError(Int_t ipar, Double_t error)
03189 {
03190    // Set error for parameter number ipar
03191 
03192    if (ipar < 0 || ipar > fNpar-1) return;
03193    fParErrors[ipar] = error;
03194 }
03195 
03196 
03197 //______________________________________________________________________________
03198 void TF1::SetParErrors(const Double_t *errors)
03199 {
03200    // Set errors for all active parameters
03201    // when calling this function, the array errors must have at least fNpar values
03202 
03203    if (!errors) return;
03204    for (Int_t i=0;i<fNpar;i++) fParErrors[i] = errors[i];
03205 }
03206 
03207 
03208 //______________________________________________________________________________
03209 void TF1::SetParLimits(Int_t ipar, Double_t parmin, Double_t parmax)
03210 {
03211    // Set limits for parameter ipar.
03212    //
03213    // The specified limits will be used in a fit operation
03214    // when the option "B" is specified (Bounds).
03215    // To fix a parameter, use TF1::FixParameter
03216 
03217    if (ipar < 0 || ipar > fNpar-1) return;
03218    Int_t i;
03219    if (!fParMin) {fParMin = new Double_t[fNpar]; for (i=0;i<fNpar;i++) fParMin[i]=0;}
03220    if (!fParMax) {fParMax = new Double_t[fNpar]; for (i=0;i<fNpar;i++) fParMax[i]=0;}
03221    fParMin[ipar] = parmin;
03222    fParMax[ipar] = parmax;
03223 }
03224 
03225 
03226 //______________________________________________________________________________
03227 void TF1::SetRange(Double_t xmin, Double_t xmax)
03228 {
03229    // Initialize the upper and lower bounds to draw the function.
03230    //
03231    // The function range is also used in an histogram fit operation
03232    // when the option "R" is specified.
03233 
03234    fXmin = xmin;
03235    fXmax = xmax;
03236    Update();
03237 }
03238 
03239 
03240 //______________________________________________________________________________
03241 void TF1::SetSavedPoint(Int_t point, Double_t value)
03242 {
03243    // Restore value of function saved at point
03244 
03245    if (!fSave) {
03246       fNsave = fNpx+3;
03247       fSave  = new Double_t[fNsave];
03248    }
03249    if (point < 0 || point >= fNsave) return;
03250    fSave[point] = value;
03251 }
03252 
03253 
03254 //______________________________________________________________________________
03255 void TF1::SetTitle(const char *title)
03256 {
03257    // Set function title
03258    //  if title has the form "fffffff;xxxx;yyyy", it is assumed that
03259    //  the function title is "fffffff" and "xxxx" and "yyyy" are the
03260    //  titles for the X and Y axis respectively.
03261 
03262    if (!title) return;
03263    fTitle = title;
03264    if (!fHistogram) return;
03265    fHistogram->SetTitle(title);
03266    if (gPad) gPad->Modified();
03267 }
03268 
03269 
03270 //______________________________________________________________________________
03271 void TF1::Streamer(TBuffer &b)
03272 {
03273    // Stream a class object.
03274 
03275    if (b.IsReading()) {
03276       UInt_t R__s, R__c;
03277       Version_t v = b.ReadVersion(&R__s, &R__c);
03278       if (v > 4) {
03279          b.ReadClassBuffer(TF1::Class(), this, v, R__s, R__c);
03280          if (v == 5 && fNsave > 0) {
03281             //correct badly saved fSave in 3.00/06
03282             Int_t np = fNsave - 3;
03283             fSave[np]   = fSave[np-1];
03284             fSave[np+1] = fXmin;
03285             fSave[np+2] = fXmax;
03286          }
03287          return;
03288       }
03289       //====process old versions before automatic schema evolution
03290       TFormula::Streamer(b);
03291       TAttLine::Streamer(b);
03292       TAttFill::Streamer(b);
03293       TAttMarker::Streamer(b);
03294       if (v < 4) {
03295          Float_t xmin,xmax;
03296          b >> xmin; fXmin = xmin;
03297          b >> xmax; fXmax = xmax;
03298       } else {
03299          b >> fXmin;
03300          b >> fXmax;
03301       }
03302       b >> fNpx;
03303       b >> fType;
03304       b >> fChisquare;
03305       b.ReadArray(fParErrors);
03306       if (v > 1) {
03307          b.ReadArray(fParMin);
03308          b.ReadArray(fParMax);
03309       } else {
03310          fParMin = new Double_t[fNpar+1];
03311          fParMax = new Double_t[fNpar+1];
03312       }
03313       b >> fNpfits;
03314       if (v == 1) {
03315          b >> fHistogram;
03316          delete fHistogram; fHistogram = 0;
03317       }
03318       if (v > 1) {
03319          if (v < 4) {
03320             Float_t minimum,maximum;
03321             b >> minimum; fMinimum =minimum;
03322             b >> maximum; fMaximum =maximum;
03323          } else {
03324             b >> fMinimum;
03325             b >> fMaximum;
03326          }
03327       }
03328       if (v > 2) {
03329          b >> fNsave;
03330          if (fNsave > 0) {
03331             fSave = new Double_t[fNsave+10];
03332             b.ReadArray(fSave);
03333             //correct fSave limits to match new version
03334             fSave[fNsave]   = fSave[fNsave-1];
03335             fSave[fNsave+1] = fSave[fNsave+2];
03336             fSave[fNsave+2] = fSave[fNsave+3];
03337             fNsave += 3;
03338          } else fSave = 0;
03339       }
03340       b.CheckByteCount(R__s, R__c, TF1::IsA());
03341       //====end of old versions
03342 
03343    } else {
03344       Int_t saved = 0;
03345       if (fType > 0 && fNsave <= 0) { saved = 1; Save(fXmin,fXmax,0,0,0,0);}
03346 
03347       b.WriteClassBuffer(TF1::Class(),this);
03348 
03349       if (saved) {delete [] fSave; fSave = 0; fNsave = 0;}
03350    }
03351 }
03352 
03353 
03354 //______________________________________________________________________________
03355 void TF1::Update()
03356 {
03357    // Called by functions such as SetRange, SetNpx, SetParameters
03358    // to force the deletion of the associated histogram or Integral
03359 
03360    delete fHistogram;
03361    fHistogram = 0;
03362    if (fIntegral) {
03363       delete [] fIntegral; fIntegral = 0;
03364       delete [] fAlpha;    fAlpha    = 0;
03365       delete [] fBeta;     fBeta     = 0;
03366       delete [] fGamma;    fGamma    = 0;
03367    }
03368 }
03369 
03370 
03371 //______________________________________________________________________________
03372 void TF1::RejectPoint(Bool_t reject)
03373 {
03374    // Static function to set the global flag to reject points
03375    // the fgRejectPoint global flag is tested by all fit functions
03376    // if TRUE the point is not included in the fit.
03377    // This flag can be set by a user in a fitting function.
03378    // The fgRejectPoint flag is reset by the TH1 and TGraph fitting functions.
03379 
03380    fgRejectPoint = reject;
03381 }
03382 
03383 
03384 //______________________________________________________________________________
03385 Bool_t TF1::RejectedPoint()
03386 {
03387    // See TF1::RejectPoint above
03388 
03389    return fgRejectPoint;
03390 }
03391 
03392 //______________________________________________________________________________
03393 Double_t TF1::Moment(Double_t n, Double_t a, Double_t b, const Double_t *params, Double_t epsilon)
03394 {
03395    // Return nth moment of function between a and b
03396    //
03397    // See TF1::Integral() for parameter definitions
03398 
03399    // wrapped function in interface for integral calculation
03400    // using abs value of integral 
03401 
03402    TF1_EvalWrapper func(this, params, kTRUE, n); 
03403 
03404    ROOT::Math::GaussIntegrator giod;
03405 
03406    giod.SetFunction(func);
03407    giod.SetRelTolerance(epsilon);
03408 
03409    Double_t norm =  giod.Integral(a, b);
03410    if (norm == 0) {
03411       Error("Moment", "Integral zero over range");
03412       return 0;
03413    }
03414 
03415    // calculate now integral of x^n f(x)
03416    // wrapped the member function EvalNum in  interface required by integrator using the functor class 
03417    ROOT::Math::Functor1D xnfunc( &func, &TF1_EvalWrapper::EvalNMom);
03418    giod.SetFunction(xnfunc);
03419 
03420    Double_t res = giod.Integral(a,b)/norm;
03421 
03422    return res;
03423 }
03424 
03425 
03426 //______________________________________________________________________________
03427 Double_t TF1::CentralMoment(Double_t n, Double_t a, Double_t b, const Double_t *params, Double_t epsilon)
03428 {
03429    // Return nth central moment of function between a and b
03430    // (i.e the n-th moment around the mean value)   
03431    //
03432    // See TF1::Integral() for parameter definitions
03433    //   Author: Gene Van Buren <gene@bnl.gov>
03434   
03435    TF1_EvalWrapper func(this, params, kTRUE, n); 
03436 
03437    ROOT::Math::GaussIntegrator giod;
03438 
03439    giod.SetFunction(func);
03440    giod.SetRelTolerance(epsilon);
03441 
03442    Double_t norm =  giod.Integral(a, b);
03443    if (norm == 0) {
03444       Error("Moment", "Integral zero over range");
03445       return 0;
03446    }
03447 
03448    // calculate now integral of xf(x)
03449    // wrapped the member function EvalFirstMom in  interface required by integrator using the functor class 
03450    ROOT::Math::Functor1D xfunc( &func, &TF1_EvalWrapper::EvalFirstMom);
03451    giod.SetFunction(xfunc);
03452 
03453    // estimate of mean value
03454    Double_t xbar = giod.Integral(a,b)/norm;
03455 
03456    // use different mean value in function wrapper 
03457    func.fX0 = xbar; 
03458    ROOT::Math::Functor1D xnfunc( &func, &TF1_EvalWrapper::EvalNMom);
03459    giod.SetFunction(xnfunc);
03460 
03461    Double_t res = giod.Integral(a,b)/norm;
03462    return res;
03463 }
03464 
03465 
03466 //______________________________________________________________________________
03467 // some useful static utility functions to compute sampling points for IntegralFast
03468 //______________________________________________________________________________
03469 #ifdef INTHEFUTURE
03470 void TF1::CalcGaussLegendreSamplingPoints(TGraph *g, Double_t eps)
03471 {
03472    // Type safe interface (static method)
03473    // The number of sampling points are taken from the TGraph
03474 
03475    if (!g) return;
03476    CalcGaussLegendreSamplingPoints(g->GetN(), g->GetX(), g->GetY(), eps);
03477 }
03478 
03479 
03480 //______________________________________________________________________________
03481 TGraph *TF1::CalcGaussLegendreSamplingPoints(Int_t num, Double_t eps)
03482 {
03483    // Type safe interface (static method)
03484    // A TGraph is created with new with num points and the pointer to the
03485    // graph is returned by the function. It is the responsibility of the
03486    // user to delete the object.
03487    // if num is invalid (<=0) NULL is returned
03488 
03489    if (num<=0)
03490       return 0;
03491 
03492    TGraph *g = new TGraph(num);
03493    CalcGaussLegendreSamplingPoints(g->GetN(), g->GetX(), g->GetY(), eps);
03494    return g;
03495 }
03496 #endif
03497 
03498 
03499 //______________________________________________________________________________
03500 void TF1::CalcGaussLegendreSamplingPoints(Int_t num, Double_t *x, Double_t *w, Double_t eps)
03501 {
03502    // Type: unsafe but fast interface filling the arrays x and w (static method)
03503    //
03504    // Given the number of sampling points this routine fills the arrays x and w
03505    // of length num, containing the abscissa and weight of the Gauss-Legendre
03506    // n-point quadrature formula.
03507    //
03508    // Gauss-Legendre: W(x)=1  -1<x<1
03509    //                 (j+1)P_{j+1} = (2j+1)xP_j-jP_{j-1}
03510    //
03511    // num is the number of sampling points (>0)
03512    // x and w are arrays of size num
03513    // eps is the relative precision
03514    //
03515    // If num<=0 or eps<=0 no action is done.
03516    //
03517    // Reference: Numerical Recipes in C, Second Edition
03518 
03519    // This function is just kept like this for backward compatibility!
03520 
03521    ROOT::Math::GaussLegendreIntegrator gli(num,eps);
03522    gli.GetWeightVectors(x, w);
03523 
03524 
03525 }

Generated on Tue Jul 5 14:24:16 2011 for ROOT_528-00b_version by  doxygen 1.5.1