inlib  1.2.0
/Users/barrand/private/dev/softinex/old/inexlib-1.2/inlib/inlib/f2cmn
Go to the documentation of this file.
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
00002 // See the file inlib.license for terms.
00003 
00004 #ifndef inlib_f2cmn
00005 #define inlib_f2cmn
00006 
00007 //  The below code is a modified version of the ROOT/TMinuit class
00008 // in order to have a stand alone C++ version of the Minuit package.
00009 //
00010 //  The usage of TString has been replaced by the usage of std::string
00011 // The reference to TNamed, TObject and TMethods has been removed. 
00012 // In "the ROOT of everything" it could be reintroduced through a 
00013 // class TMinuit that could inherit the Midnight one (we can dream no ?).
00014 //
00015 //    G.Barrand
00016 
00017 /*************************************************************************
00018  * Copyright(c) 1995-1998, The ROOT System, All rights reserved.         *
00019  * Authors: Rene Brun, Nenad Buncic, Valery Fine, Fons Rademakers.       *
00020  *                                                                       *
00021  * Permission to use, copy, modify and distribute this software and its  *
00022  * documentation for non-commercial purposes is hereby granted without   *
00023  * fee, provided that the above copyright notice appears in all copies   *
00024  * and that both the copyright notice and this permission notice appear  *
00025  * in the supporting documentation. The authors make no claims about the *
00026  * suitability of this software for any purpose.                         *
00027  * It is provided "as is" without express or implied warranty.           *
00028  *************************************************************************/
00029 
00030 //*-*-*-*-*-*-*-*-*-*-*-*The Minimization package*-*--*-*-*-*-*-*-*-*-*-*-*
00031 //*-*                    ========================                         *
00032 //*-*                                                                     *
00033 //*-*   This package was originally written in Fortran by Fred James      *
00034 //*-*   and part of PACKLIB (patch D506)                                  *
00035 //*-*                                                                     *
00036 //*-*   It has been converted to a C++ class  by R.Brun                   *
00037 //*-*   The current implementation in C++ is a straightforward conversion *
00038 //*-*   of the original Fortran version: The main changes are:            *
00039 //*-*                                                                     *
00040 //*-*   - The variables in the various Minuit labelled common blocks      *
00041 //*-*     have been changed to the Minuit class data members.            *
00042 //*-*   - The include file Minuit.h has been commented as much as possible*
00043 //*-*     using existing comments in the code or the printed documentation*
00044 //*-*   - The original Minuit subroutines are now member functions.       *
00045 //*-*   - Constructors and destructor have been added.                    *
00046 //*-*   - Instead of passing the FCN  function in the argument            *
00047 //*-*     list, the addresses of this function is stored as pointer       *
00048 //*-*     in the data members of the class. This is by far more elegant   *
00049 //*-*     and flexible in an interactive environment.                     *
00050 //*-*     The member function SetFCN can be used to define this pointer.  *
00051 //*-*   - The ROOT static function Printf is provided to replace all      *
00052 //*-*     format statements and to print on currently defined output file.*
00053 //*-*   - The derived class MinuitOld contains obsolete routines from    *
00054 //*-*     the Fortran based version.                                      *
00055 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00056 
00057 #include <string>
00058 #include <ostream>
00059 
00060 namespace inlib {
00061 namespace f2cmn {
00062 
00063 class fitter {
00064 public:
00065   typedef bool(*Function_t)(int&,double*,double&,double*,int,void*);
00066   enum {kMAXDIM = 50};
00067 private:
00068         int        fEmpty;            //Initialization flag (1 = initialized)
00069         int        fMaxpar;           //Maximum number of parameters
00070         std::string      *fCpnam;           //Array of parameters names
00071         double     *fU;               //External (visible to user in FCN) value of parameters
00072         double     *fAlim;            //Lower limits for parameters. If zero no limits
00073         double     *fBlim;            //Upper limits for parameters
00074         double     *fErp;             //Positive Minos errors if calculated
00075         double     *fErn;             //Negative Minos errors if calculated
00076         double     *fWerr;            //External parameters error (standard deviation, defined by UP)
00077         double     *fGlobcc;          //Global Correlation Coefficients
00078            int     *fNvarl;           //parameters flag (-1=undefined, 0=constant..)
00079            int     *fNiofex;          //Internal parameters number, or zero if not currently variable
00080            int     *fNexofi;          //External parameters number for currently variable parameters
00081         double     *fX;               //Internal parameters values
00082         double     *fXt;              //Internal parameters values X saved as Xt
00083         double     *fDirin;           //(Internal) step sizes for current step
00084         double     *fXs;              //Internal parameters values saved for fixed params
00085         double     *fXts;             //Internal parameters values X saved as Xt for fixed params
00086         double     *fDirins;          //(Internal) step sizes for current step for fixed params
00087         double     *fGrd;             //First derivatives
00088         double     *fG2;              //
00089         double     *fGstep;           //Step sizes
00090         double     *fGin;             //
00091         double     *fDgrd;            //Uncertainties
00092         double     *fGrds;            //
00093         double     *fG2s;             //
00094         double     *fGsteps;          //
00095         int        *fIpfix;           //List of fixed parameters
00096         int        fNpfix;            //Number of fixed parameters
00097         double     *fVhmat;           //(Internal) error matrix stored as Half MATrix, since it is symmetric
00098         double     *fVthmat;          //VHMAT is sometimes saved in VTHMAT, especially in MNMNOT
00099         double     *fP;               //
00100         double     *fPstar;           //
00101         double     *fPstst;           //
00102         double     *fPbar;            //
00103         double     *fPrho;            //Minimum point of parabola
00104         int        fMaxint;           //Maximum number of internal parameters
00105         int        fNpar;             //Number of parameters
00106         int        fMaxext;           //Maximum number of external parameters
00107         int        fNu;               //
00108         int        fIsysrd;           //standardInput unit
00109         int        fIsyswr;           //standard output unit
00110         int        fIsyssa;           //
00111         int        fNpagwd;           //Page width
00112         int        fNpagln;           //Number of lines per page
00113         int        fNewpag;           //
00114         int        fIstkrd[10];       //
00115         int        fNstkrd;           //
00116         int        fIstkwr[10];       //
00117         int        fNstkwr;           //
00118         std::string      fCfrom;            //
00119         std::string      fCstatu;           //
00120         std::string      fCtitl;            //
00121         std::string      fCword;            //
00122         std::string      fCundef;           //
00123         std::string      fCvrsn;            //
00124         std::string      fCovmes[4];        //
00125         int        fISW[7];           //Array of switches
00126         int        fIdbg[11];         //Array of internal debug switches
00127         int        fNblock;           //Number of Minuit data blocks
00128         int        fIcomnd;           //Number of commands
00129         double     fAmin;             //Minimum value found for FCN
00130         double     fUp;               //FCN+-UP defines errors (for chisquare fits UP=1)
00131         double     fEDM;              //Estimated vertical distance to the minimum
00132         double     fFval3;            //
00133         double     fEpsi;             //
00134         double     fApsi;             //
00135         double     fDcovar;           //Relative change in covariance matrix
00136         int        fNfcn;             //Number of calls to FCN
00137         int        fNfcnmx;           //Maximum number of calls to FCN
00138         int        fNfcnlc;           //
00139         int        fNfcnfr;           //
00140         int        fItaur;            //
00141         int        fIstrat;           //
00142         int        fNwrmes[2];        //
00143         double     *fWord7;           //
00144         bool       fLwarn;            //true if warning messges are to be put out (default=true)
00145         bool       fLrepor;           //true if exceptional conditions are put out (default=false)
00146         bool       fLimset;           //true if a parameter is up against limits (for MINOS)
00147         bool       fLnolim;           //true if there are no limits on any parameters (not yet used)
00148         bool       fLnewmn;           //true if the previous process has unexpectedly improved FCN
00149         bool       fLphead;           //true if a heading should be put out for the next parameter definition
00150         double     fEpsmac;           //machine precision for floating points:
00151         double     fEpsma2;           //sqrt(fEpsmac)
00152         double     fVlimlo;           //
00153         double     fVlimhi;           //
00154         double     fUndefi;           //Undefined number = -54321
00155         double     fBigedm;           //Big EDM = 123456
00156         double     fUpdflt;           //
00157         double     *fXpt;             //X array of points for contours
00158         double     *fYpt;             //Y array of points for contours
00159         std::string      *fChpt;            //Character to be plotted at the X,Y contour positions
00160         double     fXmidcr;           //
00161         double     fYmidcr;           //
00162         double     fXdircr;           //
00163         double     fYdircr;           //
00164         int        fKe1cr;            //
00165         int        fKe2cr;            //
00166         std::string      *fOrigin;          //
00167         std::string      *fWarmes;          //
00168         int        fNfcwar[20];       //
00169         int        fIcirc[2];         //
00170         Function_t fFCN;
00171         void*      fTag;
00172         std::ostream* f_out;
00173 
00174 
00175 private:
00176  fitter(const fitter &m);
00177  void      BuildArrays(int maxpar=15);
00178  void      DeleteArrays();
00179 public:
00180  fitter();
00181  fitter(int maxpar);
00182  virtual   ~fitter(){DeleteArrays();}
00183 public:
00184  void      SetFCN(Function_t,void*);
00185  void      SetOut(std::ostream*);
00186  //
00187  void      mnamin();
00188  void      mnbins(double a1, double a2, int naa, double &bl, double &bh, int &nb, double &bwid);
00189  void      mncalf(double *pvec, double &ycalf);
00190  void      mncler();
00191  void      mncntr(int ke1, int ke2, int &ierrf);
00192  void      mncomd(const std::string& crdbin, int &icondn);
00193  void      mncont(int ke1, int ke2, int nptu, double *xptu, double *yptu, int &ierrf);
00194  void      mncrck(const std::string &crdbuf, int maxcwd, std::string &comand, int &lnc,  int mxp, double *plist, int &llist, int &ierr, int isyswr);
00195  void      mncros(double &aopt, int &iercr);
00196  void      mncuve();
00197  bool      mnderi(); //GB
00198  void      mndxdi(double pint, int ipar, double &dxdi);
00199  void      mneig(double *a, int ndima, int n, int mits, double *work, double precis, int &ifault);
00200  void      mnemat(double *emat, int ndim);
00201  void      mnerrs(int number, double &eplus, double &eminus, double &eparab, double &gcc);
00202  void      mneval(double anext, double &fnext, int &ierev);
00203  void      mnexcm(const std::string& comand, const double *plist, int llist, int &ierflg) ;
00204  void      mnexin(double *pint);
00205  void      mnfixp(int iint, int &ierr);
00206  void      mnfree(int k);
00207  void      mngrad();
00208  void      mnhelp(const std::string& comd);
00209  void      mnhess();
00210  void      mnhes1();
00211  void      mnimpr();
00212  void      mninex(double *pint);
00213  void      mninit(int i1, int i2, int i3);
00214  void      mnlims();
00215  void      mnline(double *start, double fstart, double *step, double slope, double toler);
00216  void      mnmatu(int kode);
00217  bool      mnmigr(); //G.Barrand : return a bool.
00218  void      mnmnos();
00219  void      mnmnot(int ilax, int ilax2, double &val2pl, double &val2mi);
00220  void      mnparm(int k, const std::string& cnamj, double uk, double wk, double a, double b, int &ierflg);
00221  void      mnpars(const std::string& crdbuf, int &icondn);
00222  void      mnpfit(double *parx2p, double *pary2p, int npar2p, double *coef2p, double &sdev2p);
00223  void      mnpint(double &pexti, int i, double &pinti);
00224  void      mnplot(double *xpt, double *ypt, std::string *chpt, int nxypt, int npagwd, int npagln);
00225  void      mnpout(int iuext, std::string& chnam, double &val, double &err, double &xlolim, double &xuplim, int &iuint);
00226  void      mnprin(int inkode, double fval);
00227  void      mnpsdf();
00228  void      mnrazz(double ynew, double *pnew, double *y, int &jh, int &jl);
00229  void      mnrn15(double &val, int &inseed);
00230  void      mnrset(int iopt);
00231  void      mnsave();
00232  void      mnscan();
00233  void      mnseek();
00234  void      mnset();
00235  void      mnsimp();
00236  void      mnstat(double &fmin, double &fedm, double &errdef, int &npari, int &nparx, int &istat);
00237  void      mntiny(double epsp1, double &epsbak);
00238  bool    mnunpt(const std::string &cfname);
00239  void      mnvert(double *a, int l, int m, int n, int &ifail);
00240  void      mnwarn(const std::string& copt, const std::string& corg, const std::string& cmes);
00241  void      mnwerr();
00242 private:
00243   static std::string msubstr(const std::string&,
00244                              std::string::size_type,
00245                              std::string::size_type);
00246   static std::string& mreplace(std::string&,
00247                                std::string::size_type,
00248                                std::string::size_type,
00249                                const std::string&);
00250 };
00251 
00252 }}
00253 
00254 #include <cstdlib>
00255 #include <cstdio>
00256 #include <cstring>
00257 #include <cstdarg>
00258 #include <cmath>
00259 
00260 namespace inlib {
00261 namespace f2cmn {
00262 
00263 template <class T>
00264 inline T TMath_Min(const T& a,const T& b) {
00265   return (a<b?a:b);
00266 }    
00267 
00268 template <class T>
00269 inline T TMath_Max(const T& a,const T& b) {
00270   return (a>b?a:b);
00271 }    
00272 
00273 
00274 inline double TMath_Log(double a){return ::log(a);}
00275 inline double TMath_Log10(double a){return ::log10(a);}
00276 inline double TMath_Sqrt(double a){return ::sqrt(a);}
00277 inline double TMath_Power(double a,double b) {return ::pow(a,b);}
00278 inline double TMath_Abs(double a){return ::fabs(a);}
00279 inline double TMath_Sin(double a){return ::sin(a);}
00280 inline double TMath_Cos(double a){return ::cos(a);}
00281 inline double TMath_ATan(double a){return ::atan(a);}
00282 inline double TMath_ASin(double a){return ::asin(a);}
00283 
00284 inline int TMath_int_abs(int a){return a>=0?a:-a;} /*G.Barrand*/
00285 
00286 inline std::string Form(const char* aFormat,...){
00287   char sBuffer[1024];
00288   va_list args;
00289   va_start(args,aFormat);
00290 #ifdef WIN32
00291   _vsnprintf(sBuffer,sizeof(sBuffer),aFormat,args);
00292 #else
00293   ::vsnprintf(sBuffer,sizeof(sBuffer),aFormat,args);
00294 #endif
00295   va_end(args);
00296   return sBuffer;
00297 }
00298 
00299 inline void Printf(std::ostream* a_out,const char* aFormat,...){
00300   char s[2048];
00301   va_list args;
00302   va_start(args,aFormat);
00303 #ifdef WIN32
00304   _vsnprintf(s,sizeof(s),aFormat,args);
00305 #else
00306   ::vsnprintf(s,sizeof(s),aFormat,args);
00307 #endif
00308   va_end(args);
00309   if(a_out) {
00310     (*a_out) << s << std::endl;
00311   } else {
00312     ::printf("%s\n",s);
00313   }
00314 }
00315 
00316 // Some substr start outside string, crash with std::string.substr.
00317 // Instead we use the below :
00318 inline
00319 std::string fitter::msubstr(const std::string& aString,
00320                        std::string::size_type aStart,
00321                        std::string::size_type aLength ) {
00322   if(aStart>=aString.length()) return aString;
00323   return aString.substr(aStart,aLength);
00324 }
00325 // std::string.replace is not protected against outside start position.
00326 inline
00327 std::string& fitter::mreplace(std::string& aString,
00328                          std::string::size_type aStart,
00329                          std::string::size_type aLength,
00330                          const std::string& aNew) {
00331   if(aStart>=aString.length()) return aString;
00332   return aString.replace(aStart,aLength,aNew);
00333 }
00334 
00335 
00336 //______________________________________________________________________________
00337 inline
00338 fitter::fitter()
00339 {
00340 //*-*-*-*-*-*-*-*-*-*-*Minuit normal constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00341 //*-*                  ========================
00342 
00343    fEmpty = 1;
00344    f_out = 0;
00345    fFCN = 0;
00346    fTag = 0;
00347 
00348 }
00349 
00350 //______________________________________________________________________________
00351 inline
00352 fitter::fitter(int maxpar)
00353 {
00354 //*-*-*-*-*-*-*-*-*-*-*Minuit normal constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00355 //*-*                  ========================
00356 
00357    BuildArrays(maxpar);
00358 
00359    fEmpty = 0;
00360    f_out = 0;
00361    fFCN = 0;
00362    fTag = 0;
00363 
00364    mninit(5,6,7);
00365 }
00366 
00367 //______________________________________________________________________________
00368 inline
00369 fitter::fitter(const fitter &)
00370 {
00371    // Private copy ctor. This object can not be copied.
00372 
00373   //debug Error("Midnight", "can not copy construct Midnight");
00374    Printf(f_out,"Midnight can not copy construct Midnight");
00375 }
00376 
00377 //______________________________________________________________________________
00378 inline
00379 void fitter::BuildArrays(int maxpar)
00380 {
00381 //*-*-*-*-*-*-*Create internal Minuit arrays for the maxpar parameters*-*-*-*
00382 //*-*          =======================================================
00383 
00384    int mni = 25;
00385    if (maxpar > 10 && maxpar < 200) mni = maxpar;
00386    fMaxpar      = mni;
00387    int mnihl  = mni*(mni+1)/2;
00388    int maxcpt = 101;
00389    int mne    = 2*mni;
00390    fCpnam  = new std::string[mne];
00391    fU      = new double[mne];
00392    fAlim   = new double[mne];
00393    fBlim   = new double[mne];
00394    fErp    = new double[mni];
00395    fErn    = new double[mni];
00396    fWerr   = new double[mni];
00397    fGlobcc = new double[mni];
00398    fNvarl  = new int[mne];
00399    fNiofex = new int[mne];
00400    fNexofi = new int[mne];
00401    fX      = new double[mni];
00402    fXt     = new double[mni];
00403    fDirin  = new double[mni];
00404    fXs     = new double[mni];
00405    fXts    = new double[mni];
00406    fDirins = new double[mni];
00407    fGrd    = new double[mni];
00408    fG2     = new double[mni];
00409    fGstep  = new double[mni];
00410    fGin    = new double[mni];
00411    fDgrd   = new double[mni];
00412    fGrds   = new double[mni];
00413    fG2s    = new double[mni];
00414    fGsteps = new double[mni];
00415    fIpfix  = new int[mni];
00416    fVhmat  = new double[mnihl];
00417    fVthmat = new double[mnihl];
00418    fP      = new double[mni*(mni+1)];
00419    fPstar  = new double[mni*2];
00420    fPstst  = new double[mni];
00421    fPbar   = new double[mni];
00422    fPrho   = new double[mni];
00423    fWord7  = new double[30];
00424    fXpt    = new double[maxcpt];
00425    fYpt    = new double[maxcpt];
00426    fChpt   = new std::string[maxcpt];
00427    fOrigin = new std::string[100];
00428    fWarmes = new std::string[100];
00429 
00430    for (int i = 0; i < fMaxpar; i++) {
00431       fErp[i] = 0;
00432       fErn[i] = 0;
00433    }
00434 }
00435 
00436 //______________________________________________________________________________
00437 inline
00438 void fitter::DeleteArrays()
00439 {
00440 //*-*-*-*-*-*-*-*-*-*-*-*Delete internal Minuit arrays*-*-*-*-*-*-*-*-*
00441 //*-*                    =============================
00442    if (fEmpty) return;
00443    delete [] fCpnam;
00444    delete [] fU;
00445    delete [] fAlim;
00446    delete [] fBlim;
00447    delete [] fErp;
00448    delete [] fErn;
00449    delete [] fWerr;
00450    delete [] fGlobcc;
00451    delete [] fNvarl;
00452    delete [] fNiofex;
00453    delete [] fNexofi;
00454    delete [] fX;
00455    delete [] fXt;
00456    delete [] fDirin;
00457    delete [] fXs;
00458    delete [] fXts;
00459    delete [] fDirins;
00460    delete [] fGrd;
00461    delete [] fG2;
00462    delete [] fGstep;
00463    delete [] fGin;
00464    delete [] fDgrd;
00465    delete [] fGrds;
00466    delete [] fG2s;
00467    delete [] fGsteps;
00468    delete [] fIpfix;
00469    delete [] fVhmat;
00470    delete [] fVthmat;
00471    delete [] fP;
00472    delete [] fPstar;
00473    delete [] fPstst;
00474    delete [] fPbar;
00475    delete [] fPrho;
00476    delete [] fWord7;
00477    delete [] fXpt;
00478    delete [] fYpt;
00479    delete [] fChpt;
00480    delete [] fOrigin;
00481    delete [] fWarmes;
00482    fEmpty = 1;
00483 }
00484 
00485 //______________________________________________________________________________
00486 inline
00487 void fitter::SetFCN(Function_t fcn,void* aTag)
00488 {
00489 //*-*-*-*-*-*-*To set the address of the minimization function*-*-*-*-*-*-*-*
00490 //*-*          ===============================================
00491 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00492    fFCN = fcn;
00493    fTag = aTag;
00494 }
00495 
00496 inline
00497 void fitter::SetOut(std::ostream* a_out)
00498 {
00499    f_out = a_out;
00500 }
00501 
00502 //______________________________________________________________________________
00503 inline
00504 void fitter::mnamin()
00505 {
00506 //*-*-*-*-*-*-*-*-*-*-*-*-*Initialize AMIN*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00507 //*-*                      ===============
00508 //*-*C        Called  from many places.  Initializes the value of AMIN by
00509 //*-*C        calling the user function. Prints out the function value and
00510 //*-*C        parameter values if Print Flag value is high enough.
00511 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00512 
00513     /* Local variables */
00514     /*static*/ double fnew;
00515     /*static*/ int nparx;
00516 
00517     nparx = fNpar;
00518     if (fISW[4] >= 1) {
00519         Printf(f_out," FIRST CALL TO USER FUNCTION AT NEW START POINT, WITH IFLAG=4.");
00520     }
00521     mnexin(fX);
00522     //Printf(f_out,"debug : FCN : 000");
00523     (*fFCN)(nparx, fGin, fnew, fU, 4,fTag);    ++fNfcn;
00524     fAmin = fnew;
00525     fEDM  = fBigedm;
00526 } /* mnamin_ */
00527 
00528 //______________________________________________________________________________
00529 inline
00530 void fitter::mnbins(double a1, double a2, int naa, double &bl, double &bh, int &nb, double &bwid)
00531 {
00532 //*-*-*-*-*-*-*-*-*-*-*Compute reasonable histogram intervals*-*-*-*-*-*-*-*-*
00533 //*-*                  ======================================
00534 //*-*        Function TO DETERMINE REASONABLE HISTOGRAM INTERVALS
00535 //*-*        GIVEN ABSOLUTE UPPER AND LOWER BOUNDS  A1 AND A2
00536 //*-*        AND DESIRED MAXIMUM NUMBER OF BINS NAA
00537 //*-*        PROGRAM MAKES REASONABLE BINNING FROM BL TO BH OF WIDTH BWID
00538 //*-*        F. JAMES,   AUGUST, 1974 , stolen for Minuit, 1988
00539 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00540 
00541     /* Local variables */
00542     double awid,ah, al, sigfig, sigrnd, alb;
00543     /*static*/ int kwid, lwid, na, log_;
00544     na = 0; //GB
00545 
00546     al = TMath_Min(a1,a2);
00547     ah = TMath_Max(a1,a2);
00548     if (al == ah) ah = al + 1;
00549 
00550 //*-*-       IF NAA .EQ. -1 , PROGRAM USES BWID INPUT FROM CALLING ROUTINE
00551     if (naa == -1) goto L150;
00552 L10:
00553     na = naa - 1;
00554     if (na < 1) na = 1;
00555 
00556 //*-*-        GET NOMINAL BIN WIDTH IN EXPON FORM
00557 L20:
00558     awid = (ah-al) / double(na);
00559     log_ = int(TMath_Log10(awid));
00560     if (awid <= 1) --log_;
00561     sigfig = awid*TMath_Power(10., -log_);
00562 //*-*-       ROUND MANTISSA UP TO 2, 2.5, 5, OR 10
00563     if (sigfig > 2) goto L40;
00564     sigrnd = 2;
00565     goto L100;
00566 L40:
00567     if (sigfig > 2.5) goto L50;
00568     sigrnd = 2.5;
00569     goto L100;
00570 L50:
00571     if (sigfig > 5) goto L60;
00572     sigrnd = 5;
00573     goto L100;
00574 L60:
00575     sigrnd = 1;
00576     ++log_;
00577 L100:
00578     bwid = sigrnd*TMath_Power(10., log_);
00579     goto L200;
00580 //*-*-       GET NEW BOUNDS FROM NEW WIDTH BWID
00581 L150:
00582     if (bwid <= 0) goto L10;
00583 L200:
00584     alb  = al / bwid;
00585     lwid = int(alb);
00586     if (alb < 0) --lwid;
00587     bl   = bwid*double(lwid);
00588     alb  = ah / bwid + 1;
00589     kwid = int(alb);
00590     if (alb < 0) --kwid;
00591     bh = bwid*double(kwid);
00592     nb = kwid - lwid;
00593     if (naa > 5) goto L240;
00594     if (naa == -1) return;
00595 //*-*-        REQUEST FOR ONE BIN IS DIFFICULT CASE
00596     if (naa > 1 || nb == 1) return;
00597     bwid *= 2;
00598     nb = 1;
00599     return;
00600 L240:
00601     if (nb << 1 != naa) return;
00602     ++na;
00603     goto L20;
00604 } /* mnbins_ */
00605 
00606 //______________________________________________________________________________
00607 inline
00608 void fitter::mncalf(double *pvec, double &ycalf)
00609 {
00610 //*-*-*-*-*-*-*-*-*-*Transform FCN to find further minima*-*-*-*-*-*-*-*-*-*
00611 //*-*                ====================================
00612 //*-*        Called only from MNIMPR.  Transforms the function FCN
00613 //*-*        by dividing out the quadratic part in order to find further
00614 //*-*        minima.    Calculates  ycalf = (f-fmin)/(x-xmin)*v*(x-xmin)
00615 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00616 
00617     /* Local variables */
00618     /*static*/ int ndex, i, j, m, n, nparx;
00619     /*static*/ double denom, f;
00620 
00621     nparx = fNpar;
00622     mninex(&pvec[0]);
00623     //Printf(f_out,"debug : FCN : 001");
00624     (*fFCN)(nparx, fGin, f, fU, 4,fTag);    ++fNfcn;
00625     for (i = 1; i <= fNpar; ++i) {
00626         fGrd[i-1] = 0;
00627         for (j = 1; j <= fNpar; ++j) {
00628             m = TMath_Max(i,j);
00629             n = TMath_Min(i,j);
00630             ndex = m*(m-1) / 2 + n;
00631             fGrd[i-1] += fVthmat[ndex-1]*(fXt[j-1] - pvec[j-1]);
00632         }
00633     }
00634     denom = 0;
00635     for (i = 1; i <= fNpar; ++i) {denom += fGrd[i-1]*(fXt[i-1] - pvec[i-1]); }
00636     if (denom <= 0) {
00637         fDcovar = 1;
00638         fISW[1] = 0;
00639         denom   = 1;
00640     }
00641     ycalf = (f - fApsi) / denom;
00642 } /* mncalf_ */
00643 
00644 //______________________________________________________________________________
00645 inline
00646 void fitter::mncler()
00647 {
00648 //*-*-*-*-*-*-*-*-*-*-*Resets the parameter list to UNDEFINED*-*-*-*-*-*-*-*
00649 //*-*                  ======================================
00650 //*-*        Called from MINUIT and by option from MNEXCM
00651 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00652 
00653     int i;
00654 
00655     fNpfix = 0;
00656     fNu = 0;
00657     fNpar = 0;
00658     fNfcn = 0;
00659     fNwrmes[0] = 0;
00660     fNwrmes[1] = 0;
00661     for (i = 1; i <= fMaxext; ++i) {
00662         fU[i-1]      = 0;
00663         fCpnam[i-1]  = fCundef;
00664         fNvarl[i-1]  = -1;
00665         fNiofex[i-1] = 0;
00666     }
00667     mnrset(1);
00668     fCfrom  = "CLEAR   ";
00669     fNfcnfr = fNfcn;
00670     fCstatu = "UNDEFINED ";
00671     fLnolim = true;
00672     fLphead = true;
00673 } /* mncler_ */
00674 
00675 //______________________________________________________________________________
00676 inline
00677 void fitter::mncntr(int ke1, int ke2, int &ierrf)
00678 {
00679 //*-*-*-*-*Print function contours in two variables, on line printer*-*-*-*-*
00680 //*-*      =========================================================
00681 //*-*
00682 //*-*                input arguments: parx, pary, devs, ngrid
00683 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00684 
00685     static const std::string clabel = "0123456789ABCDEFGHIJ";
00686 
00687     /* Local variables */
00688     double d__1, d__2;
00689     double fcna[115], fcnb[115], contur[20];
00690     double  ylabel, fmn, fmx, xlo, ylo, xup, yup;
00691     double devs, xsav, ysav,  bwidx,  bwidy, unext, ff, xb4;
00692 
00693     /*static*/ int i,  ngrid, ixmid, nparx, ix, nx, ny, ki1, ki2, ixzero, iy, ics;
00694     /*static*/ std::string chmid, chln, chzero;
00695 
00696     if (ke1 <= 0 || ke2 <= 0) goto L1350;
00697     if (ke1 > fNu || ke2 > fNu) goto L1350;
00698     ki1 = fNiofex[ke1-1];
00699     ki2 = fNiofex[ke2-1];
00700     if (ki1 <= 0 || ki2 <= 0) goto L1350;
00701     if (ki1 == ki2) goto L1350;
00702 
00703     if (fISW[1] < 1) {
00704         mnhess();
00705         mnwerr();
00706     }
00707     nparx = fNpar;
00708     xsav = fU[ke1-1];
00709     ysav = fU[ke2-1];
00710     devs = fWord7[2];
00711     if (devs <= 0) devs = 2;
00712     xlo = fU[ke1-1] - devs*fWerr[ki1-1];
00713     xup = fU[ke1-1] + devs*fWerr[ki1-1];
00714     ylo = fU[ke2-1] - devs*fWerr[ki2-1];
00715     yup = fU[ke2-1] + devs*fWerr[ki2-1];
00716     ngrid = int(fWord7[3]);
00717     if (ngrid <= 0) {
00718         ngrid = 25;
00719 //*-*  Computing MIN
00720         nx = TMath_Min(fNpagwd - 15,ngrid);
00721 //*-*  Computing MIN
00722         ny = TMath_Min(fNpagln - 7,ngrid);
00723     } else {
00724         nx = ngrid;
00725         ny = ngrid;
00726     }
00727     if (nx < 11)   nx = 11;
00728     if (ny < 11)   ny = 11;
00729     if (nx >= 115) nx = 114;
00730 
00731 //*-*-        ask if parameter outside limits
00732     if (fNvarl[ke1-1] > 1) {
00733         if (xlo < fAlim[ke1-1]) xlo = fAlim[ke1-1];
00734         if (xup > fBlim[ke1-1]) xup = fBlim[ke1-1];
00735     }
00736     if (fNvarl[ke2-1] > 1) {
00737         if (ylo < fAlim[ke2-1]) ylo = fAlim[ke2-1];
00738         if (yup > fBlim[ke2-1]) yup = fBlim[ke2-1];
00739     }
00740     bwidx = (xup - xlo) / double(nx);
00741     bwidy = (yup - ylo) / double(ny);
00742     ixmid = int(((xsav - xlo)*double(nx) / (xup - xlo)) + 1);
00743     if (fAmin == fUndefi) mnamin();
00744 
00745     for (i = 1; i <= 20; ++i) { contur[i-1] = fAmin + fUp*(i-1)*(i-1); }
00746     contur[0] += fUp*.01;
00747 //*-*-               fill FCNB to prepare first row, and find column zero/
00748     fU[ke2-1] = yup;
00749     ixzero = 0;
00750     xb4 = 1;
00751 //TH
00752     chmid.resize(nx+1);
00753     chzero.resize(nx+1);
00754     chln.resize(nx+1);
00755     for (ix = 1; ix <= nx + 1; ++ix) {
00756         fU[ke1-1] = xlo + double(ix-1)*bwidx;
00757     //Printf(f_out,"debug : FCN : 002");
00758         (*fFCN)(nparx, fGin, ff, fU, 4,fTag);
00759         fcnb[ix-1] = ff;
00760         if (xb4 < 0 && fU[ke1-1] > 0) ixzero = ix - 1;
00761         xb4          = fU[ke1-1];
00762         chmid[ix-1]  = '*';
00763         chzero[ix-1] = '-';
00764     }
00765     Printf(f_out," Y-AXIS: PARAMETER %3d: %s",ke2,fCpnam[ke2-1].c_str());
00766     if (ixzero > 0) {
00767         chzero[ixzero-1] = '+';
00768         chln = " ";
00769         Printf(f_out,"             X=0");
00770     }
00771 //*-*-                loop over rows
00772     for (iy = 1; iy <= ny; ++iy) {
00773         unext = fU[ke2-1] - bwidy;
00774 //*-*-                prepare this line background pattern for contour
00775         chln = " ";
00776 // TH   
00777         chln.resize(nx+1);
00778         chln[ixmid-1] = '*';
00779         if (ixzero != 0) chln[ixzero-1] = ':';
00780         if (fU[ke2-1] > ysav && unext < ysav) chln = chmid;
00781         if (fU[ke2-1] > 0 && unext < 0)       chln = chzero;
00782         fU[ke2-1] = unext;
00783         ylabel = fU[ke2-1] + bwidy*.5;
00784 //*-*-                move FCNB to FCNA and fill FCNB with next row
00785         for (ix = 1; ix <= nx + 1; ++ix) {
00786             fcna[ix-1] = fcnb[ix-1];
00787             fU[ke1-1] = xlo + double(ix-1)*bwidx;
00788     //Printf(f_out,"debug : FCN : 003");
00789             (*fFCN)(nparx, fGin, ff, fU, 4,fTag);
00790             fcnb[ix-1] = ff;
00791         }
00792 //*-*-                look for contours crossing the FCNxy squares
00793         for (ix = 1; ix <= nx; ++ix) {
00794             d__1 = TMath_Max(fcna[ix-1],fcnb[ix-1]),
00795             d__2 = TMath_Max(fcna[ix],fcnb[ix]);
00796             fmx  = TMath_Max(d__1,d__2);
00797             d__1 = TMath_Min(fcna[ix-1],fcnb[ix-1]),
00798             d__2 = TMath_Min(fcna[ix],fcnb[ix]);
00799             fmn  = TMath_Min(d__1,d__2);
00800             for (ics = 1; ics <= 20; ++ics) {
00801                 if (contur[ics-1] > fmn)  goto L240;
00802             }
00803             continue;
00804 L240:
00805             if (contur[ics-1] < fmx) chln[ix-1] = clabel[ics-1];
00806         }
00807 //*-*-                print a row of the contour plot
00808         Printf(f_out," %12.4g %s",ylabel,chln.c_str());
00809     }
00810 //*-*-                contours printed, label x-axis
00811     chln          = " ";
00812     chln[0]       = 'I';
00813     chln[ixmid-1] = 'I';
00814     chln[nx-1]    = 'I';
00815     Printf(f_out,"              %s",chln.c_str());
00816 
00817 //*-*-               the hardest of all: print x-axis scale!
00818     chln =  " ";
00819     if (nx <= 26) {
00820         Printf(f_out,"        %12.4g%s%12.4g",xlo,chln.c_str(),xup);
00821         Printf(f_out,"              %s%12.4g",chln.c_str(),xsav);
00822     } else {
00823         Printf(f_out,"        %12.4g%s%12.4g%s%12.4g",xlo,chln.c_str(),xsav,chln.c_str(),xup);
00824     }
00825     Printf(f_out,"       X-AXIS: PARAMETER%3d: %s  ONE COLUMN=%12.4g"
00826             ,ke1,fCpnam[ke1-1].c_str(),bwidx);
00827     Printf(f_out," FUNCTION VALUES: F(I)=%12.4g +%12.4g *I**2",fAmin,fUp);
00828 //*-*-                finished.  reset input values
00829     fU[ke1-1] = xsav;
00830     fU[ke2-1] = ysav;
00831     ierrf     = 0;
00832     return;
00833 L1350:
00834     Printf(f_out," INVALID PARAMETER NUMBER(S) REQUESTED.  IGNORED.");
00835     ierrf = 1;
00836 } /* mncntr_ */
00837 
00838 //______________________________________________________________________________
00839 inline
00840 void fitter::mncomd(const std::string& crdbin, int &icondn)
00841 {
00842 //*-*-*-*-*-*-*-*-*-*-*Reads a command string and executes*-*-*-*-*-*-*-*-*-*
00843 //*-*                  ===================================
00844 //*-*        Called by user.  'Reads' a command string and executes.
00845 //*-*     Equivalent to MNEXCM except that the command is given as a
00846 //*-*          character string.
00847 //*-*
00848 //*-*     ICONDN = 0: command executed normally
00849 //*-*              1: command is blank, ignored
00850 //*-*              2: command line unreadable, ignored
00851 //*-*              3: unknown command, ignored
00852 //*-*              4: abnormal termination (e.g., MIGRAD not converged)
00853 //*-*              5: command is a request to read PARAMETER definitions
00854 //*-*              6: 'SET INPUT' command
00855 //*-*              7: 'SET TITLE' command
00856 //*-*              8: 'SET COVAR' command
00857 //*-*              9: reserved
00858 //*-*             10: END command
00859 //*-*             11: EXIT or STOP command
00860 //*-*             12: RETURN command
00861 //*-*
00862 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00863 
00864     static const std::string clower = "abcdefghijklmnopqrstuvwxyz";
00865     static const std::string cupper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
00866 
00867     /* Local variables */
00868     /*static*/ double plist[30];
00869     /*static*/ int ierr, ipos, i, llist, ic, lenbuf, lnc;
00870     /*static*/ bool leader;
00871     /*static*/ std::string comand, crdbuf, ctemp;
00872 
00873     lenbuf = crdbin.size();
00874     crdbuf = crdbin;
00875     icondn = 0;
00876 //*-*-    record not case-sensitive, get upper case, strip leading blanks
00877     leader = true;
00878     ipos = 1;
00879     for (i = 1; i <= TMath_Min(20,lenbuf); ++i) {
00880         if (crdbuf[i-1] == '\'') goto L111;
00881         if (crdbuf[i-1] == ' ') {
00882             if (leader) ++ipos;
00883             continue;
00884         }
00885         leader = false;
00886         for (ic = 1; ic <= 26; ++ic) {
00887             if (crdbuf[i-1] == clower[ic-1]) crdbuf[i-1] = cupper[ic-1];
00888         }
00889     }
00890 L111:
00891 //*-*-                    blank or null command
00892     if (ipos > lenbuf) {
00893         Printf(f_out," BLANK COMMAND IGNORED.");
00894         icondn = 1;
00895         goto L900;
00896     }
00897 //*-*-                                          . .   preemptive commands
00898 //*-*-              if command is 'PARAMETER'
00899     if (msubstr(crdbuf,ipos-1,3) == "PAR") {
00900         icondn = 5;
00901         fLphead = true;
00902         goto L900;
00903     }
00904 //*-*-              if command is 'SET INPUT'
00905     if (msubstr(crdbuf,ipos-1,3) == "SET INP") {
00906         icondn = 6;
00907         fLphead = true;
00908         goto L900;
00909     }
00910 //*-*-              if command is 'SET TITLE'
00911     if (msubstr(crdbuf,ipos-1,7) == "SET TIT") {
00912         icondn = 7;
00913         fLphead = true;
00914         goto L900;
00915     }
00916 //*-*-              if command is 'SET COVARIANCE'
00917     if (msubstr(crdbuf,ipos-1,7) == "SET COV") {
00918         icondn = 8;
00919         fLphead = true;
00920         goto L900;
00921     }
00922 //*-*-              crack the command . . . . . . . . . . . . . . . .
00923     ctemp = msubstr(crdbuf,ipos-1,7);
00924     mncrck(ctemp, 20, comand, lnc, 30, plist, llist, ierr, fIsyswr);
00925     if (ierr > 0) {
00926         Printf(f_out," COMMAND CANNOT BE INTERPRETED");
00927         icondn = 2;
00928         goto L900;
00929     }
00930 
00931     mnexcm(comand, plist, llist, ierr);
00932     icondn = ierr;
00933 L900:
00934     return;
00935 } /* mncomd_ */
00936 
00937 //______________________________________________________________________________
00938 inline
00939 void fitter::mncont(int ke1, int ke2, int nptu, double *xptu, double *yptu, int &ierrf)
00940 {
00941 //*-*-*-*-*-*-*Find points along a contour where FCN is minimum*-*-*-*-*-*-*
00942 //*-*          ================================================
00943 //*-*       Find NPTU points along a contour where the function
00944 //*-*             FMIN (X(KE1),X(KE2)) =  AMIN+UP
00945 //*-*       where FMIN is the minimum of FCN with respect to all
00946 //*-*       the other NPAR-2 variable parameters (if any).
00947 //*-*   IERRF on return will be equal to the number of points found:
00948 //*-*     NPTU if normal termination with NPTU points found
00949 //*-*     -1   if errors in the calling sequence (KE1, KE2 not variable)
00950 //*-*      0   if less than four points can be found (using MNMNOT)
00951 //*-*     n>3  if only n points can be found (n < NPTU)
00952 //*-*
00953 //*-*                 input arguments: parx, pary, devs, ngrid
00954 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00955     /* System generated locals */
00956     int i__1;
00957 
00958     /* Local variables */
00959     double d__1, d__2;
00960     /*static*/ double dist, xdir, ydir, aopt,  u1min, u2min;
00961     /*static*/ double gcc[kMAXDIM], w[kMAXDIM], abest, scalx, scaly;
00962     /*static*/ double a1, a2, val2mi, val2pl, dc, sclfac, bigdis, sigsav;
00963     /*static*/ int nall, iold, line, mpar, ierr, inew, move, next, i, j, nfcol, iercr;
00964     /*static*/ int idist, npcol, kints, i2, i1, lr, nfcnco, ki1, ki2, ki3, ke3;
00965     /*static*/ int nowpts, istrav, nfmxin, isw2, isw4;
00966     /*static*/ bool ldebug;
00967     idist = 0; //GB : rm warning.
00968     nfcnco = 0; //GB : rm warning.
00969 
00970     /* Function Body */
00971     ldebug = fIdbg[6] >= 1;
00972     if (ke1 <= 0 || ke2 <= 0) goto L1350;
00973     if (ke1 > fNu || ke2 > fNu) goto L1350;
00974     ki1 = fNiofex[ke1-1];
00975     ki2 = fNiofex[ke2-1];
00976     if (ki1 <= 0 || ki2 <= 0) goto L1350;
00977     if (ki1 == ki2) goto L1350;
00978     if (nptu < 4)  goto L1400;
00979 
00980     nfcnco  = fNfcn;
00981     fNfcnmx = (nptu + 5)*100*(fNpar + 1);
00982 //*-*-          The minimum
00983     mncuve();
00984     u1min  = fU[ke1-1];
00985     u2min  = fU[ke2-1];
00986     ierrf  = 0;
00987     fCfrom = "MNContour ";
00988     fNfcnfr = nfcnco;
00989     if (fISW[4] >= 0) {
00990         Printf(f_out," START MNCONTOUR CALCULATION OF%4d POINTS ON CONTOUR.",nptu);
00991         if (fNpar > 2) {
00992             if (fNpar == 3) {
00993                 ki3 = 6 - ki1 - ki2;
00994                 ke3 = fNexofi[ki3-1];
00995                 Printf(f_out," EACH POINT IS A MINIMUM WITH RESPECT TO PARAMETER %3d  %s",ke3,fCpnam[ke3-1].c_str());
00996             } else {
00997                 Printf(f_out," EACH POINT IS A MINIMUM WITH RESPECT TO THE OTHER%3d VARIABLE PARAMETERS.",fNpar - 2);
00998             }
00999         }
01000     }
01001 
01002 //*-*-          Find the first four points using MNMNOT
01003 //*-*-             ........................ first two points
01004     mnmnot(ke1, ke2, val2pl, val2mi);
01005     if (fErn[ki1-1] == fUndefi) {
01006         xptu[0] = fAlim[ke1-1];
01007         mnwarn("W", "MNContour ", "Contour squeezed by parameter limits.");
01008     } else {
01009         if (fErn[ki1-1] >= 0) goto L1500;
01010         xptu[0] = u1min + fErn[ki1-1];
01011     }
01012     yptu[0] = val2mi;
01013 
01014     if (fErp[ki1-1] == fUndefi) {
01015         xptu[2] = fBlim[ke1-1];
01016         mnwarn("W", "MNContour ", "Contour squeezed by parameter limits.");
01017     } else {
01018         if (fErp[ki1-1] <= 0) goto L1500;
01019         xptu[2] = u1min + fErp[ki1-1];
01020     }
01021     yptu[2] = val2pl;
01022     scalx = 1 / (xptu[2] - xptu[0]);
01023 //*-*-             ........................... next two points
01024     mnmnot(ke2, ke1, val2pl, val2mi);
01025     if (fErn[ki2-1] == fUndefi) {
01026         yptu[1] = fAlim[ke2-1];
01027         mnwarn("W", "MNContour ", "Contour squeezed by parameter limits.");
01028     } else {
01029         if (fErn[ki2-1] >= 0) goto L1500;
01030         yptu[1] = u2min + fErn[ki2-1];
01031     }
01032     xptu[1] = val2mi;
01033     if (fErp[ki2-1] == fUndefi) {
01034         yptu[3] = fBlim[ke2-1];
01035         mnwarn("W", "MNContour ", "Contour squeezed by parameter limits.");
01036     } else {
01037         if (fErp[ki2-1] <= 0) goto L1500;
01038         yptu[3] = u2min + fErp[ki2-1];
01039     }
01040     xptu[3] = val2pl;
01041     scaly   = 1 / (yptu[3] - yptu[1]);
01042     nowpts  = 4;
01043     next    = 5;
01044     if (ldebug) {
01045         Printf(f_out," Plot of four points found by MINOS");
01046         fXpt[0]  = u1min;
01047         fYpt[0]  = u2min;
01048         fChpt[0] = " ";
01049 //*-*  Computing MIN
01050         nall = TMath_Min(nowpts + 1,101);
01051         for (i = 2; i <= nall; ++i) {
01052             fXpt[i-1] = xptu[i-2];
01053             fYpt[i-1] = yptu[i-2];
01054         }
01055         fChpt[1] = "A";
01056         fChpt[2] = "B";
01057         fChpt[3] = "C";
01058         fChpt[4] = "D";
01059         mnplot(fXpt, fYpt, fChpt, nall, fNpagwd, fNpagln);
01060     }
01061 
01062 //*-*-              ..................... save some values before fixing
01063     isw2   = fISW[1];
01064     isw4   = fISW[3];
01065     sigsav = fEDM;
01066     istrav = fIstrat;
01067     dc     = fDcovar;
01068     fApsi  = fEpsi*.5;
01069     abest  = fAmin;
01070     mpar   = fNpar;
01071     nfmxin = fNfcnmx;
01072     for (i = 1; i <= mpar; ++i) { fXt[i-1] = fX[i-1]; }
01073     i__1 = mpar*(mpar + 1) / 2;
01074     for (j = 1; j <= i__1; ++j) { fVthmat[j-1] = fVhmat[j-1]; }
01075     for (i = 1; i <= mpar; ++i) {
01076         gcc[i-1] = fGlobcc[i-1];
01077         w[i-1] = fWerr[i-1];
01078     }
01079 //*-*-                          fix the two parameters in question
01080     kints = fNiofex[ke1-1];
01081     mnfixp(kints-1, ierr);
01082     kints = fNiofex[ke2-1];
01083     mnfixp(kints-1, ierr);
01084 //*-*-              ......................Fill in the rest of the points
01085     for (inew = next; inew <= nptu; ++inew) {
01086 //*-*            find the two neighbouring points with largest separation
01087         bigdis = 0;
01088         for (iold = 1; iold <= inew - 1; ++iold) {
01089             i2 = iold + 1;
01090             if (i2 == inew) i2 = 1;
01091             d__1 = scalx*(xptu[iold-1] - xptu[i2-1]);
01092             d__2 = scaly*(yptu[iold-1] - yptu[i2-1]);
01093             dist = d__1*d__1 + d__2*d__2;
01094             if (dist > bigdis) {
01095                 bigdis = dist;
01096                 idist  = iold;
01097             }
01098         }
01099         i1 = idist;
01100         i2 = i1 + 1;
01101         if (i2 == inew) i2 = 1;
01102 //*-*-                  next point goes between I1 and I2
01103         a1 = .5;
01104         a2 = .5;
01105 L300:
01106         fXmidcr = a1*xptu[i1-1] + a2*xptu[i2-1];
01107         fYmidcr = a1*yptu[i1-1] + a2*yptu[i2-1];
01108         xdir    = yptu[i2-1] - yptu[i1-1];
01109         ydir    = xptu[i1-1] - xptu[i2-1];
01110         sclfac  = TMath_Max(TMath_Abs(xdir*scalx),TMath_Abs(ydir*scaly));
01111         fXdircr = xdir / sclfac;
01112         fYdircr = ydir / sclfac;
01113         fKe1cr  = ke1;
01114         fKe2cr  = ke2;
01115 //*-*-               Find the contour crossing point along DIR
01116         fAmin = abest;
01117         mncros(aopt, iercr);
01118         if (iercr > 1) {
01119 //*-*-             If cannot find mid-point, try closer to point 1
01120             if (a1 > .5) {
01121                 if (fISW[4] >= 0) {
01122                     Printf(f_out," MNCONT CANNOT FIND NEXT POINT ON CONTOUR.  ONLY%3d POINTS FOUND.",nowpts);
01123                 }
01124                 goto L950;
01125             }
01126             mnwarn("W", "MNContour ", "Cannot find midpoint, try closer.");
01127             a1 = .75;
01128             a2 = .25;
01129             goto L300;
01130         }
01131 //*-*-               Contour has been located, insert new point in list
01132         for (move = nowpts; move >= i1 + 1; --move) {
01133             xptu[move] = xptu[move-1];
01134             yptu[move] = yptu[move-1];
01135         }
01136         ++nowpts;
01137         xptu[i1] = fXmidcr + fXdircr*aopt;
01138         yptu[i1] = fYmidcr + fYdircr*aopt;
01139     }
01140 L950:
01141 
01142     ierrf = nowpts;
01143     fCstatu = "SUCCESSFUL";
01144     if (nowpts < nptu)  fCstatu = "INCOMPLETE";
01145 
01146 //*-*-               make a lineprinter plot of the contour
01147     if (fISW[4] >= 0) {
01148         fXpt[0]  = u1min;
01149         fYpt[0]  = u2min;
01150         fChpt[0] = " ";
01151         nall = TMath_Min(nowpts + 1,101);
01152         for (i = 2; i <= nall; ++i) {
01153             fXpt[i-1]  = xptu[i-2];
01154             fYpt[i-1]  = yptu[i-2];
01155             fChpt[i-1] = "X";
01156         }
01157         Printf(f_out," Y-AXIS: PARAMETER %3d  %s",ke2,fCpnam[ke2-1].c_str());
01158 
01159         mnplot(fXpt, fYpt, fChpt, nall, fNpagwd, fNpagln);
01160 
01161         Printf(f_out,"                         X-AXIS: PARAMETER %3d  %s",ke1,fCpnam[ke1-1].c_str());
01162     }
01163 //*-*-                print out the coordinates around the contour
01164     if (fISW[4] >= 1) {
01165         npcol = (nowpts + 1) / 2;
01166         nfcol = nowpts / 2;
01167         Printf(f_out,"%5d POINTS ON CONTOUR.   FMIN=%13.5e   ERRDEF=%11.3g",nowpts,abest,fUp);
01168         Printf(f_out,"         %s%s%s%s",fCpnam[ke1-1].c_str(),
01169                                   fCpnam[ke2-1].c_str(),
01170                                   fCpnam[ke1-1].c_str(),
01171                                   fCpnam[ke2-1].c_str());
01172         for (line = 1; line <= nfcol; ++line) {
01173             lr = line + npcol;
01174             Printf(f_out," %5d%13.5e%13.5e          %5d%13.5e%13.5e",line,xptu[line-1],yptu[line-1],lr,xptu[lr-1],yptu[lr-1]);
01175         }
01176         if (nfcol < npcol) {
01177             Printf(f_out," %5d%13.5e%13.5e",npcol,xptu[npcol-1],yptu[npcol-1]);
01178         }
01179     }
01180 //*-*-                                   . . contour finished. reset v
01181     fItaur = 1;
01182     mnfree(1);
01183     mnfree(1);
01184     i__1 = mpar*(mpar + 1) / 2;
01185     for (j = 1; j <= i__1; ++j) { fVhmat[j-1] = fVthmat[j-1]; }
01186     for (i = 1; i <= mpar; ++i) {
01187         fGlobcc[i-1] = gcc[i-1];
01188         fWerr[i-1]   = w[i-1];
01189         fX[i-1]      = fXt[i-1];
01190     }
01191     mninex(fX);
01192     fEDM    = sigsav;
01193     fAmin   = abest;
01194     fISW[1] = isw2;
01195     fISW[3] = isw4;
01196     fDcovar = dc;
01197     fItaur  = 0;
01198     fNfcnmx = nfmxin;
01199     fIstrat = istrav;
01200     fU[ke1-1] = u1min;
01201     fU[ke2-1] = u2min;
01202     goto L2000;
01203 //*-*-                                    Error returns
01204 L1350:
01205     Printf(f_out," INVALID PARAMETER NUMBERS.");
01206     goto L1450;
01207 L1400:
01208     Printf(f_out," LESS THAN FOUR POINTS REQUESTED.");
01209 L1450:
01210     ierrf   = -1;
01211     fCstatu = "USER ERROR";
01212     goto L2000;
01213 L1500:
01214     Printf(f_out," MNCONT UNABLE TO FIND FOUR POINTS.");
01215     fU[ke1-1] = u1min;
01216     fU[ke2-1] = u2min;
01217     ierrf     = 0;
01218     fCstatu   = "FAILED";
01219 L2000:
01220     fCfrom  = "MNContour ";
01221     fNfcnfr = nfcnco;
01222 } /* mncont_ */
01223 
01224 //______________________________________________________________________________
01225 inline
01226 void fitter::mncrck(const std::string &crdbuf, int maxcwd, std::string &comand, int &lnc,
01227         int mxp, double *plist, int &llist, int &ierr, int)
01228 {
01229 //*-*-*-*-*-*-*-*-*-*-*-*Cracks the free-format input*-*-*-*-*-*-*-*-*-*-*-*-*
01230 //*-*                    ============================
01231 //*-*       Called from MNREAD.
01232 //*-*       Cracks the free-format input, expecting zero or more
01233 //*-*         alphanumeric fields (which it joins into COMAND(1:LNC))
01234 //*-*         followed by one or more numeric fields separated by
01235 //*-*         blanks and/or one comma.  The numeric fields are put into
01236 //*-*         the LLIST (but at most MXP) elements of PLIST.
01237 //*-*      IERR = 0 if no errors,
01238 //*-*           = 1 if error(s).
01239 //*-*      Diagnostic messages are written to ISYSWR
01240 //*-*
01241 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
01242     /* Initialized data */
01243 
01244     static const std::string cnull  = ")NULL STRING   ";
01245     static const std::string cnumer = "123456789-.0+";
01246 
01247     /* Local variables */
01248     /*static*/ int ifld, iend, lend, left, nreq, ipos, kcmnd, nextb, ic, ibegin, ltoadd;
01249     /*static*/ int ielmnt, lelmnt[25], nelmnt;
01250     /*static*/ std::string celmnt[25], ctemp;
01251 
01252     /* Function Body */
01253     ielmnt = 0;
01254     lend   = crdbuf.size();
01255     nextb  = 1;
01256     ierr   = 0;
01257 //*-*-                                  . . . .  loop over words CELMNT
01258 L10:
01259     for (ipos = nextb; ipos <= lend; ++ipos) {
01260         ibegin = ipos;
01261         if (crdbuf[ipos-1] == ' ') continue;
01262         if (crdbuf[ipos-1] == ',') goto L250;
01263         goto L150;
01264     }
01265     goto L300;
01266 L150:
01267 //*-*-              found beginning of word, look for end
01268     for (ipos = ibegin + 1; ipos <= lend; ++ipos) {
01269         if (crdbuf[ipos-1] == ' ') goto L250;
01270         if (crdbuf[ipos-1] == ',') goto L250;
01271     }
01272     ipos = lend + 1;
01273 L250:
01274     iend = ipos - 1;
01275     ++ielmnt;
01276     if (iend >= ibegin) 
01277       celmnt[ielmnt-1] = msubstr(crdbuf,ibegin-1, iend-ibegin+1);
01278     else                
01279       celmnt[ielmnt-1] = cnull;
01280     lelmnt[ielmnt-1] = iend - ibegin + 1;
01281     if (lelmnt[ielmnt-1] > 19) {
01282         Printf(f_out," MINUIT WARNING: INPUT DATA WORD TOO LONG.");
01283         ctemp = msubstr(crdbuf,ibegin-1,iend-ibegin+1);
01284         Printf(f_out,"     ORIGINAL:%s",ctemp.c_str());
01285         Printf(f_out," TRUNCATED TO:%s",celmnt[ielmnt-1].c_str());
01286         lelmnt[ielmnt-1] = 19;
01287     }
01288     if (ipos >= lend) goto L300;
01289     if (ielmnt >= 25) goto L300;
01290 //*-*-                    look for comma or beginning of next word
01291     for (ipos = iend + 1; ipos <= lend; ++ipos) {
01292         if (crdbuf[ipos-1] == ' ') continue;
01293         nextb = ipos;
01294         if (crdbuf[ipos-1] == ',') nextb = ipos + 1;
01295         goto L10;
01296     }
01297 //*-*-                All elements found, join the alphabetic ones to
01298 //*-*-                               form a command
01299 L300:
01300     nelmnt   = ielmnt;
01301     comand   = " ";
01302     lnc      = 1;
01303     plist[0] = 0;
01304     llist    = 0;
01305     if (ielmnt == 0) goto L900;
01306     kcmnd = 0;
01307     for (ielmnt = 1; ielmnt <= nelmnt; ++ielmnt) {
01308         if ( celmnt[ielmnt-1] == cnull) goto L450;
01309         for (ic = 1; ic <= 13; ++ic) {
01310             if (msubstr(celmnt[ielmnt-1],0,1) == 
01311                 msubstr(cnumer,ic-1,1)) goto L450;
01312         }
01313         if (kcmnd >= maxcwd) continue;
01314         left = maxcwd - kcmnd;
01315         ltoadd = lelmnt[ielmnt-1];
01316         if (ltoadd > left) ltoadd = left;
01317         //comand(kcmnd,ltoadd) = msubstr(celmnt[ielmnt-1],0,ltoadd);
01318         //comand.replace(kcmnd,ltoadd,msubstr(celmnt[ielmnt-1],0,ltoadd));
01319         mreplace(comand,kcmnd,ltoadd,msubstr(celmnt[ielmnt-1],0,ltoadd));
01320         kcmnd += ltoadd;
01321         if (kcmnd == maxcwd) continue;
01322         comand[kcmnd] = ' ';
01323         ++kcmnd;
01324     }
01325     lnc = kcmnd;
01326     goto L900;
01327 L450:
01328     lnc = kcmnd;
01329 //*-*-                     . . . .  we have come to a numeric field
01330     llist = 0;
01331     for (ifld = ielmnt; ifld <= nelmnt; ++ifld) {
01332         ++(llist);
01333         if (llist > mxp) {
01334             nreq = nelmnt - ielmnt + 1;
01335             Printf(f_out," MINUIT WARNING IN MNCRCK: ");
01336             Printf(f_out," COMMAND HAS INPUT%5d NUMERIC FIELDS, BUT MINUIT CAN ACCEPT ONLY%3d",nreq,mxp);
01337             goto L900;
01338         }
01339         if (celmnt[ifld-1] == cnull) plist[llist-1] = 0;
01340         else {
01341             Printf(f_out,"Fatal Error: mnerr code not yet implemented.");
01342         }
01343     }
01344 //*-*-                                 end loop over numeric fields
01345 L900:
01346     if (lnc <= 0) lnc = 1;
01347 } /* mncrck_ */
01348 
01349 //______________________________________________________________________________
01350 inline
01351 void fitter::mncros(double &aopt, int &iercr)
01352 {
01353 //*-*-*-*-*-*-*-*-*-*-*Find point where MNEVAL=AMIN+UP*-*-*-*-*-*-*-*-*-*-*-*
01354 //*-*                  ===============================
01355 //*-*       Find point where MNEVAL=AMIN+UP, along the line through
01356 //*-*       XMIDCR,YMIDCR with direction XDIRCR,YDIRCR,   where X and Y
01357 //*-*       are parameters KE1CR and KE2CR.  If KE2CR=0 (from MINOS),
01358 //*-*       only KE1CR is varied.  From MNCONT, both are varied.
01359 //*-*       Crossing point is at
01360 //*-*        (U(KE1),U(KE2)) = (XMID,YMID) + AOPT*(XDIR,YDIR)
01361 //*-*
01362 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
01363 
01364     static const std::string charal = " .ABCDEFGHIJKLMNOPQRSTUVWXYZ";
01365 
01366     /* Local variables */
01367     /*static*/ double alsb[3], flsb[3], bmin, bmax, zmid, sdev, zdir, zlim;
01368     /*static*/ double coeff[3], aleft, aulim, fdist, adist, aminsv;
01369     /*static*/ double anext, fnext, slope, s1, s2, x1, x2, ecarmn, ecarmx;
01370     /*static*/ double determ, rt, smalla, aright, aim, tla, tlf, dfda,ecart;
01371     /*static*/ int iout, i, ileft, ierev, maxlk, ibest, ik, it;
01372     /*static*/ int noless, iworst, iright, itoohi, kex, ipt;
01373     /*static*/ bool ldebug;
01374     /*static*/ std::string chsign;
01375     x2 = 0;
01376     iout = 0; //GB : rm warning.
01377     iworst = 0; //GB : rm warning.
01378 
01379     ldebug = fIdbg[6] >= 1;
01380     aminsv = fAmin;
01381 //*-*-       convergence when F is within TLF of AIM and next prediction
01382 //*-*-       of AOPT is within TLA of previous value of AOPT
01383     aim      = fAmin + fUp;
01384     tlf      = fUp*.01;
01385     tla      = .01;
01386     fXpt[0]  = 0;
01387     fYpt[0]  = aim;
01388     fChpt[0] = " ";
01389     ipt = 1;
01390     if (fKe2cr == 0) {
01391         fXpt[1]  = -1;
01392         fYpt[1]  = fAmin;
01393         fChpt[1] = ".";
01394         ipt      = 2;
01395     }
01396 //*-*-                   find the largest allowed A
01397     aulim = 100;
01398     for (ik = 1; ik <= 2; ++ik) {
01399         if (ik == 1) {
01400             kex  = fKe1cr;
01401             zmid = fXmidcr;
01402             zdir = fXdircr;
01403         } else {
01404             if (fKe2cr == 0) continue;
01405             kex  = fKe2cr;
01406             zmid = fYmidcr;
01407             zdir = fYdircr;
01408         }
01409         if (fNvarl[kex-1] <= 1) continue;
01410         if (zdir == 0) continue;
01411         zlim = fAlim[kex-1];
01412         if (zdir > 0) zlim = fBlim[kex-1];
01413         aulim = TMath_Min(aulim,(zlim - zmid) / zdir);
01414     }
01415 //*-*-                 LSB = Line Search Buffer
01416 //*-*-         first point
01417     anext   = 0;
01418     aopt    = anext;
01419     fLimset = false;
01420     if (aulim < aopt + tla) fLimset = true;
01421     mneval(anext, fnext, ierev);
01422 //*-* debug printout:
01423     if (ldebug) {
01424         Printf(f_out," MNCROS: calls=%8d   AIM=%10.5f  F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt);
01425     }
01426     if (ierev > 0) goto L900;
01427     if (fLimset && fnext <= aim) goto L930;
01428     ++ipt;
01429     fXpt[ipt-1]  = anext;
01430     fYpt[ipt-1]  = fnext;
01431     fChpt[ipt-1] = msubstr(charal,ipt-1,1);
01432     alsb[0] = anext;
01433     flsb[0] = fnext;
01434     fnext   = TMath_Max(fnext,aminsv + fUp*.1);
01435     aopt    = TMath_Sqrt(fUp / (fnext - aminsv)) - 1;
01436     if (TMath_Abs(fnext - aim) < tlf) goto L800;
01437 
01438     if (aopt < -.5)aopt = -.5;
01439     if (aopt > 1)  aopt = 1;
01440     fLimset = false;
01441     if (aopt > aulim) {
01442         aopt    = aulim;
01443         fLimset = true;
01444     }
01445     mneval(aopt, fnext, ierev);
01446 //*-* debug printout:
01447     if (ldebug) {
01448         Printf(f_out," MNCROS: calls=%8d   AIM=%10.5f  F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt);
01449     }
01450     if (ierev > 0) goto L900;
01451     if (fLimset && fnext <= aim) goto L930;
01452     alsb[1] = aopt;
01453     ++ipt;
01454     fXpt[ipt-1]  = alsb[1];
01455     fYpt[ipt-1]  = fnext;
01456     fChpt[ipt-1] = msubstr(charal,ipt-1,1);
01457     flsb[1]      = fnext;
01458     dfda         = (flsb[1] - flsb[0]) / (alsb[1] - alsb[0]);
01459 //*-*-                  DFDA must be positive on the contour
01460     if (dfda > 0) goto L460;
01461 L300:
01462     mnwarn("D", "MNCROS    ", "Looking for slope of the right sign");
01463     maxlk = 15 - ipt;
01464     for (it = 1; it <= maxlk; ++it) {
01465         alsb[0] = alsb[1];
01466         flsb[0] = flsb[1];
01467         aopt    = alsb[0] + double(it)*.2;
01468         fLimset = false;
01469         if (aopt > aulim) {
01470             aopt    = aulim;
01471             fLimset = true;
01472         }
01473         mneval(aopt, fnext, ierev);
01474 //*-* debug printout:
01475         if (ldebug) {
01476             Printf(f_out," MNCROS: calls=%8d   AIM=%10.5f  F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt);
01477         }
01478         if (ierev > 0) goto L900;
01479         if (fLimset && fnext <= aim) goto L930;
01480         alsb[1] = aopt;
01481         ++ipt;
01482         fXpt[ipt-1]  = alsb[1];
01483         fYpt[ipt-1]  = fnext;
01484         fChpt[ipt-1] = msubstr(charal,ipt-1,1);
01485         flsb[1]      = fnext;
01486         dfda         = (flsb[1] - flsb[0]) / (alsb[1] - alsb[0]);
01487         if (dfda > 0) goto L450;
01488     }
01489     mnwarn("W", "MNCROS    ", "Cannot find slope of the right sign");
01490     goto L950;
01491 L450:
01492 //*-*-                   we have two points with the right slope
01493 L460:
01494     aopt  = alsb[1] + (aim - flsb[1]) / dfda;
01495     fdist = TMath_Min(TMath_Abs(aim - flsb[0]),TMath_Abs(aim - flsb[1]));
01496     adist = TMath_Min(TMath_Abs(aopt - alsb[0]),TMath_Abs(aopt - alsb[1]));
01497     tla = .01;
01498     if (TMath_Abs(aopt) > 1) tla = TMath_Abs(aopt)*.01;
01499     if (adist < tla && fdist < tlf) goto L800;
01500     if (ipt >= 15) goto L950;
01501     bmin = TMath_Min(alsb[0],alsb[1]) - 1;
01502     if (aopt < bmin) aopt = bmin;
01503     bmax = TMath_Max(alsb[0],alsb[1]) + 1;
01504     if (aopt > bmax) aopt = bmax;
01505 //*-*-                   Try a third point
01506     fLimset = false;
01507     if (aopt > aulim) {
01508         aopt    = aulim;
01509         fLimset = true;
01510     }
01511     mneval(aopt, fnext, ierev);
01512 //*-* debug printout:
01513     if (ldebug) {
01514         Printf(f_out," MNCROS: calls=%8d   AIM=%10.5f  F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt);
01515     }
01516     if (ierev > 0) goto L900;
01517     if (fLimset && fnext <= aim) goto L930;
01518     alsb[2] = aopt;
01519     ++ipt;
01520     fXpt[ipt-1]  = alsb[2];
01521     fYpt[ipt-1]  = fnext;
01522     fChpt[ipt-1] = msubstr(charal,ipt-1,1);
01523     flsb[2]      = fnext;
01524 //*-*-               now we have three points, ask how many <AIM
01525     ecarmn = TMath_Abs(fnext-aim);
01526     ibest  = 3;
01527     ecarmx = 0;
01528     noless = 0;
01529     for (i = 1; i <= 3; ++i) {
01530         ecart = TMath_Abs(flsb[i-1] - aim);
01531         if (ecart > ecarmx) { ecarmx = ecart; iworst = i; }
01532         if (ecart < ecarmn) { ecarmn = ecart; ibest = i; }
01533         if (flsb[i-1] < aim) ++noless;
01534     }
01535 //*-*-          if at least one on each side of AIM, fit a parabola
01536     if (noless == 1 || noless == 2) goto L500;
01537 //*-*-          if all three are above AIM, third must be closest to AIM
01538     if (noless == 0 && ibest != 3) goto L950;
01539 //*-*-          if all three below, and third is not best, then slope
01540 //*-*-            has again gone negative, look for positive slope.
01541     if (noless == 3 && ibest != 3) {
01542         alsb[1] = alsb[2];
01543         flsb[1] = flsb[2];
01544         goto L300;
01545     }
01546 //*-*-          in other cases, new straight line thru last two points
01547     alsb[iworst-1] = alsb[2];
01548     flsb[iworst-1] = flsb[2];
01549     dfda = (flsb[1] - flsb[0]) / (alsb[1] - alsb[0]);
01550     goto L460;
01551 //*-*-               parabola fit
01552 L500:
01553     mnpfit(alsb, flsb, 3, coeff, sdev);
01554     if (coeff[2] <= 0) {
01555         mnwarn("D", "MNCROS    ", "Curvature is negative near contour line.");
01556     }
01557     determ = coeff[1]*coeff[1] - coeff[2]*4*(coeff[0] - aim);
01558     if (determ <= 0) {
01559         mnwarn("D", "MNCROS    ", "Problem 2, impossible determinant");
01560         goto L950;
01561     }
01562 //*-*-               Find which root is the right one
01563     rt = TMath_Sqrt(determ);
01564     x1 = (-coeff[1] + rt) / (coeff[2]*2);
01565     x2 = (-coeff[1] - rt) / (coeff[2]*2);
01566     s1 = coeff[1] + x1*2*coeff[2];
01567     s2 = coeff[1] + x2*2*coeff[2];
01568     if (s1*s2 > 0) {
01569         Printf(f_out," MNCONTour problem 1");
01570     }
01571     aopt  = x1;
01572     slope = s1;
01573     if (s2 > 0) {
01574         aopt  = x2;
01575         slope = s2;
01576     }
01577 //*-*-        ask if converged
01578     tla = .01;
01579     if (TMath_Abs(aopt) > 1) tla = TMath_Abs(aopt)*.01;
01580     if (TMath_Abs(aopt - alsb[ibest-1]) < tla && TMath_Abs(flsb[ibest-1] - aim) < tlf) {
01581         goto L800;
01582     }
01583     if (ipt >= 15) goto L950;
01584 
01585 //*-*-        see if proposed point is in acceptable zone between L and R
01586 //*-*-        first find ILEFT, IRIGHT, IOUT and IBEST
01587     ileft  = 0;
01588     iright = 0;
01589     ibest  = 1;
01590     ecarmx = 0;
01591     ecarmn = TMath_Abs(aim - flsb[0]);
01592     for (i = 1; i <= 3; ++i) {
01593         ecart = TMath_Abs(flsb[i-1] - aim);
01594         if (ecart < ecarmn) { ecarmn = ecart; ibest = i; }
01595         if (ecart > ecarmx) { ecarmx = ecart; }
01596         if (flsb[i-1] > aim) {
01597             if (iright == 0) iright = i;
01598             else if (flsb[i-1] > flsb[iright-1]) iout = i;
01599             else { iout = iright; iright = i; }
01600         }
01601         else if (ileft == 0) ileft = i;
01602         else if (flsb[i-1] < flsb[ileft-1]) iout = i;
01603         else { iout = ileft; ileft = i; }
01604     }
01605 //*-*-      avoid keeping a very bad point next time around
01606     if (ecarmx > TMath_Abs(flsb[iout-1] - aim)*10) {
01607         aopt = aopt*.5 + (alsb[iright-1] + alsb[ileft-1])*.25;
01608     }
01609 //*-*-        knowing ILEFT and IRIGHT, get acceptable window
01610     smalla = tla*.1;
01611     if (slope*smalla > tlf) smalla = tlf / slope;
01612     aleft  = alsb[ileft-1] + smalla;
01613     aright = alsb[iright-1] - smalla;
01614 //*-*-        move proposed point AOPT into window if necessary
01615     if (aopt < aleft)   aopt = aleft;
01616     if (aopt > aright)  aopt = aright;
01617     if (aleft > aright) aopt = (aleft + aright)*.5;
01618 
01619 //*-*-        see if proposed point outside limits (should be impossible!)
01620     fLimset = false;
01621     if (aopt > aulim) {
01622         aopt    = aulim;
01623         fLimset = true;
01624     }
01625 //*-*-                 Evaluate function at new point AOPT
01626     mneval(aopt, fnext, ierev);
01627 //*-* debug printout:
01628     if (ldebug) {
01629         Printf(f_out," MNCROS: calls=%8d   AIM=%10.5f  F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt);
01630     }
01631     if (ierev > 0) goto L900;
01632     if (fLimset && fnext <= aim) goto L930;
01633     ++ipt;
01634     fXpt[ipt-1]  = aopt;
01635     fYpt[ipt-1]  = fnext;
01636     fChpt[ipt-1] = msubstr(charal,ipt-1,1);
01637 //*-*-               Replace odd point by new one
01638     alsb[iout-1] = aopt;
01639     flsb[iout-1] = fnext;
01640 //*-*-         the new point may not be the best, but it is the only one
01641 //*-*-         which could be good enough to pass convergence criteria
01642     ibest = iout;
01643     goto L500;
01644 
01645 //*-*-      Contour has been located, return point to MNCONT OR MINOS
01646 L800:
01647     iercr = 0;
01648     goto L1000;
01649 //*-*-               error in the minimization
01650 L900:
01651     if (ierev == 1) goto L940;
01652     goto L950;
01653 //*-*-               parameter up against limit
01654 L930:
01655     iercr = 1;
01656     goto L1000;
01657 //*-*-               too many calls to FCN
01658 L940:
01659     iercr = 2;
01660     goto L1000;
01661 //*-*-               cannot find next point
01662 L950:
01663     iercr = 3;
01664 //*-*-               in any case
01665 L1000:
01666     if (ldebug) {
01667         itoohi = 0;
01668         for (i = 1; i <= ipt; ++i) {
01669             if (fYpt[i-1] > aim + fUp) {
01670                 fYpt[i-1]  = aim + fUp;
01671                 fChpt[i-1] = "+";
01672                 itoohi     = 1;
01673             }
01674         }
01675         chsign = "POSI";
01676         if (fXdircr < 0) chsign = "NEGA";
01677         if (fKe2cr == 0) {
01678             Printf(f_out,"  %sTIVE MINOS ERROR, PARAMETER %3d",
01679                    chsign.c_str(),fKe1cr);
01680         }
01681         if (itoohi == 1) {
01682             Printf(f_out,"POINTS LABELLED '+' WERE TOO HIGH TO PLOT.");
01683         }
01684         if (iercr == 1) {
01685             Printf(f_out,"RIGHTMOST POINT IS UP AGAINST LIMIT.");
01686         }
01687         mnplot(fXpt, fYpt, fChpt, ipt, fNpagwd, fNpagln);
01688     }
01689 } /* mncros_ */
01690 
01691 //______________________________________________________________________________
01692 inline
01693 void fitter::mncuve()
01694 {
01695 //*-*-*-*-*-*-*-*Makes sure that the current point is a local minimum*-*-*-*-*
01696 //*-*            ====================================================
01697 //*-*        Makes sure that the current point is a local
01698 //*-*        minimum and that the error matrix exists,
01699 //*-*        or at least something good enough for MINOS and MNCONT
01700 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
01701 
01702     /* Local variables */
01703     /*static*/ double dxdi, wint;
01704     /*static*/ int ndex, iext, i, j;
01705 
01706     if (fISW[3] < 1) {
01707         Printf(f_out," FUNCTION MUST BE MINIMIZED BEFORE CALLING %s",fCfrom.c_str());
01708         fApsi = fEpsi;
01709         mnmigr();
01710     }
01711     if (fISW[1] < 3) {
01712         mnhess();
01713         if (fISW[1] < 1) {
01714             mnwarn("W", fCfrom.c_str(), "NO ERROR MATRIX.  WILL IMPROVISE.");
01715             for (i = 1; i <= fNpar; ++i) {
01716                 ndex = i*(i-1) / 2;
01717                 for (j = 1; j <= i-1; ++j) {
01718                     ++ndex;
01719                     fVhmat[ndex-1] = 0;
01720                 }
01721                 ++ndex;
01722                 if (fG2[i-1] <= 0) {
01723                     wint = fWerr[i-1];
01724                     iext = fNexofi[i-1];
01725                     if (fNvarl[iext-1] > 1) {
01726                         mndxdi(fX[i-1], i-1, dxdi);
01727                         if (TMath_Abs(dxdi) < .001) wint = .01;
01728                         else                   wint /= TMath_Abs(dxdi);
01729                     }
01730                     fG2[i-1] = fUp / (wint*wint);
01731                 }
01732                 fVhmat[ndex-1] = 2 / fG2[i-1];
01733             }
01734             fISW[1] = 1;
01735             fDcovar = 1;
01736         } else  mnwerr();
01737     }
01738 } /* mncuve_ */
01739 
01740 //______________________________________________________________________________
01741 inline
01742 bool fitter::mnderi() //GB : return a bool.
01743 {
01744 //*-*-*-*-*-*-*-*Calculates the first derivatives of FCN (GRD)*-*-*-*-*-*-*-*
01745 //*-*            =============================================
01746 //*-*        Calculates the first derivatives of FCN (GRD),
01747 //*-*        either by finite differences or by transforming the user-
01748 //*-*        supplied derivatives to internal coordinates,
01749 //*-*        according to whether ISW(3) is zero or one.
01750 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
01751 
01752     /* Local variables */
01753     /*static*/ double step, dfmin, stepb4, dd, df, fs1;
01754     /*static*/ double tlrstp, tlrgrd, epspri, optstp, stpmax, stpmin, fs2, grbfor, d1d2, xtf;
01755     /*static*/ int icyc, ncyc, iint, iext, i, nparx;
01756     /*static*/ bool ldebug;
01757     grbfor = 0; //GB
01758 
01759     nparx = fNpar;
01760     ldebug = fIdbg[2] >= 1;
01761     if (fAmin == fUndefi) mnamin();
01762     if (fISW[2] == 1) goto L100;
01763 
01764     if (ldebug) {
01765 //*-*-                      make sure starting at the right place
01766         mninex(fX);
01767         nparx = fNpar;
01768         if(!(*fFCN)(nparx, fGin, fs1, fU, 4,fTag)) return false;
01769         ++fNfcn;
01770         if (fs1 != fAmin) {
01771             df    = fAmin - fs1;
01772             mnwarn("D", "MNDERI", Form("function value differs from AMIN by %12.3g",df));
01773             fAmin = fs1;
01774         }
01775         Printf(f_out,"  FIRST DERIVATIVE DEBUG PRINTOUT.  MNDERI");
01776         Printf(f_out," PAR    DERIV     STEP      MINSTEP   OPTSTEP  D1-D2    2ND DRV");
01777     }
01778     dfmin = fEpsma2*8*(TMath_Abs(fAmin) + fUp);
01779     if (fIstrat <= 0) {
01780         ncyc   = 2;
01781         tlrstp = .5;
01782         tlrgrd = .1;
01783     } else if (fIstrat == 1) {
01784         ncyc   = 3;
01785         tlrstp = .3;
01786         tlrgrd = .05;
01787     } else {
01788         ncyc   = 5;
01789         tlrstp = .1;
01790         tlrgrd = .02;
01791     }
01792 //*-*-                               loop over variable parameters
01793     for (i = 1; i <= fNpar; ++i) {
01794         epspri = fEpsma2 + TMath_Abs(fGrd[i-1]*fEpsma2);
01795 //*-*-        two-point derivatives always assumed necessary
01796 //*-*-        maximum number of cycles over step size depends on strategy
01797         xtf = fX[i-1];
01798         stepb4 = 0;
01799 //*-*-                              loop as little as possible here!/
01800         for (icyc = 1; icyc <= ncyc; ++icyc) {
01801 //*-*-                ........ theoretically best step
01802             optstp = TMath_Sqrt(dfmin / (TMath_Abs(fG2[i-1]) + epspri));
01803 //*-*-                    step cannot decrease by more than a factor of ten
01804             step = TMath_Max(optstp,TMath_Abs(fGstep[i-1]*.1));
01805 //*-*-                but if parameter has limits, max step size = 0.5
01806             if (fGstep[i-1] < 0 && step > .5) step = .5;
01807 //*-*-                and not more than ten times the previous step
01808             stpmax = TMath_Abs(fGstep[i-1])*10;
01809             if (step > stpmax) step = stpmax;
01810 //*-*-                minimum step size allowed by machine precision
01811             stpmin = TMath_Abs(fEpsma2*fX[i-1])*8;
01812             if (step < stpmin) step = stpmin;
01813 //*-*-                end of iterations if step change less than factor 2
01814             if (TMath_Abs((step - stepb4) / step) < tlrstp) goto L50;
01815 //*-*-        take step positive
01816             stepb4 = step;
01817             if (fGstep[i-1] > 0) fGstep[i-1] =  TMath_Abs(step);
01818             else                 fGstep[i-1] = -TMath_Abs(step);
01819             stepb4  = step;
01820             fX[i-1] = xtf + step;
01821             mninex(fX);
01822             if(!(*fFCN)(nparx, fGin, fs1, fU, 4,fTag)) return false; //GB
01823             ++fNfcn;
01824 //*-*-        take step negative
01825             fX[i-1] = xtf - step;
01826             mninex(fX);
01827             if(!(*fFCN)(nparx, fGin, fs2, fU, 4,fTag)) return false; //GB
01828             ++fNfcn;
01829             grbfor = fGrd[i-1];
01830             fGrd[i-1] = (fs1 - fs2) / (step*2);
01831             fG2[i-1]  = (fs1 + fs2 - fAmin*2) / (step*step);
01832             fX[i-1]   = xtf;
01833             if (ldebug) {
01834                 d1d2 = (fs1 + fs2 - fAmin*2) / step;
01835                 Printf(f_out,"%4d%11.3g%11.3g%10.2g%10.2g%10.2g%10.2g%10.2g",i,fGrd[i-1],step,stpmin,optstp,d1d2,fG2[i-1]);
01836             }
01837 //*-*-        see if another iteration is necessary
01838             if (TMath_Abs(grbfor - fGrd[i-1]) / (TMath_Abs(fGrd[i-1]) + dfmin/step) < tlrgrd)
01839                 goto L50;
01840         }
01841 //*-*-                          end of ICYC loop. too many iterations
01842         if (ncyc == 1) goto L50;
01843         mnwarn("D", "MNDERI", Form("First derivative not converged. %g%g",fGrd[i-1],grbfor));
01844 L50:
01845         ;
01846     }
01847     mninex(fX);
01848     return true;
01849 //*-*-                                       .  derivatives calc by fcn
01850 L100:
01851     for (iint = 1; iint <= fNpar; ++iint) {
01852         iext = fNexofi[iint-1];
01853         if (fNvarl[iext-1] <= 1) {
01854            fGrd[iint-1] = fGin[iext-1];
01855         } else {
01856            dd = (fBlim[iext-1] - fAlim[iext-1])*.5*TMath_Cos(fX[iint-1]);
01857            fGrd[iint-1] = fGin[iext-1]*dd;
01858         }
01859     }
01860     return true;
01861 } /* mnderi_ */
01862 
01863 //______________________________________________________________________________
01864 inline
01865 void fitter::mndxdi(double pint, int ipar, double &dxdi)
01866 {
01867 //*-*-*-*Calculates the transformation factor between ext/internal values*-*
01868 //*-*    =====================================================================
01869 //*-*        calculates the transformation factor between external and
01870 //*-*        internal parameter values.     this factor is one for
01871 //*-*        parameters which are not limited.     called from MNEMAT.
01872 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
01873 
01874     int i = fNexofi[ipar];
01875     dxdi = 1;
01876     if (fNvarl[i-1] > 1) {
01877         dxdi = TMath_Abs((fBlim[i-1] - fAlim[i-1])*TMath_Cos(pint))*.5;
01878     }
01879 } /* mndxdi_ */
01880 
01881 //______________________________________________________________________________
01882 inline
01883 void fitter::mneig(double *a, int ndima, int n, int mits, double *work, double precis, int &ifault)
01884 {
01885 //*-*-*-*-*-*-*-*-*-*-*-*Compute matrix eigen values*-*-*-*-*-*-*-*-*-*-*-*-*
01886 //*-*                    ===========================
01887     /* System generated locals */
01888     int a_offset;
01889     double d__1;
01890 
01891     /* Local variables */
01892     /*static*/ double b, c, f, h, r, s, hh, gl, pr, pt;
01893     /*static*/ int i, j, k, l, m, i0, i1, j1, m1, n1;
01894     m = 0; //GB : rm warning.
01895 
01896 //*-*-         PRECIS is the machine precision EPSMAC
01897     /* Parameter adjustments */
01898     a_offset = ndima + 1;
01899     a -= a_offset;
01900     --work;
01901 
01902     /* Function Body */
01903     ifault = 1;
01904 
01905     i = n;
01906     for (i1 = 2; i1 <= n; ++i1) {
01907         l  = i-2;
01908         f  = a[i + (i-1)*ndima];
01909         gl = 0;
01910 
01911         if (l < 1) goto L25;
01912 
01913         for (k = 1; k <= l; ++k) {
01914             d__1 = a[i + k*ndima];
01915             gl  += d__1*d__1;
01916         }
01917 L25:
01918         h = gl + f*f;
01919 
01920         if (gl > 1e-35) goto L30;
01921 
01922         work[i]     = 0;
01923         work[n + i] = f;
01924         goto L65;
01925 L30:
01926         ++l;
01927         gl = TMath_Sqrt(h);
01928         if (f >= 0) gl = -gl;
01929         work[n + i] = gl;
01930         h -= f*gl;
01931         a[i + (i-1)*ndima] = f - gl;
01932         f = 0;
01933         for (j = 1; j <= l; ++j) {
01934             a[j + i*ndima] = a[i + j*ndima] / h;
01935             gl = 0;
01936             for (k = 1; k <= j; ++k) { gl += a[j + k*ndima]*a[i + k*ndima]; }
01937             if (j >= l) goto L47;
01938             j1 = j + 1;
01939             for (k = j1; k <= l; ++k) { gl += a[k + j*ndima]*a[i + k*ndima]; }
01940 L47:
01941             work[n + j] = gl / h;
01942             f += gl*a[j + i*ndima];
01943         }
01944         hh = f / (h + h);
01945         for (j = 1; j <= l; ++j) {
01946             f  = a[i + j*ndima];
01947             gl = work[n + j] - hh*f;
01948             work[n + j] = gl;
01949             for (k = 1; k <= j; ++k) {
01950                 a[j + k*ndima] = a[j + k*ndima] - f*work[n + k] - gl*a[i + k*ndima];
01951             }
01952         }
01953         work[i] = h;
01954 L65:
01955         --i;
01956     }
01957     work[1] = 0;
01958     work[n + 1] = 0;
01959     for (i = 1; i <= n; ++i) {
01960         l = i-1;
01961         if (work[i] == 0 || l == 0) goto L100;
01962 
01963         for (j = 1; j <= l; ++j) {
01964             gl = 0;
01965             for (k = 1; k <= l; ++k) { gl += a[i + k*ndima]*a[k + j*ndima]; }
01966             for (k = 1; k <= l; ++k) { a[k + j*ndima] -= gl*a[k + i*ndima]; }
01967         }
01968 L100:
01969         work[i] = a[i + i*ndima];
01970         a[i + i*ndima] = 1;
01971         if (l == 0) continue;
01972 
01973         for (j = 1; j <= l; ++j) {
01974             a[i + j*ndima] = 0;
01975             a[j + i*ndima] = 0;
01976         }
01977     }
01978 
01979     n1 = n - 1;
01980     for (i = 2; i <= n; ++i) {
01981         i0 = n + i-1;
01982         work[i0] = work[i0 + 1];
01983     }
01984     work[n + n] = 0;
01985     b = 0;
01986     f = 0;
01987     for (l = 1; l <= n; ++l) {
01988         j = 0;
01989         h = precis*(TMath_Abs(work[l]) + TMath_Abs(work[n + l]));
01990         if (b < h) b = h;
01991         for (m1 = l; m1 <= n; ++m1) {
01992             m = m1;
01993             if (TMath_Abs(work[n + m]) <= b)    goto L150;
01994         }
01995 
01996 L150:
01997         if (m == l) goto L205;
01998 
01999 L160:
02000         if (j == mits) return;
02001         ++j;
02002         pt = (work[l + 1] - work[l]) / (work[n + l]*2);
02003         r  = TMath_Sqrt(pt*pt + 1);
02004         pr = pt + r;
02005         if (pt < 0) pr = pt - r;
02006 
02007         h = work[l] - work[n + l] / pr;
02008         for (i = l; i <= n; ++i) { work[i] -= h; }
02009         f += h;
02010         pt = work[m];
02011         c  = 1;
02012         s  = 0;
02013         m1 = m - 1;
02014         i  = m;
02015         for (i1 = l; i1 <= m1; ++i1) {
02016             j = i;
02017             --i;
02018             gl = c*work[n + i];
02019             h  = c*pt;
02020             if (TMath_Abs(pt) >= TMath_Abs(work[n + i])) goto L180;
02021 
02022             c = pt / work[n + i];
02023             r = TMath_Sqrt(c*c + 1);
02024             work[n + j] = s*work[n + i]*r;
02025             s  = 1 / r;
02026             c /= r;
02027             goto L190;
02028 L180:
02029             c = work[n + i] / pt;
02030             r = TMath_Sqrt(c*c + 1);
02031             work[n + j] = s*pt*r;
02032             s = c / r;
02033             c = 1 / r;
02034 L190:
02035             pt = c*work[i] - s*gl;
02036             work[j] = h + s*(c*gl + s*work[i]);
02037             for (k = 1; k <= n; ++k) {
02038                 h = a[k + j*ndima];
02039                 a[k + j*ndima] = s*a[k + i*ndima] + c*h;
02040                 a[k + i*ndima] = c*a[k + i*ndima] - s*h;
02041             }
02042         }
02043         work[n + l] = s*pt;
02044         work[l]     = c*pt;
02045 
02046         if (TMath_Abs(work[n + l]) > b) goto L160;
02047 
02048 L205:
02049         work[l] += f;
02050     }
02051     for (i = 1; i <= n1; ++i) {
02052         k  = i;
02053         pt = work[i];
02054         i1 = i + 1;
02055         for (j = i1; j <= n; ++j) {
02056             if (work[j] >= pt) continue;
02057             k  = j;
02058             pt = work[j];
02059         }
02060 
02061         if (k == i) continue;
02062 
02063         work[k] = work[i];
02064         work[i] = pt;
02065         for (j = 1; j <= n; ++j) {
02066             pt = a[j + i*ndima];
02067             a[j + i*ndima] = a[j + k*ndima];
02068             a[j + k*ndima] = pt;
02069         }
02070     }
02071     ifault = 0;
02072 } /* mneig_ */
02073 
02074 //______________________________________________________________________________
02075 inline
02076 void fitter::mnemat(double *emat, int ndim)
02077 {
02078 //*-*-*-*-*-*Calculates the external error matrix from the internal matrix*-*
02079 //*-*        =============================================================
02080 //*-*        Calculates the external error matrix from the internal
02081 //*-*        to be called by user.
02082 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
02083 
02084     /* System generated locals */
02085     int emat_dim1, emat_offset;
02086 
02087     /* Local variables */
02088     /*static*/ double dxdi, dxdj;
02089     /*static*/ int i, j, k, npard, k2, kk, iz, nperln, kga, kgb;
02090     /*static*/ std::string ctemp;
02091 
02092     /* Parameter adjustments */
02093     emat_dim1 = ndim;
02094     emat_offset = emat_dim1 + 1;
02095     emat -= emat_offset;
02096 
02097     /* Function Body */
02098     if (fISW[1] < 1) return;
02099     if (fISW[4] >= 2) {
02100         Printf(f_out," EXTERNAL ERROR MATRIX.    NDIM=%4d    NPAR=%3d    ERR DEF=%g",ndim,fNpar,fUp);
02101     }
02102 //*-*-                   size of matrix to be printed
02103     npard = fNpar;
02104     if (ndim < fNpar) {
02105         npard = ndim;
02106         if (fISW[4] >= 0) {
02107             Printf(f_out," USER-DIMENSIONED  ARRAY EMAT NOT BIG ENOUGH. REDUCED MATRIX CALCULATED.");
02108         }
02109     }
02110 //*-*-                NPERLN is the number of elements that fit on one line
02111 
02112     nperln = (fNpagwd - 5) / 10;
02113     nperln = TMath_Min(nperln,13);
02114     if (fISW[4] >= 1 && npard > nperln) {
02115         Printf(f_out," ELEMENTS ABOVE DIAGONAL ARE NOT PRINTED.");
02116     }
02117 //*-*-                I counts the rows of the matrix
02118     for (i = 1; i <= npard; ++i) {
02119         mndxdi(fX[i-1], i-1, dxdi);
02120         kga = i*(i-1) / 2;
02121         for (j = 1; j <= i; ++j) {
02122             mndxdi(fX[j-1], j-1, dxdj);
02123             kgb = kga + j;
02124             emat[i + j*emat_dim1] = dxdi*fVhmat[kgb-1]*dxdj*fUp;
02125             emat[j + i*emat_dim1] = emat[i + j*emat_dim1];
02126         }
02127     }
02128 //*-*-                   IZ is number of columns to be printed in row I
02129     if (fISW[4] >= 2) {
02130         for (i = 1; i <= npard; ++i) {
02131             iz = npard;
02132             if (npard >= nperln) iz = i;
02133             ctemp = " ";
02134             for (k = 1; nperln < 0 ? k >= iz : k <= iz; k += nperln) {
02135                 k2 = k + nperln - 1;
02136                 if (k2 > iz) k2 = iz;
02137                 for (kk = k; kk <= k2; ++kk) {
02138                     ctemp += Form("%10.3e ",emat[i + kk*emat_dim1]);
02139                 }
02140                 Printf(f_out,"%s",ctemp.c_str());
02141             }
02142         }
02143     }
02144 } /* mnemat_ */
02145 
02146 //______________________________________________________________________________
02147 inline
02148 void fitter::mnerrs(int number, double &eplus, double &eminus, double &eparab, double &gcc)
02149 {
02150 //*-*-*-*-*-*-*-*-*-*Utility routine to get MINOS errors*-*-*-*-*-*-*-*-*-*-*
02151 //*-*                ===================================
02152 //*-*    Called by user.
02153 //*-*    NUMBER is the parameter number
02154 //*-*    values returned by MNERRS:
02155 //*-*       EPLUS, EMINUS are MINOS errors of parameter NUMBER,
02156 //*-*       EPARAB is 'parabolic' error (from error matrix).
02157 //*-*                 (Errors not calculated are set = 0)
02158 //*-*       GCC is global correlation coefficient from error matrix
02159 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
02160 
02161     /*static*/ double dxdi;
02162     /*static*/ int ndiag, iin, iex;
02163 
02164     iex = number+1;
02165 
02166     if (iex > fNu || iex <= 0) goto L900;
02167     iin = fNiofex[iex-1];
02168     if (iin <= 0) goto L900;
02169 
02170 //*-*-            IEX is external number, IIN is internal number
02171     eplus  = fErp[iin-1];
02172     if (eplus == fUndefi)  eplus = 0;
02173     eminus = fErn[iin-1];
02174     if (eminus == fUndefi) eminus = 0;
02175     mndxdi(fX[iin-1], iin-1, dxdi);
02176     ndiag  = iin*(iin + 1) / 2;
02177     eparab = TMath_Abs(dxdi*TMath_Sqrt(TMath_Abs(fUp*fVhmat[ndiag- 1])));
02178 //*-*-             global correlation coefficient
02179     gcc = 0;
02180     if (fISW[1] < 2) return;
02181     gcc = fGlobcc[iin-1];
02182     return;
02183 //*-*-                 ERROR.  parameter number not valid
02184 L900:
02185     eplus  = 0;
02186     eminus = 0;
02187     eparab = 0;
02188     gcc    = 0;
02189 } /* mnerrs_ */
02190 
02191 //______________________________________________________________________________
02192 inline
02193 void fitter::mneval(double anext, double &fnext, int &ierev)
02194 {
02195 //*-*-*-*-*-*-*Evaluates the function being analyzed by MNCROS*-*-*-*-*-*-*-*
02196 //*-*          ===============================================
02197 //*-*      Evaluates the function being analyzed by MNCROS, which is
02198 //*-*      generally the minimum of FCN with respect to all remaining
02199 //*-*      variable parameters.  The class data members contains the
02200 //*-*      data necessary to know the values of U(KE1CR) and U(KE2CR)
02201 //*-*      to be used, namely     U(KE1CR) = XMIDCR + ANEXT*XDIRCR
02202 //*-*      and (if KE2CR .NE. 0)  U(KE2CR) = YMIDCR + ANEXT*YDIRCR
02203 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
02204 
02205     /*static*/ int nparx;
02206 
02207     fU[fKe1cr-1] = fXmidcr + anext*fXdircr;
02208     if (fKe2cr != 0) fU[fKe2cr-1] = fYmidcr + anext*fYdircr;
02209     mninex(fX);
02210     nparx = fNpar;
02211     //Printf(f_out,"debug : FCN : 007");
02212     (*fFCN)(nparx, fGin, fnext, fU, 4,fTag);    ++fNfcn;
02213     ierev = 0;
02214     if (fNpar > 0) {
02215         fItaur = 1;
02216         fAmin = fnext;
02217         fISW[0] = 0;
02218         mnmigr();
02219         fItaur = 0;
02220         fnext = fAmin;
02221         if (fISW[0] >= 1) ierev = 1;
02222         if (fISW[3] < 1)  ierev = 2;
02223     }
02224 } /* mneval_ */
02225 
02226 //______________________________________________________________________________
02227 //GB : const for plist.
02228 inline
02229 void fitter::mnexcm(const std::string& comand, const double *plist, int llist, int &ierflg)
02230 {
02231 //*-*-*-*-*-*Interprets a command and takes appropriate action*-*-*-*-*-*-*-*
02232 //*-*        =================================================
02233 //*-*        either directly by skipping to the corresponding code in
02234 //*-*        MNEXCM, or by setting up a call to a function
02235 //*-*
02236 //*-*  recognized MINUIT commands:
02237 //*-*  obsolete commands:
02238 //*-*      IERFLG is now (94.5) defined the same as ICONDN in MNCOMD
02239 //*-*            = 0: command executed normally
02240 //*-*              1: command is blank, ignored
02241 //*-*              2: command line unreadable, ignored
02242 //*-*              3: unknown command, ignored
02243 //*-*              4: abnormal termination (e.g., MIGRAD not converged)
02244 //*-*              9: reserved
02245 //*-*             10: END command
02246 //*-*             11: EXIT or STOP command
02247 //*-*             12: RETURN command
02248 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
02249 
02250     /* Initialized data */
02251 
02252     static const std::string clower = "abcdefghijklmnopqrstuvwxyz";
02253     static const std::string cupper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
02254     static const std::string cname[40] = {
02255       "MINImize  ",
02256       "SEEk      ",
02257       "SIMplex   ",
02258       "MIGrad    ",
02259       "MINOs     ",
02260       "SET xxx   ",
02261       "SHOw xxx  ",
02262       "TOP of pag",
02263       "FIX       ",
02264       "REStore   ",
02265       "RELease   ",
02266       "SCAn      ",
02267       "CONtour   ",
02268       "HESse     ",
02269       "SAVe      ",
02270       "IMProve   ",
02271       "CALl fcn  ",
02272       "STAndard  ",
02273       "END       ",
02274       "EXIt      ",
02275       "RETurn    ",
02276       "CLEar     ",
02277       "HELP      ",
02278       "MNContour ",
02279       "STOp      ",
02280       "JUMp      ",
02281       "          ",
02282       "          ",
02283       "          ",
02284       "          ",
02285       "          ",
02286       "          ",
02287       "          ",
02288       "COVARIANCE",
02289       "PRINTOUT  ",
02290       "GRADIENT  ",
02291       "MATOUT    ",
02292       "ERROR DEF ",
02293       "LIMITS    ",
02294       "PUNCH     "};
02295 
02296     /*static*/ int nntot = 40;
02297 
02298     /* Local variables */
02299     /*static*/ double step, xptu[101], yptu[101], f, rno;
02300     /*static*/ int icol, kcol, ierr, iint, iext, lnow, nptu, i, iflag, ierrf;
02301     /*static*/ int ilist, nparx, izero, nf, lk, it, iw, inonde, nsuper;
02302     /*static*/ int it2, ke1, ke2, nowprt, kll, let, krl;
02303     /*static*/ std::string chwhy, c26, cvblnk, cneway, comd;
02304     /*static*/ std::string ctemp;
02305     /*static*/ bool lfreed, ltofix, lfixed;
02306 
02307 //*-*  alphabetical order of command names!
02308 
02309     /* Function Body */
02310 
02311     lk = comand.size();
02312     if (lk > 20) lk = 20;
02313     fCword =  comand;
02314 //*-*-             get upper case
02315     for (icol = 1; icol <= lk; ++icol) {
02316         for (let = 1; let <= 26; ++let) {
02317             if (fCword[icol-1] == clower[let-1]) {
02318                 fCword[icol-1] = cupper[let-1];
02319             }
02320         }
02321     }
02322 //*-*-          Copy the first MAXP arguments into WORD7, making
02323 //*-*-          sure that WORD7(1)=0 if LLIST=0
02324     for (iw = 1; iw <= 30; ++iw) {
02325         fWord7[iw-1] = 0;
02326         if (iw <= llist) fWord7[iw-1] = plist[iw-1];
02327     }
02328     ++fIcomnd;
02329     fNfcnlc = fNfcn;
02330     if (msubstr(fCword,0,7) != "SET PRI" || fWord7[0] >= 0) {
02331         if (fISW[4] >= 0) {
02332             lnow = llist;
02333             if (lnow > 4) lnow = 4;
02334             Printf(f_out," **********");
02335             ctemp = Form(" **%5d **%s",fIcomnd,fCword.c_str());
02336             for (i = 1; i <= lnow; ++i) {
02337                 ctemp += Form("%12.4g",plist[i-1]);
02338             }
02339             Printf(f_out,"%s",ctemp.c_str());
02340             inonde = 0;
02341             if (llist > lnow) {
02342                 kll = llist;
02343                 if (llist > 30) {
02344                     inonde = 1;
02345                     kll = 30;
02346                 }
02347                 Printf(f_out," ***********");
02348                 for (i = lnow + 1; i <= kll; ++i) {
02349                    Printf(f_out,"%12.4g",plist[i-1]);
02350                 }
02351             }
02352             Printf(f_out," **********");
02353             if (inonde > 0) {
02354                 Printf(f_out,"  ERROR: ABOVE CALL TO MNEXCM TRIED TO PASS MORE THAN 30 PARAMETERS.");
02355             }
02356         }
02357     }
02358     fNfcnmx = int(fWord7[0]);
02359     if (fNfcnmx <= 0) {
02360         fNfcnmx = fNpar*100 + 200 + fNpar*fNpar*5;
02361     }
02362     fEpsi = fWord7[1];
02363     if (fEpsi <= 0) {
02364         fEpsi = fUp*.1;
02365     }
02366     fLnewmn = false;
02367     fLphead = true;
02368     fISW[0] = 0;
02369     ierflg = 0;
02370 //*-*-               look for command in list CNAME . . . . . . . . . .
02371     for (i = 1; i <= nntot; ++i) {
02372         if (msubstr(fCword,0,3) == msubstr(cname[i-1],0,3)) goto L90;
02373     }
02374     Printf(f_out,"UNKNOWN COMMAND IGNORED:%s", comand.c_str());
02375     ierflg = 3;
02376     return;
02377 //*-*-               normal case: recognized MINUIT command . . . . . . .
02378 L90:
02379     if (msubstr(fCword,0,4) == "MINO") i = 5;
02380     if (i != 6 && i != 7 && i != 8 && i != 23) {
02381         fCfrom  = cname[i-1];
02382         fNfcnfr = fNfcn;
02383     }
02384 //*-*-             1    2    3    4    5    6    7    8    9   10
02385     switch (i) {
02386         case 1:  goto L400;
02387         case 2:  goto L200;
02388         case 3:  goto L300;
02389         case 4:  goto L400;
02390         case 5:  goto L500;
02391         case 6:  goto L700;
02392         case 7:  goto L700;
02393         case 8:  goto L800;
02394         case 9:  goto L900;
02395         case 10:  goto L1000;
02396         case 11:  goto L1100;
02397         case 12:  goto L1200;
02398         case 13:  goto L1300;
02399         case 14:  goto L1400;
02400         case 15:  goto L1500;
02401         case 16:  goto L1600;
02402         case 17:  goto L1700;
02403         case 18:  goto L1800;
02404         case 19:  goto L1900;
02405         case 20:  goto L1900;
02406         case 21:  goto L1900;
02407         case 22:  goto L2200;
02408         case 23:  goto L2300;
02409         case 24:  goto L2400;
02410         case 25:  goto L1900;
02411         case 26:  goto L2600;
02412         case 27:  goto L3300;
02413         case 28:  goto L3300;
02414         case 29:  goto L3300;
02415         case 30:  goto L3300;
02416         case 31:  goto L3300;
02417         case 32:  goto L3300;
02418         case 33:  goto L3300;
02419         case 34:  goto L3400;
02420         case 35:  goto L3500;
02421         case 36:  goto L3600;
02422         case 37:  goto L3700;
02423         case 38:  goto L3800;
02424         case 39:  goto L3900;
02425         case 40:  goto L4000;
02426     }
02427 //*-*-                                       . . . . . . . . . . seek
02428 L200:
02429     mnseek();
02430     return;
02431 //*-*-                                       . . . . . . . . . . simplex
02432 L300:
02433     mnsimp();
02434     if (fISW[3] < 1) ierflg = 4;
02435     return;
02436 //*-*-                                       . . . . . . migrad, minimize
02437 L400:
02438     nf = fNfcn;
02439     fApsi = fEpsi;
02440     if(!mnmigr()) {
02441       Printf(f_out,"fitter::mnexcm : mnmigr aborted.");
02442       ierflg = 4;
02443       return;
02444     }
02445     mnwerr();
02446     if (fISW[3] >= 1) return;
02447     ierflg = 4;
02448     if (fISW[0] == 1) return;
02449     if (msubstr(fCword,0,3) == "MIG") return;
02450 
02451     fNfcnmx = fNfcnmx + nf - fNfcn;
02452     nf = fNfcn;
02453     mnsimp();
02454     if (fISW[0] == 1) return;
02455     fNfcnmx = fNfcnmx + nf - fNfcn;
02456     mnmigr();
02457     if (fISW[3] >= 1) ierflg = 0;
02458     mnwerr();
02459     return;
02460 //*-*-                                       . . . . . . . . . . minos
02461 L500:
02462     //GB : NT/cl.exe gives a warning about << and precedence 
02463     //     in the below original code :
02464 //GB    nsuper = fNfcn + (fNpar + 1 << 1)*fNfcnmx;
02465     //GB : I have change for the below. The precedence had been
02466     //     on a Linux/gxx, MacOSX/gxx and OSF1/cxx.
02467     nsuper = fNfcn + ((fNpar + 1) << 1)*fNfcnmx; //GB
02468 //*-*-         possible loop over new minima
02469     fEpsi = fUp*.1;
02470 L510:
02471     mncuve();
02472     mnmnos();
02473     if (! fLnewmn) return;
02474     mnrset(0);
02475     mnmigr();
02476     mnwerr();
02477     if (fNfcn < nsuper) goto L510;
02478     Printf(f_out," TOO MANY FUNCTION CALLS. MINOS GIVES UP");
02479     ierflg = 4;
02480     return;
02481 //*-*-                                       . . . . . . . . . .set, show
02482 L700:
02483     mnset();
02484     return;
02485 //*-*-                                       . . . . . . . . . . top of page
02486 
02487 L800:
02488     Printf(f_out,"1");
02489     return;
02490 //*-*-                                       . . . . . . . . . . fix
02491 L900:
02492     ltofix = true;
02493 //*-*-                                       . . (also release) ....
02494 L901:
02495     lfreed = false;
02496     lfixed = false;
02497     if (llist == 0) {
02498         Printf(f_out,"%s:  NO PARAMETERS REQUESTED ",fCword.c_str());
02499         return;
02500     }
02501     for (ilist = 1; ilist <= llist; ++ilist) {
02502         iext = int(plist[ilist-1]);
02503         chwhy = " IS UNDEFINED.";
02504         if (iext <= 0) goto L930;
02505         if (iext > fNu) goto L930;
02506         if (fNvarl[iext-1] < 0) goto L930;
02507         chwhy = " IS CONSTANT.  ";
02508         if (fNvarl[iext-1] == 0) goto L930;
02509         iint = fNiofex[iext-1];
02510         if (ltofix) {
02511             chwhy = " ALREADY FIXED.";
02512             if (iint == 0) goto L930;
02513             mnfixp(iint-1, ierr);
02514             if (ierr == 0) lfixed = true;
02515             else           ierflg = 4;
02516         } else {
02517             chwhy = " ALREADY VARIABLE.";
02518             if (iint > 0) goto L930;
02519             krl = -TMath_int_abs(iext);
02520             mnfree(krl);
02521             lfreed = true;
02522         }
02523         continue;
02524 L930:
02525         Printf(f_out," PARAMETER%4d %s IGNORED.",iext,chwhy.c_str());
02526     }
02527     if (lfreed || lfixed) mnrset(0);
02528     if (lfreed) {
02529         fISW[1] = 0;
02530         fDcovar = 1;
02531         fEDM = fBigedm;
02532         fISW[3] = 0;
02533     }
02534     mnwerr();
02535     if (fISW[4] > 1) mnprin(5, fAmin);
02536     return;
02537 //*-*-                                       . . . . . . . . . . restore
02538 L1000:
02539     it = int(fWord7[0]);
02540     if (it > 1 || it < 0) goto L1005;
02541     lfreed = fNpfix > 0;
02542     mnfree(it);
02543     if (lfreed) {
02544         mnrset(0);
02545         fISW[1] = 0;
02546         fDcovar = 1;
02547         fEDM    = fBigedm;
02548     }
02549     return;
02550 L1005:
02551     Printf(f_out," IGNORED.  UNKNOWN ARGUMENT:%4d",it);
02552     ierflg = 3;
02553     return;
02554 //*-*-                                       . . . . . . . . . . release
02555 L1100:
02556     ltofix = false;
02557     goto L901;
02558 //*-*-                                      . . . . . . . . . . scan . . .
02559 L1200:
02560     iext = int(fWord7[0]);
02561     if (iext <= 0) goto L1210;
02562     it2 = 0;
02563     if (iext <= fNu) it2 = fNiofex[iext-1];
02564     if (it2 <= 0) goto L1250;
02565 
02566 L1210:
02567     mnscan();
02568     return;
02569 L1250:
02570     Printf(f_out," PARAMETER%4d NOT VARIABLE.",iext);
02571     ierflg = 3;
02572     return;
02573 //*-*-                                       . . . . . . . . . . contour
02574 L1300:
02575     ke1 = int(fWord7[0]);
02576     ke2 = int(fWord7[1]);
02577     if (ke1 == 0) {
02578         if (fNpar == 2) {
02579             ke1 = fNexofi[0];
02580             ke2 = fNexofi[1];
02581         } else {
02582             Printf(f_out,"%s:  NO PARAMETERS REQUESTED ",fCword.c_str());
02583             ierflg = 3;
02584             return;
02585         }
02586     }
02587     fNfcnmx = 1000;
02588     mncntr(ke1, ke2, ierrf);
02589     if (ierrf > 0) ierflg = 3;
02590     return;
02591 //*-*-                                       . . . . . . . . . . hesse
02592 L1400:
02593     mnhess();
02594     mnwerr();
02595     if (fISW[4] >= 0) mnprin(2, fAmin);
02596     if (fISW[4] >= 1) mnmatu(1);
02597     return;
02598 //*-*-                                       . . . . . . . . . . save
02599 L1500:
02600     mnsave();
02601     return;
02602 //*-*-                                       . . . . . . . . . . improve
02603 L1600:
02604     mncuve();
02605     mnimpr();
02606     if (fLnewmn) goto L400;
02607     ierflg = 4;
02608     return;
02609 //*-*-                                       . . . . . . . . . . call fcn
02610 L1700:
02611     iflag = int(fWord7[0]);
02612     nparx = fNpar;
02613     f = fUndefi;
02614     //Printf(f_out,"debug : FCN : 008");
02615     (*fFCN)(nparx, fGin, f, fU, iflag,fTag);    ++fNfcn;
02616     nowprt = 0;
02617     if (f != fUndefi) {
02618         if (fAmin == fUndefi) {
02619             fAmin  = f;
02620             nowprt = 1;
02621         } else if (f < fAmin) {
02622             fAmin  = f;
02623             nowprt = 1;
02624         }
02625         if (fISW[4] >= 0 && iflag <= 5 && nowprt == 1) {
02626             mnprin(5, fAmin);
02627         }
02628         if (iflag == 3)  fFval3 = f;
02629     }
02630     if (iflag > 5) mnrset(1);
02631     return;
02632 //*-*-                                       . . . . . . . . . . standard
02633 L1800:
02634 //    stand();
02635     return;
02636 //*-*-                                      . . . return, stop, end, exit
02637 L1900:
02638     it = int(fWord7[0]);
02639     if (fFval3 != fAmin && it == 0) {
02640         iflag = 3;
02641         Printf(f_out," CALL TO USER FUNCTION WITH IFLAG = 3");
02642         nparx = fNpar;
02643     //Printf(f_out,"debug : FCN : 009");
02644         (*fFCN)(nparx, fGin, f, fU, iflag,fTag);        ++fNfcn;
02645     }
02646     ierflg = 11;
02647     if (msubstr(fCword,0,3) == "END") ierflg = 10;
02648     if (msubstr(fCword,0,3) == "RET") ierflg = 12;
02649     return;
02650 //*-*-                                       . . . . . . . . . . clear
02651 L2200:
02652     mncler();
02653     if (fISW[4] >= 1) {
02654         Printf(f_out," MINUIT MEMORY CLEARED. NO PARAMETERS NOW DEFINED.");
02655     }
02656     return;
02657 //*-*-                                       . . . . . . . . . . help
02658 L2300:
02659     kcol = 0;
02660     for (icol = 5; icol <= lk; ++icol) {
02661         if (fCword[icol-1] == ' ') continue;
02662         kcol = icol;
02663         goto L2320;
02664     }
02665 L2320:
02666     if (kcol == 0) comd = "*   ";
02667     else           comd.assign(1,fCword[kcol-1]);
02668     mnhelp(comd);
02669     return;
02670 //*-*-                                      . . . . . . . . . . MNContour
02671 L2400:
02672     fEpsi = fUp*.05;
02673     ke1 = int(fWord7[0]);
02674     ke2 = int(fWord7[1]);
02675     if (ke1 == 0 && fNpar == 2) {
02676         ke1 = fNexofi[0];
02677         ke2 = fNexofi[1];
02678     }
02679     nptu = int(fWord7[2]);
02680     if (nptu <= 0)  nptu = 20;
02681     if (nptu > 101) nptu = 101;
02682     fNfcnmx = (nptu + 5)*100*(fNpar + 1);
02683     mncont(ke1, ke2, nptu, xptu, yptu, ierrf);
02684     if (ierrf < nptu) ierflg = 4;
02685     if (ierrf == -1)  ierflg = 3;
02686     return;
02687 //*-*-                                     . . . . . . . . . . jump
02688 L2600:
02689     step = fWord7[0];
02690     if (step <= 0) step = 2;
02691     rno = 0;
02692     izero = 0;
02693     for (i = 1; i <= fNpar; ++i) {
02694         mnrn15(rno, izero);
02695         rno      = rno*2 - 1;
02696         fX[i-1] += rno*step*fWerr[i-1];
02697     }
02698     mninex(fX);
02699     mnamin();
02700     mnrset(0);
02701     return;
02702 //*-*-                                     . . . . . . . . . . blank line
02703 L3300:
02704     Printf(f_out," BLANK COMMAND IGNORED.");
02705     ierflg = 1;
02706     return;
02707 //*-*  . . . . . . . . obsolete commands     . . . . . . . . . . . . . .
02708 //*-*-                                     . . . . . . . . . . covariance
02709 L3400:
02710     Printf(f_out," THE *COVARIANCE* COMMAND IS OSBSOLETE. THE COVARIANCE MATRIX IS NOW SAVED IN A DIFFERENT FORMAT WITH THE *SAVE* COMMAND AND READ IN WITH:*SET COVARIANCE*");
02711     ierflg = 3;
02712     return;
02713 //*-*-                                       . . . . . . . . . . printout
02714 L3500:
02715     cneway = "SET PRInt ";
02716     goto L3100;
02717 //*-*-                                       . . . . . . . . . . gradient
02718 L3600:
02719     cneway = "SET GRAd  ";
02720     goto L3100;
02721 //*-*-                                       . . . . . . . . . . matout
02722 L3700:
02723     cneway = "SHOW COVar";
02724     goto L3100;
02725 //*-*-                                       . . . . . . . . . error def
02726 L3800:
02727     cneway = "SET ERRdef";
02728     goto L3100;
02729 //*-*-                                       . . . . . . . . . . limits
02730 L3900:
02731     cneway = "SET LIMits";
02732     goto L3100;
02733 //*-*-                                       . . . . . . . . . . punch
02734 L4000:
02735     cneway = "SAVE      ";
02736 //*-*-                               ....... come from obsolete commands
02737 L3100:
02738     Printf(f_out," OBSOLETE COMMAND:%s   PLEASE USE: %s",fCword.c_str()
02739                                                  ,cneway.c_str());
02740     fCword = cneway;
02741     if (fCword == "SAVE      ") goto L1500;
02742     goto L700;
02743 //*-*                                 . . . . . . . . . . . . . . . . . .
02744 } /* mnexcm_ */
02745 
02746 //______________________________________________________________________________
02747 inline
02748 void fitter::mnexin(double *pint)
02749 {
02750 //*-*-*-*-*Transforms the external parameter values U to internal values*-*-*
02751 //*-*      =============================================================
02752 //*-*        Transforms the external parameter values U to internal
02753 //*-*        values in the dense array PINT.
02754 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
02755 
02756     /*static*/ double pinti;
02757     /*static*/ int iint, iext;
02758 
02759     fLimset = false;
02760     for (iint = 1; iint <= fNpar; ++iint) {
02761         iext = fNexofi[iint-1];
02762         mnpint(fU[iext-1], iext-1, pinti);
02763         pint[iint-1] = pinti;
02764     }
02765 } /* mnexin_ */
02766 
02767 //______________________________________________________________________________
02768 inline
02769 void fitter::mnfixp(int iint1, int &ierr)
02770 {
02771 //*-*-*-*-*-*-*Removes parameter IINT from the internal parameter list*-*-*
02772 //*-*          =======================================================
02773 //*-*        and arranges the rest of the list to fill the hole.
02774 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
02775 
02776     /* Local variables */
02777     /*static*/ double yy[kMAXDIM], yyover;
02778     /*static*/ int kold, nold, ndex, knew, iext, i, j, m, n, lc, ik;
02779 
02780 //*-*-                          first see if it can be done
02781     ierr = 0;
02782     int iint = iint1+1;
02783     if (iint > fNpar || iint <= 0) {
02784         ierr = 1;
02785         Printf(f_out," MINUIT ERROR.  ARGUMENT TO MNFIXP=%4d",iint);
02786         return;
02787     }
02788     iext = fNexofi[iint-1];
02789     if (fNpfix >= fMaxpar) {
02790         ierr = 1;
02791         Printf(f_out," MINUIT CANNOT FIX PARAMETER%4d MAXIMUM NUMBER THAT CAN BE FIXED IS %d",iext,fMaxpar);
02792         return;
02793     }
02794 //*-*-                          reduce number of variable parameters by one
02795 
02796     fNiofex[iext-1] = 0;
02797     nold = fNpar;
02798     --fNpar;
02799 //*-*-                      save values in case parameter is later restored
02800 
02801     ++fNpfix;
02802     fIpfix[fNpfix-1]  = iext;
02803     lc                = iint;
02804     fXs[fNpfix-1]     = fX[lc-1];
02805     fXts[fNpfix-1]    = fXt[lc-1];
02806     fDirins[fNpfix-1] = fWerr[lc-1];
02807     fGrds[fNpfix-1]   = fGrd[lc-1];
02808     fG2s[fNpfix-1]    = fG2[lc-1];
02809     fGsteps[fNpfix-1] = fGstep[lc-1];
02810 //*-*-                       shift values for other parameters to fill hole
02811     for (ik = iext + 1; ik <= fNu; ++ik) {
02812         if (fNiofex[ik-1] > 0) {
02813             lc = fNiofex[ik-1] - 1;
02814             fNiofex[ik-1] = lc;
02815             fNexofi[lc-1] = ik;
02816             fX[lc-1]      = fX[lc];
02817             fXt[lc-1]     = fXt[lc];
02818             fDirin[lc-1]  = fDirin[lc];
02819             fWerr[lc-1]   = fWerr[lc];
02820             fGrd[lc-1]    = fGrd[lc];
02821             fG2[lc-1]     = fG2[lc];
02822             fGstep[lc-1]  = fGstep[lc];
02823         }
02824     }
02825     if (fISW[1] <= 0) return;
02826 //*-*-                   remove one row and one column from variance matrix
02827     if (fNpar <= 0)   return;
02828     for (i = 1; i <= nold; ++i) {
02829         m       = TMath_Max(i,iint);
02830         n       = TMath_Min(i,iint);
02831         ndex    = m*(m-1) / 2 + n;
02832         yy[i-1] = fVhmat[ndex-1];
02833     }
02834     yyover = 1 / yy[iint-1];
02835     knew   = 0;
02836     kold   = 0;
02837     for (i = 1; i <= nold; ++i) {
02838         for (j = 1; j <= i; ++j) {
02839             ++kold;
02840             if (j == iint || i == iint) continue;
02841             ++knew;
02842             fVhmat[knew-1] = fVhmat[kold-1] - yy[j-1]*yy[i-1]*yyover;
02843         }
02844     }
02845 } /* mnfixp_ */
02846 
02847 //______________________________________________________________________________
02848 inline
02849 void fitter::mnfree(int k)
02850 {
02851 //*-*-*-*Restores one or more fixed parameter(s) to variable status*-*-*-*-*-*
02852 //*-*    ==========================================================
02853 //*-*        Restores one or more fixed parameter(s) to variable status
02854 //*-*        by inserting it into the internal parameter list at the
02855 //*-*        appropriate place.
02856 //*-*
02857 //*-*        K = 0 means restore all parameters
02858 //*-*        K = 1 means restore the last parameter fixed
02859 //*-*        K = -I means restore external parameter I (if possible)
02860 //*-*        IQ = fix-location where internal parameters were stored
02861 //*-*        IR = external number of parameter being restored
02862 //*-*        IS = internal number of parameter being restored
02863 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
02864 
02865     /* Local variables */
02866     /*static*/ double grdv, xv, dirinv, g2v, gstepv, xtv;
02867     /*static*/ int i, ipsav, ka, lc, ik, iq, ir, is;
02868 
02869     if (k > 1) {
02870         Printf(f_out," CALL TO MNFREE IGNORED.  ARGUMENT GREATER THAN ONE");
02871     }
02872     if (fNpfix < 1) {
02873         Printf(f_out," CALL TO MNFREE IGNORED.  THERE ARE NO FIXED PARAMETERS");
02874     }
02875     if (k == 1 || k == 0) goto L40;
02876 
02877 //*-*-                  release parameter with specified external number
02878     ka = TMath_int_abs(k);
02879     if (fNiofex[ka-1] == 0) goto L15;
02880     Printf(f_out," IGNORED.  PARAMETER SPECIFIED IS ALREADY VARIABLE.");
02881     return;
02882 L15:
02883     if (fNpfix < 1) goto L21;
02884     for (ik = 1; ik <= fNpfix; ++ik) { if (fIpfix[ik-1] == ka) goto L24; }
02885 L21:
02886     Printf(f_out," PARAMETER%4d NOT FIXED.  CANNOT BE RELEASED.",ka);
02887     return;
02888 L24:
02889     if (ik == fNpfix) goto L40;
02890 
02891 //*-*-                  move specified parameter to end of list
02892     ipsav  = ka;
02893     xv     = fXs[ik-1];
02894     xtv    = fXts[ik-1];
02895     dirinv = fDirins[ik-1];
02896     grdv   = fGrds[ik-1];
02897     g2v    = fG2s[ik-1];
02898     gstepv = fGsteps[ik-1];
02899     for (i = ik + 1; i <= fNpfix; ++i) {
02900         fIpfix[i-2]  = fIpfix[i-1];
02901         fXs[i-2]     = fXs[i-1];
02902         fXts[i-2]    = fXts[i-1];
02903         fDirins[i-2] = fDirins[i-1];
02904         fGrds[i-2]   = fGrds[i-1];
02905         fG2s[i-2]    = fG2s[i-1];
02906         fGsteps[i-2] = fGsteps[i-1];
02907     }
02908     fIpfix[fNpfix-1]  = ipsav;
02909     fXs[fNpfix-1]     = xv;
02910     fXts[fNpfix-1]    = xtv;
02911     fDirins[fNpfix-1] = dirinv;
02912     fGrds[fNpfix-1]   = grdv;
02913     fG2s[fNpfix-1]    = g2v;
02914     fGsteps[fNpfix-1] = gstepv;
02915 //*-*-               restore last parameter in fixed list  -- IPFIX(NPFIX)
02916 L40:
02917     if (fNpfix < 1) goto L300;
02918     ir = fIpfix[fNpfix-1];
02919     is = 0;
02920     for (ik = fNu; ik >= ir; --ik) {
02921         if (fNiofex[ik-1] > 0) {
02922             lc = fNiofex[ik-1] + 1;
02923             is = lc - 1;
02924             fNiofex[ik-1] = lc;
02925             fNexofi[lc-1] = ik;
02926             fX[lc-1]      = fX[lc-2];
02927             fXt[lc-1]     = fXt[lc-2];
02928             fDirin[lc-1]  = fDirin[lc-2];
02929             fWerr[lc-1]   = fWerr[lc-2];
02930             fGrd[lc-1]    = fGrd[lc-2];
02931             fG2[lc-1]     = fG2[lc-2];
02932             fGstep[lc-1]  = fGstep[lc-2];
02933         }
02934     }
02935     ++fNpar;
02936     if (is == 0) is = fNpar;
02937     fNiofex[ir-1] = is;
02938     fNexofi[is-1] = ir;
02939     iq           = fNpfix;
02940     fX[is-1]     = fXs[iq-1];
02941     fXt[is-1]    = fXts[iq-1];
02942     fDirin[is-1] = fDirins[iq-1];
02943     fWerr[is-1]  = fDirins[iq-1];
02944     fGrd[is-1]   = fGrds[iq-1];
02945     fG2[is-1]    = fG2s[iq-1];
02946     fGstep[is-1] = fGsteps[iq-1];
02947     --fNpfix;
02948     fISW[1] = 0;
02949     fDcovar = 1;
02950     if (fISW[4] - fItaur >= 1) {
02951         Printf(f_out,"                    PARAMETER%4d  %s RESTORED TO VARIABLE.",ir,fCpnam[ir-1].c_str());
02952     }
02953     if (k == 0) goto L40;
02954 L300:
02955 //*-*-        if different from internal, external values are taken
02956     mnexin(fX);
02957 } /* mnfree_ */
02958 
02959 //______________________________________________________________________________
02960 inline
02961 void fitter::mngrad()
02962 {
02963 //*-*-*-*-*-*-*-*-*-*Interprets the SET GRAD command*-*-*-*-*-*-*-*-*-*-*-*-*
02964 //*-*                ===============================
02965 //*-*       Called from MNSET
02966 //*-*       Interprets the SET GRAD command, which informs MINUIT whether
02967 //*-*       the first derivatives of FCN will be calculated by the user
02968 //*-*       inside FCN.  It can check the user derivative calculation
02969 //*-*       by comparing it with a finite difference approximation.
02970 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
02971 
02972     /* Local variables */
02973     /*static*/ double gf[kMAXDIM], fzero, err;
02974     /*static*/ int i, nparx, lc, istsav;
02975     /*static*/ bool lnone;
02976     /*static*/ std::string cwd = "    ";
02977 
02978     fISW[2] = 1;
02979     nparx   = fNpar;
02980     if (fWord7[0] > 0) goto L2000;
02981 
02982 //*-*-                 get user-calculated first derivatives from FCN
02983     for (i = 1; i <= fNu; ++i) { fGin[i-1] = fUndefi; }
02984     mninex(fX);
02985     //Printf(f_out,"debug : FCN : 010");
02986     (*fFCN)(nparx, fGin, fzero, fU, 2,fTag);    ++fNfcn;
02987     mnderi();
02988     for (i = 1; i <= fNpar; ++i) { gf[i-1] = fGrd[i-1]; }
02989 //*-*-                   get MINUIT-calculated first derivatives
02990     fISW[2] = 0;
02991     istsav  = fIstrat;
02992     fIstrat = 2;
02993     mnhes1();
02994     fIstrat = istsav;
02995     Printf(f_out," CHECK OF GRADIENT CALCULATION IN FCN");
02996     Printf(f_out,"            PARAMETER      G(IN FCN)   G(MINUIT)  DG(MINUIT)   AGREEMENT");
02997     fISW[2] = 1;
02998     lnone = false;
02999     for (lc = 1; lc <= fNpar; ++lc) {
03000         i   = fNexofi[lc-1];
03001         cwd = "GOOD";
03002         err = fDgrd[lc-1];
03003         if (TMath_Abs(gf[lc-1] - fGrd[lc-1]) > err)  cwd = " BAD";
03004         if (fGin[i-1] == fUndefi) {
03005             cwd      = "NONE";
03006             lnone    = true;
03007             gf[lc-1] = 0;
03008         }
03009         if (cwd != "GOOD") fISW[2] = 0;
03010         Printf(f_out,"       %5d  %10s%12.4e%12.4e%12.4e    %s",i
03011                ,fCpnam[i-1].c_str()
03012                ,gf[lc-1],fGrd[lc-1],err,cwd.c_str());
03013     }
03014     if (lnone) {
03015         Printf(f_out,"  AGREEMENT=NONE  MEANS FCN DID NOT CALCULATE THE DERIVATIVE");
03016     }
03017     if (fISW[2] == 0) {
03018         Printf(f_out," MINUIT DOES NOT ACCEPT DERIVATIVE CALCULATIONS BY FCN");
03019         Printf(f_out," TO FORCE ACCEPTANCE, ENTER *SET GRAD    1*");
03020     }
03021 
03022 L2000:
03023     return;
03024 } /* mngrad_ */
03025 
03026 //______________________________________________________________________________
03027 inline
03028 void fitter::mnhelp(const std::string& comd)
03029 {
03030 //*-*-*-*-*-*-*-*HELP routine for MINUIT interactive commands*-*-*-*-*-*-*-*-*
03031 //*-*            ============================================
03032 //*-*
03033 //*-*      COMD ='*   '  prints a global help for all commands
03034 //*-*      COMD =Command_name: print detailed help for one command.
03035 //*-*         Note that at least 3 characters must be given for the command
03036 //*-*         name.
03037 //*-*
03038 //*-*     Author: Rene Brun
03039 //*-*             comments extracted from the MINUIT documentation file.
03040 //*-*
03041 //*-*
03042 //*-* command name ASSUMED to be in upper case
03043 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
03044 
03045     /*static*/ std::string cmd3 = "    ";
03046 
03047 //*-*.......................................................................
03048 //*-*
03049 //*-*  Global HELP: Summary of all commands
03050 //*-*  ====================================
03051 //*-*
03052     if (comd[0] == '*') {
03053        Printf(f_out,"   ==>List of MINUIT Interactive commands:");
03054        Printf(f_out," CLEar     Reset all parameter names and values undefined");
03055        Printf(f_out," CONtour   Make contour map of the user function");
03056        Printf(f_out," EXIT      Exit from Interactive Minuit");
03057        Printf(f_out," FIX       Cause parameter(s) to remain constant");
03058        Printf(f_out," HESse     Calculate the Hessian or error matrix.");
03059        Printf(f_out," IMPROVE   Search for a new minimum around current minimum");
03060        Printf(f_out," MIGrad    Minimize by the method of Migrad");
03061        Printf(f_out," MINImize  MIGRAD + SIMPLEX method if Migrad fails");
03062        Printf(f_out," MINOs     Exact (non-linear) parameter error analysis");
03063        Printf(f_out," MNContour Calculate one MINOS function contour");
03064        Printf(f_out," PARameter Define or redefine new parameters and values");
03065        Printf(f_out," RELease   Make previously FIXed parameters variable again");
03066        Printf(f_out," REStore   Release last parameter fixed");
03067        Printf(f_out," SAVe      Save current parameter values on a file");
03068        Printf(f_out," SCAn      Scan the user function by varying parameters");
03069        Printf(f_out," SEEk      Minimize by the method of Monte Carlo");
03070        Printf(f_out," SET       Set various MINUIT constants or conditions");
03071        Printf(f_out," SHOw      Show values of current constants or conditions");
03072        Printf(f_out," SIMplex   Minimize by the method of Simplex");
03073         goto L99;
03074     }
03075 
03076     cmd3 = comd;
03077 //*-* __________________________________________________________________
03078 //*-*
03079 //*-* --  Command CLEAR
03080 //*-* --  =============
03081 //*-*
03082     if (cmd3 == "CLE") {
03083        Printf(f_out," ***>CLEAR");
03084        Printf(f_out," Resets all parameter names and values to undefined.");
03085        Printf(f_out," Must normally be followed by a PARameters command or ");
03086        Printf(f_out," equivalent, in order to define parameter values.");
03087         goto L99;
03088     }
03089 //*-* __________________________________________________________________
03090 //*-* --
03091 //*-* --  Command CONTOUR
03092 //*-* --  ===============
03093 //*-* .
03094     if (cmd3 == "CON") {
03095        Printf(f_out," ***>CONTOUR <par1>  <par2>  [devs]  [ngrid]");
03096        Printf(f_out," Instructs Minuit to trace contour lines of the user function");
03097        Printf(f_out," with respect to the two parameters whose external numbers");
03098        Printf(f_out," are <par1> and <par2>.");
03099        Printf(f_out," Other variable parameters of the function, if any, will have");
03100        Printf(f_out," their values fixed at the current values during the contour");
03101        Printf(f_out," tracing. The optional parameter [devs] (default value 2.)");
03102        Printf(f_out," gives the number of standard deviations in each parameter");
03103        Printf(f_out," which should lie entirely within the plotting area.");
03104        Printf(f_out," Optional parameter [ngrid] (default value 25 unless page");
03105        Printf(f_out," size is too small) determines the resolution of the plot,");
03106        Printf(f_out," i.e. the number of rows and columns of the grid at which the");
03107        Printf(f_out," function will be evaluated. [See also MNContour.]");
03108         goto L99;
03109     }
03110 //*-* __________________________________________________________________
03111 //*-* --
03112 //*-* --  Command END
03113 //*-* --  ===========
03114 //*-* .
03115     if (cmd3 == "END") {
03116        Printf(f_out," ***>END");
03117        Printf(f_out," Signals the end of a data block (i.e., the end of a fit),");
03118        Printf(f_out," and implies that execution should continue, because another");
03119        Printf(f_out," Data Block follows. A Data Block is a set of Minuit data");
03120        Printf(f_out," consisting of");
03121        Printf(f_out,"     (1) A Title,");
03122        Printf(f_out,"     (2) One or more Parameter Definitions,");
03123        Printf(f_out,"     (3) A blank line, and");
03124        Printf(f_out,"     (4) A set of Minuit Commands.");
03125        Printf(f_out," The END command is used when more than one Data Block is to");
03126        Printf(f_out," be used with the same FCN function. It first causes Minuit");
03127        Printf(f_out," to issue a CALL FCN with IFLAG=3, in order to allow FCN to");
03128        Printf(f_out," perform any calculations associated with the final fitted");
03129        Printf(f_out," parameter values, unless a CALL FCN 3 command has already");
03130        Printf(f_out," been executed at the current FCN value.");
03131         goto L99;
03132     }
03133 //*-* __________________________________________________________________
03134 //*-* .
03135 //*-* --
03136 //*-* --  Command EXIT
03137 //*-* --  ============
03138     if (cmd3 == "EXI") {
03139        Printf(f_out," ***>EXIT");
03140        Printf(f_out," Signals the end of execution.");
03141        Printf(f_out," The EXIT command first causes Minuit to issue a CALL FCN");
03142        Printf(f_out," with IFLAG=3, to allow FCN to perform any calculations");
03143        Printf(f_out," associated with the final fitted parameter values, unless a");
03144        Printf(f_out," CALL FCN 3 command has already been executed.");
03145         goto L99;
03146     }
03147 //*-* __________________________________________________________________
03148 //*-* --
03149 //*-* --  Command FIX
03150 //*-* --  ===========
03151 //*-* .
03152     if (cmd3 == "FIX") {
03153        Printf(f_out," ***>FIX} <parno> [parno] ... [parno]");
03154        Printf(f_out," Causes parameter(s) <parno> to be removed from the list of");
03155        Printf(f_out," variable parameters, and their value(s) will remain constant");
03156        Printf(f_out," during subsequent minimizations, etc., until another command");
03157        Printf(f_out," changes their value(s) or status.");
03158         goto L99;
03159     }
03160 //*-* __________________________________________________________________
03161 //*-* --
03162 //*-* --  Command HESSE
03163 //*-* --  =============
03164 //*-* .
03165     if (cmd3 == "HES") {
03166        Printf(f_out," ***>HESse  [maxcalls]");
03167        Printf(f_out," Calculate, by finite differences, the Hessian or error matrix.");
03168        Printf(f_out,"  That is, it calculates the full matrix of second derivatives");
03169        Printf(f_out," of the function with respect to the currently variable");
03170        Printf(f_out," parameters, and inverts it, printing out the resulting error");
03171        Printf(f_out," matrix. The optional argument [maxcalls] specifies the");
03172        Printf(f_out," (approximate) maximum number of function calls after which");
03173        Printf(f_out," the calculation will be stopped.");
03174         goto L99;
03175     }
03176 //*-* __________________________________________________________________
03177 //*-* --
03178 //*-* --  Command IMPROVE
03179 //*-* --  ===============
03180 //*-* .
03181     if (cmd3 == "IMP") {
03182        Printf(f_out," ***>IMPROVE  [maxcalls]");
03183        Printf(f_out," If a previous minimization has converged, and the current");
03184        Printf(f_out," values of the parameters therefore correspond to a local");
03185        Printf(f_out," minimum of the function, this command requests a search for");
03186        Printf(f_out," additional distinct local minima.");
03187        Printf(f_out," The optional argument [maxcalls] specifies the (approximate");
03188        Printf(f_out," maximum number of function calls after which the calculation");
03189        Printf(f_out," will be stopped.");
03190         goto L99;
03191     }
03192 //*-* __________________________________________________________________
03193 //*-* --
03194 //*-* --  Command MIGRAD
03195 //*-* --  ==============
03196 //*-* .
03197     if (cmd3 == "MIG") {
03198        Printf(f_out," ***>MIGrad  [maxcalls]  [tolerance]");
03199        Printf(f_out," Causes minimization of the function by the method of Migrad,");
03200        Printf(f_out," the most efficient and complete single method, recommended");
03201        Printf(f_out," for general functions (see also MINImize).");
03202        Printf(f_out," The minimization produces as a by-product the error matrix");
03203        Printf(f_out," of the parameters, which is usually reliable unless warning");
03204        Printf(f_out," messages are produced.");
03205        Printf(f_out," The optional argument [maxcalls] specifies the (approximate)");
03206        Printf(f_out," maximum number of function calls after which the calculation");
03207        Printf(f_out," will be stopped even if it has not yet converged.");
03208        Printf(f_out," The optional argument [tolerance] specifies required tolerance");
03209        Printf(f_out," on the function value at the minimum.");
03210        Printf(f_out," The default tolerance is 0.1, and the minimization will stop");
03211        Printf(f_out," when the estimated vertical distance to the minimum (EDM) is");
03212        Printf(f_out," less than 0.001*[tolerance]*UP (see [SET ERRordef]).");
03213         goto L99;
03214     }
03215 //*-* __________________________________________________________________
03216 //*-* --
03217 //*-* --  Command MINIMIZE
03218 //*-* --  ================
03219 //*-* .
03220     if (comd == "MINI") {
03221        Printf(f_out," ***>MINImize  [maxcalls] [tolerance]");
03222        Printf(f_out," Causes minimization of the function by the method of Migrad,");
03223        Printf(f_out," as does the MIGrad command, but switches to the SIMplex method");
03224        Printf(f_out," if Migrad fails to converge. Arguments are as for MIGrad.");
03225        Printf(f_out," Note that command requires four characters to be unambiguous.");
03226         goto L99;
03227     }
03228 //*-* __________________________________________________________________
03229 //*-* --
03230 //*-* --  Command MINOS
03231 //*-* --  =============
03232 //*-* .
03233     if (comd == "MINO") {
03234        Printf(f_out," ***>MINOs  [maxcalls]  [parno] [parno] ...");
03235        Printf(f_out," Causes a Minos error analysis to be performed on the parameters");
03236        Printf(f_out," whose numbers [parno] are specified. If none are specified,");
03237        Printf(f_out," Minos errors are calculated for all variable parameters.");
03238        Printf(f_out," Minos errors may be expensive to calculate, but are very");
03239        Printf(f_out," reliable since they take account of non-linearities in the");
03240        Printf(f_out," problem as well as parameter correlations, and are in general");
03241        Printf(f_out," asymmetric.");
03242        Printf(f_out," The optional argument [maxcalls] specifies the (approximate)");
03243        Printf(f_out," maximum number of function calls per parameter requested,");
03244        Printf(f_out," after which the calculation will stop for that parameter.");
03245         goto L99;
03246     }
03247 //*-* __________________________________________________________________
03248 //*-* --
03249 //*-* --  Command MNCONTOUR
03250 //*-* --  =================
03251 //*-* .
03252     if (cmd3 == "MNC") {
03253        Printf(f_out," ***>MNContour  <par1> <par2> [npts]");
03254        Printf(f_out," Calculates one function contour of FCN with respect to");
03255        Printf(f_out," parameters par1 and par2, with FCN minimized always with");
03256        Printf(f_out," respect to all other NPAR-2 variable parameters (if any).");
03257        Printf(f_out," Minuit will try to find npts points on the contour (default 20)");
03258        Printf(f_out," If only two parameters are variable at the time, it is not");
03259        Printf(f_out," necessary to specify their numbers. To calculate more than");
03260        Printf(f_out," one contour, it is necessary to SET ERRordef to the appropriate");
03261        Printf(f_out," value and issue the MNContour command for each contour.");
03262         goto L99;
03263     }
03264 //*-* __________________________________________________________________
03265 //*-* --
03266 //*-* --  Command PARAMETER
03267 //*-* --  =================
03268 //*-* .
03269     if (cmd3 == "PAR") {
03270        Printf(f_out," ***>PARameters");
03271        Printf(f_out," followed by one or more parameter definitions.");
03272        Printf(f_out," Parameter definitions are of the form:");
03273        Printf(f_out,"   <number>  ''name''  <value>  <step>  [lolim] [uplim] ");
03274        Printf(f_out," for example:");
03275        Printf(f_out,"  3  ''K width''  1.2   0.1");
03276        Printf(f_out," the last definition is followed by a blank line or a zero.");
03277         goto L99;
03278     }
03279 //*-* __________________________________________________________________
03280 //*-* --
03281 //*-* --  Command RELEASE
03282 //*-* --  ===============
03283 //*-* .
03284     if (cmd3 == "REL") {
03285        Printf(f_out," ***>RELease  <parno> [parno] ... [parno]");
03286        Printf(f_out," If <parno> is the number of a previously variable parameter");
03287        Printf(f_out," which has been fixed by a command: FIX <parno>, then that");
03288        Printf(f_out," parameter will return to variable status.  Otherwise a warning");
03289        Printf(f_out," message is printed and the command is ignored.");
03290        Printf(f_out," Note that this command operates only on parameters which were");
03291        Printf(f_out," at one time variable and have been FIXed. It cannot make");
03292        Printf(f_out," constant parameters variable; that must be done by redefining");
03293        Printf(f_out," the parameter with a PARameters command.");
03294         goto L99;
03295     }
03296 //*-* __________________________________________________________________
03297 //*-* --
03298 //*-* --  Command RESTORE
03299 //*-* --  ===============
03300 //*-* .
03301     if (cmd3 == "RES") {
03302        Printf(f_out," ***>REStore  [code]");
03303        Printf(f_out," If no [code] is specified, this command restores all previously");
03304        Printf(f_out," FIXed parameters to variable status. If [code]=1, then only");
03305        Printf(f_out," the last parameter FIXed is restored to variable status.");
03306        Printf(f_out," If code is neither zero nor one, the command is ignored.");
03307         goto L99;
03308     }
03309 //*-* __________________________________________________________________
03310 //*-* --
03311 //*-* --  Command RETURN
03312 //*-* --  ==============
03313 //*-* .
03314     if (cmd3 == "RET") {
03315        Printf(f_out," ***>RETURN");
03316        Printf(f_out," Signals the end of a data block, and instructs Minuit to return");
03317        Printf(f_out," to the program which called it. The RETurn command first");
03318        Printf(f_out," causes Minuit to CALL FCN with IFLAG=3, in order to allow FCN");
03319        Printf(f_out," to perform any calculations associated with the final fitted");
03320        Printf(f_out," parameter values, unless a CALL FCN 3 command has already been");
03321        Printf(f_out," executed at the current FCN value.");
03322         goto L99;
03323     }
03324 //*-* __________________________________________________________________
03325 //*-* --
03326 //*-* --  Command SAVE
03327 //*-* --  ============
03328 //*-* .
03329     if (cmd3 == "SAV") {
03330        Printf(f_out," ***>SAVe");
03331        Printf(f_out," Causes the current parameter values to be saved on a file in");
03332        Printf(f_out," such a format that they can be read in again as Minuit");
03333        Printf(f_out," parameter definitions. If the covariance matrix exists, it is");
03334        Printf(f_out," also output in such a format. The unit number is by default 7,");
03335        Printf(f_out," or that specified by the user in his call to MINTIO or");
03336        Printf(f_out," MNINIT. The user is responsible for opening the file previous");
03337        Printf(f_out," to issuing the [SAVe] command (except where this can be done");
03338        Printf(f_out," interactively).");
03339         goto L99;
03340     }
03341 //*-* __________________________________________________________________
03342 //*-* --
03343 //*-* --  Command SCAN
03344 //*-* --  ============
03345 //*-* .
03346     if (cmd3 == "SCA") {
03347        Printf(f_out," ***>SCAn  [parno]  [numpts] [from]  [to]");
03348        Printf(f_out," Scans the value of the user function by varying parameter");
03349        Printf(f_out," number [parno], leaving all other parameters fixed at the");
03350        Printf(f_out," current value. If [parno] is not specified, all variable");
03351        Printf(f_out," parameters are scanned in sequence.");
03352        Printf(f_out," The number of points [numpts] in the scan is 40 by default,");
03353        Printf(f_out," and cannot exceed 100. The range of the scan is by default");
03354        Printf(f_out," 2 standard deviations on each side of the current best value,");
03355        Printf(f_out," but can be specified as from [from] to [to].");
03356        Printf(f_out," After each scan, if a new minimum is found, the best parameter");
03357        Printf(f_out," values are retained as start values for future scans or");
03358        Printf(f_out," minimizations. The curve resulting from each scan is plotted");
03359        Printf(f_out," on the output unit in order to show the approximate behaviour");
03360        Printf(f_out," of the function.");
03361        Printf(f_out," This command is not intended for minimization, but is sometimes");
03362        Printf(f_out," useful for debugging the user function or finding a");
03363        Printf(f_out," reasonable starting point.");
03364         goto L99;
03365     }
03366 //*-* __________________________________________________________________
03367 //*-* --
03368 //*-* --  Command SEEK
03369 //*-* --  ============
03370 //*-* .
03371     if (cmd3 == "SEE") {
03372        Printf(f_out," ***>SEEk  [maxcalls]  [devs]");
03373        Printf(f_out," Causes a Monte Carlo minimization of the function, by choosing");
03374        Printf(f_out," random values of the variable parameters, chosen uniformly");
03375        Printf(f_out," over a hypercube centered at the current best value.");
03376        Printf(f_out," The region size is by default 3 standard deviations on each");
03377        Printf(f_out," side, but can be changed by specifying the value of [devs].");
03378         goto L99;
03379     }
03380 //*-* __________________________________________________________________
03381 //*-* --
03382 //*-* --  Command SET
03383 //*-* --  ===========
03384 //*-* .
03385     if (cmd3 == "SET") {
03386        Printf(f_out," ***>SET <option_name>");
03387        Printf(f_out,"  SET BATch");
03388        Printf(f_out,"    Informs Minuit that it is running in batch mode.");
03389 
03390        Printf(f_out," ");
03391        Printf(f_out,"  SET EPSmachine  <accuracy>");
03392        Printf(f_out,"    Informs Minuit that the relative floating point arithmetic");
03393        Printf(f_out,"    precision is <accuracy>. Minuit determines the nominal");
03394        Printf(f_out,"    precision itself, but the SET EPSmachine command can be");
03395        Printf(f_out,"    used to override Minuit own determination, when the user");
03396        Printf(f_out,"    knows that the FCN function value is not calculated to");
03397        Printf(f_out,"    the nominal machine accuracy. Typical values of <accuracy>");
03398        Printf(f_out,"    are between 10**-5 and 10**-14.");
03399 
03400        Printf(f_out," ");
03401        Printf(f_out,"  SET ERRordef  <up>");
03402        Printf(f_out,"    Sets the value of UP (default value= 1.), defining parameter");
03403        Printf(f_out,"    errors. Minuit defines parameter errors as the change");
03404        Printf(f_out,"    in parameter value required to change the function value");
03405        Printf(f_out,"    by UP. Normally, for chisquared fits UP=1, and for negative");
03406        Printf(f_out,"    log likelihood, UP=0.5.");
03407 
03408        Printf(f_out," ");
03409        Printf(f_out,"   SET GRAdient  [force]");
03410        Printf(f_out,"    Informs Minuit that the user function is prepared to");
03411        Printf(f_out,"    calculate its own first derivatives and return their values");
03412        Printf(f_out,"    in the array GRAD when IFLAG=2 (see specs of FCN).");
03413        Printf(f_out,"    If [force] is not specified, Minuit will calculate");
03414        Printf(f_out,"    the FCN derivatives by finite differences at the current");
03415        Printf(f_out,"    point and compare with the user calculation at that point,");
03416        Printf(f_out,"    accepting the user values only if they agree.");
03417        Printf(f_out,"    If [force]=1, Minuit does not do its own derivative");
03418        Printf(f_out,"    calculation, and uses the derivatives calculated in FCN.");
03419 
03420        Printf(f_out," ");
03421        Printf(f_out,"   SET INPut  [unitno]  [filename]");
03422        Printf(f_out,"    Causes Minuit, in data-driven mode only, to read subsequent");
03423        Printf(f_out,"    commands (or parameter definitions) from a different input");
03424        Printf(f_out,"    file. If no [unitno] is specified, reading reverts to the");
03425        Printf(f_out,"    previous input file, assuming that there was one.");
03426        Printf(f_out,"    If [unitno] is specified, and that unit has not been opened,");
03427        Printf(f_out,"    then Minuit attempts to open the file [filename]} if a");
03428        Printf(f_out,"    name is specified. If running in interactive mode and");
03429        Printf(f_out,"    [filename] is not specified and [unitno] is not opened,");
03430        Printf(f_out,"    Minuit prompts the user to enter a file name.");
03431        Printf(f_out,"    If the word REWIND is added to the command (note:no blanks");
03432        Printf(f_out,"    between INPUT and REWIND), the file is rewound before");
03433        Printf(f_out,"    reading. Note that this command is implemented in standard");
03434        Printf(f_out,"    Fortran 77 and the results may depend on the  system;");
03435        Printf(f_out,"    for example, if a filename is given under VM/CMS, it must");
03436        Printf(f_out,"    be preceeded by a slash.");
03437 
03438        Printf(f_out," ");
03439        Printf(f_out,"   SET INTeractive");
03440        Printf(f_out,"    Informs Minuit that it is running interactively.");
03441 
03442        Printf(f_out," ");
03443        Printf(f_out,"   SET LIMits  [parno]  [lolim]  [uplim]");
03444        Printf(f_out,"    Allows the user to change the limits on one or all");
03445        Printf(f_out,"    parameters. If no arguments are specified, all limits are");
03446        Printf(f_out,"    removed from all parameters. If [parno] alone is specified,");
03447        Printf(f_out,"    limits are removed from parameter [parno].");
03448        Printf(f_out,"    If all arguments are specified, then parameter [parno] will");
03449        Printf(f_out,"    be bounded between [lolim] and [uplim].");
03450        Printf(f_out,"    Limits can be specified in either order, Minuit will take");
03451        Printf(f_out,"    the smaller as [lolim] and the larger as [uplim].");
03452        Printf(f_out,"    However, if [lolim] is equal to [uplim], an error condition");
03453        Printf(f_out,"    results.");
03454 
03455        Printf(f_out," ");
03456        Printf(f_out,"   SET LINesperpage");
03457        Printf(f_out,"     Sets the number of lines for one page of output.");
03458        Printf(f_out,"     Default value is 24 for interactive mode");
03459 
03460        Printf(f_out," ");
03461        Printf(f_out,"   SET NOGradient");
03462        Printf(f_out,"    The inverse of SET GRAdient, instructs Minuit not to");
03463        Printf(f_out,"    use the first derivatives calculated by the user in FCN.");
03464 
03465        Printf(f_out," ");
03466        Printf(f_out,"   SET NOWarnings");
03467        Printf(f_out,"    Supresses Minuit warning messages.");
03468 
03469        Printf(f_out," ");
03470        Printf(f_out,"   SET OUTputfile  <unitno>");
03471        Printf(f_out,"    Instructs Minuit to write further output to unit <unitno>.");
03472 
03473        Printf(f_out," ");
03474        Printf(f_out,"   SET PAGethrow  <integer>");
03475        Printf(f_out,"    Sets the carriage control character for ``new page'' to");
03476        Printf(f_out,"    <integer>. Thus the value 1 produces a new page, and 0");
03477        Printf(f_out,"    produces a blank line, on some devices (see TOPofpage)");
03478 
03479 
03480        Printf(f_out," ");
03481        Printf(f_out,"   SET PARameter  <parno>  <value>");
03482        Printf(f_out,"    Sets the value of parameter <parno> to <value>.");
03483        Printf(f_out,"    The parameter in question may be variable, fixed, or");
03484        Printf(f_out,"    constant, but must be defined.");
03485 
03486        Printf(f_out," ");
03487        Printf(f_out,"   SET PRIntout  <level>");
03488        Printf(f_out,"    Sets the print level, determining how much output will be");
03489        Printf(f_out,"    produced. Allowed values and their meanings are displayed");
03490        Printf(f_out,"    after a SHOw PRInt command, and are currently <level>=:");
03491        Printf(f_out,"      [-1]  no output except from SHOW commands");
03492        Printf(f_out,"       [0]  minimum output");
03493        Printf(f_out,"       [1]  default value, normal output");
03494        Printf(f_out,"       [2]  additional output giving intermediate results.");
03495        Printf(f_out,"       [3]  maximum output, showing progress of minimizations.");
03496        Printf(f_out,"    Note: See also the SET WARnings command.");
03497 
03498        Printf(f_out," ");
03499        Printf(f_out,"   SET RANdomgenerator  <seed>");
03500        Printf(f_out,"    Sets the seed of the random number generator used in SEEk.");
03501        Printf(f_out,"    This can be any integer between 10000 and 900000000, for");
03502        Printf(f_out,"    example one which was output from a SHOw RANdom command of");
03503        Printf(f_out,"    a previous run.");
03504 
03505        Printf(f_out," ");
03506        Printf(f_out,"   SET STRategy  <level>");
03507        Printf(f_out,"    Sets the strategy to be used in calculating first and second");
03508        Printf(f_out,"    derivatives and in certain minimization methods.");
03509        Printf(f_out,"    In general, low values of <level> mean fewer function calls");
03510        Printf(f_out,"    and high values mean more reliable minimization.");
03511        Printf(f_out,"    Currently allowed values are 0, 1 (default), and 2.");
03512 
03513        Printf(f_out," ");
03514        Printf(f_out,"   SET TITle");
03515        Printf(f_out,"    Informs Minuit that the next input line is to be considered");
03516        Printf(f_out,"    the (new) title for this task or sub-task.  This is for");
03517        Printf(f_out,"    the convenience of the user in reading his output.");
03518 
03519        Printf(f_out," ");
03520        Printf(f_out,"   SET WARnings");
03521        Printf(f_out,"    Instructs Minuit to output warning messages when suspicious");
03522        Printf(f_out,"    conditions arise which may indicate unreliable results.");
03523        Printf(f_out,"    This is the default.");
03524 
03525        Printf(f_out," ");
03526        Printf(f_out,"    SET WIDthpage");
03527        Printf(f_out,"    Informs Minuit of the output page width.");
03528        Printf(f_out,"    Default values are 80 for interactive jobs");
03529         goto L99;
03530     }
03531 //*-* __________________________________________________________________
03532 //*-* --
03533 //*-* --  Command SHOW
03534 //*-* --  ============
03535 //*-* .
03536     if (cmd3 == "SHO") {
03537        Printf(f_out," ***>SHOw  <option_name>");
03538        Printf(f_out,"  All SET XXXX commands have a corresponding SHOw XXXX command.");
03539        Printf(f_out,"  In addition, the SHOw commands listed starting here have no");
03540        Printf(f_out,"  corresponding SET command for obvious reasons.");
03541 
03542        Printf(f_out," ");
03543        Printf(f_out,"   SHOw CORrelations");
03544        Printf(f_out,"    Calculates and prints the parameter correlations from the");
03545        Printf(f_out,"    error matrix.");
03546 
03547        Printf(f_out," ");
03548        Printf(f_out,"   SHOw COVariance");
03549        Printf(f_out,"    Prints the (external) covariance (error) matrix.");
03550 
03551        Printf(f_out," ");
03552        Printf(f_out,"   SHOw EIGenvalues");
03553        Printf(f_out,"    Calculates and prints the eigenvalues of the covariance");
03554        Printf(f_out,"    matrix.");
03555 
03556        Printf(f_out," ");
03557        Printf(f_out,"   SHOw FCNvalue");
03558        Printf(f_out,"    Prints the current value of FCN.");
03559         goto L99;
03560     }
03561 //*-* __________________________________________________________________
03562 //*-* --
03563 //*-* --  Command SIMPLEX
03564 //*-* --  ===============
03565 //*-* .
03566     if (cmd3 == "SIM") {
03567        Printf(f_out," ***>SIMplex  [maxcalls]  [tolerance]");
03568        Printf(f_out," Performs a function minimization using the simplex method of");
03569        Printf(f_out," Nelder and Mead. Minimization terminates either when the");
03570        Printf(f_out," function has been called (approximately) [maxcalls] times,");
03571        Printf(f_out," or when the estimated vertical distance to minimum (EDM) is");
03572        Printf(f_out," less than [tolerance].");
03573        Printf(f_out," The default value of [tolerance] is 0.1*UP(see SET ERRordef).");
03574         goto L99;
03575     }
03576 //*-* __________________________________________________________________
03577 //*-* --
03578 //*-* --  Command STANDARD
03579 //*-* --  ================
03580 //*-* .
03581     if (cmd3 == "STA") {
03582        Printf(f_out," ***>STAndard");
03583         goto L99;
03584     }
03585 //*-* __________________________________________________________________
03586 //*-* --
03587 //*-* --  Command STOP
03588 //*-* --  ============
03589 //*-* .
03590     if (cmd3 == "STO") {
03591        Printf(f_out," ***>STOP");
03592        Printf(f_out," Same as EXIT.");
03593         goto L99;
03594     }
03595 //*-* __________________________________________________________________
03596 //*-* --
03597 //*-* --  Command TOPOFPAGE
03598 //*-* --  =================
03599 //*-* .
03600     if (cmd3 == "TOP") {
03601        Printf(f_out," ***>TOPofpage");
03602        Printf(f_out," Causes Minuit to write the character specified in a");
03603        Printf(f_out," SET PAGethrow command (default = 1) to column 1 of the output");
03604        Printf(f_out," file, which may or may not position your output medium to");
03605        Printf(f_out," the top of a page depending on the device and system.");
03606         goto L99;
03607     }
03608 //*-* __________________________________________________________________
03609        Printf(f_out," Unknown MINUIT command. Type HELP for list of commands.");
03610 
03611 L99:
03612     return;
03613 } /* mnhelp_ */
03614 
03615 //______________________________________________________________________________
03616 inline
03617 void fitter::mnhess()
03618 {
03619 //*-*-*-*-*-*Calculates the full second-derivative matrix of FCN*-*-*-*-*-*-*-*
03620 //*-*        ===================================================
03621 //*-*        by taking finite differences. When calculating diagonal
03622 //*-*        elements, it may iterate so that step size is nearly that
03623 //*-*        which gives function change= UP/10. The first derivatives
03624 //*-*        of course come as a free side effect, but with a smaller
03625 //*-*        step size in order to obtain a known accuracy.
03626 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
03627 
03628     /* Local variables */
03629     /*static*/ double dmin_, dxdi, elem, wint, tlrg2, d, dlast, ztemp, g2bfor;
03630     /*static*/ double  yy[kMAXDIM], df, aimsag, fs1, tlrstp, fs2, stpinm, g2i, sag, xtf, xti, xtj;
03631     /*static*/ int icyc, ncyc, ndex, idrv, iext, npar2, i, j, ifail, npard, nparx, idn, multpy;
03632     /*static*/ bool ldebug;
03633     sag = 0; //GB : to rm warning.
03634 
03635     ldebug = fIdbg[3] >= 1;
03636     if (fAmin == fUndefi) {
03637         mnamin();
03638     }
03639     if (fIstrat <= 0) {
03640         ncyc   = 3;
03641         tlrstp = .5;
03642         tlrg2  = .1;
03643     } else if (fIstrat == 1) {
03644         ncyc   = 5;
03645         tlrstp = .3;
03646         tlrg2  = .05;
03647     } else {
03648         ncyc   = 7;
03649         tlrstp = .1;
03650         tlrg2  = .02;
03651     }
03652     if (fISW[4] >= 2 || ldebug) {
03653         Printf(f_out,"   START COVARIANCE MATRIX CALCULATION.");
03654     }
03655     fCfrom  = "HESSE   ";
03656     fNfcnfr = fNfcn;
03657     fCstatu = "OK        ";
03658     npard   = fNpar;
03659 //*-*-                make sure starting at the right place
03660     mninex(fX);
03661     nparx = fNpar;
03662     //Printf(f_out,"debug : FCN : 011");
03663     (*fFCN)(nparx, fGin, fs1, fU, 4,fTag);    ++fNfcn;
03664     if (fs1 != fAmin) {
03665         df    = fAmin - fs1;
03666         mnwarn("D", "MNHESS", Form("function value differs from AMIN by %g",df));
03667     }
03668     fAmin = fs1;
03669     if (ldebug) {
03670         Printf(f_out," PAR D   GSTEP           D          G2         GRD         SAG    ");
03671     }
03672 //*-*-                                       . . . . . . diagonal elements .
03673 
03674 //*-*-        ISW(2) = 1 if approx, 2 if not posdef, 3 if ok
03675 //*-*-        AIMSAG is the sagitta we are aiming for in second deriv calc.
03676 
03677     aimsag = TMath_Sqrt(fEpsma2)*(TMath_Abs(fAmin) + fUp);
03678 //*-*-        Zero the second derivative matrix
03679     npar2 = fNpar*(fNpar + 1) / 2;
03680     for (i = 1; i <= npar2; ++i) { fVhmat[i-1] = 0; }
03681 
03682 //*-*-        Loop over variable parameters for second derivatives
03683     idrv = 2;
03684     for (idn = 1; idn <= npard; ++idn) {
03685         i = idn + fNpar - npard;
03686         iext = fNexofi[i-1];
03687         if (fG2[i-1] == 0) {
03688             mnwarn("W", "HESSE", Form("Second derivative enters zero, param %d",iext));
03689             wint = fWerr[i-1];
03690             if (fNvarl[iext-1] > 1) {
03691                 mndxdi(fX[i-1], i-1, dxdi);
03692                 if (TMath_Abs(dxdi) < .001) wint = .01;
03693                 else                          wint /= TMath_Abs(dxdi);
03694             }
03695             fG2[i-1] = fUp / (wint*wint);
03696         }
03697         xtf   = fX[i-1];
03698         dmin_ = fEpsma2*8*TMath_Abs(xtf);
03699 
03700 //*-*-                              find step which gives sagitta = AIMSAG
03701         d = TMath_Abs(fGstep[i-1]);
03702         int skip50 = 0;
03703         for (icyc = 1; icyc <= ncyc; ++icyc) {
03704 //*-*-                              loop here only if SAG=0
03705             for (multpy = 1; multpy <= 5; ++multpy) {
03706 //*-*-          take two steps
03707                 fX[i-1] = xtf + d;
03708                 mninex(fX);
03709                 nparx = fNpar;
03710     //Printf(f_out,"debug : FCN : 012");
03711                 (*fFCN)(nparx, fGin, fs1, fU, 4,fTag);    ++fNfcn;
03712                 fX[i-1] = xtf - d;
03713                 mninex(fX);
03714                 (*fFCN)(nparx, fGin, fs2, fU, 4,fTag);    ++fNfcn;
03715                 fX[i-1] = xtf;
03716                 sag = (fs1 + fs2 - fAmin*2)*.5;
03717                 if (sag != 0) goto L30;
03718                 if (fGstep[i-1] < 0) {
03719                     if (d >= .5) goto L26;
03720                     d *= 10;
03721                     if (d > .5)         d = .51;
03722                     continue;
03723                 }
03724                 d *= 10;
03725             }
03726 L26:
03727             mnwarn("W", "HESSE", Form("Second derivative zero for parameter%d",iext));
03728             goto L390;
03729 //*-*-                            SAG is not zero
03730 L30:
03731             g2bfor    = fG2[i-1];
03732             fG2[i-1]  = sag*2 / (d*d);
03733             fGrd[i-1] = (fs1 - fs2) / (d*2);
03734             if (ldebug) {
03735                 Printf(f_out,"%4d%2d%12.5g%12.5g%12.5g%12.5g%12.5g%12.5g",i,idrv,fGstep[i-1],fG2[i-1],fGrd[i-1],sag);
03736             }
03737             if (fGstep[i-1] > 0) fGstep[i-1] =  TMath_Abs(d);
03738             else                 fGstep[i-1] = -TMath_Abs(d);
03739             fDirin[i-1] = d;
03740             yy[i-1]     = fs1;
03741             dlast       = d;
03742             d           = TMath_Sqrt(aimsag*2 / TMath_Abs(fG2[i-1]));
03743 //*-*-        if parameter has limits, max int step size = 0.5
03744             stpinm = .5;
03745             if (fGstep[i-1] < 0) d = TMath_Min(d,stpinm);
03746             if (d < dmin_) d = dmin_;
03747 //*-*-          see if converged
03748             if (TMath_Abs((d - dlast) / d) < tlrstp ||
03749                 TMath_Abs((fG2[i-1] - g2bfor) / fG2[i-1]) < tlrg2) {
03750                skip50 = 1;
03751                break;
03752             }
03753             d = TMath_Min(d,dlast*102);
03754             d = TMath_Max(d,dlast*.1);
03755         }
03756 //*-*-                      end of step size loop
03757         if (!skip50)
03758            mnwarn("D", "MNHESS", Form("Second Deriv. SAG,AIM= %d%g%g",iext,sag,aimsag));
03759 
03760         ndex = i*(i + 1) / 2;
03761         fVhmat[ndex-1] = fG2[i-1];
03762     }
03763 //*-*-                             end of diagonal second derivative loop
03764     mninex(fX);
03765 //*-*-                                    refine the first derivatives
03766     if (fIstrat > 0) mnhes1();
03767     fISW[1] = 3;
03768     fDcovar = 0;
03769 //*-*-                                       . . . .  off-diagonal elements
03770 
03771     if (fNpar == 1) goto L214;
03772     for (i = 1; i <= fNpar; ++i) {
03773         for (j = 1; j <= i-1; ++j) {
03774             xti     = fX[i-1];
03775             xtj     = fX[j-1];
03776             fX[i-1] = xti + fDirin[i-1];
03777             fX[j-1] = xtj + fDirin[j-1];
03778             mninex(fX);
03779     //Printf(f_out,"debug : FCN : 013");
03780             (*fFCN)(nparx, fGin, fs1, fU, 4,fTag);          ++fNfcn;
03781             fX[i-1] = xti;
03782             fX[j-1] = xtj;
03783             elem = (fs1 + fAmin - yy[i-1] - yy[j-1]) / (
03784                     fDirin[i-1]*fDirin[j-1]);
03785             ndex = i*(i-1) / 2 + j;
03786             fVhmat[ndex-1] = elem;
03787         }
03788     }
03789 L214:
03790     mninex(fX);
03791 //*-*-                 verify matrix positive-definite
03792     mnpsdf();
03793     for (i = 1; i <= fNpar; ++i) {
03794         for (j = 1; j <= i; ++j) {
03795             ndex = i*(i-1) / 2 + j;
03796             fP[i + j*fMaxpar - fMaxpar-1] = fVhmat[ndex-1];
03797             fP[j + i*fMaxpar - fMaxpar-1] = fP[i + j*fMaxpar - fMaxpar-1];
03798         }
03799     }
03800     mnvert(fP, fMaxint, fMaxint, fNpar, ifail);
03801     if (ifail > 0) {
03802         mnwarn("W", "HESSE", "Matrix inversion fails.");
03803         goto L390;
03804     }
03805 //*-*-                                       . . . . . . .  calculate  e d m
03806     fEDM = 0;
03807 
03808     for (i = 1; i <= fNpar; ++i) {
03809 //*-*-                             off-diagonal elements
03810         ndex = i*(i-1) / 2;
03811         for (j = 1; j <= i-1; ++j) {
03812             ++ndex;
03813             ztemp = fP[i + j*fMaxpar - fMaxpar-1]*2;
03814             fEDM += fGrd[i-1]*ztemp*fGrd[j-1];
03815             fVhmat[ndex-1] = ztemp;
03816         }
03817 //*-*-                             diagonal elements
03818         ++ndex;
03819         fVhmat[ndex-1] = fP[i + i*fMaxpar - fMaxpar-1]*2;
03820         fEDM += fP[i + i*fMaxpar - fMaxpar-1]*(fGrd[i-1]*fGrd[i-1]);
03821     }
03822     if (fISW[4] >= 1 && fISW[1] == 3 && fItaur == 0) {
03823         Printf(f_out," COVARIANCE MATRIX CALCULATED SUCCESSFULLY");
03824     }
03825     goto L900;
03826 //*-*-                             failure to invert 2nd deriv matrix
03827 L390:
03828     fISW[1] = 1;
03829     fDcovar = 1;
03830     fCstatu = "FAILED    ";
03831     if (fISW[4] >= 0) {
03832         Printf(f_out,"  MNHESS FAILS AND WILL RETURN DIAGONAL MATRIX. ");
03833     }
03834     for (i = 1; i <= fNpar; ++i) {
03835         ndex = i*(i-1) / 2;
03836         for (j = 1; j <= i-1; ++j) {
03837             ++ndex;
03838             fVhmat[ndex-1] = 0;
03839         }
03840         ++ndex;
03841         g2i = fG2[i-1];
03842         if (g2i <= 0) g2i = 1;
03843         fVhmat[ndex-1] = 2 / g2i;
03844     }
03845 L900:
03846     return;
03847 } /* mnhess_ */
03848 
03849 //______________________________________________________________________________
03850 inline
03851 void fitter::mnhes1()
03852 {
03853 //*-*-*-*Calculate first derivatives (GRD) and uncertainties (DGRD)*-*-*-*-*-*
03854 //*-*    ==========================================================
03855 //*-*         and appropriate step sizes GSTEP
03856 //*-*      Called from MNHESS and MNGRAD
03857 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
03858 
03859     /* Local variables */
03860     /*static*/ double dmin_, d, dfmin, dgmin, change, chgold, grdold, epspri;
03861     /*static*/ double fs1, optstp, fs2, grdnew, sag, xtf;
03862     /*static*/ int icyc, ncyc, idrv, i, nparx;
03863     /*static*/ bool ldebug;
03864     dgmin = 0; //GB : to rm warning.
03865     grdnew = 0; //GB
03866     grdold = 0; //GB
03867 
03868     ldebug = fIdbg[5] >= 1;
03869     if (fIstrat <= 0) ncyc = 1;
03870     if (fIstrat == 1) ncyc = 2;
03871     if (fIstrat > 1)  ncyc = 6;
03872     idrv = 1;
03873     nparx = fNpar;
03874     dfmin = fEpsma2*4*(TMath_Abs(fAmin) + fUp);
03875 //*-*-                                    main loop over parameters
03876     for (i = 1; i <= fNpar; ++i) {
03877         xtf    = fX[i-1];
03878         dmin_  = fEpsma2*4*TMath_Abs(xtf);
03879         epspri = fEpsma2 + TMath_Abs(fGrd[i-1]*fEpsma2);
03880         optstp = TMath_Sqrt(dfmin / (TMath_Abs(fG2[i-1]) + epspri));
03881         d = TMath_Abs(fGstep[i-1])*.2;
03882         if (d > optstp) d = optstp;
03883         if (d < dmin_)  d = dmin_;
03884         chgold = 1e4;
03885 //*-*-                                      iterate reducing step size
03886         for (icyc = 1; icyc <= ncyc; ++icyc) {
03887             fX[i-1] = xtf + d;
03888             mninex(fX);
03889     //Printf(f_out,"debug : FCN : 014");
03890             (*fFCN)(nparx, fGin, fs1, fU, 4,fTag);          ++fNfcn;
03891             fX[i-1] = xtf - d;
03892             mninex(fX);
03893             (*fFCN)(nparx, fGin, fs2, fU, 4,fTag);          ++fNfcn;
03894             fX[i-1] = xtf;
03895 //*-*-                                      check if step sizes appropriate
03896             sag    = (fs1 + fs2 - fAmin*2)*.5;
03897             grdold = fGrd[i-1];
03898             grdnew = (fs1 - fs2) / (d*2);
03899             dgmin  = fEpsmac*(TMath_Abs(fs1) + TMath_Abs(fs2)) / d;
03900             if (ldebug) {
03901                 Printf(f_out,"%4d%2d%12.5g%12.5g%12.5g%12.5g%12.5g%12.5g",i,idrv,fGstep[i-1],d,fG2[i-1],grdnew,sag);
03902             }
03903             if (grdnew == 0) goto L60;
03904             change = TMath_Abs((grdold - grdnew) / grdnew);
03905             if (change > chgold && icyc > 1) goto L60;
03906             chgold    = change;
03907             fGrd[i-1] = grdnew;
03908             if (fGstep[i-1] > 0) fGstep[i-1] =  TMath_Abs(d);
03909             else                 fGstep[i-1] = -TMath_Abs(d);
03910 //*-*-                 decrease step until first derivative changes by <5%
03911             if (change < .05) goto L60;
03912             if (TMath_Abs(grdold - grdnew) < dgmin) goto L60;
03913             if (d < dmin_) {
03914                 mnwarn("D", "MNHES1", "Step size too small for 1st drv.");
03915                 goto L60;
03916             }
03917             d *= .2;
03918         }
03919 //*-*-                                      loop satisfied = too many iter
03920         mnwarn("D", "MNHES1", Form("Too many iterations on D1.%g%g",grdold,grdnew));
03921 L60:
03922         fDgrd[i-1] = TMath_Max(dgmin,TMath_Abs(grdold - grdnew));
03923     }
03924 //*-*-                                       end of first deriv. loop
03925     mninex(fX);
03926 } /* mnhes1_ */
03927 
03928 //______________________________________________________________________________
03929 inline
03930 void fitter::mnimpr()
03931 {
03932 //*-*-*-*-*-*-*Attempts to improve on a good local minimum*-*-*-*-*-*-*-*-*-*
03933 //*-*          ===========================================
03934 //*-*        Attempts to improve on a good local minimum by finding a
03935 //*-*        better one.   The quadratic part of FCN is removed by MNCALF
03936 //*-*        and this transformed function is minimized using the simplex
03937 //*-*        method from several random starting points.
03938 //*-*        ref. -- Goldstein and Price, Math.Comp. 25, 569 (1971)
03939 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
03940 
03941     /* Initialized data */
03942 
03943     /*static*/ double rnum = 0;
03944 
03945     /* Local variables */
03946     /*static*/ double amax, dsav[kMAXDIM], y[kMAXDIM+1], ycalf, ystar, ystst;
03947     /*static*/ double pb, ep, wg, xi, sigsav, reg, sig2;
03948     /*static*/ int npfn, ndex, loop, i, j, ifail, iseed;
03949     /*static*/ int jhold, nloop, nparx, nparp1, jh, jl;
03950     loop = 0; //GB : rm warning.
03951 
03952     if (fNpar <= 0) return;
03953     if (fAmin == fUndefi) mnamin();
03954     fCstatu = "UNCHANGED ";
03955     fItaur  = 1;
03956     fEpsi   = fUp*.1;
03957     npfn    = fNfcn;
03958     nloop   = int(fWord7[1]);
03959     if (nloop <= 0) nloop = fNpar + 4;
03960     nparx  = fNpar;
03961     nparp1 = fNpar + 1;
03962     wg = 1 / double(fNpar);
03963     sigsav = fEDM;
03964     fApsi  = fAmin;
03965     for (i = 1; i <= fNpar; ++i) {
03966         fXt[i-1]  = fX[i-1];
03967         dsav[i-1] = fWerr[i-1];
03968         for (j = 1; j <= i; ++j) {
03969             ndex = i*(i-1) / 2 + j;
03970             fP[i + j*fMaxpar - fMaxpar-1] = fVhmat[ndex-1];
03971             fP[j + i*fMaxpar - fMaxpar-1] = fP[i + j*fMaxpar - fMaxpar-1];
03972         }
03973     }
03974     mnvert(fP, fMaxint, fMaxint, fNpar, ifail);
03975     if (ifail >= 1) goto L280;
03976 //*-*-              Save inverted matrix in VT
03977     for (i = 1; i <= fNpar; ++i) {
03978         ndex = i*(i-1) / 2;
03979         for (j = 1; j <= i; ++j) {
03980             ++ndex;
03981             fVthmat[ndex-1] = fP[i + j*fMaxpar - fMaxpar-1];
03982         }
03983     }
03984     loop = 0;
03985 
03986 L20:
03987     for (i = 1; i <= fNpar; ++i) {
03988         fDirin[i-1] = dsav[i-1]*2;
03989         mnrn15(rnum, iseed);
03990         fX[i-1] = fXt[i-1] + fDirin[i-1]*2*(rnum - .5);
03991     }
03992     ++loop;
03993     reg = 2;
03994     if (fISW[4] >= 0) {
03995         Printf(f_out,"START ATTEMPT NO.%2d TO FIND NEW MINIMUM",loop);
03996     }
03997 L30:
03998     mncalf(fX, ycalf);
03999     fAmin = ycalf;
04000 //*-*-                                       . . . . set up  random simplex
04001     jl = nparp1;
04002     jh = nparp1;
04003     y[nparp1-1] = fAmin;
04004     amax = fAmin;
04005     for (i = 1; i <= fNpar; ++i) {
04006         xi = fX[i-1];
04007         mnrn15(rnum, iseed);
04008         fX[i-1] = xi - fDirin[i-1]*(rnum - .5);
04009         mncalf(fX, ycalf);
04010         y[i-1] = ycalf;
04011         if (y[i-1] < fAmin) {
04012             fAmin = y[i-1];
04013             jl    = i;
04014         } else if (y[i-1] > amax) {
04015             amax = y[i-1];
04016             jh   = i;
04017         }
04018         for (j = 1; j <= fNpar; ++j) { fP[j + i*fMaxpar - fMaxpar-1] = fX[j-1]; }
04019         fP[i + nparp1*fMaxpar - fMaxpar-1] = xi;
04020         fX[i-1] = xi;
04021     }
04022 
04023     fEDM = fAmin;
04024     sig2 = fEDM;
04025 //*-*-                                       . . . . . . .  start main loop
04026 L50:
04027     if (fAmin < 0)   goto L95;
04028     if (fISW[1] <= 2) goto L280;
04029     ep = fAmin*.1;
04030     if (sig2 < ep && fEDM < ep) goto L100;
04031     sig2 = fEDM;
04032     if (fNfcn - npfn > fNfcnmx) goto L300;
04033 //*-*-        calculate new point * by reflection
04034     for (i = 1; i <= fNpar; ++i) {
04035         pb = 0;
04036         for (j = 1; j <= nparp1; ++j) { pb += wg*fP[i + j*fMaxpar - fMaxpar-1]; }
04037         fPbar[i-1]  = pb - wg*fP[i + jh*fMaxpar - fMaxpar-1];
04038         fPstar[i-1] = fPbar[i-1]*2 - fP[i + jh*fMaxpar - fMaxpar-1]*1;
04039     }
04040     mncalf(fPstar, ycalf);
04041     ystar = ycalf;
04042     if (ystar >= fAmin) goto L70;
04043 //*-*-        point * better than jl, calculate new point **
04044     for (i = 1; i <= fNpar; ++i) {
04045         fPstst[i-1] = fPstar[i-1]*2 + fPbar[i- 1]*-1;
04046     }
04047     mncalf(fPstst, ycalf);
04048     ystst = ycalf;
04049     if (ystst < y[jl-1]) goto L67;
04050     mnrazz(ystar, fPstar, y, jh, jl);
04051     goto L50;
04052 L67:
04053     mnrazz(ystst, fPstst, y, jh, jl);
04054     goto L50;
04055 //*-*-        point * is not as good as jl
04056 L70:
04057     if (ystar >= y[jh-1]) goto L73;
04058     jhold = jh;
04059     mnrazz(ystar, fPstar, y, jh, jl);
04060     if (jhold != jh) goto L50;
04061 //*-*-        calculate new point **
04062 L73:
04063     for (i = 1; i <= fNpar; ++i) {
04064         fPstst[i-1] = fP[i + jh*fMaxpar - fMaxpar-1]*.5 + fPbar[i-1]*.5;
04065     }
04066     mncalf(fPstst, ycalf);
04067     ystst = ycalf;
04068     if (ystst > y[jh-1]) goto L30;
04069 //*-*-    point ** is better than jh
04070     if (ystst < fAmin) goto L67;
04071     mnrazz(ystst, fPstst, y, jh, jl);
04072     goto L50;
04073 //*-*-                                       . . . . . .  end main loop
04074 L95:
04075     if (fISW[4] >= 0) {
04076         Printf(f_out," AN IMPROVEMENT ON THE PREVIOUS MINIMUM HAS BEEN FOUND");
04077     }
04078     reg = .1;
04079 //*-*-                                       . . . . . ask if point is new
04080 L100:
04081     mninex(fX);
04082     //Printf(f_out,"debug : FCN : 015");
04083     (*fFCN)(nparx, fGin, fAmin, fU, 4,fTag);    ++fNfcn;
04084     for (i = 1; i <= fNpar; ++i) {
04085         fDirin[i-1] = reg*dsav[i-1];
04086         if (TMath_Abs(fX[i-1] - fXt[i-1]) > fDirin[i-1])     goto L150;
04087     }
04088     goto L230;
04089 L150:
04090     fNfcnmx = fNfcnmx + npfn - fNfcn;
04091     npfn    = fNfcn;
04092     mnsimp();
04093     if (fAmin >= fApsi) goto L325;
04094     for (i = 1; i <= fNpar; ++i) {
04095         fDirin[i-1] = dsav[i-1]*.1;
04096         if (TMath_Abs(fX[i-1] - fXt[i-1]) > fDirin[i-1])     goto L250;
04097     }
04098 L230:
04099     if (fAmin < fApsi)  goto L350;
04100     goto L325;
04101 /*                                        . . . . . . truly new minimum */
04102 L250:
04103     fLnewmn = true;
04104     if (fISW[1] >= 1) {
04105         fISW[1] = 1;
04106         fDcovar = TMath_Max(fDcovar,.5);
04107     } else fDcovar = 1;
04108     fItaur  = 0;
04109     fNfcnmx = fNfcnmx + npfn - fNfcn;
04110     fCstatu = "NEW MINIMU";
04111     if (fISW[4] >= 0) {
04112         Printf(f_out," IMPROVE HAS FOUND A TRULY NEW MINIMUM");
04113         Printf(f_out," *************************************");
04114     }
04115     return;
04116 //*-*-                                       . . . return to previous region
04117 L280:
04118     if (fISW[4] > 0) {
04119         Printf(f_out," COVARIANCE MATRIX WAS NOT POSITIVE-DEFINITE");
04120     }
04121     goto L325;
04122 L300:
04123     fISW[0] = 1;
04124 L325:
04125     for (i = 1; i <= fNpar; ++i) {
04126         fDirin[i-1] = dsav[i-1]*.01;
04127         fX[i-1]     = fXt[i-1];
04128     }
04129     fAmin = fApsi;
04130     fEDM  = sigsav;
04131 L350:
04132     mninex(fX);
04133     if (fISW[4] > 0) {
04134         Printf(f_out," IMPROVE HAS RETURNED TO REGION OF ORIGINAL MINIMUM");
04135     }
04136     fCstatu = "UNCHANGED ";
04137     mnrset(0);
04138     if (fISW[1] < 2) goto L380;
04139     if (loop < nloop && fISW[0] < 1) goto L20;
04140 L380:
04141     mnprin(5, fAmin);
04142     fItaur = 0;
04143 } /* mnimpr_ */
04144 
04145 //______________________________________________________________________________
04146 inline
04147 void fitter::mninex(double *pint)
04148 {
04149 //*-*-*-*-*Transforms from internal coordinates (PINT) to external (U)*-*-*-*
04150 //*-*      ===========================================================
04151 //*-*        The minimizing routines which work in
04152 //*-*        internal coordinates call this routine before calling FCN.
04153 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
04154 
04155     int i, j;
04156 
04157     for (j = 1; j <= fNpar; ++j) {
04158         i = fNexofi[j-1];
04159         if (fNvarl[i-1] == 1) {
04160             fU[i-1] = pint[j-1];
04161         } else {
04162             fU[i-1] = fAlim[i-1] + (TMath_Sin(pint[j-1]) + 1)*.5*(fBlim[i-1] - fAlim[i-1]);
04163         }
04164     }
04165 } /* mninex_ */
04166 
04167 //______________________________________________________________________________
04168 inline
04169 void fitter::mninit(int i1, int i2, int i3)
04170 {
04171 //*-*-*-*-*-*Main initialization member function for MINUIT*-*-*-*-*-*-*-*-*
04172 //*-*        ==============================================
04173 //*-*     It initializes some constants
04174 //*-*                (including the logical I/O unit nos.),
04175 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
04176 
04177     /* Local variables */
04178     /*static*/ double piby2, epsp1, epsbak, epstry, distnn;
04179     /*static*/ int i, idb;
04180 
04181 //*-*-           I/O unit numbers
04182     fIsysrd = i1;
04183     fIsyswr = i2;
04184     fIstkwr[0] = fIsyswr;
04185     fNstkwr = 1;
04186     fIsyssa = i3;
04187     fNstkrd = 0;
04188 //*-*-              version identifier
04189     fCvrsn  = "95.03++ ";
04190 //*-*-              some CONSTANT
04191     fMaxint = fMaxpar;
04192     fMaxext = 2*fMaxpar;
04193     fUndefi = -54321;
04194     fBigedm = 123456;
04195     fCundef = ")UNDEFINED";
04196     fCovmes[0] = "NO ERROR MATRIX       ";
04197     fCovmes[1] = "ERR MATRIX APPROXIMATE";
04198     fCovmes[2] = "ERR MATRIX NOT POS-DEF";
04199     fCovmes[3] = "ERROR MATRIX ACCURATE ";
04200 //*-*-               some starting values
04201     fNblock = 0;
04202     fIcomnd = 0;
04203     fCtitl  = fCundef;
04204     fCfrom  = "INPUT   ";
04205     fNfcn   = 0;
04206     fNfcnfr = fNfcn;
04207     fCstatu = "INITIALIZE";
04208     fISW[2] = 0;
04209     fISW[3] = 0;
04210     fISW[4] = 1;
04211 //*-*-        ISW(6)=0 for batch jobs,  =1 for interactive jobs
04212 //*-*-                     =-1 for originally interactive temporarily batch
04213 
04214     fISW[5] = 0;
04215 //    if (intrac(&dummy)) fISW[5] = 1;
04216 //*-*-       DEBUG options set to default values
04217     for (idb = 0; idb <= 10; ++idb) { fIdbg[idb] = 0; }
04218     fLrepor = false;
04219     fLwarn  = true;
04220     fLimset = false;
04221     fLnewmn = false;
04222     fIstrat = 1;
04223     fItaur  = 0;
04224 //*-*-       default page dimensions and 'new page' carriage control integer
04225     fNpagwd = 120;
04226     fNpagln = 56;
04227     fNewpag = 1;
04228     if (fISW[5] > 0) {
04229         fNpagwd = 80;
04230         fNpagln = 30;
04231         fNewpag = 0;
04232     }
04233     fUp = 1;
04234     fUpdflt = fUp;
04235 //*-*-                  determine machine accuracy epsmac
04236     epstry = .5;
04237     for (i = 1; i <= 100; ++i) {
04238         epstry *= .5;
04239         epsp1 = epstry + 1;
04240         mntiny(epsp1, epsbak);
04241         if (epsbak < epstry) goto L35;
04242     }
04243     epstry = 1e-7;
04244     fEpsmac = epstry*4;
04245     Printf(f_out," MNINIT UNABLE TO DETERMINE ARITHMETIC PRECISION. WILL ASSUME:%g",fEpsmac);
04246 L35:
04247     fEpsmac = epstry*8;
04248     fEpsma2 = TMath_Sqrt(fEpsmac)*2;
04249 //*-*-                the vlims are a non-negligible distance from pi/2
04250 //*-*-        used by MNPINT to set variables "near" the physical limits
04251     piby2   = TMath_ATan(1.)*2;
04252     distnn  = TMath_Sqrt(fEpsma2)*8;
04253     fVlimhi =  piby2 - distnn;
04254     fVlimlo = -piby2 + distnn;
04255     mncler();
04256 //    Printf(f_out,"  MINUIT RELEASE %s INITIALIZED.   DIMENSIONS 100/50  EPSMAC=%g",fCvrsn.c_str(),fEpsmac);
04257 } /* mninit_ */
04258 
04259 //______________________________________________________________________________
04260 inline
04261 void fitter::mnlims()
04262 {
04263 //*-*-*-*Interprets the SET LIM command, to reset the parameter limits*-*-*-*
04264 //*-*    =============================================================
04265 //*-*       Called from MNSET
04266 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
04267 
04268     /* Local variables */
04269     /*static*/ double dxdi, snew;
04270     /*static*/ int kint, i2, newcod, ifx, inu;
04271     ifx = 1; //GB
04272 
04273     fCfrom  = "SET LIM ";
04274     fNfcnfr = fNfcn;
04275     fCstatu = "NO CHANGE ";
04276     i2 = int(fWord7[0]);
04277     if (i2 > fMaxext || i2 < 0) goto L900;
04278     if (i2 > 0) goto L30;
04279 //*-*-                                    set limits on all parameters
04280     newcod = 4;
04281     if (fWord7[1] == fWord7[2]) newcod = 1;
04282     for (inu = 1; inu <= fNu; ++inu) {
04283         if (fNvarl[inu-1] <= 0) continue;
04284         if (fNvarl[inu-1] == 1 && newcod == 1) continue;
04285         kint = fNiofex[inu-1];
04286 //*-*-            see if parameter has been fixed
04287         if (kint <= 0) {
04288             if (fISW[4] >= 0) {
04289                 Printf(f_out,"           LIMITS NOT CHANGED FOR FIXED PARAMETER:%4d",inu);
04290             }
04291             continue;
04292         }
04293         if (newcod == 1) {
04294 //*-*-           remove limits from parameter
04295             if (fISW[4] > 0) {
04296                 Printf(f_out," LIMITS REMOVED FROM PARAMETER  :%3d",inu);
04297             }
04298             fCstatu = "NEW LIMITS";
04299             mndxdi(fX[kint-1], kint-1, dxdi);
04300             snew           = fGstep[kint-1]*dxdi;
04301             fGstep[kint-1] = TMath_Abs(snew);
04302             fNvarl[inu-1]  = 1;
04303         } else {
04304 //*-*-            put limits on parameter
04305             fAlim[inu-1] = TMath_Min(fWord7[1],fWord7[2]);
04306             fBlim[inu-1] = TMath_Max(fWord7[1],fWord7[2]);
04307             if (fISW[4] > 0) {
04308                 Printf(f_out," PARAMETER %3d LIMITS SET TO  %15.5g%15.5g",inu,fAlim[inu-1],fBlim[inu-1]);
04309             }
04310             fNvarl[inu-1]  = 4;
04311             fCstatu        = "NEW LIMITS";
04312             fGstep[kint-1] = -.1;
04313         }
04314     }
04315     goto L900;
04316 //*-*-                                      set limits on one parameter
04317 L30:
04318     if (fNvarl[i2-1] <= 0) {
04319         Printf(f_out," PARAMETER %3d IS NOT VARIABLE.", i2);
04320         goto L900;
04321     }
04322     kint = fNiofex[i2-1];
04323 //*-*-                                      see if parameter was fixed
04324     if (kint == 0) {
04325         Printf(f_out," REQUEST TO CHANGE LIMITS ON FIXED PARAMETER:%3d",i2);
04326         for (ifx = 1; ifx <= fNpfix; ++ifx) {
04327             if (i2 == fIpfix[ifx-1]) goto L92;
04328         }
04329         Printf(f_out," MINUIT BUG IN MNLIMS. SEE F. JAMES");
04330 L92:
04331         ;
04332     }
04333     if (fWord7[1] != fWord7[2]) goto L235;
04334 //*-*-                                      remove limits
04335     if (fNvarl[i2-1] != 1) {
04336         if (fISW[4] > 0) {
04337             Printf(f_out," LIMITS REMOVED FROM PARAMETER  %2d",i2);
04338         }
04339         fCstatu = "NEW LIMITS";
04340         if (kint <= 0) {
04341             fGsteps[ifx-1] = TMath_Abs(fGsteps[ifx-1]);
04342         } else {
04343             mndxdi(fX[kint-1], kint-1, dxdi);
04344             if (TMath_Abs(dxdi) < .01) dxdi = .01;
04345             fGstep[kint-1] = TMath_Abs(fGstep[kint-1]*dxdi);
04346             fGrd[kint-1]  *= dxdi;
04347         }
04348         fNvarl[i2-1] = 1;
04349     } else {
04350         Printf(f_out," NO LIMITS SPECIFIED.  PARAMETER %3d IS ALREADY UNLIMITED.  NO CHANGE.",i2);
04351     }
04352     goto L900;
04353 //*-*-                                       put on limits
04354 L235:
04355     fAlim[i2-1]  = TMath_Min(fWord7[1],fWord7[2]);
04356     fBlim[i2-1]  = TMath_Max(fWord7[1],fWord7[2]);
04357     fNvarl[i2-1] = 4;
04358     if (fISW[4] > 0) {
04359         Printf(f_out," PARAMETER %3d LIMITS SET TO  %15.5g%15.5g",i2,fAlim[i2-1],fBlim[i2-1]);
04360     }
04361     fCstatu = "NEW LIMITS";
04362     if (kint <= 0) fGsteps[ifx-1] = -.1;
04363     else           fGstep[kint-1] = -.1;
04364 
04365 L900:
04366     if (fCstatu != "NO CHANGE ") {
04367         mnexin(fX);
04368         mnrset(1);
04369     }
04370 } /* mnlims_ */
04371 
04372 //______________________________________________________________________________
04373 inline
04374 void fitter::mnline(double *start, double fstart, double *step, double slope, double toler)
04375 {
04376 //*-*-*-*-*-*-*-*-*-*Perform a line search from position START*-*-*-*-*-*-*-*
04377 //*-*                =========================================
04378 //*-*        along direction STEP, where the length of vector STEP
04379 //*-*                   gives the expected position of minimum.
04380 //*-*        FSTART is value of function at START
04381 //*-*        SLOPE (if non-zero) is df/dx along STEP at START
04382 //*-*        TOLER is initial tolerance of minimum in direction STEP
04383 //*-*
04384 //*-* SLAMBG and ALPHA control the maximum individual steps allowed.
04385 //*-* The first step is always =1. The max length of second step is SLAMBG.
04386 //*-* The max size of subsequent steps is the maximum previous successful
04387 //*-*   step multiplied by ALPHA + the size of most recent successful step,
04388 //*-*   but cannot be smaller than SLAMBG.
04389 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
04390 
04391     static const std::string charal = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
04392 
04393     /* Local variables */
04394     /*static*/ double xpq[12], ypq[12], slam, sdev, coeff[3], denom, flast;
04395     /*static*/ double fvals[3], xvals[3], f1, fvmin, xvmin, ratio, f2, f3, fvmax;
04396     /*static*/ double toler8, toler9, overal, undral, slamin, slamax, slopem;
04397     /*static*/ int i, nparx, nvmax, nxypt, kk, ipt;
04398     /*static*/ bool ldebug;
04399     std::string cmess, chpq[12];
04400     int     l65, l70, l80;
04401 
04402     /* Function Body */
04403     l65 = 0; l70 = 0; l80 = 0;
04404     ldebug = fIdbg[1] >= 1;
04405 //*-*-                 starting values for overall limits on total step SLAM
04406     overal = 1e3;
04407     undral = -100;
04408 //*-*-                             debug check if start is ok
04409     if (ldebug) {
04410         mninex(&start[0]);
04411     //Printf(f_out,"debug : FCN : 016");
04412         (*fFCN)(nparx, fGin, f1, fU, 4,fTag);   ++fNfcn;
04413         if (f1 != fstart) {
04414             Printf(f_out," MNLINE start point not consistent, F values, parameters=");
04415             for (kk = 1; kk <= fNpar; ++kk) {
04416                 Printf(f_out,"  %14.5e",fX[kk-1]);
04417             }
04418         }
04419     }
04420 //*-*-                                     . set up linear search along STEP
04421     fvmin   = fstart;
04422     xvmin   = 0;
04423     nxypt   = 1;
04424     chpq[0].assign(1,charal[0]);
04425     xpq[0]  = 0;
04426     ypq[0]  = fstart;
04427 //*-*-              SLAMIN = smallest possible value of ABS(SLAM)
04428     slamin = 0;
04429     for (i = 1; i <= fNpar; ++i) {
04430         if (step[i-1] != 0) {
04431            ratio = TMath_Abs(start[i-1] / step[i-1]);
04432            if (slamin == 0)    slamin = ratio;
04433            if (ratio < slamin) slamin = ratio;
04434         }
04435         fX[i-1] = start[i-1] + step[i-1];
04436     }
04437     if (slamin == 0) slamin = fEpsmac;
04438     slamin *= fEpsma2;
04439     nparx = fNpar;
04440 
04441     mninex(fX);
04442     //Printf(f_out,"debug : FCN : 018");
04443     (*fFCN)(nparx, fGin, f1, fU, 4,fTag);    ++fNfcn;
04444     ++nxypt;
04445     chpq[nxypt-1].assign(1,charal[nxypt-1]);
04446     xpq[nxypt-1] = 1;
04447     ypq[nxypt-1] = f1;
04448     if (f1 < fstart) {
04449         fvmin = f1;
04450         xvmin = 1;
04451     }
04452 //*-*-                        . quadr interp using slope GDEL and two points
04453     slam   = 1;
04454     toler8 = toler;
04455     slamax = 5;
04456     flast  = f1;
04457 //*-*-                        can iterate on two-points (cut) if no imprvmnt
04458 
04459     do {
04460        denom = (flast - fstart - slope*slam)*2 / (slam*slam);
04461        slam  = 1;
04462        if (denom != 0)    slam = -slope / denom;
04463        if (slam < 0)      slam = slamax;
04464        if (slam > slamax) slam = slamax;
04465        if (slam < toler8) slam = toler8;
04466        if (slam < slamin) {
04467           l80 = 1;
04468           break;
04469        }
04470        if (TMath_Abs(slam - 1) < toler8 && f1 < fstart) {
04471           l70 = 1;
04472           break;
04473        }
04474        if (TMath_Abs(slam - 1) < toler8) slam = toler8 + 1;
04475        if (nxypt >= 12) {
04476          l65 = 1;
04477          break;
04478        }
04479        for (i = 1; i <= fNpar; ++i) { fX[i-1] = start[i-1] + slam*step[i-1]; }
04480        mninex(fX);
04481     //Printf(f_out,"debug : FCN : 019");
04482        (*fFCN)(fNpar, fGin, f2, fU, 4,fTag);    ++fNfcn;
04483        ++nxypt;
04484        chpq[nxypt-1].assign(1,charal[nxypt-1]);
04485        xpq[nxypt-1]  = slam;
04486        ypq[nxypt-1]  = f2;
04487        if (f2 < fvmin) {
04488           fvmin = f2;
04489           xvmin = slam;
04490        }
04491        if (fstart == fvmin) {
04492           flast  = f2;
04493           toler8 = toler*slam;
04494           overal = slam - toler8;
04495           slamax = overal;
04496        }
04497     } while (fstart == fvmin);
04498 
04499     if (!l65 && !l70 && !l80) {
04500 //*-*-                                       . quadr interp using 3 points
04501        xvals[0] = xpq[0];
04502        fvals[0] = ypq[0];
04503        xvals[1] = xpq[nxypt-2];
04504        fvals[1] = ypq[nxypt-2];
04505        xvals[2] = xpq[nxypt-1];
04506        fvals[2] = ypq[nxypt-1];
04507 //*-*-                            begin iteration, calculate desired step
04508        do {
04509           slamax = TMath_Max(slamax,TMath_Abs(xvmin)*2);
04510           mnpfit(xvals, fvals, 3, coeff, sdev);
04511           if (coeff[2] <= 0) {
04512              slopem = coeff[2]*2*xvmin + coeff[1];
04513              if (slopem <= 0)  slam = xvmin + slamax;
04514              else              slam = xvmin - slamax;
04515           } else {
04516              slam = -coeff[1] / (coeff[2]*2);
04517              if (slam > xvmin + slamax) slam = xvmin + slamax;
04518              if (slam < xvmin - slamax) slam = xvmin - slamax;
04519           }
04520           if (slam > 0) {if (slam > overal) slam = overal;} //GB : brace.
04521           else          {if (slam < undral) slam = undral;} //GB : brace.
04522 
04523 //*-*-              come here if step was cut below
04524           do {
04525              toler9 = TMath_Max(toler8,TMath_Abs(toler8*slam));
04526              for (ipt = 1; ipt <= 3; ++ipt) {
04527                 if (TMath_Abs(slam - xvals[ipt-1]) < toler9) {
04528                    l70 = 1;
04529                    break;
04530                 }
04531              }
04532              if (l70) break;
04533 //*-*-               take the step
04534              if (nxypt >= 12) {
04535                 l65 = 1;
04536                 break;
04537              }
04538              for (i = 1; i <= fNpar; ++i) { fX[i-1] = start[i-1] + slam*step[i-1]; }
04539              mninex(fX);
04540     //Printf(f_out,"debug : FCN : 020");
04541              (*fFCN)(nparx, fGin, f3, fU, 4,fTag);    ++fNfcn;
04542              ++nxypt;
04543              chpq[nxypt-1].assign(1,charal[nxypt-1]);
04544              xpq[nxypt-1]  = slam;
04545              ypq[nxypt-1]  = f3;
04546 //*-*-            find worst previous point out of three
04547              fvmax = fvals[0];
04548              nvmax = 1;
04549              if (fvals[1] > fvmax) {
04550                 fvmax = fvals[1];
04551                 nvmax = 2;
04552              }
04553              if (fvals[2] > fvmax) {
04554                 fvmax = fvals[2];
04555                 nvmax = 3;
04556              }
04557 //*-*-             if latest point worse than all three previous, cut step
04558              if (f3 >= fvmax) {
04559                 if (nxypt >= 12) {
04560                    l65 = 1;
04561                    break;
04562                 }
04563                 if (slam > xvmin) overal = TMath_Min(overal,slam - toler8);
04564                 if (slam < xvmin) undral = TMath_Max(undral,slam + toler8);
04565                 slam = (slam + xvmin)*.5;
04566              }
04567           } while (f3 >= fvmax);
04568 
04569 //*-*-             prepare another iteration, replace worst previous point
04570           if (l65 || l70) break;
04571 
04572           xvals[nvmax-1] = slam;
04573           fvals[nvmax-1] = f3;
04574           if (f3 < fvmin) {
04575              fvmin = f3;
04576              xvmin = slam;
04577           } else {
04578              if (slam > xvmin) overal = TMath_Min(overal,slam - toler8);
04579              if (slam < xvmin) undral = TMath_Max(undral,slam + toler8);
04580           }
04581        } while (nxypt < 12);
04582     }
04583 
04584 //*-*-                                           . . end of iteration . . .
04585 //*-*-           stop because too many iterations
04586     if (!l70 && !l80) {
04587        cmess = " LINE SEARCH HAS EXHAUSTED THE LIMIT OF FUNCTION CALLS ";
04588        if (ldebug) {
04589           Printf(f_out," MNLINE DEBUG: steps=");
04590           for (kk = 1; kk <= fNpar; ++kk) {
04591              Printf(f_out,"  %12.4g",step[kk-1]);
04592           }
04593        }
04594     }
04595 //*-*-           stop because within tolerance
04596     if (l70) cmess = " LINE SEARCH HAS ATTAINED TOLERANCE ";
04597     if (l80) cmess = " STEP SIZE AT ARITHMETICALLY ALLOWED MINIMUM";
04598 
04599     fAmin = fvmin;
04600     for (i = 1; i <= fNpar; ++i) {
04601         fDirin[i-1] = step[i-1]*xvmin;
04602         fX[i-1]     = start[i-1] + fDirin[i-1];
04603     }
04604     mninex(fX);
04605     if (xvmin < 0) {
04606         mnwarn("D", "MNLINE", " LINE MINIMUM IN BACKWARDS DIRECTION");
04607     }
04608     if (fvmin == fstart) {
04609         mnwarn("D", "MNLINE", " LINE SEARCH FINDS NO IMPROVEMENT ");
04610     }
04611     if (ldebug) {
04612         Printf(f_out," AFTER%3d POINTS,%s",nxypt,cmess.c_str());
04613         mnplot(xpq, ypq, chpq, nxypt, fNpagwd, fNpagln);
04614     }
04615 } /* mnline_ */
04616 
04617 //______________________________________________________________________________
04618 inline
04619 void fitter::mnmatu(int kode)
04620 {
04621 //*-*-*-*-*-*-*-*Prints the covariance matrix v when KODE=1*-*-*-*-*-*-*-*-*
04622 //*-*            ==========================================
04623 //*-*        always prints the global correlations, and
04624 //*-*        calculates and prints the individual correlation coefficients
04625 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
04626 
04627     /* Local variables */
04628     /*static*/ double vline[kMAXDIM];
04629     /*static*/ int ndex, i, j, m, n, ncoef, nparm, idn, it, ix;
04630     /*static*/ int nsofar, ndi, ndj, iso, isw2, isw5;
04631     /*static*/ std::string ctemp;
04632 
04633     isw2 = fISW[1];
04634     if (isw2 < 1) {
04635         Printf(f_out,"%s",fCovmes[isw2].c_str());
04636         return;
04637     }
04638     if (fNpar == 0) {
04639         Printf(f_out," MNMATU: NPAR=0");
04640         return;
04641     }
04642 //*-*-                                      . . . . .external error matrix
04643     if (kode == 1) {
04644         isw5    = fISW[4];
04645         fISW[4] = 2;
04646         mnemat(fP, fMaxint);
04647         if (isw2 < 3) {
04648             Printf(f_out,"%s",fCovmes[isw2].c_str());
04649         }
04650         fISW[4] = isw5;
04651     }
04652 //*-*-                                      . . . . . correlation coeffs. .
04653     if (fNpar <= 1) return;
04654     mnwerr();
04655 //*-*-    NCOEF is number of coeff. that fit on one line, not to exceed 20
04656     ncoef = (fNpagwd - 19) / 6;
04657     ncoef = TMath_Min(ncoef,20);
04658     nparm = TMath_Min(fNpar,ncoef);
04659     Printf(f_out," PARAMETER  CORRELATION COEFFICIENTS  ");
04660     ctemp = "       NO.  GLOBAL";
04661     for (idn = 1; idn <= nparm; ++idn) {
04662         ctemp += Form(" %6d",fNexofi[idn-1]);
04663     }
04664     Printf(f_out,"%s",ctemp.c_str());
04665     for (i = 1; i <= fNpar; ++i) {
04666         ix  = fNexofi[i-1];
04667         ndi = i*(i + 1) / 2;
04668         for (j = 1; j <= fNpar; ++j) {
04669             m    = TMath_Max(i,j);
04670             n    = TMath_Min(i,j);
04671             ndex = m*(m-1) / 2 + n;
04672             ndj  = j*(j + 1) / 2;
04673             vline[j-1] = fVhmat[ndex-1] / TMath_Sqrt(TMath_Abs(fVhmat[ndi-1]*fVhmat[ndj-1]));
04674         }
04675         nparm = TMath_Min(fNpar,ncoef);
04676         ctemp = Form("      %3d  %7.5f ",ix);
04677         for (it = 1; it <= nparm; ++it) {
04678             ctemp += Form(" %6.3f",vline[it-1]);
04679         }
04680         Printf(f_out,"%s",ctemp.c_str());
04681         if (i <= nparm) continue;
04682         ctemp = "                   ";
04683         for (iso = 1; iso <= 10; ++iso) {
04684             nsofar = nparm;
04685             nparm  = TMath_Min(fNpar,nsofar + ncoef);
04686             for (it = nsofar + 1; it <= nparm; ++it) {
04687                 ctemp += Form(" %6.3f",vline[it-1]);
04688             }
04689             Printf(f_out,"%s",ctemp.c_str());
04690             if (i <= nparm) break;
04691         }
04692     }
04693     if (isw2 < 3) {
04694         Printf(f_out," %s",fCovmes[isw2].c_str());
04695     }
04696 } /* mnmatu_ */
04697 
04698 //______________________________________________________________________________
04699 inline
04700 bool fitter::mnmigr() //G.Barrand : return a bool
04701 {
04702 //*-*-*-*-*-*-*-*-*Performs a local function minimization*-*-*-*-*-*-*-*-*-*
04703 //*-*              ======================================
04704 //*-*        Performs a local function minimization using basically the
04705 //*-*        method of Davidon-Fletcher-Powell as modified by Fletcher
04706 //*-*        ref. -- Fletcher, Comp.J. 13,317 (1970)   "switching method"
04707 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
04708 
04709     /* Local variables */
04710     /*static*/ double gdel, gami, flnu[kMAXDIM], vlen, step[kMAXDIM], dsum, gssq, vsum, d;
04711     /*static*/ double fzero, gs[kMAXDIM], fs, ri, vg[kMAXDIM], delgam, rhotol;
04712     /*static*/ double gdgssq, gvg, vgi, xxs[kMAXDIM];
04713     /*static*/ int npfn, ndex, iext, i, j, m, n, npsdf, nparx;
04714     /*static*/ int iswtr, lined2, kk, nfcnmg, nrstrt,iter;
04715     /*static*/ bool ldebug;
04716     /*static*/ double toler = 0.05;
04717 
04718     if (fNpar <= 0) return false; //G.Barrand : return a bool.
04719     if (fAmin == fUndefi) mnamin();
04720     ldebug  = false; if ( fIdbg[4] >= 1) ldebug = true;
04721     fCfrom  = "MIGRAD  ";
04722     fNfcnfr = fNfcn;
04723     nfcnmg  = fNfcn;
04724     fCstatu = "INITIATE  ";
04725     iswtr   = fISW[4] - 2*fItaur;
04726     npfn    = fNfcn;
04727     nparx   = fNpar;
04728     vlen    = (double) (fNpar*(fNpar + 1) / 2);
04729     nrstrt  = 0;
04730     npsdf   = 0;
04731     lined2  = 0;
04732     fISW[3] = -1;
04733     rhotol  = fApsi*.001;
04734     if (iswtr >= 1) {
04735         Printf(f_out," START MIGRAD MINIMIZATION.  STRATEGY%2d.  CONVERGENCE WHEN EDM .LT.%9.2e",fIstrat,rhotol);
04736     }
04737 //*-*-                                          initialization strategy
04738     if (fIstrat < 2 || fISW[1] >= 3) goto L2;
04739 //*-*-                               come (back) here to restart completely
04740 L1:
04741     if (nrstrt > fIstrat) {
04742         fCstatu = "FAILED    ";
04743         fISW[3] = -1;
04744         goto L230;
04745     }
04746 //*-*-                                     . get full covariance and gradient
04747     mnhess();
04748     mnwerr();
04749     npsdf = 0;
04750     if (fISW[1] >= 1) goto L10;
04751 //*-*-                                       . get gradient at start point
04752 L2:
04753     mninex(fX);
04754     if (fISW[2] == 1) {
04755         if(!(*fFCN)(nparx, fGin, fzero, fU, 2,fTag)) return false; //GB
04756         ++fNfcn;
04757     }
04758     if(!mnderi()) return false;
04759     if (fISW[1] >= 1) goto L10;
04760 //*-*-                                  sometimes start with diagonal matrix
04761     for (i = 1; i <= fNpar; ++i) {
04762         xxs[i-1]  = fX[i-1];
04763         step[i-1] = 0;
04764     }
04765 //*-*-                          do line search if second derivative negative
04766     ++lined2;
04767     if (lined2 < (fIstrat + 1)*fNpar) {
04768         for (i = 1; i <= fNpar; ++i) {
04769             if (fG2[i-1] > 0) continue;
04770             if (fGrd[i-1] > 0) step[i-1] = -TMath_Abs(fGstep[i-1]);
04771             else               step[i-1] =  TMath_Abs(fGstep[i-1]);
04772             gdel = step[i-1]*fGrd[i-1];
04773             fs   = fAmin;
04774             mnline(xxs, fs, step, gdel, toler);
04775             mnwarn("D", "MNMIGR", "Negative G2 line search");
04776             iext = fNexofi[i-1];
04777             if (ldebug) {
04778                 Printf(f_out," Negative G2 line search, param %3d %13.3g%13.3g",iext,fs,fAmin);
04779             }
04780             goto L2;
04781         }
04782     }
04783 //*-*-                          make diagonal error matrix
04784     for (i = 1; i <= fNpar; ++i) {
04785         ndex = i*(i-1) / 2;
04786         for (j = 1; j <= i-1; ++j) {
04787             ++ndex;
04788             fVhmat[ndex-1] = 0;
04789         }
04790         ++ndex;
04791         if (fG2[i-1] <= 0) fG2[i-1] = 1;
04792         fVhmat[ndex-1] = 2 / fG2[i-1];
04793     }
04794     fDcovar = 1;
04795     if (ldebug) {
04796         Printf(f_out," DEBUG MNMIGR, STARTING MATRIX DIAGONAL,  VHMAT=");
04797         for (kk = 1; kk <= int(vlen); ++kk) {
04798             Printf(f_out," %10.2g",fVhmat[kk-1]);
04799         }
04800     }
04801 //*-*-                                        ready to start first iteration
04802 L10:
04803     ++nrstrt;
04804     if (nrstrt > fIstrat + 1) {
04805         fCstatu = "FAILED    ";
04806         goto L230;
04807     }
04808     fs = fAmin;
04809 //*-*-                                       . . . get EDM and set up loop
04810     fEDM = 0;
04811     for (i = 1; i <= fNpar; ++i) {
04812         gs[i-1]  = fGrd[i-1];
04813         xxs[i-1] = fX[i-1];
04814         ndex     = i*(i-1) / 2;
04815         for (j = 1; j <= i-1; ++j) {
04816             ++ndex;
04817             fEDM += gs[i-1]*fVhmat[ndex-1]*gs[j-1];
04818         }
04819         ++ndex;
04820         fEDM += gs[i-1]*gs[i-1]*.5*fVhmat[ndex-1];
04821     }
04822     fEDM = fEDM*.5*(fDcovar*3 + 1);
04823     if (fEDM < 0) {
04824         mnwarn("W", "MIGRAD", "STARTING MATRIX NOT POS-DEFINITE.");
04825         fISW[1] = 0;
04826         fDcovar = 1;
04827         goto L2;
04828     }
04829     if (fISW[1] == 0) fEDM = fBigedm;
04830     iter = 0;
04831     mninex(fX);
04832     mnwerr();
04833     if (iswtr >= 1) mnprin(3, fAmin);
04834     if (iswtr >= 2) mnmatu(0);
04835 //*-*-                                       . . . . .  start main loop
04836 L24:
04837     if (fNfcn - npfn >= fNfcnmx) goto L190;
04838     gdel = 0;
04839     gssq = 0;
04840     for (i = 1; i <= fNpar; ++i) {
04841         ri = 0;
04842         gssq += gs[i-1]*gs[i-1];
04843         for (j = 1; j <= fNpar; ++j) {
04844             m    = TMath_Max(i,j);
04845             n    = TMath_Min(i,j);
04846             ndex = m*(m-1) / 2 + n;
04847             ri  += fVhmat[ndex-1]*gs[j-1];
04848         }
04849         step[i-1] = ri*-.5;
04850         gdel += step[i-1]*gs[i-1];
04851     }
04852     if (gssq == 0) {
04853         mnwarn("D", "MIGRAD", " FIRST DERIVATIVES OF FCN ARE ALL ZERO");
04854         goto L300;
04855     }
04856 //*-*-                if gdel positive, V not posdef
04857     if (gdel >= 0) {
04858         mnwarn("D", "MIGRAD", " NEWTON STEP NOT DESCENT.");
04859         if (npsdf == 1) goto L1;
04860         mnpsdf();
04861         npsdf = 1;
04862         goto L24;
04863     }
04864 //*-*-                                       . . . . do line search
04865     mnline(xxs, fs, step, gdel, toler);
04866     if (fAmin == fs) goto L200;
04867     fCfrom  = "MIGRAD  ";
04868     fNfcnfr = nfcnmg;
04869     fCstatu = "PROGRESS  ";
04870 //*-*-                                       . get gradient at new point
04871     mninex(fX);
04872     if (fISW[2] == 1) {
04873         if(!(*fFCN)(nparx, fGin, fzero, fU, 2,fTag)) return false; //GB
04874         ++fNfcn;
04875     }
04876     if(!mnderi()) return false;
04877 //*-*-                                        . calculate new EDM
04878     npsdf = 0;
04879 L81:
04880     fEDM = 0;
04881     gvg = 0;
04882     delgam = 0;
04883     gdgssq = 0;
04884     for (i = 1; i <= fNpar; ++i) {
04885         ri  = 0;
04886         vgi = 0;
04887         for (j = 1; j <= fNpar; ++j) {
04888             m    = TMath_Max(i,j);
04889             n    = TMath_Min(i,j);
04890             ndex = m*(m-1) / 2 + n;
04891             vgi += fVhmat[ndex-1]*(fGrd[j-1] - gs[j-1]);
04892             ri  += fVhmat[ndex-1]*fGrd[j-1];
04893         }
04894         vg[i-1] = vgi*.5;
04895         gami    = fGrd[i-1] - gs[i-1];
04896         gdgssq += gami*gami;
04897         gvg    += gami*vg[i-1];
04898         delgam += fDirin[i-1]*gami;
04899         fEDM   += fGrd[i-1]*ri*.5;
04900     }
04901     fEDM = fEDM*.5*(fDcovar*3 + 1);
04902 //*-*-                         . if EDM negative,  not positive-definite
04903     if (fEDM < 0 || gvg <= 0) {
04904         mnwarn("D", "MIGRAD", "NOT POS-DEF. EDM OR GVG NEGATIVE.");
04905         fCstatu = "NOT POSDEF";
04906         if (npsdf == 1) goto L230;
04907         mnpsdf();
04908         npsdf = 1;
04909         goto L81;
04910     }
04911 //*-*-                           print information about this iteration
04912     ++iter;
04913     //GB : if (iswtr >= 3 || iswtr == 2 && iter % 10 == 1) {
04914     if ( (iswtr >= 3) || ((iswtr == 2) && (iter % 10 == 1))) { //GB : have ()
04915         mnwerr();
04916         mnprin(3, fAmin);
04917     }
04918     if (gdgssq == 0) {
04919         mnwarn("D", "MIGRAD", "NO CHANGE IN FIRST DERIVATIVES OVER LAST STEP");
04920     }
04921     if (delgam < 0) {
04922         mnwarn("D", "MIGRAD", "FIRST DERIVATIVES INCREASING ALONG SEARCH LINE");
04923     }
04924 //*-*-                                       .  update covariance matrix
04925     fCstatu = "IMPROVEMNT";
04926     if (ldebug) {
04927         Printf(f_out," VHMAT 1 =");
04928         for (kk = 1; kk <= 10; ++kk) {
04929             Printf(f_out," %10.2g",fVhmat[kk-1]);
04930         }
04931     }
04932     dsum = 0;
04933     vsum = 0;
04934     for (i = 1; i <= fNpar; ++i) {
04935         for (j = 1; j <= i; ++j) {
04936             d = fDirin[i-1]*fDirin[j-1] / delgam - vg[i-1]*vg[j-1] / gvg;
04937             dsum += TMath_Abs(d);
04938             ndex  = i*(i-1) / 2 + j;
04939             fVhmat[ndex-1] += d*2;
04940             vsum += TMath_Abs(fVhmat[ndex-1]);
04941         }
04942     }
04943 //*-*-               smooth local fluctuations by averaging DCOVAR
04944     fDcovar = (fDcovar + dsum / vsum)*.5;
04945     if (iswtr >= 3 || ldebug) {
04946         Printf(f_out," RELATIVE CHANGE IN COV. MATRIX=%5.1f per cent",fDcovar*100);
04947     }
04948     if (ldebug) {
04949         Printf(f_out," VHMAT 2 =");
04950         for (kk = 1; kk <= 10; ++kk) {
04951             Printf(f_out," %10.3g",fVhmat[kk-1]);
04952         }
04953     }
04954     if (delgam <= gvg) goto L135;
04955     for (i = 1; i <= fNpar; ++i) {
04956         flnu[i-1] = fDirin[i-1] / delgam - vg[i-1] / gvg;
04957     }
04958     for (i = 1; i <= fNpar; ++i) {
04959         for (j = 1; j <= i; ++j) {
04960             ndex = i*(i-1) / 2 + j;
04961             fVhmat[ndex-1] += gvg*2*flnu[i-1]*flnu[j-1];
04962         }
04963     }
04964 L135:
04965 //*-*-                                             and see if converged
04966     if (fEDM < rhotol*.1) goto L300;
04967 //*-*-                                   if not, prepare next iteration
04968     for (i = 1; i <= fNpar; ++i) {
04969         xxs[i-1] = fX[i-1];
04970         gs[i-1]  = fGrd[i-1];
04971     }
04972     fs = fAmin;
04973     if (fISW[1] == 0 && fDcovar < .5)  fISW[1] = 1;
04974     if (fISW[1] == 3 && fDcovar > .1)  fISW[1] = 1;
04975     if (fISW[1] == 1 && fDcovar < .05) fISW[1] = 3;
04976     goto L24;
04977 //*-*-                                       . . . . .  end main loop
04978 //*-*-                                        . . call limit in MNMIGR
04979 L190:
04980     fISW[0] = 1;
04981     if (fISW[4] >= 0) {
04982         Printf(f_out," CALL LIMIT EXCEEDED IN MIGRAD.");
04983     }
04984     fCstatu = "CALL LIMIT";
04985     goto L230;
04986 //*-*-                                        . . fails to improve . .
04987 L200:
04988     if (iswtr >= 1) {
04989         Printf(f_out," MIGRAD FAILS TO FIND IMPROVEMENT");
04990     }
04991     for (i = 1; i <= fNpar; ++i) { fX[i-1] = xxs[i-1]; }
04992     if (fEDM < rhotol) goto L300;
04993     if (fEDM < TMath_Abs(fEpsma2*fAmin)) {
04994         if (iswtr >= 0) {
04995             Printf(f_out," MACHINE ACCURACY LIMITS FURTHER IMPROVEMENT.");
04996         }
04997         goto L300;
04998     }
04999     if (fIstrat < 1) {
05000         if (fISW[4] >= 0) {
05001             Printf(f_out," MIGRAD FAILS WITH STRATEGY=0.   WILL TRY WITH STRATEGY=1.");
05002         }
05003         fIstrat = 1;
05004     }
05005     goto L1;
05006 //*-*-                                        . . fails to converge
05007 L230:
05008     if (iswtr >= 0) {
05009         Printf(f_out," MIGRAD TERMINATED WITHOUT CONVERGENCE.");
05010     }
05011     if (fISW[1] == 3) fISW[1] = 1;
05012     fISW[3] = -1;
05013     goto L400;
05014 //*-*-                                        . . apparent convergence
05015 L300:
05016     if (iswtr >= 0) {
05017         Printf(f_out," MIGRAD MINIMIZATION HAS CONVERGED.");
05018     }
05019     if (fItaur == 0) {
05020         if (fIstrat >= 2 || (fIstrat == 1 && fISW[1] < 3)) {
05021             if (fISW[4] >= 0) {
05022                 Printf(f_out," MIGRAD WILL VERIFY CONVERGENCE AND ERROR MATRIX.");
05023             }
05024             mnhess();
05025             mnwerr();
05026             npsdf = 0;
05027             if (fEDM > rhotol) goto L10;
05028         }
05029     }
05030     fCstatu = "CONVERGED ";
05031     fISW[3] = 1;
05032 //*-*-                                          come here in any case
05033 L400:
05034     fCfrom  = "MIGRAD  ";
05035     fNfcnfr = nfcnmg;
05036     mninex(fX);
05037     mnwerr();
05038     if (iswtr >= 0) mnprin(3, fAmin);
05039     if (iswtr >= 1) mnmatu(1);
05040     return true; //G.Barrand
05041 } /* mnmigr_ */
05042 
05043 //______________________________________________________________________________
05044 inline
05045 void fitter::mnmnos()
05046 {
05047 //*-*-*-*-*-*-*-*-*-*-*Performs a MINOS error analysis*-*-*-*-*-*-*-*-*-*-*-*
05048 //*-*                  ===============================
05049 //*-*        Performs a MINOS error analysis on those parameters for
05050 //*-*        which it is requested on the MINOS command by calling
05051 //*-*        MNMNOT for each parameter requested.
05052 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
05053 
05054     /* Local variables */
05055     /*static*/ double val2mi, val2pl;
05056     /*static*/ int nbad, ilax, ilax2, ngood, nfcnmi, iin, knt;
05057 
05058     if (fNpar <= 0) goto L700;
05059     ngood = 0;
05060     nbad = 0;
05061     nfcnmi = fNfcn;
05062 //*-*-                                     . loop over parameters requested
05063     for (knt = 1; knt <= fNpar; ++knt) {
05064         if (int(fWord7[1]) == 0) {
05065             ilax = fNexofi[knt-1];
05066         } else {
05067             if (knt >= 7) break;
05068             ilax = int(fWord7[knt]);
05069             if (ilax == 0) break;
05070             if (ilax > 0 && ilax <= fNu) {
05071                 if (fNiofex[ilax-1] > 0) goto L565;
05072             }
05073             Printf(f_out," PARAMETER NUMBER %3d NOT VARIABLE. IGNORED.",ilax);
05074             continue;
05075         }
05076 L565:
05077 //*-*-                                        calculate one pair of M E s
05078         ilax2 = 0;
05079         mnmnot(ilax, ilax2, val2pl, val2mi);
05080         if (fLnewmn) goto L650;
05081 //*-*-                                         update NGOOD and NBAD
05082         iin = fNiofex[ilax-1];
05083         if (fErp[iin-1] > 0) ++ngood;
05084         else                   ++nbad;
05085         if (fErn[iin-1] < 0) ++ngood;
05086         else                   ++nbad;
05087     }
05088 //*-*-                                          end of loop . . . . . . .
05089 //*-*-                                       . . . . printout final values .
05090     fCfrom  = "MINOS   ";
05091     fNfcnfr = nfcnmi;
05092     fCstatu = "UNCHANGED ";
05093     if (ngood == 0 && nbad == 0) goto L700;
05094     if (ngood > 0 && nbad == 0)  fCstatu = "SUCCESSFUL";
05095     if (ngood == 0 && nbad > 0)  fCstatu = "FAILURE   ";
05096     if (ngood > 0 && nbad > 0)   fCstatu = "PROBLEMS  ";
05097     if (fISW[4] >= 0)    mnprin(4, fAmin);
05098     if (fISW[4] >= 2)    mnmatu(0);
05099     return;
05100 //*-*-                                       . . . new minimum found . . . .
05101 L650:
05102     fCfrom  = "MINOS   ";
05103     fNfcnfr = nfcnmi;
05104     fCstatu = "NEW MINIMU";
05105     if (fISW[4] >= 0) mnprin(4, fAmin);
05106     Printf(f_out," NEW MINIMUM FOUND.  GO BACK TO MINIMIZATION STEP.");
05107     Printf(f_out," =================================================");
05108     Printf(f_out,"                                                  V");
05109     Printf(f_out,"                                                  V");
05110     Printf(f_out,"                                                  V");
05111     Printf(f_out,"                                               VVVVVVV");
05112     Printf(f_out,"                                                VVVVV");
05113     Printf(f_out,"                                                 VVV");
05114     Printf(f_out,"                                                  V");
05115     Printf(f_out,"");
05116     return;
05117 L700:
05118     Printf(f_out," THERE ARE NO MINOS ERRORS TO CALCULATE.");
05119 } /* mnmnos_ */
05120 
05121 //______________________________________________________________________________
05122 inline
05123 void fitter::mnmnot(int ilax, int ilax2, double &val2pl, double &val2mi)
05124 {
05125 //*-*-*-*-*-*Performs a MINOS error analysis on one parameter*-*-*-*-*-*-*-*-*
05126 //*-*        ================================================
05127 //*-*        The parameter ILAX is varied, and the minimum of the
05128 //*-*        function with respect to the other parameters is followed
05129 //*-*        until it crosses the value FMIN+UP.
05130 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
05131 
05132     /* System generated locals */
05133     int i__1;
05134 
05135     /* Local variables */
05136     /*static*/ double xdev[kMAXDIM], delu, aopt, eros;
05137     /*static*/ double w[kMAXDIM], abest, xunit, dc, ut, sigsav, du1;
05138     /*static*/ double fac, gcc[kMAXDIM], sig, sav;
05139     /*static*/ int marc, isig, mpar, ndex, imax, indx, ierr, i, j;
05140     /*static*/ int iercr, it, istrav, nfmxin, nlimit, isw2, isw4;
05141     /*static*/ std::string csig;
05142 
05143 //*-*-                                       . . save and prepare start vals
05144     isw2    = fISW[1];
05145     isw4    = fISW[3];
05146     sigsav  = fEDM;
05147     istrav  = fIstrat;
05148     dc      = fDcovar;
05149     fLnewmn = false;
05150     fApsi   = fEpsi*.5;
05151     abest   = fAmin;
05152     mpar    = fNpar;
05153     nfmxin  = fNfcnmx;
05154     for (i = 1; i <= mpar; ++i) { fXt[i-1] = fX[i-1]; }
05155     i__1 = mpar*(mpar + 1) / 2;
05156     for (j = 1; j <= i__1; ++j) { fVthmat[j-1] = fVhmat[j-1]; }
05157     for (i = 1; i <= mpar; ++i) {
05158         gcc[i-1] = fGlobcc[i-1];
05159         w[i-1]   = fWerr[i-1];
05160     }
05161     it = fNiofex[ilax-1];
05162     fErp[it-1] = 0;
05163     fErn[it-1] = 0;
05164     mninex(fXt);
05165     ut = fU[ilax-1];
05166     if (fNvarl[ilax-1] == 1) {
05167         fAlim[ilax-1] = ut - w[it-1]*100;
05168         fBlim[ilax-1] = ut + w[it-1]*100;
05169     }
05170     ndex  = it*(it + 1) / 2;
05171     xunit = TMath_Sqrt(fUp / fVthmat[ndex-1]);
05172     marc  = 0;
05173     for (i = 1; i <= mpar; ++i) {
05174         if (i == it) continue;
05175         ++marc;
05176         imax = TMath_Max(it,i);
05177         indx = imax*(imax-1) / 2 + TMath_Min(it,i);
05178         xdev[marc-1] = xunit*fVthmat[indx-1];
05179     }
05180 //*-*-                          fix the parameter in question
05181     mnfixp(it-1, ierr);
05182     if (ierr > 0) {
05183         Printf(f_out," MINUIT ERROR. CANNOT FIX PARAMETER%4d    INTERNAL%3d",ilax,it);
05184         goto L700;
05185     }
05186 //*-*-                      . . . . . Nota Bene: from here on, NPAR=MPAR-1
05187 //*-*-     Remember: MNFIXP squeezes IT out of X, XT, WERR, and VHMAT,
05188 //*-*-                                                   not W, VTHMAT
05189     for (isig = 1; isig <= 2; ++isig) {
05190         if (isig == 1) {
05191             sig  = 1;
05192             csig = "POSI";
05193         } else {
05194             sig  = -1;
05195             csig = "NEGA";
05196         }
05197 //*-*-                                       . sig=sign of error being calcd
05198         if (fISW[4] > 1) {
05199             Printf(f_out," DETERMINATION OF %sTIVE MINOS ERROR FOR PARAMETER%d"
05200                             ,csig.c_str(),ilax
05201                             ,fCpnam[ilax-1].c_str());
05202         }
05203         if (fISW[1] <= 0) {
05204             mnwarn("D", "MINOS", "NO COVARIANCE MATRIX.");
05205         }
05206         nlimit     = fNfcn + nfmxin;
05207         fIstrat    = TMath_Max(istrav-1,0);
05208         du1        = w[it-1];
05209         fU[ilax-1] = ut + sig*du1;
05210         fU[ilax-1] = TMath_Min(fU[ilax-1],fBlim[ilax-1]);
05211         fU[ilax-1] = TMath_Max(fU[ilax-1],fAlim[ilax-1]);
05212         delu = fU[ilax-1] - ut;
05213 //*-*-        stop if already at limit with negligible step size
05214         if (TMath_Abs(delu) / (TMath_Abs(ut) + TMath_Abs(fU[ilax-1])) < fEpsmac) goto L440;
05215         fac = delu / w[it-1];
05216         for (i = 1; i <= fNpar; ++i) {
05217             fX[i-1] = fXt[i-1] + fac*xdev[i-1];
05218         }
05219         if (fISW[4] > 1) {
05220             Printf(f_out," PARAMETER%4d SET TO%11.3e + %10.3e = %12.3e",ilax,ut,delu,fU[ilax-1]);
05221         }
05222 //*-*-                                       loop to hit AMIN+UP
05223         fKe1cr  = ilax;
05224         fKe2cr  = 0;
05225         fXmidcr = fU[ilax-1];
05226         fXdircr = delu;
05227 
05228         fAmin = abest;
05229         fNfcnmx = nlimit - fNfcn;
05230         mncros(aopt, iercr);
05231         if (abest - fAmin > fUp*.01) goto L650;
05232         if (iercr == 1) goto L440;
05233         if (iercr == 2) goto L450;
05234         if (iercr == 3) goto L460;
05235 //*-*-                                       . error successfully calculated
05236         eros = fXmidcr - ut + aopt*fXdircr;
05237         if (fISW[4] > 1) {
05238             Printf(f_out,"         THE %4sTIVE MINOS ERROR OF PARAMETER%3d  %10s, IS %12.4e"
05239                            ,csig.c_str(),ilax
05240                            ,fCpnam[ilax-1].c_str(),eros);
05241         }
05242         goto L480;
05243 //*-*-                                       . . . . . . . . failure returns
05244 L440:
05245         if (fISW[4] >= 1) {
05246             Printf(f_out,"     THE %4sTIVE MINOS ERROR OF PARAMETER%3d, %s EXCEEDS ITS LIMIT."
05247                               ,csig.c_str(),ilax
05248                               ,fCpnam[ilax-1].c_str());
05249         }
05250         eros = fUndefi;
05251         goto L480;
05252 L450:
05253         if (fISW[4] >= 1) {
05254             Printf(f_out,"         THE %4sTIVE MINOS ERROR%4d REQUIRES MORE THAN%5d FUNCTION CALLS.",csig.c_str(),ilax,nfmxin);
05255         }
05256         eros = 0;
05257         goto L480;
05258 L460:
05259         if (fISW[4] >= 1) {
05260             Printf(f_out,"                         %4sTIVE MINOS ERROR NOT CALCULATED FOR PARAMETER%d",csig.c_str(),ilax);
05261         }
05262         eros = 0;
05263 
05264 L480:
05265         if (fISW[4] > 1) {
05266             Printf(f_out,"     **************************************************************************");
05267         }
05268         if (sig < 0) {
05269             fErn[it-1] = eros;
05270             if (ilax2 > 0 && ilax2 <= fNu) val2mi = fU[ilax2-1];
05271         } else {
05272             fErp[it-1] = eros;
05273             if (ilax2 > 0 && ilax2 <= fNu) val2pl = fU[ilax2-1];
05274         }
05275     }
05276 //*-*-                                       . . parameter finished. reset v
05277 //*-*-                      normal termination */
05278     fItaur = 1;
05279     mnfree(1);
05280     i__1 = mpar*(mpar + 1) / 2;
05281     for (j = 1; j <= i__1; ++j) { fVhmat[j-1] = fVthmat[j-1]; }
05282     for (i = 1; i <= mpar; ++i) {
05283         fWerr[i-1]   = w[i-1];
05284         fGlobcc[i-1] = gcc[i-1];
05285         fX[i-1]      = fXt[i-1];
05286     }
05287     mninex(fX);
05288     fEDM    = sigsav;
05289     fAmin   = abest;
05290     fISW[1] = isw2;
05291     fISW[3] = isw4;
05292     fDcovar = dc;
05293     goto L700;
05294 //*-*-                      new minimum
05295 L650:
05296     fLnewmn = true;
05297     fISW[1] = 0;
05298     fDcovar = 1;
05299     fISW[3] = 0;
05300     sav     = fU[ilax-1];
05301     fItaur  = 1;
05302     mnfree(1);
05303     fU[ilax-1] = sav;
05304     mnexin(fX);
05305     fEDM = fBigedm;
05306 //*-*-                      in any case
05307 L700:
05308     fItaur  = 0;
05309     fNfcnmx = nfmxin;
05310     fIstrat = istrav;
05311 } /* mnmnot_ */
05312 
05313 //______________________________________________________________________________
05314 inline
05315 void fitter::mnparm(int k1, const std::string& cnamj, double uk, double wk, double a, double b, int &ierflg)
05316 {
05317 //*-*-*-*-*-*-*-*-*Implements one parameter definition*-*-*-*-*-*-*-*-*-*-*-*
05318 //*-*              ===================================
05319 //*-*        Called from MNPARS and user-callable
05320 //*-*    Implements one parameter definition, that is:
05321 //*-*          K     (external) parameter number
05322 //*-*          CNAMK parameter name
05323 //*-*          UK    starting value
05324 //*-*          WK    starting step size or uncertainty
05325 //*-*          A, B  lower and upper physical parameter limits
05326 //*-*    and sets up (updates) the parameter lists.
05327 //*-*    Output: IERFLG=0 if no problems
05328 //*-*                  >0 if MNPARM unable to implement definition
05329 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
05330 
05331     /* Local variables */
05332     /*static*/ double vplu, a_small, gsmin, pinti, vminu, danger, sav, sav2;
05333     /*static*/ int ierr, kint, in, ix, ktofix, lastin, kinfix, nvl;
05334     /*static*/ std::string cnamk, chbufi;
05335     ierr = 0; //GB
05336 
05337     int k = k1+1;
05338     cnamk   = cnamj;
05339     kint    = fNpar;
05340     if (k < 1 || k > fMaxext) {
05341 //*-*-                    parameter number exceeds allowed maximum value
05342         Printf(f_out," MINUIT USER ERROR.  PARAMETER NUMBER IS %3d  ALLOWED RANGE IS ONE TO %4d",k,fMaxext);
05343         goto L800;
05344     }
05345 //*-*-                    normal parameter request
05346     ktofix = 0;
05347     if (fNvarl[k-1] < 0) goto L50;
05348 //*-*-        previously defined parameter is being redefined
05349 //*-*-                                    find if parameter was fixed
05350     for (ix = 1; ix <= fNpfix; ++ix) {
05351         if (fIpfix[ix-1] == k) ktofix = k;
05352     }
05353     if (ktofix > 0) {
05354         mnwarn("W", "PARAM DEF", "REDEFINING A FIXED PARAMETER.");
05355         if (kint >= fMaxint) {
05356             Printf(f_out," CANNOT RELEASE. MAX NPAR EXCEEDED.");
05357             goto L800;
05358         }
05359         mnfree(1);
05360     }
05361 //*-*-                      if redefining previously variable parameter
05362     if (fNiofex[k-1] > 0) kint = fNpar - 1;
05363 L50:
05364 
05365 //*-*-                                     . . .print heading
05366     if (fLphead && fISW[4] >= 0) {
05367         Printf(f_out," PARAMETER DEFINITIONS:");
05368         Printf(f_out,"    NO.   NAME         VALUE      STEP SIZE      LIMITS");
05369         fLphead = false;
05370     }
05371     if (wk > 0) goto L122;
05372 //*-*-                                       . . .constant parameter . . . .
05373     if (fISW[4] >= 0) {
05374         Printf(f_out," %5d %-10s %13.5e  constant",
05375                k,cnamk.c_str(),uk);
05376     }
05377     nvl = 0;
05378     goto L200;
05379 L122:
05380     if (a == 0 && b == 0) {
05381 //*-*-                                     variable parameter without limits
05382         nvl = 1;
05383         if (fISW[4] >= 0) {
05384             Printf(f_out," %5d %-10s %13.5e%13.5e     no limits",
05385                    k,cnamk.c_str(),uk,wk);
05386         }
05387     } else {
05388 //*-*-                                        variable parameter with limits
05389         nvl = 4;
05390         fLnolim = false;
05391         if (fISW[4] >= 0) {
05392             Printf(f_out," %5d '%-10s' %13.5e%13.5e  %13.5e%13.5e",
05393                    k,cnamk.c_str(),uk,wk,a,b);
05394         }
05395     }
05396 //*-*-                            . . request for another variable parameter
05397     ++kint;
05398     if (kint > fMaxint) {
05399         Printf(f_out," MINUIT USER ERROR.   TOO MANY VARIABLE PARAMETERS.");
05400         goto L800;
05401     }
05402     if (nvl == 1) goto L200;
05403     if (a == b) {
05404         Printf(f_out," USER ERROR IN MINUIT PARAMETER");
05405         Printf(f_out," DEFINITION");
05406         Printf(f_out," UPPER AND LOWER LIMITS EQUAL.");
05407         goto L800;
05408     }
05409     if (b < a) {
05410         sav = b;
05411         b = a;
05412         a = sav;
05413         mnwarn("W", "PARAM DEF", "PARAMETER LIMITS WERE REVERSED.");
05414         if (fLwarn) fLphead = true;
05415     }
05416     if (b - a > 1e7) {
05417         mnwarn("W", "PARAM DEF", Form("LIMITS ON PARAM%d TOO FAR APART.",k));
05418         if (fLwarn) fLphead = true;
05419     }
05420     danger = (b - uk)*(uk - a);
05421     if (danger < 0) {
05422         mnwarn("W", "PARAM DEF", "STARTING VALUE OUTSIDE LIMITS.");
05423     }
05424     if (danger == 0) {
05425         mnwarn("W", "PARAM DEF", "STARTING VALUE IS AT LIMIT.");
05426     }
05427 L200:
05428 //*-*-                          . . . input OK, set values, arrange lists,
05429 //*-*-                                   calculate step sizes GSTEP, DIRIN
05430     fCfrom      = "PARAMETR";
05431     fNfcnfr     = fNfcn;
05432     fCstatu     = "NEW VALUES";
05433     fNu         = TMath_Max(fNu,k);
05434     fCpnam[k-1] = cnamk;
05435     fU[k-1]     = uk;
05436     fAlim[k-1]  = a;
05437     fBlim[k-1]  = b;
05438     fNvarl[k-1] = nvl;
05439     mnrset(1);
05440 //*-*-                            K is external number of new parameter
05441 //*-*-          LASTIN is the number of var. params with ext. param. no.< K
05442     lastin = 0;
05443     for (ix = 1; ix <= k-1; ++ix) { if (fNiofex[ix-1] > 0) ++lastin; }
05444 //*-*-                KINT is new number of variable params, NPAR is old
05445     if (kint == fNpar) goto L280;
05446     if (kint > fNpar) {
05447 //*-*-                         insert new variable parameter in list
05448         for (in = fNpar; in >= lastin + 1; --in) {
05449             ix            = fNexofi[in-1];
05450             fNiofex[ix-1] = in + 1;
05451             fNexofi[in]   = ix;
05452             fX[in]        = fX[in-1];
05453             fXt[in]       = fXt[in-1];
05454             fDirin[in]    = fDirin[in-1];
05455             fG2[in]       = fG2[in-1];
05456             fGstep[in]    = fGstep[in-1];
05457         }
05458     } else {
05459 //*-*-                         remove variable parameter from list
05460         for (in = lastin + 1; in <= kint; ++in) {
05461             ix            = fNexofi[in];
05462             fNiofex[ix-1] = in;
05463             fNexofi[in-1] = ix;
05464             fX[in-1]      = fX[in];
05465             fXt[in-1]     = fXt[in];
05466             fDirin[in-1]  = fDirin[in];
05467             fG2[in-1]     = fG2[in];
05468             fGstep[in-1]  = fGstep[in];
05469         }
05470     }
05471 L280:
05472     ix = k;
05473     fNiofex[ix-1] = 0;
05474     fNpar = kint;
05475 //*-*-                                      lists are now arranged . . . .
05476     if (nvl > 0) {
05477         in            = lastin + 1;
05478         fNexofi[in-1] = ix;
05479         fNiofex[ix-1] = in;
05480         sav           = fU[ix-1];
05481         mnpint(sav, ix-1, pinti);
05482         fX[in-1]    = pinti;
05483         fXt[in-1]   = fX[in-1];
05484         fWerr[in-1] = wk;
05485         sav2        = sav + wk;
05486         mnpint(sav2, ix-1, pinti);
05487         vplu = pinti - fX[in-1];
05488         sav2 = sav - wk;
05489         mnpint(sav2, ix-1, pinti);
05490         vminu = pinti - fX[in-1];
05491         fDirin[in-1] = (TMath_Abs(vplu) + TMath_Abs(vminu))*.5;
05492         fG2[in-1] = fUp*2 / (fDirin[in-1]*fDirin[in-1]);
05493         gsmin = fEpsma2*8*TMath_Abs(fX[in-1]);
05494         fGstep[in-1] = TMath_Max(gsmin,fDirin[in-1]*.1);
05495         if (fAmin != fUndefi) {
05496             a_small      = TMath_Sqrt(fEpsma2*(fAmin + fUp) / fUp);
05497             fGstep[in-1] = TMath_Max(gsmin,a_small*fDirin[in-1]);
05498         }
05499         fGrd[in-1] = fG2[in-1]*fDirin[in-1];
05500 //*-*-                  if parameter has limits
05501         if (fNvarl[k-1] > 1) {
05502             if (fGstep[in-1] > .5) fGstep[in-1] = .5;
05503             fGstep[in-1] = -fGstep[in-1];
05504         }
05505     }
05506     if (ktofix > 0) {
05507         kinfix = fNiofex[ktofix-1];
05508         if (kinfix > 0) mnfixp(kinfix-1, ierr);
05509         if (ierr > 0)   goto L800;
05510     }
05511     ierflg = 0;
05512     return;
05513 //*-*-                  error on input, unable to implement request  . . . .
05514 L800:
05515     ierflg = 1;
05516 } /* mnparm_ */
05517 
05518 //______________________________________________________________________________
05519 inline
05520 void fitter::mnpars(const std::string& crdbuf, int &icondn)
05521 {
05522 //*-*-*-*-*-*-*-*Implements one parameter definition*-*-*-*-*-*-*-*-*-*-*-*-*
05523 //*-*            =========== =======================
05524 //*-*        Called from MNREAD and user-callable
05525 //*-*    Implements one parameter definition, that is:
05526 //*-*       parses the string CRDBUF and calls MNPARM
05527 //*-*
05528 //*-* output conditions:
05529 //*-*        ICONDN = 0    all OK
05530 //*-*        ICONDN = 1    error, attempt to define parameter is ignored
05531 //*-*        ICONDN = 2    end of parameter definitions
05532 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
05533 
05534     /* Local variables */
05535     /*static*/ double a, b, plist[30], fk, uk, wk, xk;
05536     /*static*/ int ierr, kapo1, kapo2;
05537     /*static*/ int k, llist, ibegin, lenbuf, istart, lnc, icy;
05538     /*static*/ std::string cnamk, comand, celmnt, ctemp;
05539     char stmp[128];
05540 
05541     lenbuf = crdbuf.size();
05542 //*-*-                    find out whether fixed or free-field format
05543     kapo1 = strspn(crdbuf.c_str(), "'");
05544     if (kapo1 == 0) goto L150;
05545     kapo2 = strspn(crdbuf.c_str() + kapo1, "'");
05546     if (kapo2 == 0) goto L150;
05547 //*-*-         new (free-field) format
05548     kapo2 += kapo1;
05549 //*-*-                            skip leading blanks if any
05550     for (istart = 1; istart <= kapo1-1; ++istart) {
05551         if (crdbuf[istart-1] != ' ') goto L120;
05552     }
05553     goto L210;
05554 L120:
05555 //*-*-                              parameter number integer
05556     celmnt = msubstr(crdbuf,istart-1, kapo1-istart);
05557     //GB : have dummy if() to quiet g++-4.4.1
05558     if(scanf(celmnt.c_str(),fk)){}
05559     k = int(fk);
05560     if (k <= 0) goto L210;
05561     cnamk = "PARAM ";
05562     cnamk += celmnt;
05563     if (kapo2 - kapo1 > 1) {
05564         cnamk = msubstr(crdbuf,kapo1, kapo2-1-kapo1);
05565     }
05566 //*-*  special handling if comma or blanks and a comma follow 'name'
05567     for (icy = kapo2 + 1; icy <= lenbuf; ++icy) {
05568         if (crdbuf[icy-1] == ',') goto L139;
05569         if (crdbuf[icy-1] != ' ') goto L140;
05570     }
05571     uk = 0;
05572     wk = 0;
05573     a  = 0;
05574     b  = 0;
05575     goto L170;
05576 L139:
05577     ++icy;
05578 L140:
05579     ibegin = icy;
05580     ctemp = msubstr(crdbuf,ibegin-1,lenbuf-ibegin);
05581     mncrck(ctemp, 20, comand, lnc, 30, plist, llist, ierr, fIsyswr);
05582     if (ierr > 0) goto L180;
05583     uk = plist[0];
05584     wk = 0;
05585     if (llist >= 2) wk = plist[1];
05586     a = 0;
05587     if (llist >= 3) a = plist[2];
05588     b = 0;
05589     if (llist >= 4) b = plist[3];
05590     goto L170;
05591 //*-*-         old (fixed-field) format
05592 L150:
05593     //GB : have dummy if() to quiet g++-4.4.1
05594     if(scanf(crdbuf.c_str(),xk,stmp,uk,wk,a,b)){}
05595     cnamk = stmp;
05596     k = int(xk);
05597     if (k == 0)    goto L210;
05598 //*-*-         parameter format cracked, implement parameter definition
05599 L170:
05600     mnparm(k-1, cnamk, uk, wk, a, b, ierr);
05601     icondn = ierr;
05602     return;
05603 //*-*-         format or other error
05604 L180:
05605     icondn = 1;
05606     return;
05607 //*-*-       end of data
05608 L210:
05609     icondn = 2;
05610 } /* mnpars_ */
05611 
05612 //______________________________________________________________________________
05613 inline
05614 void fitter::mnpfit(double *parx2p, double *pary2p, int npar2p, double *coef2p, double &sdev2p)
05615 {
05616 //*-*-*-*-*-*-*-*-*-*To fit a parabola to npar2p points*-*-*-*-*-*-*-*-*-*-*
05617 //*-*                ==================================
05618 //*-*   npar2p   no. of points
05619 //*-*   parx2p(i)   x value of point i
05620 //*-*   pary2p(i)   y value of point i
05621 //*-*
05622 //*-*   coef2p(1...3)  coefficients of the fitted parabola
05623 //*-*   y=coef2p(1) + coef2p(2)*x + coef2p(3)*x**2
05624 //*-*   sdev2p= variance
05625 //*-*   method : chi**2 = min equation solved explicitly
05626 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
05627 
05628     /* Local variables */
05629     /*static*/ double a, f, s, t, y, s2, x2, x3, x4, y2, cz[3], xm, xy, x2y;
05630     x2 = x3 = 0;
05631     int i;
05632 
05633     /* Parameter adjustments */
05634     --coef2p;
05635     --pary2p;
05636     --parx2p;
05637 
05638     /* Function Body */
05639     for (i = 1; i <= 3; ++i) { cz[i-1] = 0; }
05640     sdev2p = 0;
05641     if (npar2p < 3) goto L10;
05642     f = (double) (npar2p);
05643 //*-* --- center x values for reasons of machine precision
05644     xm  = 0;
05645     for (i = 1; i <= npar2p; ++i) { xm += parx2p[i]; }
05646     xm /= f;
05647     x2  = 0;
05648     x3  = 0;
05649     x4  = 0;
05650     y   = 0;
05651     y2  = 0;
05652     xy  = 0;
05653     x2y = 0;
05654     for (i = 1; i <= npar2p; ++i) {
05655         s    = parx2p[i] - xm;
05656         t    = pary2p[i];
05657         s2   = s*s;
05658         x2  += s2;
05659         x3  += s*s2;
05660         x4  += s2*s2;
05661         y   += t;
05662         y2  += t*t;
05663         xy  += s*t;
05664         x2y += s2*t;
05665     }
05666     a = (f*x4 - x2*x2)*x2 - f*(x3*x3);
05667     if (a == 0) goto L10;
05668     cz[2] = (x2*(f*x2y - x2*y) - f*x3*xy) / a;
05669     cz[1] = (xy - x3*cz[2]) / x2;
05670     cz[0] = (y - x2*cz[2]) / f;
05671     if (npar2p == 3) goto L6;
05672     sdev2p = y2 - (cz[0]*y + cz[1]*xy + cz[2]*x2y);
05673     if (sdev2p < 0) sdev2p = 0;
05674     sdev2p /= f - 3;
05675 L6:
05676     cz[0] += xm*(xm*cz[2] - cz[1]);
05677     cz[1] -= xm*2*cz[2];
05678 L10:
05679     for (i = 1; i <= 3; ++i) { coef2p[i] = cz[i-1]; }
05680 } /* mnpfit_ */
05681 
05682 //______________________________________________________________________________
05683 inline
05684 void fitter::mnpint(double &pexti, int i1, double &pinti)
05685 {
05686 //*-*-*-*-*-*-*Calculates the internal parameter value PINTI*-*-*-*-*-*-*-*
05687 //*-*          =============================================
05688 //*-*        corresponding  to the external value PEXTI for parameter I.
05689 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
05690 
05691     /* Local variables */
05692     /*static*/ double a, alimi, blimi, yy, yy2;
05693     /*static*/ int igo;
05694     /*static*/ std::string chbuf2, chbufi;
05695 
05696     int i = i1+1;
05697     pinti   = pexti;
05698     igo     = fNvarl[i-1];
05699     if (igo == 4) {
05700 //*-* --                          there are two limits
05701         alimi = fAlim[i-1];
05702         blimi = fBlim[i-1];
05703         yy = (pexti - alimi)*2 / (blimi - alimi) - 1;
05704         yy2 = yy*yy;
05705         if (yy2 >= 1 - fEpsma2) {
05706             if (yy < 0) {
05707                 a      = fVlimlo;
05708                 chbuf2 = " IS AT ITS LOWER ALLOWED LIMIT.";
05709             } else {
05710                 a      = fVlimhi;
05711                 chbuf2 = " IS AT ITS UPPER ALLOWED LIMIT.";
05712             }
05713             pinti   = a;
05714             pexti   = alimi + (blimi - alimi)*.5*(TMath_Sin(a) + 1);
05715             fLimset = true;
05716             if (yy2 > 1) chbuf2 = " BROUGHT BACK INSIDE LIMITS.";
05717             mnwarn("W", fCfrom.c_str(), Form("VARIABLE%d%s",i,chbuf2.c_str()));
05718         } else {
05719             pinti = TMath_ASin(yy);
05720         }
05721     }
05722 } /* mnpint_ */
05723 
05724 //______________________________________________________________________________
05725 inline
05726 void fitter::mnplot(double *xpt, double *ypt, std::string *chpt, int nxypt, int npagwd, int npagln)
05727 {
05728  //*-*-*-*Plots points in array xypt onto one page with labelled axes*-*-*-*-*
05729  //*-*    ===========================================================
05730  //*-*        NXYPT is the number of points to be plotted
05731  //*-*        XPT(I) = x-coord. of ith point
05732  //*-*        YPT(I) = y-coord. of ith point
05733  //*-*        CHPT(I) = character to be plotted at this position
05734  //*-*        the input point arrays XPT, YPT, CHPT are destroyed.
05735  //*-*
05736  //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
05737 
05738      /* Initialized data */
05739 
05740      static const std::string cdot   = ".";
05741      static const std::string cslash = "/";
05742      static const std::string cblank = " ";
05743 
05744      /* Local variables */
05745      /*static*/ double xmin, ymin, xmax, ymax, savx, savy, yprt;
05746      /*static*/ double bwidx, bwidy, xbest, ybest, ax, ay, bx, by;
05747      /*static*/ double xvalus[12], any, dxx, dyy;
05748      /*static*/ int iten, i, j, k, maxnx, maxny, iquit, ni, linodd;
05749      /*static*/ int nxbest, nybest, km1, ibk, isp1, nx, ny, ks, ix;
05750      /*static*/ std::string cline, chsav, chmess, chbest, ctemp;
05751      /*static*/ bool overpr;
05752      bwidx = 0; //GB : rm warning.
05753      bwidy = 0; //GB : rm warning.
05754 
05755      /* Function Body */
05756  //*-*  Computing MIN
05757      maxnx = TMath_Min(npagwd-20,100);
05758      if (maxnx < 10) maxnx = 10;
05759      maxny = npagln;
05760      if (maxny < 10) maxny = 10;
05761      if (nxypt <= 1) return;
05762      xbest  = xpt[0];
05763      ybest  = ypt[0];
05764      chbest = chpt[0];
05765  //*-*-        order the points by decreasing y
05766      km1 = nxypt - 1;
05767      for (i = 1; i <= km1; ++i) {
05768         iquit = 0;
05769         ni    = nxypt - i;
05770         for (j = 1; j <= ni; ++j) {
05771             if (ypt[j-1] > ypt[j]) continue;
05772             savx     = xpt[j-1];
05773             xpt[j-1] = xpt[j];
05774             xpt[j]   = savx;
05775             savy     = ypt[j-1];
05776             ypt[j-1] = ypt[j];
05777             ypt[j]   = savy;
05778             chsav    = chpt[j-1];
05779             chpt[j-1]= chpt[j];
05780             chpt[j]  = chsav;
05781             iquit    = 1;
05782         }
05783         if (iquit == 0) break;
05784      }
05785  //*-*-        find extreme values
05786      xmax = xpt[0];
05787      xmin = xmax;
05788      for (i = 1; i <= nxypt; ++i) {
05789         if (xpt[i-1] > xmax) xmax = xpt[i-1];
05790         if (xpt[i-1] < xmin) xmin = xpt[i-1];
05791      }
05792      dxx   = (xmax - xmin)*.001;
05793      xmax += dxx;
05794      xmin -= dxx;
05795      mnbins(xmin, xmax, maxnx, xmin, xmax, nx, bwidx);
05796      ymax = ypt[0];
05797      ymin = ypt[nxypt-1];
05798      if (ymax == ymin) ymax = ymin + 1;
05799      dyy   = (ymax - ymin)*.001;
05800      ymax += dyy;
05801      ymin -= dyy;
05802      mnbins(ymin, ymax, maxny, ymin, ymax, ny, bwidy);
05803      any = (double) ny;
05804  //*-*-        if first point is blank, it is an 'origin'
05805      if (chbest == cblank) goto L50;
05806      xbest = (xmax + xmin)*.5;
05807      ybest = (ymax + ymin)*.5;
05808  L50:
05809  //*-*-        find scale constants
05810      ax = 1 / bwidx;
05811      ay = 1 / bwidy;
05812      bx = -ax*xmin + 2;
05813      by = -ay*ymin - 2;
05814  //*-*-        convert points to grid positions
05815      for (i = 1; i <= nxypt; ++i) {
05816         xpt[i-1] = ax*xpt[i-1] + bx;
05817         ypt[i-1] = any - ay*ypt[i-1] - by;
05818      }
05819      nxbest = int((ax*xbest + bx));
05820      nybest = int((any - ay*ybest - by));
05821  //*-*-        print the points
05822      ny += 2;
05823      nx += 2;
05824      isp1 = 1;
05825      linodd = 1;
05826      overpr = false;
05827 
05828      for (i = 1; i <= ny; ++i) {
05829       cline.resize(nx+2);  // added Z.Sz.
05830         for (ibk = 1; ibk <= nx; ++ibk) { cline[ibk-1] = ' '; }
05831 //      cline[nx] = '\0';  // removed Z.Sz.
05832         cline[nx+1] = '\0';
05833         cline[0]        = '.';
05834         cline[nx-1]     = '.';
05835         cline[nxbest-1] = '.';
05836         if (i != 1 && i != nybest && i != ny) goto L320;
05837         for (j = 1; j <= nx; ++j) { cline[j-1] = '.'; }
05838  L320:
05839         yprt = ymax - double(i-1)*bwidy;
05840         if (isp1 > nxypt) goto L350;
05841  //*-*-        find the points to be plotted on this line
05842         for (k = isp1; k <= nxypt; ++k) {
05843             ks = int(ypt[k-1]);
05844             if (ks > i) goto L345;
05845             ix = int(xpt[k-1]);
05846             if (cline[ix-1] == '.')   goto L340;
05847             if (cline[ix-1] == ' ') goto L340;
05848             if (cline[ix-1] == chpt[k-1][0])   continue;
05849             overpr = true;
05850  //*-*-        OVERPR is true if one or more positions contains more than
05851  //*-*-           one point
05852             cline[ix-1] = '&';
05853             continue;
05854  L340:
05855             cline[ix-1] = chpt[k-1][0];
05856         }
05857         isp1 = nxypt + 1;
05858         goto L350;
05859  L345:
05860         isp1 = k;
05861  L350:
05862         if (linodd == 1 || i == ny) goto L380;
05863         linodd = 1;
05864         ctemp  = msubstr(cline,0,nx);
05865         Printf(f_out,"                  %s",ctemp.c_str());
05866         goto L400;
05867  L380:
05868         ctemp = msubstr(cline,0,nx);
05869         Printf(f_out," %14.7g ..%s",yprt,ctemp.c_str());
05870         linodd = 0;
05871  L400:
05872         ;
05873      }
05874  //*-*-        print labels on x-axis every ten columns
05875      for (ibk = 1; ibk <= nx; ++ibk) {
05876         cline[ibk-1] = ' ';
05877         if (ibk % 10 == 1) cline[ibk-1] = '/';
05878      }
05879      Printf(f_out,"                  %s",cline.c_str());
05880 
05881      for (ibk = 1; ibk <= 12; ++ibk) {
05882         xvalus[ibk-1] = xmin + double(ibk-1)*10*bwidx;
05883      }
05884      Printf(f_out,"           ");
05885      iten = (nx + 9) / 10;
05886 
05887 // wrong: numbers should be printed in one line !!!!!!!!!!!!!!!!!!!!!!!!! Z.Sz.
05888      for (ibk = 1; ibk <= iten; ++ibk) {
05889          Printf(f_out," %9.4g", xvalus[ibk-1]);
05890      }
05891 // until here !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
05892 
05893      chmess = " ";
05894      if (overpr) chmess = "   Overprint character is &";
05895      Printf(f_out,"                         ONE COLUMN=%13.7g%s",
05896             bwidx,chmess.c_str());
05897 } /* mnplot_ */
05898 
05899 //______________________________________________________________________________
05900 inline
05901 void fitter::mnpout(int iuext1, std::string& chnam, double &val, double &err, double &xlolim, double &xuplim, int &iuint)
05902 {
05903 //*-*-*-*Provides the user with information concerning the current status*-*-*
05904 //*-*    ================================================================
05905 //*-*          of parameter number IUEXT. Namely, it returns:
05906 //*-*        CHNAM: the name of the parameter
05907 //*-*        VAL: the current (external) value of the parameter
05908 //*-*        ERR: the current estimate of the parameter uncertainty
05909 //*-*        XLOLIM: the lower bound (or zero if no limits)
05910 //*-*        XUPLIM: the upper bound (or zero if no limits)
05911 //*-*        IUINT: the internal parameter number (or zero if not variable,
05912 //*-*           or negative if undefined).
05913 //*-*  Note also:  If IUEXT is negative, then it is -internal parameter
05914 //*-*           number, and IUINT is returned as the EXTERNAL number.
05915 //*-*     Except for IUINT, this is exactly the inverse of MNPARM
05916 //*-*     User-called
05917 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
05918 
05919     /* Local variables */
05920     /*static*/ int iint, iext, nvl;
05921 
05922     int iuext = iuext1 + 1;
05923     xlolim = 0;
05924     xuplim = 0;
05925     err    = 0;
05926     if (iuext == 0) goto L100;
05927     if (iuext < 0) {
05928 //*-*-                  internal parameter number specified
05929         iint  = -(iuext);
05930         if (iint > fNpar) goto L100;
05931         iext  = fNexofi[iint-1];
05932         iuint = iext;
05933     } else {
05934 //*-*-                   external parameter number specified
05935         iext = iuext;
05936         if (iext == 0) goto L100;
05937         if (iext > fNu) goto L100;
05938         iint  = fNiofex[iext-1];
05939         iuint = iint;
05940     }
05941 //*-*-                    in both cases
05942     nvl = fNvarl[iext-1];
05943     if (nvl < 0) goto L100;
05944     chnam = fCpnam[iext-1];
05945     val   = fU[iext-1];
05946     if (iint > 0) err = fWerr[iint-1];
05947     if (nvl == 4) {
05948         xlolim = fAlim[iext-1];
05949         xuplim = fBlim[iext-1];
05950     }
05951     return;
05952 //*-*-               parameter is undefined
05953 L100:
05954     iuint = -1;
05955     chnam = "undefined";
05956     val = 0;
05957 } /* mnpout_ */
05958 
05959 //______________________________________________________________________________
05960 inline
05961 void fitter::mnprin(int inkode, double fval)
05962 {
05963 //*-*-*-*Prints the values of the parameters at the time of the call*-*-*-*-*
05964 //*-*    ===========================================================
05965 //*-*        also prints other relevant information such as function value,
05966 //*-*        estimated distance to minimum, parameter errors, step sizes.
05967 //*-*
05968 //*-*         According to the value of IKODE, the printout is:/
05969 //*-*    IKODE=INKODE= 0    only info about function value
05970 //*-*                  1    parameter values, errors, limits
05971 //*-*                  2    values, errors, step sizes, internal values
05972 //*-*                  3    values, errors, step sizes, first derivs.
05973 //*-*                  4    values, parabolic errors, MINOS errors
05974 //*-*    when INKODE=5, MNPRIN chooses IKODE=1,2, or 3, according to ISW(2)
05975 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
05976 
05977     /* Initialized data */
05978 
05979     static const std::string cblank = "           ";
05980     /*static*/ std::string cnambf = "           ";
05981 
05982     /* Local variables */
05983     double dcmax, x1, x2, x3, dc;
05984     x2 = x3 = 0;
05985     /*static*/ int nadd, i, k, l, m, ikode, ic, nc, ntrail, lbl;
05986     /*static*/ std::string chedm;
05987     /*static*/ std::string colhdl[6], colhdu[6], cx2, cx3, cheval;
05988 
05989     if (fNu == 0) {
05990         Printf(f_out," THERE ARE CURRENTLY NO PARAMETERS DEFINED");
05991         return;
05992     }
05993 //*-*-                 get value of IKODE based in INKODE, ISW(2)
05994     ikode = inkode;
05995     if (inkode == 5) {
05996         ikode = fISW[1] + 1;
05997         if (ikode > 3) ikode = 3;
05998     }
05999 //*-*-                 set 'default' column headings
06000     for (k = 1; k <= 6; ++k) {
06001         colhdu[k-1] = "UNDEFINED";
06002         colhdl[k-1] = "COLUMN HEAD";
06003     }
06004 //*-*-             print title if Minos errors, and title exists.
06005     if (ikode == 4 && fCtitl != fCundef) {
06006         Printf(f_out," MINUIT TASK: %s",fCtitl.c_str());
06007     }
06008 //*-*-             report function value and status
06009     if (fval == fUndefi) cheval = " unknown       ";
06010     else                 cheval = Form("%g",fval);
06011 
06012     if (fEDM == fBigedm) chedm = " unknown  ";
06013     else                 chedm = Form("%g",fEDM);
06014 
06015     nc = fNfcn - fNfcnfr;
06016     Printf(f_out," FCN=%s FROM %8s  STATUS=%10s %6d CALLS   %9d TOTAL"
06017            ,cheval.c_str()
06018            ,fCfrom.c_str()
06019            ,fCstatu.c_str(),nc,fNfcn);
06020     m = fISW[1];
06021     if (m == 0 || m == 2 || fDcovar == 0) {
06022         Printf(f_out,"                     EDM=%s    STRATEGY=%2d      %s"
06023                       ,chedm.c_str(),fIstrat
06024                       ,fCovmes[m].c_str());
06025     } else {
06026         dcmax = 1;
06027         dc    = TMath_Min(fDcovar,dcmax)*100;
06028         Printf(f_out,"                     EDM=%s    STRATEGY=%2d  ERROR MATRIX UNCERTAINTY %5.1f per cent"
06029                       ,chedm.c_str(),fIstrat,dc);
06030     }
06031 
06032     if (ikode == 0) return;
06033 //*-*-              find longest name (for Rene!)
06034     ntrail = 10;
06035     for (i = 1; i <= fNu; ++i) {
06036         if (fNvarl[i-1] < 0) continue;
06037         for (ic = 10; ic >= 1; --ic) {
06038           // FIXME : This substr starts outside string !
06039             if (msubstr(fCpnam[i-1],ic-1,1) != " ") goto L16;
06040         }
06041         ic = 1;
06042 L16:
06043         lbl = 10 - ic;
06044         if (lbl < ntrail) ntrail = lbl;
06045     }
06046     nadd = ntrail / 2 + 1;
06047     if (ikode == 1) {
06048         colhdu[0] = "              ";
06049         colhdl[0] = "      ERROR   ";
06050         colhdu[1] = "      PHYSICAL";
06051         colhdu[2] = " LIMITS       ";
06052         colhdl[1] = "    NEGATIVE  ";
06053         colhdl[2] = "    POSITIVE  ";
06054     }
06055     if (ikode == 2) {
06056         colhdu[0] = "              ";
06057         colhdl[0] = "      ERROR   ";
06058         colhdu[1] = "    INTERNAL  ";
06059         colhdl[1] = "    STEP SIZE ";
06060         colhdu[2] = "    INTERNAL  ";
06061         colhdl[2] = "      VALUE   ";
06062     }
06063     if (ikode == 3) {
06064         colhdu[0] = "              ";
06065         colhdl[0] = "      ERROR   ";
06066         colhdu[1] = "       STEP   ";
06067         colhdl[1] = "       SIZE   ";
06068         colhdu[2] = "      FIRST   ";
06069         colhdl[2] = "   DERIVATIVE ";
06070     }
06071     if (ikode == 4) {
06072         colhdu[0] = "    PARABOLIC ";
06073         colhdl[0] = "      ERROR   ";
06074         colhdu[1] = "        MINOS ";
06075         colhdu[2] = "ERRORS        ";
06076         colhdl[1] = "   NEGATIVE   ";
06077         colhdl[2] = "   POSITIVE   ";
06078     }
06079 
06080     if (ikode != 4) {
06081         if (fISW[1] < 3) colhdu[0] = "  APPROXIMATE ";
06082         if (fISW[1] < 1) colhdu[0] = " CURRENT GUESS";
06083     }
06084     Printf(f_out,"  EXT PARAMETER              %-14s%-14s%-14s",
06085            colhdu[0].c_str(),colhdu[1].c_str(),colhdu[2].c_str());
06086     Printf(f_out,"  NO.   NAME      VALUE      %-14s%-14s%-14s",
06087            colhdl[0].c_str(),colhdl[1].c_str(),colhdl[2].c_str());
06088     //*-*-                                       . . . loop over parameters . .
06089     for (i = 1; i <= fNu; ++i) {
06090         if (fNvarl[i-1] < 0) continue;
06091         l = fNiofex[i-1];
06092         cnambf = msubstr(cblank,0,nadd);
06093         cnambf += fCpnam[i-1];
06094         if (l == 0) goto L55;
06095 //*-*-             variable parameter.
06096         x1  = fWerr[l-1];
06097         cx2 = "PLEASE GET X..";
06098         cx3 = "PLEASE GET X..";
06099         if (ikode == 1) {
06100             if (fNvarl[i-1] <= 1) {
06101                 Printf(f_out,"%4d %-11s%14.5e%14.5e",i,cnambf.c_str(),fU[i-1],x1);
06102                 continue;
06103             } else {
06104                 x2 = fAlim[i-1];
06105                 x3 = fBlim[i-1];
06106             }
06107         }
06108         if (ikode == 2) {
06109             x2 = fDirin[l-1];
06110             x3 = fX[l-1];
06111         }
06112         if (ikode == 3) {
06113             x2 = fDirin[l-1];
06114             x3 = fGrd[l-1];
06115             if (fNvarl[i-1] > 1 && TMath_Abs(TMath_Cos(fX[l-1])) < .001) {
06116                 cx3 = "** at limit **";
06117             }
06118         }
06119         if (ikode == 4) {
06120             x2 = fErn[l-1];
06121             if (x2 == 0)        cx2 = " ";
06122             if (x2 == fUndefi)  cx2 = "   at limit   ";
06123             x3 = fErp[l-1];
06124             if (x3 == 0)        cx3 = " ";
06125             if (x3 == fUndefi)  cx3 = "   at limit   ";
06126         }
06127         if (cx2 == "PLEASE GET X..")  cx2 = Form("%14.5e",x2);
06128         if (cx3 == "PLEASE GET X..")  cx3 = Form("%14.5e",x3);
06129         Printf(f_out,"%4d %-11s%14.5e%14.5e%-14s%-14s",i
06130                    ,cnambf.c_str(),fU[i-1],x1
06131                    ,cx2.c_str(),cx3.c_str());
06132 
06133 //*-*-              check if parameter is at limit
06134         if (fNvarl[i-1] <= 1 || ikode == 3) continue;
06135         if (TMath_Abs(TMath_Cos(fX[l-1])) < .001) {
06136             Printf(f_out,"                                 WARNING -   - ABOVE PARAMETER IS AT LIMIT.");
06137         }
06138         continue;
06139 
06140 //*-*-                               print constant or fixed parameter.
06141 L55:
06142         colhdu[0] = "   constant   ";
06143         if (fNvarl[i-1] > 0)  colhdu[0] = "     fixed    ";
06144         if (fNvarl[i-1] == 4 && ikode == 1) {
06145             Printf(f_out,"%4d %-11s%14.5e%-14s%14.5e%14.5e",i
06146               ,cnambf.c_str(),fU[i-1]
06147               ,colhdu[0].c_str(),fAlim[i-1],fBlim[i-1]);
06148         } else {
06149             Printf(f_out,"%4d %-11s%14.5e%s",i
06150                    ,cnambf.c_str(),fU[i-1],colhdu[0].c_str());
06151         }
06152     }
06153 
06154     if (fUp != fUpdflt) {
06155         Printf(f_out,"                               ERR DEF= %g",fUp);
06156     }
06157     return;
06158 } /* mnprin_ */
06159 
06160 //______________________________________________________________________________
06161 inline
06162 void fitter::mnpsdf()
06163 {
06164 //*-*-*-*-*-*Calculates the eigenvalues of v to see if positive-def*-*-*-*-*
06165 //*-*        ======================================================
06166 //*-*        if not, adds constant along diagonal to make positive.
06167 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
06168 
06169     /* Local variables */
06170     /*static*/ double s[kMAXDIM], dgmin, padd, pmin, pmax, dg, epspdf, epsmin;
06171     /*static*/ int ndex, i, j, ndexd, ip, ifault;
06172     /*static*/ std::string chbuff, ctemp;
06173 
06174     epsmin = 1e-6;
06175     epspdf = TMath_Max(epsmin,fEpsma2);
06176     dgmin  = fVhmat[0];
06177 //*-*-                       Check if negative or zero on diagonal
06178     for (i = 1; i <= fNpar; ++i) {
06179         ndex = i*(i + 1) / 2;
06180         if (fVhmat[ndex-1] <= 0) {
06181             mnwarn("W", fCfrom.c_str(), Form("Negative diagonal element %d in Error Matrix",i));
06182         }
06183         if (fVhmat[ndex-1] < dgmin) dgmin = fVhmat[ndex-1];
06184     }
06185     if (dgmin <= 0) {
06186         dg    = epspdf + 1 - dgmin;
06187         mnwarn("W", fCfrom.c_str(), Form("%g added to diagonal of error matrix",dg));
06188     } else {
06189         dg = 0;
06190     }
06191 //*-*-                   Store VHMAT in P, make sure diagonal pos.
06192     for (i = 1; i <= fNpar; ++i) {
06193         ndex  = i*(i-1) / 2;
06194         ndexd = ndex + i;
06195         fVhmat[ndexd-1] += dg;
06196         s[i-1] = 1 / TMath_Sqrt(fVhmat[ndexd-1]);
06197         for (j = 1; j <= i; ++j) {
06198             ++ndex;
06199             fP[i + j*fMaxpar - fMaxpar-1] = fVhmat[ndex-1]*s[i-1]*s[j-1];
06200         }
06201     }
06202 //*-*-     call eigen (p,p,maxint,npar,pstar,-npar)
06203     mneig(fP, fMaxint, fNpar, fMaxint, fPstar, epspdf, ifault);
06204     pmin = fPstar[0];
06205     pmax = fPstar[0];
06206     for (ip = 2; ip <= fNpar; ++ip) {
06207         if (fPstar[ip-1] < pmin) pmin = fPstar[ip-1];
06208         if (fPstar[ip-1] > pmax) pmax = fPstar[ip-1];
06209     }
06210     pmax = TMath_Max(TMath_Abs(pmax),double(1));
06211     //GB : if (pmin <= 0 && fLwarn || fISW[4] >= 2) {
06212     if (((pmin <= 0) && fLwarn) || (fISW[4] >= 2)) { //GB : have ()
06213         Printf(f_out," EIGENVALUES OF SECOND-DERIVATIVE MATRIX:");
06214         ctemp = "       ";
06215         for (ip = 1; ip <= fNpar; ++ip) {
06216             ctemp += Form(" %11.4e",fPstar[ip-1]);
06217         }
06218         Printf(f_out,ctemp.c_str());
06219     }
06220     if (pmin > epspdf*pmax) return;
06221     if (fISW[1] == 3) fISW[1] = 2;
06222     padd = pmax*.001 - pmin;
06223     for (ip = 1; ip <= fNpar; ++ip) {
06224         ndex = ip*(ip + 1) / 2;
06225         fVhmat[ndex-1] *= padd + 1;
06226     }
06227     fCstatu = "NOT POSDEF";
06228     mnwarn("W", fCfrom.c_str(), Form("MATRIX FORCED POS-DEF BY ADDING %f TO DIAGONAL.",padd));
06229 
06230 } /* mnpsdf_ */
06231 
06232 //______________________________________________________________________________
06233 inline
06234 void fitter::mnrazz(double ynew, double *pnew, double *y, int &jh, int &jl)
06235 {
06236 //*-*-*-*-*Called only by MNSIMP (and MNIMPR) to add a new point*-*-*-*-*-*-*
06237 //*-*      =====================================================
06238 //*-*        and remove an old one from the current simplex, and get the
06239 //*-*        estimated distance to minimum.
06240 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
06241 
06242     /* Local variables */
06243     /*static*/ double pbig, plit;
06244     /*static*/ int i, j, nparp1;
06245 
06246     /* Function Body */
06247     for (i = 1; i <= fNpar; ++i) { fP[i + jh*fMaxpar - fMaxpar-1] = pnew[i-1]; }
06248     y[jh-1] = ynew;
06249     if (ynew < fAmin) {
06250         for (i = 1; i <= fNpar; ++i) { fX[i-1] = pnew[i-1]; }
06251         mninex(fX);
06252         fAmin   = ynew;
06253         fCstatu = "PROGRESS  ";
06254         jl      = jh;
06255     }
06256     jh     = 1;
06257     nparp1 = fNpar + 1;
06258     for (j = 2; j <= nparp1; ++j) { if (y[j-1] > y[jh-1]) jh = j; }
06259     fEDM = y[jh-1] - y[jl-1];
06260     if (fEDM <= 0) goto L45;
06261     for (i = 1; i <= fNpar; ++i) {
06262         pbig = fP[i-1];
06263         plit = pbig;
06264         for (j = 2; j <= nparp1; ++j) {
06265             if (fP[i + j*fMaxpar - fMaxpar-1] > pbig) pbig = fP[i + j*fMaxpar - fMaxpar-1];
06266             if (fP[i + j*fMaxpar - fMaxpar-1] < plit) plit = fP[i + j*fMaxpar - fMaxpar-1];
06267         }
06268         fDirin[i-1] = pbig - plit;
06269     }
06270 L40:
06271     return;
06272 L45:
06273     Printf(f_out,"   FUNCTION VALUE DOES NOT SEEM TO DEPEND ON ANY OF THE%d VARIABLE PARAMETERS.",fNpar);
06274     Printf(f_out,"          VERIFY THAT STEP SIZES ARE BIG ENOUGH AND CHECK FCN LOGIC.");
06275     Printf(f_out," *******************************************************************************");
06276     Printf(f_out," *******************************************************************************");
06277     goto L40;
06278 } /* mnrazz_ */
06279 
06280 //______________________________________________________________________________
06281 inline
06282 void fitter::mnrn15(double &val, int &inseed)
06283 {
06284 //*-*-*-*-*-*-*This is a super-portable random number generator*-*-*-*-*-*-*
06285 //*-*          ================================================
06286 //*-*         It should not overflow on any 32-bit machine.
06287 //*-*         The cycle is only ~10**9, so use with care!
06288 //*-*         Note especially that VAL must not be undefined on input.
06289 //*-*                    Set Default Starting Seed
06290 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
06291 
06292     /* Initialized data */
06293 
06294     /*static*/ int iseed = 12345;
06295 
06296     int k;
06297 
06298     if (val == 3) goto L100;
06299     inseed = iseed;
06300     k      = iseed / 53668;
06301     iseed  = (iseed - k*53668)*40014 - k*12211;
06302     if (iseed < 0) iseed += 2147483563;
06303     val = double(iseed*4.656613e-10);
06304     return;
06305 //*-*               "entry" to set seed, flag is VAL=3
06306 L100:
06307     iseed = inseed;
06308 } /* mnrn15_ */
06309 
06310 //______________________________________________________________________________
06311 inline
06312 void fitter::mnrset(int iopt)
06313 {
06314 //*-*-*-*-*-*-*-*Resets function value and errors to UNDEFINED*-*-*-*-*-*-*-*
06315 //*-*            =============================================
06316 //*-*    If IOPT=1,
06317 //*-*    If IOPT=0, sets only MINOS errors to undefined
06318 //*-*        Called from MNCLER and whenever problem changes, for example
06319 //*-*        after SET LIMITS, SET PARAM, CALL FCN 6
06320 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
06321 
06322     /*static*/ int iext, i;
06323 
06324     fCstatu = "RESET     ";
06325     if (iopt >= 1) {
06326         fAmin   = fUndefi;
06327         fFval3  = TMath_Abs(fAmin)*2 + 1;
06328         fEDM    = fBigedm;
06329         fISW[3] = 0;
06330         fISW[1] = 0;
06331         fDcovar = 1;
06332         fISW[0] = 0;
06333     }
06334     fLnolim = true;
06335     for (i = 1; i <= fNpar; ++i) {
06336         iext = fNexofi[i-1];
06337         if (fNvarl[iext-1] >= 4) fLnolim = false;
06338         fErp[i-1] = 0;
06339         fErn[i-1] = 0;
06340         fGlobcc[i-1] = 0;
06341     }
06342     if (fISW[1] >= 1) {
06343         fISW[1] = 1;
06344         fDcovar = TMath_Max(fDcovar,.5);
06345     }
06346 } /* mnrset_ */
06347 
06348 //______________________________________________________________________________
06349 inline
06350 void fitter::mnsave()
06351 {
06352 //*-*-*-*Writes current parameter values and step sizes onto file ISYSSA*-*-*
06353 //*-*    ===============================================================
06354 //*-*          in format which can be reread by Minuit for restarting.
06355 //*-*       The covariance matrix is also output if it exists.
06356 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
06357 
06358    Printf(f_out,"mnsave is dummy in the base class Minuit: Use MinuitOld");
06359 
06360 } /* mnsave_ */
06361 
06362 //______________________________________________________________________________
06363 inline
06364 void fitter::mnscan()
06365 {
06366 //*-*-*-*-*Scans the values of FCN as a function of one parameter*-*-*-*-*-*
06367 //*-*      ======================================================
06368 //*-*        and plots the resulting values as a curve using MNPLOT.
06369 //*-*        It may be called to scan one parameter or all parameters.
06370 //*-*        retains the best function and parameter values found.
06371 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
06372 
06373     /* Local variables */
06374     /*static*/ double step, uhigh, xhreq, xlreq, ubest, fnext, unext, xh, xl;
06375     /*static*/ int ipar, iint, icall, ncall, nbins, nparx;
06376     /*static*/ int nxypt, nccall, iparwd;
06377     step = 0; //GB
06378 
06379     xlreq = TMath_Min(fWord7[2],fWord7[3]);
06380     xhreq = TMath_Max(fWord7[2],fWord7[3]);
06381     ncall = int((fWord7[1] + .01));
06382     if (ncall <= 1)  ncall = 41;
06383     if (ncall > 101) ncall = 101;
06384     nccall = ncall;
06385     if (fAmin == fUndefi) mnamin();
06386     iparwd  = int((fWord7[0] + .1));
06387     ipar    = TMath_Max(iparwd,0);
06388     iint    = fNiofex[ipar-1];
06389     fCstatu = "NO CHANGE";
06390     if (iparwd > 0) goto L200;
06391 
06392 //*-*-        equivalent to a loop over parameters requested
06393 L100:
06394     ++ipar;
06395     if (ipar > fNu) goto L900;
06396     iint = fNiofex[ipar-1];
06397     if (iint <= 0) goto L100;
06398 //*-*-        set up range for parameter IPAR
06399 L200:
06400     ubest    = fU[ipar-1];
06401     fXpt[0]  = ubest;
06402     fYpt[0]  = fAmin;
06403     fChpt[0] = " ";
06404     fXpt[1]  = ubest;
06405     fYpt[1]  = fAmin;
06406     fChpt[1] = "X";
06407     nxypt    = 2;
06408     if (fNvarl[ipar-1] > 1) goto L300;
06409 
06410 //*-*-        no limits on parameter
06411     if (xlreq == xhreq) goto L250;
06412     unext = xlreq;
06413     step = (xhreq - xlreq) / double(ncall-1);
06414     goto L500;
06415 L250:
06416     xl = ubest - fWerr[iint-1];
06417     xh = ubest + fWerr[iint-1];
06418     mnbins(xl, xh, ncall, unext, uhigh, nbins, step);
06419     nccall = nbins + 1;
06420     goto L500;
06421 //*-*-        limits on parameter
06422 L300:
06423     if (xlreq == xhreq) goto L350;
06424 //*-*  Computing MAX
06425     xl = TMath_Max(xlreq,fAlim[ipar-1]);
06426 //*-*  Computing MIN
06427     xh = TMath_Min(xhreq,fBlim[ipar-1]);
06428     if (xl >= xh) goto L700;
06429     unext = xl;
06430     step  = (xh - xl) / double(ncall-1);
06431     goto L500;
06432 L350:
06433     unext = fAlim[ipar-1];
06434     step = (fBlim[ipar-1] - fAlim[ipar-1]) / double(ncall-1);
06435 //*-*-        main scanning loop over parameter IPAR
06436 L500:
06437     for (icall = 1; icall <= nccall; ++icall) {
06438         fU[ipar-1] = unext;
06439         nparx = fNpar;
06440     //Printf(f_out,"debug : FCN : 023");
06441         (*fFCN)(nparx, fGin, fnext, fU, 4,fTag);        ++fNfcn;
06442         ++nxypt;
06443         fXpt[nxypt-1]  = unext;
06444         fYpt[nxypt-1]  = fnext;
06445         fChpt[nxypt-1] = "*";
06446         if (fnext < fAmin) {
06447             fAmin   = fnext;
06448             ubest   = unext;
06449             fCstatu = "IMPROVED  ";
06450         }
06451         unext += step;
06452     }
06453 //*-*-        finished with scan of parameter IPAR
06454     fU[ipar-1] = ubest;
06455     mnexin(fX);
06456     Printf(f_out,"%dSCAN OF PARAMETER NO. %d,  %s"
06457          ,fNewpag,ipar,fCpnam[ipar-1].c_str());
06458     mnplot(fXpt, fYpt, fChpt, nxypt, fNpagwd, fNpagln);
06459     goto L800;
06460 L700:
06461     Printf(f_out," REQUESTED RANGE OUTSIDE LIMITS FOR PARAMETER  %d",ipar);
06462 L800:
06463     if (iparwd <= 0) goto L100;
06464 //*-*-        finished with all parameters
06465 L900:
06466     mnprin(5, fAmin);
06467 } /* mnscan_ */
06468 
06469 //______________________________________________________________________________
06470 inline
06471 void fitter::mnseek()
06472 {
06473 //*-*-*-*Performs a rough (but global) minimization by monte carlo search*-*
06474 //*-*    ================================================================
06475 //*-*        Each time a new minimum is found, the search area is shifted
06476 //*-*        to be centered at the best value.  Random points are chosen
06477 //*-*        uniformly over a hypercube determined by current step sizes.
06478 //*-*   The Metropolis algorithm accepts a worse point with probability
06479 //*-*      exp(-d/UP), where d is the degradation.  Improved points
06480 //*-*      are of course always accepted.  Actual steps are random
06481 //*-*      multiples of the nominal steps (DIRIN).
06482 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
06483 
06484     /* Local variables */
06485     /*static*/ double xmid[kMAXDIM], dxdi, rnum, ftry, rnum1, rnum2, alpha;
06486     /*static*/ double flast, xbest[kMAXDIM], bar;
06487     /*static*/ int ipar, iext, j, ifail, iseed, nparx, istep, ib, mxfail, mxstep;
06488 
06489     mxfail = int(fWord7[0]);
06490     if (mxfail <= 0) mxfail = fNpar*20 + 100;
06491     mxstep = mxfail*10;
06492     if (fAmin == fUndefi) mnamin();
06493     alpha = fWord7[1];
06494     if (alpha <= 0) alpha = 3;
06495     if (fISW[4] >= 1) {
06496         Printf(f_out," MNSEEK: MONTE CARLO MINIMIZATION USING METROPOLIS ALGORITHM");
06497         Printf(f_out," TO STOP AFTER %6d SUCCESSIVE FAILURES, OR %7d STEPS",mxfail,mxstep);
06498         Printf(f_out," MAXIMUM STEP SIZE IS %9.3f ERROR BARS.",alpha);
06499     }
06500     fCstatu = "INITIAL  ";
06501     if (fISW[4] >= 2) mnprin(2, fAmin);
06502     fCstatu = "UNCHANGED ";
06503     ifail   = 0;
06504     rnum    = 0;
06505     rnum1   = 0;
06506     rnum2   = 0;
06507     nparx   = fNpar;
06508     flast   = fAmin;
06509 //*-*-             set up step sizes, starting values
06510     for (ipar = 1; ipar <= fNpar; ++ipar) {
06511         iext = fNexofi[ipar-1];
06512         fDirin[ipar-1] = alpha*2*fWerr[ipar-1];
06513         if (fNvarl[iext-1] > 1) {
06514 //*-*-             parameter with limits
06515             mndxdi(fX[ipar-1], ipar-1, dxdi);
06516             if (dxdi == 0) dxdi = 1;
06517             fDirin[ipar-1] = alpha*2*fWerr[ipar-1] / dxdi;
06518             if (TMath_Abs(fDirin[ipar-1]) > 6.2831859999999997) {
06519                 fDirin[ipar-1] = 6.2831859999999997;
06520             }
06521         }
06522         xmid[ipar-1] = fX[ipar-1];
06523         xbest[ipar-1] = fX[ipar-1];
06524     }
06525 //*-*-                             search loop
06526     for (istep = 1; istep <= mxstep; ++istep) {
06527         if (ifail >= mxfail) break;
06528         for (ipar = 1; ipar <= fNpar; ++ipar) {
06529             mnrn15(rnum1, iseed);
06530             mnrn15(rnum2, iseed);
06531             fX[ipar-1] = xmid[ipar-1] + (rnum1 + rnum2 - 1)*.5*fDirin[ipar-1];
06532         }
06533         mninex(fX);
06534     //Printf(f_out,"debug : FCN : 024");
06535         (*fFCN)(nparx, fGin, ftry, fU, 4,fTag); ++fNfcn;
06536         if (ftry < flast) {
06537             if (ftry < fAmin) {
06538                 fCstatu = "IMPROVEMNT";
06539                 fAmin = ftry;
06540                 for (ib = 1; ib <= fNpar; ++ib) { xbest[ib-1] = fX[ib-1]; }
06541                 ifail = 0;
06542                 if (fISW[4] >= 2) mnprin(2, fAmin);
06543             }
06544             goto L300;
06545         } else {
06546             ++ifail;
06547 //*-*-                  Metropolis algorithm
06548             bar = (fAmin - ftry) / fUp;
06549             mnrn15(rnum, iseed);
06550             if (bar < TMath_Log(rnum)) continue;
06551         }
06552 //*-*-                   Accept new point, move there
06553 L300:
06554         for (j = 1; j <= fNpar; ++j) { xmid[j-1] = fX[j-1];     }
06555         flast = ftry;
06556     }
06557 //*-*-                              end search loop
06558     if (fISW[4] > 1) {
06559         Printf(f_out," MNSEEK: %5d SUCCESSIVE UNSUCCESSFUL TRIALS.",ifail);
06560     }
06561     for (ib = 1; ib <= fNpar; ++ib) { fX[ib-1] = xbest[ib-1]; }
06562     mninex(fX);
06563     if (fISW[4] >= 1) mnprin(2, fAmin);
06564     if (fISW[4] == 0) mnprin(0, fAmin);
06565 } /* mnseek_ */
06566 
06567 //______________________________________________________________________________
06568 inline
06569 void fitter::mnset()
06570 {
06571 //*-*-*-*-*Interprets the commands that start with SET and SHOW*-*-*-*-*-*-*
06572 //*-*      ====================================================
06573 //*-*        Called from MNEXCM
06574 //*-*        file characteristics for SET INPUT
06575 //*-*       'SET ' or 'SHOW',  'ON ' or 'OFF', 'SUPPRESSED' or 'REPORTED  '
06576 //*-*        explanation of print level numbers -1:3  and strategies 0:2
06577 //*-*        identification of debug options
06578 //*-*        things that can be set or shown
06579 //*-*        options not intended for normal users
06580 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
06581 
06582     /* Initialized data */
06583 
06584     static const std::string cname[30] = {
06585       "FCN value ",
06586       "PARameters",
06587       "LIMits    ",
06588       "COVariance",
06589       "CORrelatio",
06590       "PRInt levl",
06591       "NOGradient",
06592       "GRAdient  ",
06593       "ERRor def ",
06594       "INPut file",
06595       "WIDth page",
06596       "LINes page",
06597       "NOWarnings",
06598       "WARnings  ",
06599       "RANdom gen",
06600       "TITle     ",
06601       "STRategy  ",
06602       "EIGenvalue",
06603       "PAGe throw",
06604       "MINos errs",
06605       "EPSmachine",
06606       "OUTputfile",
06607       "BATch     ",
06608       "INTeractiv",
06609       "VERsion   ",
06610       "reserve   ",
06611       "NODebug   ",
06612       "DEBug     ",
06613       "SHOw      ",
06614       "SET       "};
06615 
06616     /*static*/ int nname = 25;
06617     /*static*/ int nntot = 30;
06618     static const std::string cprlev[5] = {
06619       "-1: NO OUTPUT EXCEPT FROM SHOW    ",
06620       " 0: REDUCED OUTPUT                ",
06621       " 1: NORMAL OUTPUT                 ",
06622       " 2: EXTRA OUTPUT FOR PROBLEM CASES",
06623       " 3: MAXIMUM OUTPUT                "};
06624 
06625     static const std::string cstrat[3] = {
06626       " 0: MINIMIZE THE NUMBER OF CALLS TO FUNCTION",
06627       " 1: TRY TO BALANCE SPEED AGAINST RELIABILITY",
06628       " 2: MAKE SURE MINIMUM TRUE, ERRORS CORRECT  "};
06629 
06630     static const std::string cdbopt[7] = {
06631       "REPORT ALL EXCEPTIONAL CONDITIONS      ",
06632       "MNLINE: LINE SEARCH MINIMIZATION       ",
06633       "MNDERI: FIRST DERIVATIVE CALCULATIONS  ",
06634       "MNHESS: SECOND DERIVATIVE CALCULATIONS ",
06635       "MNMIGR: COVARIANCE MATRIX UPDATES      ",
06636       "MNHES1: FIRST DERIVATIVE UNCERTAINTIES ",
06637       "MNCONT: MNCONTOUR PLOT (MNCROS SEARCH) "};
06638 
06639     /* System generated locals */
06640     int f_inqu();
06641 
06642     /* Local variables */
06643     /*static*/ double val;
06644     /*static*/ int iset, iprm, i, jseed, kname, iseed, iunit, idx, ii, kk;
06645     /*static*/ int ikseed, idbopt, igrain, iswsav, isw2;
06646     /*static*/ std::string  cfname, cmode, ckind,  cwarn, copt, ctemp, ctemp2;
06647     //G.Barrand /*static*/ bool lname;
06648     igrain = 0; //GB : rm warning.
06649 
06650     for (i = 1; i <= nntot; ++i) {
06651         ctemp  = msubstr(cname[i-1],0,3);
06652         ctemp2 = msubstr(fCword,3,7);
06653         if (strstr(ctemp2.c_str(), ctemp.c_str())) goto L5;
06654     }
06655     i = 0;
06656 L5:
06657     kname = i;
06658 
06659 //*-*-          Command could be SET xxx, SHOW xxx,  HELP SET or HELP SHOW
06660     if (msubstr(fCword,0,3) == "HEL")  goto L2000;
06661     if (msubstr(fCword,0,3) == "SHO")  goto L1000;
06662     if (msubstr(fCword,0,3) != "SET")  goto L1900;
06663 //*-*-                          ---
06664     ckind = "SET ";
06665 //*-*-                                       . . . . . . . . . . set unknown
06666     if (kname <= 0) goto L1900;
06667 //*-*-                                       . . . . . . . . . . set known
06668     switch ((int)kname) {
06669         case 1:  goto L3000;
06670         case 2:  goto L20;
06671         case 3:  goto L30;
06672         case 4:  goto L40;
06673         case 5:  goto L3000;
06674         case 6:  goto L60;
06675         case 7:  goto L70;
06676         case 8:  goto L80;
06677         case 9:  goto L90;
06678         case 10:  goto L100;
06679         case 11:  goto L110;
06680         case 12:  goto L120;
06681         case 13:  goto L130;
06682         case 14:  goto L140;
06683         case 15:  goto L150;
06684         case 16:  goto L160;
06685         case 17:  goto L170;
06686         case 18:  goto L3000;
06687         case 19:  goto L190;
06688         case 20:  goto L3000;
06689         case 21:  goto L210;
06690         case 22:  goto L220;
06691         case 23:  goto L230;
06692         case 24:  goto L240;
06693         case 25:  goto L3000;
06694         case 26:  goto L1900;
06695         case 27:  goto L270;
06696         case 28:  goto L280;
06697         case 29:  goto L290;
06698         case 30:  goto L300;
06699     }
06700 
06701 //*-*-                                       . . . . . . . . . . set param
06702 L20:
06703     iprm = int(fWord7[0]);
06704     if (iprm > fNu) goto L25;
06705     if (iprm <= 0) goto L25;
06706     if (fNvarl[iprm-1] < 0) goto L25;
06707     fU[iprm-1] = fWord7[1];
06708     mnexin(fX);
06709     isw2 = fISW[1];
06710     mnrset(1);
06711 //*-*-       Keep approximate covariance matrix, even if new param value
06712     fISW[1] = TMath_Min(isw2,1);
06713     fCfrom  = "SET PARM";
06714     fNfcnfr = fNfcn;
06715     fCstatu = "NEW VALUES";
06716     return;
06717 L25:
06718     Printf(f_out," UNDEFINED PARAMETER NUMBER.  IGNORED.");
06719     return;
06720 //*-*-                                       . . . . . . . . . . set limits
06721 L30:
06722     mnlims();
06723     return;
06724 //*-*-                                       . . . . . . . . . . set covar
06725 L40:
06726 //*-*   this command must be handled by MNREAD, and is not Fortran-callable
06727     goto L3000;
06728 //*-*-                                       . . . . . . . . . . set print
06729 L60:
06730     fISW[4] = int(fWord7[0]);
06731     return;
06732 //*-*-                                       . . . . . . . . . . set nograd
06733 L70:
06734     fISW[2] = 0;
06735     return;
06736 //*-*-                                       . . . . . . . . . . set grad
06737 L80:
06738     mngrad();
06739     return;
06740 //*-*-                                       . . . . . . . . . . set errdef
06741 L90:
06742     if (fWord7[0] == fUp) return;
06743     if (fWord7[0] <= 0) {
06744         if (fUp == fUpdflt) return;
06745         fUp = fUpdflt;
06746     } else {
06747         fUp = fWord7[0];
06748     }
06749     for (i = 1; i <= fNpar; ++i) {
06750         fErn[i-1] = 0;
06751         fErp[i-1] = 0;
06752     }
06753     mnwerr();
06754     return;
06755 //*-*-                                       . . . . . . . . . . set input
06756 //*-* This command must be handled by MNREAD. If it gets this far,
06757 //*-*-        it is illegal.
06758 L100:
06759     goto L3000;
06760 //*-*-                                       . . . . . . . . . . set width
06761 L110:
06762     fNpagwd = int(fWord7[0]);
06763     fNpagwd = TMath_Max(fNpagwd,50);
06764     return;
06765 
06766 L120:
06767     fNpagln = int(fWord7[0]);
06768     return;
06769 //*-*-                                       . . . . . . . . . . set nowarn
06770 
06771 L130:
06772     fLwarn = false;
06773     return;
06774 //*-*-                                       . . . . . . . . . . set warn
06775 L140:
06776     fLwarn = true;
06777     mnwarn("W", "SHO", "SHO");
06778     return;
06779 //*-*-                                       . . . . . . . . . . set random
06780 L150:
06781     jseed = int(fWord7[0]);
06782     val = 3;
06783     mnrn15(val, jseed);
06784     if (fISW[4] > 0) {
06785         Printf(f_out," MINUIT RANDOM NUMBER SEED SET TO %d",jseed);
06786     }
06787     return;
06788 //*-*-                                       . . . . . . . . . . set title
06789 L160:
06790 //*-*   this command must be handled by MNREAD, and is not Fortran-callable
06791     goto L3000;
06792 //*-*-                                       . . . . . . . . . set strategy
06793 L170:
06794     fIstrat = int(fWord7[0]);
06795     fIstrat = TMath_Max(fIstrat,0);
06796     fIstrat = TMath_Min(fIstrat,2);
06797     if (fISW[4] > 0) goto L1172;
06798     return;
06799 //*-*-                                      . . . . . . . . . set page throw
06800 L190:
06801     fNewpag = int(fWord7[0]);
06802     goto L1190;
06803 //*-*-                                       . . . . . . . . . . set epsmac
06804 L210:
06805     if (fWord7[0] > 0 && fWord7[0] < .1) {
06806         fEpsmac = fWord7[0];
06807     }
06808     fEpsma2 = TMath_Sqrt(fEpsmac);
06809     goto L1210;
06810 //*-*-                                      . . . . . . . . . . set outputfile
06811 L220:
06812     iunit = int(fWord7[0]);
06813     fIsyswr = iunit;
06814     fIstkwr[0] = iunit;
06815     if (fISW[4] >= 0) goto L1220;
06816     return;
06817 //*-*-                                       . . . . . . . . . . set batch
06818 L230:
06819     fISW[5] = 0;
06820     if (fISW[4] >= 0) goto L1100;
06821     return;
06822 //*-*-                                      . . . . . . . . . . set interactive
06823 L240:
06824     fISW[5] = 1;
06825     if (fISW[4] >= 0) goto L1100;
06826     return;
06827 //*-*-                                       . . . . . . . . . . set nodebug
06828 L270:
06829     iset = 0;
06830     goto L281;
06831 //*-*-                                       . . . . . . . . . . set debug
06832 L280:
06833     iset = 1;
06834 L281:
06835     idbopt = int(fWord7[0]);
06836     if (idbopt > 6) goto L288;
06837     if (idbopt >= 0) {
06838         fIdbg[idbopt] = iset;
06839         if (iset == 1) fIdbg[0] = 1;
06840     } else {
06841 //*-*-            SET DEBUG -1  sets all debug options
06842         /*G.Barrand : have idx*/
06843         for (idx = 0; idx <= 6; ++idx) { fIdbg[idx] = iset; }
06844     }
06845     fLrepor = fIdbg[0] >= 1;
06846     mnwarn("D", "SHO", "SHO");
06847     return;
06848 L288:
06849     Printf(f_out," UNKNOWN DEBUG OPTION %d REQUESTED. IGNORED",idbopt);
06850     return;
06851 //*-*-                                       . . . . . . . . . . set show
06852 L290:
06853 //*-*-                                       . . . . . . . . . . set set
06854 L300:
06855     goto L3000;
06856 //*-*-               -----------------------------------------------------
06857 L1000:
06858 //*-*-              at this point, CWORD must be 'SHOW'
06859     ckind = "SHOW";
06860     if (kname <= 0) goto L1900;
06861 
06862     switch ((int)kname) {
06863         case 1:  goto L1010;
06864         case 2:  goto L1020;
06865         case 3:  goto L1030;
06866         case 4:  goto L1040;
06867         case 5:  goto L1050;
06868         case 6:  goto L1060;
06869         case 7:  goto L1070;
06870         case 8:  goto L1070;
06871         case 9:  goto L1090;
06872         case 10:  goto L1100;
06873         case 11:  goto L1110;
06874         case 12:  goto L1120;
06875         case 13:  goto L1130;
06876         case 14:  goto L1130;
06877         case 15:  goto L1150;
06878         case 16:  goto L1160;
06879         case 17:  goto L1170;
06880         case 18:  goto L1180;
06881         case 19:  goto L1190;
06882         case 20:  goto L1200;
06883         case 21:  goto L1210;
06884         case 22:  goto L1220;
06885         case 23:  goto L1100;
06886         case 24:  goto L1100;
06887         case 25:  goto L1250;
06888         case 26:  goto L1900;
06889         case 27:  goto L1270;
06890         case 28:  goto L1270;
06891         case 29:  goto L1290;
06892         case 30:  goto L1300;
06893     }
06894 
06895 //*-*-                                       . . . . . . . . . . show fcn
06896 L1010:
06897     if (fAmin == fUndefi) mnamin();
06898     mnprin(0, fAmin);
06899     return;
06900 //*-*-                                       . . . . . . . . . . show param
06901 L1020:
06902     if (fAmin == fUndefi) mnamin();
06903     mnprin(5, fAmin);
06904     return;
06905 //*-*-                                       . . . . . . . . . . show limits
06906 L1030:
06907     if (fAmin == fUndefi) mnamin();
06908     mnprin(1, fAmin);
06909     return;
06910 //*-*-                                       . . . . . . . . . . show covar
06911 L1040:
06912     mnmatu(1);
06913     return;
06914 //*-*-                                       . . . . . . . . . . show corre
06915 L1050:
06916     mnmatu(0);
06917     return;
06918 //*-*-                                       . . . . . . . . . . show print
06919 L1060:
06920     if (fISW[4] < -1) fISW[4] = -1;
06921     if (fISW[4] > 3)  fISW[4] = 3;
06922     Printf(f_out," ALLOWED PRINT LEVELS ARE:");
06923     Printf(f_out,"                           %s",cprlev[0].c_str());
06924     Printf(f_out,"                           %s",cprlev[1].c_str());
06925     Printf(f_out,"                           %s",cprlev[2].c_str());
06926     Printf(f_out,"                           %s",cprlev[3].c_str());
06927     Printf(f_out,"                           %s",cprlev[4].c_str());
06928     Printf(f_out," CURRENT PRINTOUT LEVEL IS %s",cprlev[fISW[4]].c_str());
06929     return;
06930 //*-*-                                       . . . . . . . show nograd, grad
06931 L1070:
06932     if (fISW[2] <= 0) {
06933         Printf(f_out," NOGRAD IS SET.  DERIVATIVES NOT COMPUTED IN FCN.");
06934     } else {
06935         Printf(f_out,"   GRAD IS SET.  USER COMPUTES DERIVATIVES IN FCN.");
06936     }
06937     return;
06938 //*-*-                                      . . . . . . . . . . show errdef
06939 L1090:
06940     Printf(f_out," ERRORS CORRESPOND TO FUNCTION CHANGE OF %g",fUp);
06941     return;
06942 //*-*-                                      . . . . . . . . . . show input,
06943 //*-*-                                               batch, or interactive
06944 L1100:
06945 //    ioin__1.inerr = 0;
06946 //    ioin__1.inunit = fIsysrd;
06947 //    ioin__1.infile = 0;
06948 //    ioin__1.inex = 0;
06949 //    ioin__1.inopen = 0;
06950 //    ioin__1.innum = 0;
06951 //    ioin__1.innamed = &lname;
06952 //    ioin__1.innamlen = 64;
06953 //    ioin__1.inname = cfname;
06954 //    ioin__1.inacc = 0;
06955 //    ioin__1.inseq = 0;
06956 //    ioin__1.indir = 0;
06957 //    ioin__1.infmt = 0;
06958 //    ioin__1.inform = 0;
06959 //    ioin__1.inunf = 0;
06960 //    ioin__1.inrecl = 0;
06961 //    ioin__1.innrec = 0;
06962 //    ioin__1.inblank = 0;
06963 //    f_inqu(&ioin__1);
06964     cmode = "BATCH MODE      ";
06965     if (fISW[5] == 1) cmode  = "INTERACTIVE MODE";
06966     /*G.Barrand if (! lname)*/      cfname = "unknown";
06967     Printf(f_out," INPUT NOW BEING READ IN %s FROM UNIT NO. %d FILENAME: %s"
06968            ,cmode.c_str(),fIsysrd,cfname.c_str());
06969     return;
06970 //*-*-                                      . . . . . . . . . . show width
06971 L1110:
06972     Printf(f_out,"          PAGE WIDTH IS SET TO %d COLUMNS",fNpagwd);
06973     return;
06974 //*-*-                                      . . . . . . . . . . show lines
06975 L1120:
06976     Printf(f_out,"          PAGE LENGTH IS SET TO %d LINES",fNpagln);
06977     return;
06978 //*-*-                                      . . . . . . .show nowarn, warn
06979 L1130:
06980     cwarn = "SUPPRESSED";
06981     if (fLwarn) cwarn = "REPORTED  ";
06982     Printf(f_out,"%s",cwarn.c_str());
06983     if (! fLwarn) mnwarn("W", "SHO", "SHO");
06984     return;
06985 //*-*-                                     . . . . . . . . . . show random
06986 L1150:
06987     val = 0;
06988     mnrn15(val, igrain);
06989     ikseed = igrain;
06990     Printf(f_out," MINUIT RNDM SEED IS CURRENTLY=",ikseed);
06991     val   = 3;
06992     iseed = ikseed;
06993     mnrn15(val, iseed);
06994     return;
06995 //*-*-                                       . . . . . . . . . show title
06996 L1160:
06997     Printf(f_out," TITLE OF CURRENT TASK IS:%s",fCtitl.c_str());
06998     return;
06999 //*-*-                                       . . . . . . . show strategy
07000 L1170:
07001     Printf(f_out," ALLOWED STRATEGIES ARE:");
07002     Printf(f_out,"                    %s",cstrat[0].c_str());
07003     Printf(f_out,"                    %s",cstrat[1].c_str());
07004     Printf(f_out,"                    %s",cstrat[2].c_str());
07005 L1172:
07006     Printf(f_out," NOW USING STRATEGY %s",cstrat[fIstrat].c_str());
07007     return;
07008 //*-*-                                         . . . . . show eigenvalues
07009 L1180:
07010     iswsav = fISW[4];
07011     fISW[4] = 3;
07012     if (fISW[1] < 1) {
07013         Printf(f_out,"%s",fCovmes[0].c_str());
07014     } else {
07015         mnpsdf();
07016     }
07017     fISW[4] = iswsav;
07018     return;
07019 //*-*-                                           . . . . . show page throw
07020 L1190:
07021     Printf(f_out," PAGE THROW CARRIAGE CONTROL = %d",fNewpag);
07022     if (fNewpag == 0) {
07023         Printf(f_out," NO PAGE THROWS IN MINUIT OUTPUT");
07024     }
07025     return;
07026 //*-*-                                       . . . . . . show minos errors
07027 L1200:
07028     for (ii = 1; ii <= fNpar; ++ii) {
07029         if (fErp[ii-1] > 0 || fErn[ii-1] < 0) goto L1204;
07030     }
07031     Printf(f_out,"       THERE ARE NO MINOS ERRORS CURRENTLY VALID.");
07032     return;
07033 L1204:
07034     mnprin(4, fAmin);
07035     return;
07036 //*-*-                                       . . . . . . . . . show epsmac
07037 L1210:
07038     Printf(f_out," FLOATING-POINT NUMBERS ASSUMED ACCURATE TO %g",fEpsmac);
07039     return;
07040 //*-*-                                       . . . . . . show outputfiles
07041 L1220:
07042     Printf(f_out,"  MINUIT PRIMARY OUTPUT TO UNIT %d",fIsyswr);
07043     return;
07044 //*-*-                                       . . . . . . show version
07045 L1250:
07046     Printf(f_out," THIS IS MINUIT VERSION:%s",fCvrsn.c_str());
07047     return;
07048 //*-*-                                       . . . . . . show nodebug, debug
07049 L1270:
07050     /*G.Barrand : have idx.*/
07051     for (idx = 0; idx <= 6; ++idx) {
07052         copt = "OFF";
07053         if (fIdbg[idx] >= 1) copt = "ON ";
07054         Printf(f_out,"          DEBUG OPTION %3d IS %3s :%s"
07055              ,idx,copt.c_str(),cdbopt[idx].c_str());
07056     }
07057     if (! fLrepor) mnwarn("D", "SHO", "SHO");
07058     return;
07059 //*-*-                                       . . . . . . . . . . show show
07060 L1290:
07061     ckind = "SHOW";
07062     goto L2100;
07063 //*-*-                                       . . . . . . . . . . show set
07064 L1300:
07065     ckind = "SET ";
07066     goto L2100;
07067 //*-*-               -----------------------------------------------------
07068 //*-*-                             UNKNOWN COMMAND
07069 L1900:
07070     Printf(f_out," THE COMMAND:%10s IS UNKNOWN.",fCword.c_str());
07071     goto L2100;
07072 //*-*-               -----------------------------------------------------
07073 //*-*-                   HELP SHOW,  HELP SET,  SHOW SET, or SHOW SHOW
07074 L2000:
07075     ckind = "SET ";
07076     ctemp = msubstr(fCword,3,7);
07077     if (ctemp=="SHO") ckind = "SHOW";
07078 L2100:
07079     Printf(f_out," THE FORMAT OF THE %4s COMMAND IS:",ckind.c_str());
07080     Printf(f_out," %s xxx    [numerical arguments if any]",ckind.c_str());
07081     Printf(f_out," WHERE xxx MAY BE ONE OF THE FOLLOWING:");
07082     for (kk = 1; kk <= nname; ++kk) {
07083         Printf(f_out," %s",cname[kk-1].c_str());
07084     }
07085     return;
07086 //*-*-               -----------------------------------------------------
07087 //*-*-                              ILLEGAL COMMAND
07088 L3000:
07089     Printf(f_out," ABOVE COMMAND IS ILLEGAL.   IGNORED");
07090 
07091 } /* mnset_ */
07092 
07093 //______________________________________________________________________________
07094 inline
07095 void fitter::mnsimp()
07096 {
07097 //*-*-*-*-*Minimization using the simplex method of Nelder and Mead*-*-*-*-*
07098 //*-*      ========================================================
07099 //*-*        Performs a minimization using the simplex method of Nelder
07100 //*-*        and Mead (ref. -- Comp. J. 7,308 (1965)).
07101 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
07102 
07103     /* Initialized data */
07104 
07105     /*static*/ double alpha = 1;
07106     /*static*/ double beta = .5;
07107     /*static*/ double gamma = 2;
07108     /*static*/ double rhomin = 4;
07109     /*static*/ double rhomax = 8;
07110 
07111     /* Local variables */
07112     /*static*/ double dmin_, dxdi, yrho, f, ynpp1, y[kMAXDIM+1], aming, ypbar;
07113     /*static*/ double bestx, ystar, y1, y2, ystst, pb, wg;
07114     /*static*/ double absmin, rho, sig2, rho1, rho2;
07115     /*static*/ int npfn, i, j, k, jhold, ncycl, nparx;
07116     /*static*/ int nparp1, kg, jh, nf, jl, ns;
07117 
07118     if (fNpar <= 0) return;
07119     if (fAmin == fUndefi) mnamin();
07120     fCfrom  = "SIMPLEX ";
07121     fNfcnfr = fNfcn;
07122     fCstatu = "UNCHANGED ";
07123     npfn    = fNfcn;
07124     nparp1  = fNpar + 1;
07125     nparx   = fNpar;
07126     rho1    = alpha + 1;
07127     rho2    = rho1 + alpha*gamma;
07128     wg      = 1 / double(fNpar);
07129     if (fISW[4] >= 0) {
07130         Printf(f_out," START SIMPLEX MINIMIZATION.    CONVERGENCE WHEN EDM .LT. %g",fEpsi);
07131     }
07132     for (i = 1; i <= fNpar; ++i) {
07133         fDirin[i-1] = fWerr[i-1];
07134         mndxdi(fX[i-1], i-1, dxdi);
07135         if (dxdi != 0) fDirin[i-1] = fWerr[i-1] / dxdi;
07136         dmin_ = fEpsma2*TMath_Abs(fX[i-1]);
07137         if (fDirin[i-1] < dmin_) fDirin[i-1] = dmin_;
07138     }
07139 //*-* **       choose the initial simplex using single-parameter searches
07140 L1:
07141     ynpp1 = fAmin;
07142     jl = nparp1;
07143     y[nparp1-1] = fAmin;
07144     absmin = fAmin;
07145     for (i = 1; i <= fNpar; ++i) {
07146         aming      = fAmin;
07147         fPbar[i-1] = fX[i-1];
07148         bestx      = fX[i-1];
07149         kg         = 0;
07150         ns         = 0;
07151         nf         = 0;
07152 L4:
07153         fX[i-1] = bestx + fDirin[i-1];
07154         mninex(fX);
07155     //Printf(f_out,"debug : FCN : 025");
07156         (*fFCN)(nparx, fGin, f, fU, 4,fTag);    ++fNfcn;
07157         if (f <= aming) goto L6;
07158 //*-*-        failure
07159         if (kg == 1) goto L8;
07160         kg = -1;
07161         ++nf;
07162         fDirin[i-1] *= -.4;
07163         if (nf < 3) goto L4;
07164         ns = 6;
07165 //*-*-        success
07166 L6:
07167         bestx        = fX[i-1];
07168         fDirin[i-1] *= 3;
07169         aming        = f;
07170         fCstatu      = "PROGRESS  ";
07171         kg           = 1;
07172         ++ns;
07173         if (ns < 6) goto L4;
07174 //*-*-        local minimum found in ith direction
07175 L8:
07176         y[i-1] = aming;
07177         if (aming < absmin) jl = i;
07178         if (aming < absmin) absmin = aming;
07179         fX[i-1] = bestx;
07180         for (k = 1; k <= fNpar; ++k) { fP[k + i*fMaxpar - fMaxpar-1] = fX[k-1]; }
07181     }
07182     jh    = nparp1;
07183     fAmin = y[jl-1];
07184     mnrazz(ynpp1, fPbar, y, jh, jl);
07185     for (i = 1; i <= fNpar; ++i) { fX[i-1] = fP[i + jl*fMaxpar - fMaxpar-1]; }
07186     mninex(fX);
07187     fCstatu = "PROGRESS  ";
07188     if (fISW[4] >= 1) mnprin(5, fAmin);
07189     fEDM  = fBigedm;
07190     sig2  = fEDM;
07191     ncycl = 0;
07192 //*-*-                                       . . . . .  start main loop
07193 L50:
07194     if (sig2 < fEpsi && fEDM < fEpsi) goto L76;
07195     sig2 = fEDM;
07196     if (fNfcn - npfn > fNfcnmx) goto L78;
07197 //*-*-        calculate new point * by reflection
07198     for (i = 1; i <= fNpar; ++i) {
07199         pb = 0;
07200         for (j = 1; j <= nparp1; ++j) { pb += wg*fP[i + j*fMaxpar - fMaxpar-1]; }
07201         fPbar[i-1]  = pb - wg*fP[i + jh*fMaxpar - fMaxpar-1];
07202         fPstar[i-1] = (alpha + 1)*fPbar[i-1] - alpha*fP[i + jh*fMaxpar - fMaxpar-1];
07203     }
07204     mninex(fPstar);
07205     //Printf(f_out,"debug : FCN : 026");
07206     (*fFCN)(nparx, fGin, ystar, fU, 4,fTag);    ++fNfcn;
07207     if (ystar >= fAmin) goto L70;
07208 //*-*-        point * better than jl, calculate new point **
07209     for (i = 1; i <= fNpar; ++i) {
07210         fPstst[i-1] = gamma*fPstar[i-1] + (1 - gamma)*fPbar[i-1];
07211     }
07212     mninex(fPstst);
07213     //Printf(f_out,"debug : FCN : 027");
07214     (*fFCN)(nparx, fGin, ystst, fU, 4,fTag);    ++fNfcn;
07215 //*-*-        try a parabola through ph, pstar, pstst.  min = prho
07216     y1 = (ystar - y[jh-1])*rho2;
07217     y2 = (ystst - y[jh-1])*rho1;
07218     rho = (rho2*y1 - rho1*y2)*.5 / (y1 - y2);
07219     if (rho < rhomin) goto L66;
07220     if (rho > rhomax) rho = rhomax;
07221     for (i = 1; i <= fNpar; ++i) {
07222         fPrho[i-1] = rho*fPbar[i-1] + (1 - rho)*fP[i + jh*fMaxpar - fMaxpar-1];
07223     }
07224     mninex(fPrho);
07225     //Printf(f_out,"debug : FCN : 028");
07226     (*fFCN)(nparx, fGin, yrho, fU, 4,fTag);    ++fNfcn;
07227     if (yrho < y[jl-1] && yrho < ystst) goto L65;
07228     if (ystst < y[jl-1]) goto L67;
07229     if (yrho > y[jl-1])  goto L66;
07230 //*-*-        accept minimum point of parabola, PRHO
07231 L65:
07232     mnrazz(yrho, fPrho, y, jh, jl);
07233     goto L68;
07234 L66:
07235     if (ystst < y[jl-1]) goto L67;
07236     mnrazz(ystar, fPstar, y, jh, jl);
07237     goto L68;
07238 L67:
07239     mnrazz(ystst, fPstst, y, jh, jl);
07240 L68:
07241     ++ncycl;
07242     if (fISW[4] < 2) goto L50;
07243     if (fISW[4] >= 3 || ncycl % 10 == 0) {
07244         mnprin(5, fAmin);
07245     }
07246     goto L50;
07247 //*-*-        point * is not as good as jl
07248 L70:
07249     if (ystar >= y[jh-1]) goto L73;
07250     jhold = jh;
07251     mnrazz(ystar, fPstar, y, jh, jl);
07252     if (jhold != jh) goto L50;
07253 //*-*-        calculate new point **
07254 L73:
07255     for (i = 1; i <= fNpar; ++i) {
07256         fPstst[i-1] = beta*fP[i + jh*fMaxpar - fMaxpar-1] + (1 - beta)*fPbar[i-1];
07257     }
07258     mninex(fPstst);
07259     //Printf(f_out,"debug : FCN : 029");
07260     (*fFCN)(nparx, fGin, ystst, fU, 4,fTag);    ++fNfcn;
07261     if (ystst > y[jh-1]) goto L1;
07262 //*-*-    point ** is better than jh
07263     if (ystst < fAmin) goto L67;
07264     mnrazz(ystst, fPstst, y, jh, jl);
07265     goto L50;
07266 //*-*-                                       . . . . . .  end main loop
07267 L76:
07268     if (fISW[4] >= 0) {
07269         Printf(f_out," SIMPLEX MINIMIZATION HAS CONVERGED.");
07270     }
07271     fISW[3] = 1;
07272     goto L80;
07273 L78:
07274     if (fISW[4] >= 0) {
07275         Printf(f_out," SIMPLEX TERMINATES WITHOUT CONVERGENCE.");
07276     }
07277     fCstatu = "CALL LIMIT";
07278     fISW[3] = -1;
07279     fISW[0] = 1;
07280 L80:
07281     for (i = 1; i <= fNpar; ++i) {
07282         pb = 0;
07283         for (j = 1; j <= nparp1; ++j) { pb += wg*fP[i + j*fMaxpar - fMaxpar-1]; }
07284         fPbar[i-1] = pb - wg*fP[i + jh*fMaxpar - fMaxpar-1];
07285     }
07286     mninex(fPbar);
07287     //Printf(f_out,"debug : FCN : 030");
07288     (*fFCN)(nparx, fGin, ypbar, fU, 4,fTag);    ++fNfcn;
07289     if (ypbar < fAmin)  mnrazz(ypbar, fPbar, y, jh, jl);
07290     mninex(fX);
07291     if (fNfcnmx + npfn - fNfcn < fNpar*3) goto L90;
07292     if (fEDM > fEpsi*2) goto L1;
07293 L90:
07294     if (fISW[4] >= 0) mnprin(5, fAmin);
07295 } /* mnsimp_ */
07296 
07297 //______________________________________________________________________________
07298 inline
07299 void fitter::mnstat(double &fmin, double &fedm, double &errdef, int &npari, int &nparx, int &istat)
07300 {
07301 
07302 //*-*-*-*-*Returns concerning the current status of the minimization*-*-*-*-*
07303 //*-*      =========================================================
07304 //*-*       User-called
07305 //*-*          Namely, it returns:
07306 //*-*        FMIN: the best function value found so far
07307 //*-*        FEDM: the estimated vertical distance remaining to minimum
07308 //*-*        ERRDEF: the value of UP defining parameter uncertainties
07309 //*-*        NPARI: the number of currently variable parameters
07310 //*-*        NPARX: the highest (external) parameter number defined by user
07311 //*-*        ISTAT: a status integer indicating how good is the covariance
07312 //*-*           matrix:  0= not calculated at all
07313 //*-*                    1= approximation only, not accurate
07314 //*-*                    2= full matrix, but forced positive-definite
07315 //*-*                    3= full accurate covariance matrix
07316 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
07317 
07318     fmin   = fAmin;
07319     fedm   = fEDM;
07320     errdef = fUp;
07321     npari  = fNpar;
07322     nparx  = fNu;
07323     istat  = fISW[1];
07324     if (fEDM == fBigedm) fedm = fUp;
07325     if (fAmin == fUndefi) {
07326         fmin  = 0;
07327         fedm  = fUp;
07328         istat = 0;
07329     }
07330 } /* mnstat_ */
07331 
07332 //______________________________________________________________________________
07333 inline
07334 void fitter::mntiny(double epsp1, double &epsbak)
07335 {
07336 //*-*-*-*-*-*-*-*To find the machine precision*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
07337 //*-*            =============================
07338 //*-*        Compares its argument with the value 1.0, and returns
07339 //*-*        the value .TRUE. if they are equal.  To find EPSMAC
07340 //*-*        safely by foiling the Fortran optimizer
07341 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
07342 
07343     epsbak = epsp1 - 1;
07344 } /* mntiny_ */
07345 
07346 //______________________________________________________________________________
07347 inline
07348 bool fitter::mnunpt(const std::string &cfname)
07349 {
07350 //*-*-*-*-*-*Returns .TRUE. if CFNAME contains unprintable characters*-*-*-*
07351 //*-*        ========================================================
07352 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
07353 
07354     /*static*/ int i, l, ic;
07355     bool ret_val;
07356     static const std::string cpt = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./;:[]$%*_!@#&+()";
07357 
07358     ret_val = false;
07359     l = cfname.size();
07360     for (i = 1; i <= l; ++i) {
07361         for (ic = 1; ic <= 80; ++ic) {
07362             if (cfname[i-1] == cpt[ic-1]) goto L100;
07363         }
07364         return true;
07365 L100:
07366         ;
07367     }
07368     return ret_val;
07369 } /* mnunpt_ */
07370 
07371 //______________________________________________________________________________
07372 inline
07373 void fitter::mnvert(double *a, int l, int, int n, int &ifail)
07374 {
07375 //*-*-*-*-*-*-*-*-*-*-*-*Inverts a symmetric matrix*-*-*-*-*-*-*-*-*-*-*-*-*
07376 //*-*                    ==========================
07377 //*-*        inverts a symmetric matrix.   matrix is first scaled to
07378 //*-*        have all ones on the diagonal (equivalent to change of units)
07379 //*-*        but no pivoting is done since matrix is positive-definite.
07380 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
07381 
07382     /* System generated locals */
07383     int a_offset;
07384 
07385     /* Local variables */
07386     /*static*/ double q[kMAXDIM], s[kMAXDIM], si, pp[kMAXDIM];
07387     /*static*/ int i, j, k, kp1, km1;
07388 
07389     /* Parameter adjustments */
07390     a_offset = l + 1;
07391     a -= a_offset;
07392 
07393     /* Function Body */
07394     ifail = 0;
07395     if (n < 1) goto L100;
07396     if (n > fMaxint) goto L100;
07397 //*-*-                  scale matrix by sqrt of diag elements
07398     for (i = 1; i <= n; ++i) {
07399         si = a[i + i*l];
07400         if (si <= 0) goto L100;
07401         s[i-1] = 1 / TMath_Sqrt(si);
07402     }
07403     for (i = 1; i <= n; ++i) {
07404         for (j = 1; j <= n; ++j) {
07405             a[i + j*l] = a[i + j*l]*s[i-1]*s[j-1];
07406         }
07407     }
07408 //*-*-                                       . . . start main loop . . . .
07409     for (i = 1; i <= n; ++i) {
07410         k = i;
07411 //*-*-                  preparation for elimination step1
07412         if (a[k + k*l] != 0) q[k-1] = 1 / a[k + k*l];
07413         else goto L100;
07414         pp[k-1] = 1;
07415         a[k + k*l] = 0;
07416         kp1 = k + 1;
07417         km1 = k - 1;
07418         if (km1 < 0) goto L100;
07419         else if (km1 == 0) goto L50;
07420         else               goto L40;
07421 L40:
07422         for (j = 1; j <= km1; ++j) {
07423             pp[j-1]    = a[j + k*l];
07424             q[j-1]     = a[j + k*l]*q[k-1];
07425             a[j + k*l] = 0;
07426         }
07427 L50:
07428         if (k - n < 0) goto L51;
07429         else if (k - n == 0) goto L60;
07430         else                goto L100;
07431 L51:
07432         for (j = kp1; j <= n; ++j) {
07433             pp[j-1]    = a[k + j*l];
07434             q[j-1]     = -a[k + j*l]*q[k-1];
07435             a[k + j*l] = 0;
07436         }
07437 //*-*-                  elimination proper
07438 L60:
07439         for (j = 1; j <= n; ++j) {
07440             for (k = j; k <= n; ++k) { a[j + k*l] += pp[j-1]*q[k-1]; }
07441         }
07442     }
07443 //*-*-                  elements of left diagonal and unscaling
07444     for (j = 1; j <= n; ++j) {
07445         for (k = 1; k <= j; ++k) {
07446             a[k + j*l] = a[k + j*l]*s[k-1]*s[j-1];
07447             a[j + k*l] = a[k + j*l];
07448         }
07449     }
07450     return;
07451 //*-*-                  failure return
07452 L100:
07453     ifail = 1;
07454 } /* mnvert_ */
07455 
07456 //______________________________________________________________________________
07457 inline
07458 void fitter::mnwarn(const std::string& copt1, const std::string& corg1, const std::string& cmes1)
07459 {
07460 //*-*-*-*-*-*-*-*-*-*-*-*Prints Warning messages*-*-*-*-*-*-*-*-*-*-*-*-*-*
07461 //*-*                    =======================
07462 //*-*     If COPT='W', CMES is a WARning message from CORG.
07463 //*-*     If COPT='D', CMES is a DEBug message from CORG.
07464 //*-*         If SET WARnings is in effect (the default), this routine
07465 //*-*             prints the warning message CMES coming from CORG.
07466 //*-*         If SET NOWarnings is in effect, the warning message is
07467 //*-*             stored in a circular buffer of length MAXMES.
07468 //*-*         If called with CORG=CMES='SHO', it prints the messages in
07469 //*-*             the circular buffer, FIFO, and empties the buffer.
07470 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
07471 
07472     std::string copt = copt1;
07473     std::string corg = corg1;
07474     std::string cmes = cmes1;
07475 
07476     const int MAXMES = 10;
07477     /*static*/ int ityp, i, ic, nm;
07478     /*static*/ std::string englsh, ctyp;
07479 
07480     if (msubstr(corg,0,3) != "SHO" || msubstr(cmes,0,3) != "SHO") {
07481 
07482 //*-*-            Either print warning or put in buffer
07483        if (copt == "W") {
07484           ityp = 1;
07485           if (fLwarn) {
07486              Printf(f_out," MINUIT WARNING IN %s",corg.c_str());
07487              Printf(f_out," ============== ",cmes.c_str());
07488              return;
07489           }
07490        } else {
07491           ityp = 2;
07492           if (fLrepor) {
07493              Printf(f_out," MINUIT DEBUG FOR %s",corg.c_str());
07494              Printf(f_out," =============== %s ",cmes.c_str());
07495              return;
07496           }
07497        }
07498 //*-*-                if appropriate flag is off, fill circular buffer
07499        if (fNwrmes[ityp-1] == 0) fIcirc[ityp-1] = 0;
07500        ++fNwrmes[ityp-1];
07501        ++fIcirc[ityp-1];
07502        if (fIcirc[ityp-1] > 10)         fIcirc[ityp-1] = 1;
07503        ic = fIcirc[ityp-1];
07504        fOrigin[ic + ityp*10 - 11] = corg;
07505        fWarmes[ic + ityp*10 - 11] = cmes;
07506        fNfcwar[ic + ityp*10 - 11] = fNfcn;
07507        return;
07508    }
07509 
07510 //*-*-            'SHO WARnings', ask if any suppressed mess in buffer
07511     if (copt == "W") {
07512         ityp = 1;
07513         ctyp = "WARNING";
07514     } else {
07515         ityp = 2;
07516         ctyp = "*DEBUG*";
07517     }
07518     if (fNwrmes[ityp-1] > 0) {
07519         englsh = " WAS SUPPRESSED.  ";
07520         if (fNwrmes[ityp-1] > 1) englsh = "S WERE SUPPRESSED.";
07521         Printf(f_out," %5d MINUIT %s MESSAGE%s",fNwrmes[ityp-1]
07522              ,ctyp.c_str(),englsh.c_str());
07523         nm = fNwrmes[ityp-1];
07524         ic = 0;
07525         if (nm > MAXMES) {
07526             Printf(f_out," ONLY THE MOST RECENT 10 WILL BE LISTED BELOW.");
07527             nm = MAXMES;
07528             ic = fIcirc[ityp-1];
07529         }
07530         Printf(f_out,"  CALLS  ORIGIN         MESSAGE");
07531         for (i = 1; i <= nm; ++i) {
07532             ++ic;
07533             if (ic > MAXMES) ic = 1;
07534             Printf(f_out," %6d %s %s", fNfcwar[ic + ityp*10 - 11],
07535                                fOrigin[(ic + ityp*10 - 11)*10].c_str(),
07536                                fWarmes[(ic + ityp*10 - 11)*60].c_str());
07537         }
07538         fNwrmes[ityp-1] = 0;
07539         Printf(f_out," ");
07540     }
07541 } /* mnwarn_ */
07542 
07543 //______________________________________________________________________________
07544 inline
07545 void fitter::mnwerr()
07546 {
07547 //*-*-*-*-*-*-*-*Calculates the WERR, external parameter errors*-*-*-*-*-*-*
07548 //*-*            ==============================================
07549 //*-*      and the global correlation coefficients, to be called
07550 //*-*      whenever a new covariance matrix is available.
07551 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
07552 
07553     /*static*/ double denom, ba, al, dx, du1, du2;
07554     /*static*/ int ndex, ierr, i, j, k, l, ndiag, k1, iin;
07555 
07556 //*-*-                        calculate external error if v exists
07557     if (fISW[1] >= 1) {
07558         for (l = 1; l <= fNpar; ++l) {
07559             ndex = l*(l + 1) / 2;
07560             dx = TMath_Sqrt(TMath_Abs(fVhmat[ndex-1]*fUp));
07561             i = fNexofi[l-1];
07562             if (fNvarl[i-1] > 1) {
07563                 al = fAlim[i-1];
07564                 ba = fBlim[i-1] - al;
07565                 du1 = al + 0.5*(TMath_Sin(fX[l-1] + dx) + 1)*ba - fU[i-1];
07566                 du2 = al + 0.5*(TMath_Sin(fX[l-1] - dx) + 1)*ba - fU[i-1];
07567                 if (dx > 1) du1 = ba;
07568                 dx = 0.5*(TMath_Abs(du1) + TMath_Abs(du2));
07569             }
07570             fWerr[l-1] = dx;
07571         }
07572     }
07573 //*-*-                         global correlation coefficients
07574     if (fISW[1] >= 1) {
07575         for (i = 1; i <= fNpar; ++i) {
07576             fGlobcc[i-1] = 0;
07577             k1 = i*(i-1) / 2;
07578             for (j = 1; j <= i; ++j) {
07579                 k = k1 + j;
07580                 fP[i + j*fMaxpar - fMaxpar-1] = fVhmat[k-1];
07581                 fP[j + i*fMaxpar - fMaxpar-1] = fP[i + j*fMaxpar - fMaxpar-1];
07582             }
07583         }
07584         mnvert(fP, fMaxint, fMaxint, fNpar, ierr);
07585         if (ierr == 0) {
07586             for (iin = 1; iin <= fNpar; ++iin) {
07587                 ndiag = iin*(iin + 1) / 2;
07588                 denom = fP[iin + iin*fMaxpar - fMaxpar-1]*fVhmat[ndiag-1];
07589                 if (denom <= 1 && denom >= 0) fGlobcc[iin-1] = 0;
07590                 else                          fGlobcc[iin-1] = TMath_Sqrt(1 - 1 / denom);
07591             }
07592         }
07593     }
07594 } /* mnwerr_ */
07595 
07596 }} //namespace
07597 
07598 #include "fit_func"
07599 
07600 namespace inlib {
07601 namespace f2cmn {
07602 
07603 class point {
07604 public:
07605   point():m_value(0),m_error(0){}
07606   virtual ~point(){}
07607 public:
07608   point(const point& a_from)
07609   :m_coords(a_from.m_coords)
07610   ,m_value(a_from.m_value)
07611   ,m_error(a_from.m_error)
07612   {}
07613   point& operator=(const point& a_from){
07614     m_coords = a_from.m_coords;
07615     m_value = a_from.m_value;
07616     m_error = a_from.m_error;
07617     return *this;
07618   }
07619 public:
07620   std::vector<double> m_coords;
07621   double m_value;  
07622   double m_error;  
07623 };
07624 
07625 class parameter {
07626 public:
07627   parameter():m_start(0),m_step(0),m_min(0),m_max(0) {}
07628   virtual ~parameter(){}
07629 public:
07630   parameter(const parameter& a_from)
07631   :m_name(a_from.m_name)
07632   ,m_start(a_from.m_start)
07633   ,m_step(a_from.m_step)
07634   ,m_min(a_from.m_min)
07635   ,m_max(a_from.m_max)
07636   {}
07637   parameter& operator=(const parameter& a_from){
07638     m_name = a_from.m_name;
07639     m_start = a_from.m_start;
07640     m_step = a_from.m_step;
07641     m_min = a_from.m_min;
07642     m_max = a_from.m_max;
07643     return *this;
07644   }
07645 public:
07646   std::string m_name;  
07647   double m_start;  
07648   double m_step;  
07649   double m_min;  
07650   double m_max;  
07651 };
07652 
07653 class command {
07654 public:
07655 #ifdef ANDROID_NDK
07656   command() //FIXME : for inlib/stl/vector.
07657   :m_argn(0)
07658   {}
07659 #endif
07660   command(const std::string& a_name,
07661                  unsigned int a_argn = 0,
07662                  double  a_0 = 0,double  a_1 = 0,double  a_2 = 0,
07663                  double  a_3 = 0,double  a_4 = 0,double  a_5 = 0,
07664                  double  a_6 = 0,double  a_7 = 0,double  a_8 = 0,
07665                  double  a_9 = 0,double a_10 = 0,double a_11 = 0,
07666                  double a_12 = 0,double a_13 = 0,double a_14 = 0,
07667                  double a_15 = 0,double a_16 = 0,double a_17 = 0,
07668                  double a_18 = 0,double a_19 = 0,double a_20 = 0,
07669                  double a_21 = 0,double a_22 = 0,double a_23 = 0,
07670                  double a_24 = 0,double a_25 = 0,double a_26 = 0,
07671                  double a_27 = 0,double a_28 = 0,double a_29 = 0)
07672   :m_name(a_name)
07673   ,m_argn(a_argn)
07674   {
07675     if(m_argn>30) m_argn = 30;
07676     m_args[ 0] = a_0; m_args[ 1] = a_1; m_args[ 2] = a_2;
07677     m_args[ 3] = a_3; m_args[ 4] = a_4; m_args[ 5] = a_5;
07678     m_args[ 6] = a_6; m_args[ 7] = a_7; m_args[ 8] = a_8;
07679     m_args[ 9] = a_9; m_args[10] = a_10;m_args[11] = a_11;
07680     m_args[12] = a_12;m_args[13] = a_13;m_args[14] = a_14;
07681     m_args[15] = a_15;m_args[16] = a_16;m_args[17] = a_17;
07682     m_args[18] = a_18;m_args[19] = a_19;m_args[20] = a_20;
07683     m_args[21] = a_21;m_args[22] = a_22;m_args[23] = a_23;
07684     m_args[24] = a_24;m_args[25] = a_25;m_args[26] = a_26;
07685     m_args[27] = a_27;m_args[28] = a_28;m_args[29] = a_29;
07686   }
07687   command(const std::string& a_name,const std::vector<double>& a_args)
07688   :m_name(a_name)
07689   ,m_argn(a_args.size())
07690   {
07691     if(m_argn>30) m_argn = 30;
07692     for(unsigned int index=0;index<m_argn;index++) m_args[index] = a_args[index];
07693   }
07694   virtual ~command(){}
07695 public:
07696   command(const command& a_from)
07697   :m_name(a_from.m_name)
07698   ,m_argn(a_from.m_argn)
07699   {
07700     ::memcpy(m_args,a_from.m_args,30*sizeof(double));
07701   }
07702   command& operator=(const command& a_from){
07703     m_name = a_from.m_name;
07704     m_argn = a_from.m_argn;
07705     ::memcpy(m_args,a_from.m_args,30*sizeof(double));
07706     return *this;
07707   }
07708   const std::string& name() const {return m_name;}
07709   std::string name() {return m_name;}
07710 
07711   unsigned int argn() const {return m_argn;}
07712   const double* args() const {return m_args;}
07713 private:
07714   std::string m_name;  
07715   unsigned int m_argn;
07716   double m_args[30];
07717 };
07718 
07719 class func_fitter {
07720 public:
07721   bool value(int /*a_paramn*/,double* a_params,double& a_value) {
07722     //{printf("debug : param number : %d\n",a_paramn);
07723     // for(unsigned int i=0;i<a_paramn;i++) {
07724     //   printf("debug :    %d %g\n",i,a_params[i]);
07725     //}}
07726     m_chi2 = 0;
07727     if(!m_func.set(a_params)) {a_value = 0;return false;}
07728     unsigned int npt = m_data.size();
07729     for(unsigned int ipt=0;ipt<npt;ipt++) {
07730       double value = m_func.value(m_data[ipt].m_coords);
07731       double chinew = (m_data[ipt].m_value - value)/m_data[ipt].m_error;
07732       m_chi2 += (chinew * chinew);
07733     }
07734     a_value = m_chi2;
07735     return true;
07736   }
07737   virtual double chi2() const { return m_chi2;}
07738 
07739 protected:
07740   func_fitter(const std::vector<point>& a_data,fit_func& a_func)
07741   :m_data(a_data),m_func(a_func),m_chi2(0)
07742   {}
07743   virtual ~func_fitter() {}
07744 protected:
07745   static bool function(int& aParamn,double* /*aGrad*/,double& aValue,
07746                               double* aParams,int /*aStatus*/,void* aTag){
07747     func_fitter& fcn = *((func_fitter*)aTag);
07748     return fcn.value(aParamn,aParams,aValue);
07749   }
07750 public:
07751   static bool fit(std::ostream& a_out,
07752                          const std::vector<point>& a_data,
07753                          const std::vector<parameter> a_params,
07754                          fit_func& a_func,
07755                          std::vector<double>& a_output,
07756                          const std::vector<command>& a_cmds =
07757                            std::vector<command>(1,command("MIGRAD")) ){
07758 
07759     //NOTE : the size of a_output is : 
07760     //         2 + a_params.size() * 4
07761     //       with :
07762     //         a_output[0] = chi2
07763     //         a_output[1] = number of degree of freedom
07764 
07765     //exa cmd : MINIMIZE, MINOS
07766   
07767     a_output.clear();
07768 
07769     func_fitter fcn(a_data,a_func);
07770     fitter minuit(0);
07771     minuit.SetFCN(function,&fcn);
07772     minuit.SetOut(&a_out);
07773 
07774 
07775    {double args[10];
07776     args[0] = -1; //shut up by default.
07777     int status;
07778     minuit.mnexcm("SET PRI",args,1,status);}
07779 
07780     unsigned int paramn = a_params.size();
07781     for(unsigned int index=0;index<paramn;index++) {
07782       int status;
07783       minuit.mnparm(index,
07784                     a_params[index].m_name.c_str(),
07785                     a_params[index].m_start,
07786                     a_params[index].m_step,
07787                     a_params[index].m_min,
07788                     a_params[index].m_max,
07789                     status);
07790     }
07791 
07792     std::vector<command>::const_iterator it;
07793     for(it=a_cmds.begin();it!=a_cmds.end();++it) {
07794       int status;
07795       minuit.mnexcm((*it).name(),(*it).args(),(*it).argn(),status);
07796       if(status>0) return false;
07797     }
07798 
07799     //in principle a_func should have the ending (fitted) parameters.
07800 
07801     // output :
07802     a_output.push_back(fcn.chi2());
07803     a_output.push_back(a_data.size()-a_params.size()); //ndf (num deg of freedom)
07804     for(unsigned int index=0;index<paramn;index++) {
07805       std::string s;
07806       double value,err;
07807       double bmin,bmax;
07808       int ierr;
07809       minuit.mnpout(index,s,value,err,bmin,bmax,ierr);
07810       a_output.push_back(value);
07811       a_output.push_back(err);
07812       a_output.push_back(bmin);
07813       a_output.push_back(bmax);
07814     }
07815 
07816     return true;  
07817   }
07818 private:
07819   const std::vector<point>& m_data;
07820   fit_func& m_func;
07821   double m_chi2;
07822 };
07823 
07824 inline bool fit_data(std::ostream& a_out,
07825                      const std::vector< inlib::f2cmn::point >& a_data,
07826                      const std::vector< inlib::f2cmn::parameter >& a_params,
07827                      inlib::fit_func& a_func,
07828                      std::vector<double>& a_output,
07829                      const std::vector<command>& a_cmds =
07830                        std::vector<command>(1,command("MIGRAD"))){
07831 
07832   //NOTE : the size of a_output is : 
07833   //         2 + a_params.size() * 4
07834   //       with :
07835   //         a_output[0] = chi2
07836   //         a_output[1] = number of degree of freedom
07837 
07838   if(a_data.empty()) {
07839     a_out << "inlib::f2cmn::fit_data :"
07840           << " no starting points."
07841           << std::endl;
07842     return false;
07843   }
07844 
07845   if(!func_fitter::fit(a_out,a_data,a_params,a_func,a_output,a_cmds)) {
07846     a_out << "inlib::f2cmn::fit_data :"
07847           << " fit failed."
07848           << std::endl;
07849     return false;
07850   }
07851 
07852   return true;
07853 }
07854 
07855 //T can be h1d or p1D
07856 template <class T>
07857 inline bool fit_1D(std::ostream& a_out,
07858                    T& a_histo,
07859                    const std::vector< inlib::f2cmn::parameter >& a_params,
07860                    inlib::fit_func& a_func,
07861                    std::vector<double>& a_output,
07862                    const std::vector<command>& a_cmds =
07863                      std::vector<command>(1,command("MIGRAD")) ){
07864 
07865   //NOTE : the size of a_output is : 
07866   //         2 + a_params.size() * 4
07867   //       with :
07868   //         a_output[0] = chi2
07869   //         a_output[1] = number of degree of freedom
07870 
07871   if(a_histo.entries()==0) {
07872     a_out << "inlib::f2cmn::fit_1D :"
07873           << " histogram has no entries."
07874           << std::endl;
07875     return false;
07876   }
07877 
07878   int nbin = a_histo.axis().bins();
07879   if(nbin<=0) {
07880     a_out << "inlib::f2cmn::fit_1D :"
07881           << " has no bins."
07882           << std::endl;
07883     return false;
07884   }
07885 
07886   std::vector<double> pt;
07887   pt.resize(1,0);
07888 
07889   std::vector< inlib::f2cmn::point > data;
07890 
07891   for(int index=0;index<nbin;index++) { 
07892     int nent = a_histo.bin_entries(index);
07893     if(nent==0) continue;  // Do not take bin without entry.
07894     // Take middle of bin.
07895     double xx = 
07896       (a_histo.axis().bin_lower_edge(index)+
07897        a_histo.axis().bin_upper_edge(index))/2.;
07898     double val = a_histo.bin_height(index);
07899     double err = ::sqrt(::fabs(val)); // Take statistical error.
07900     if(err==0.) { 
07901       a_out << "inlib::f2cmn::fit_1D :"
07902           << " null error for bin " << index 
07903           << " x " << xx << " value " << val
07904           << ". Set error to 0.01."
07905           << std::endl;
07906       //return 0;
07907       err = 0.01; //FIXME
07908     }
07909     inlib::f2cmn::point fpt;
07910     pt[0] = xx;
07911     fpt.m_coords = pt;
07912     fpt.m_value = val;
07913     fpt.m_error = err;
07914     data.push_back(fpt); 
07915   }
07916   if(data.empty()) {
07917     a_out << "inlib::f2cmn::fit_1D :"
07918           << " no starting points."
07919           << std::endl;
07920     return false;
07921   }
07922 
07923   if(!func_fitter::fit(a_out,data,a_params,a_func,a_output,a_cmds)) {
07924     a_out << "inlib::f2cmn::fit_1D :"
07925           << " fit failed."
07926           << std::endl;
07927     return false;
07928   }
07929 
07930   return true;
07931 }
07932 
07933 template <class T>
07934 inline bool fit_xve(std::ostream& a_out,
07935                    const std::vector<T>& a_xs, //one dim coordinates
07936                    const std::vector<T>& a_vs, //values
07937                    const std::vector<T>& a_es, //errors
07938                    const std::vector< inlib::f2cmn::parameter >& a_params,
07939                    inlib::fit_func& a_func,
07940                    std::vector<double>& a_output,
07941                    const std::vector<command>& a_cmds =
07942                      std::vector<command>(1,command("MIGRAD"))){
07943 
07944   //NOTE : the size of a_output is : 
07945   //         2 + a_params.size() * 4
07946   //       with :
07947   //         a_output[0] = chi2
07948   //         a_output[1] = number of degree of freedom
07949 
07950   if(a_vs.size() != a_xs.size() ) {
07951     a_out << "inlib::f2cmn::fit_xve :"
07952           << " coordinate and value vectors have different sizes."
07953           << std::endl;
07954     return false;
07955   }
07956   
07957   if(a_es.size() != a_xs.size() ) {
07958     a_out << "inlib::f2cmn::fit_xve :"
07959           << " coordinate and error vectors have different sizes."
07960           << std::endl;
07961     return false;
07962   }
07963   
07964   int nbin = a_xs.size();
07965 
07966   std::vector<double> pt;
07967   pt.resize(1,0);
07968 
07969   std::vector< inlib::f2cmn::point > data;
07970 
07971   for(int index=0;index<nbin;index++) {     
07972     inlib::f2cmn::point fpt;
07973     pt[0] = a_xs[index];
07974     fpt.m_coords = pt;
07975     fpt.m_value = a_vs[index];
07976     fpt.m_error = a_es[index];
07977     data.push_back(fpt); 
07978   }
07979   if(data.empty()) {
07980     a_out << "inlib::f2cmn::fit_xve :"
07981           << " no starting points."
07982           << std::endl;
07983     return false;
07984   }
07985 
07986   if(!func_fitter::fit(a_out,data,a_params,a_func,a_output,a_cmds)) {
07987     a_out << "inlib::f2cmn::fit_xve :"
07988           << " fit failed."
07989           << std::endl;
07990     return false;
07991   }
07992 
07993   return true;
07994 }
07995 
07996 }} //namespace
07997 
07998 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines