Logo ROOT   6.08/07
Reference Guide
TMinuit.cxx
Go to the documentation of this file.
1 // @(#)root/minuit:$Id$
2 // Author: Rene Brun, Frederick James 12/08/95
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /**
13 
14  \defgroup MinuitOld TMinuit
15  \ingroup Math
16 
17  The Minuit Minimization package.
18  Direct C++ implementation of the Minuit minimization package.
19  This package was originally written in Fortran by Fred James
20  and part of PACKLIB (patch D506)
21  It has been converted to a C++ class, TMinuit, by R.Brun.
22 */
23 
24 /** \class TMinuit
25 
26 Implementation in C++ of the Minuit package written by Fred James.
27 This is a straightforward conversion of the original Fortran version.
28 
29 The main changes are:
30 
31  - The variables in the various Minuit labelled common blocks
32  have been changed to the TMinuit class data members.
33 
34  - The internal arrays with a maximum dimension depending on the
35  maximum number of parameters are now data members arrays with
36  a dynamic dimension such that one can fit very large problems
37  by simply initialising the TMinuit constructor with the maximum
38  number of parameters.
39 
40  - The include file Minuit.h has been commented as much as possible
41  using existing comments in the code or the printed documentation
42 
43  - The original Minuit subroutines are now member functions.
44 
45  - Constructors and destructor have been added.
46 
47  - Instead of passing the FCN function in the argument
48  list, the addresses of this function is stored as pointer
49  in the data members of the class. This is by far more elegant
50  and flexible in an interactive environment.
51  The member function SetFCN can be used to define this pointer.
52 
53  - The ROOT static function Printf is provided to replace all
54  format statements and to print on currently defined output file.
55  - The functions SetObjectFit(TObject * obj)/GetObjectFit() can be
56  used inside the FCN function to set/get a referenced object
57  instead of using global variables.
58 
59 
60 ## Basic concepts of MINUIT
61 
62 The [MINUIT](https://root.cern.ch/sites/d35c7d8c.web.cern.ch/files/minuit.pdf)
63 package acts on a multiparameter Fortran function to which one
64 must give the generic name <TT>FCN</TT>. In the ROOT implementation,
65 the function <TT>FCN</TT> is defined via the MINUIT SetFCN member function
66 when an Histogram.Fit command is invoked.
67 The value of <TT>FCN</TT> will in general depend on one
68 or more variable parameters.
69 
70 To take a simple example, in case of ROOT histograms (classes TH1C,TH1S,TH1F,TH1D)
71 the Fit function defines the Minuit fitting function as being H1FitChisquare
72 or H1FitLikelihood depending on the options selected.
73 H1FitChisquare
74 calculates the chisquare between the user fitting function (gaussian, polynomial,
75 user defined,etc) and the data for given values of the parameters.
76 It is the task of MINUIT to find those values of the parameters
77 which give the lowest value of chisquare.
78 
79 ### Basic concepts - The transformation for parameters with limits.
80 
81 For variable parameters with limits, MINUIT uses the following
82 transformation:
83 
84 \f[
85 P_{\mathrm{int}} = \arcsin
86  \left( 2\: \frac{P_{\mathrm{ext}}-a}{b-a} - 1 \right)
87 P_{\mathrm{ext}} = a + \frac{b - a}{2} \left( \sin P_{\mathrm{int}} + 1 \right)
88 \f]
89 
90 so that the internal value \f$P_{\mathrm{int}}\f$ can take on any value, while
91 the external value \f$P_{\mathrm{ext}}\f$ can take on values only between the lower
92 limit \f$a\f$ and the upper limit \f$b\f$.
93 Since the transformation is necessarily non-linear, it would transform a
94 nice linear problem into a nasty non-linear one, which is the reason why
95 limits should be avoided if not necessary.
96 In addition, the transformation
97 does require some computer time, so it slows down the computation a little
98 bit, and more importantly, it introduces additional numerical inaccuracy into
99 the problem in addition to what is introduced in the numerical calculation
100 of the FCN value.
101 The effects of non-linearity and numerical roundoff both
102 become more important as the external value gets closer to one of the limits
103 (expressed as the distance to nearest limit divided by distance between limits).
104 The user must therefore be aware of the fact that, for example,
105 if he puts limits of \f$(0,10^{10})\f$ on a parameter, then the values \f$0.0\f$
106 and \f$1.0\f$ will be indistinguishable to the accuracy of most machines.
107 
108 The transformation also affects the parameter error matrix, of course,
109 so Minuit does a transformation of the error matrix (and the
110 ``parabolic'' parameter errors) when there are parameter limits.
111 Users should however realize that the transformation is only a linear
112 approximation, and that it cannot give a meaningful result if one or more
113 parameters is very close to a limit, where
114 \f$\partial P_{\mathrm{ext}} / \partial P_{\mathrm{int}} \approx 0\f$.
115 Therefore, it is recommended that:
116 
117  1. Limits on variable parameters should be used only when needed in order
118 to prevent the parameter from taking on unphysical values.
119 
120  2. When a satisfactory minimum has been found using limits, the limits
121 should then be removed if possible, in order to perform or re-perform the
122 error analysis without limits.
123 
124 
125 ### How to get the right answer from MINUIT.
126 
127 MINUIT offers the user a choice of several minimization algorithms. The
128 MIGRAD algorithm is in general the best minimizer for
129 nearly all functions. It is a variable-metric method with inexact line
130 search, a stable metric updating scheme, and checks for
131 positive-definiteness. Its main weakness is that it depends heavily on
132 knowledge of the first derivatives, and fails miserably if they are very
133 inaccurate.
134 
135 If parameter limits are needed, in spite of the side effects, then the
136 user should be aware of the following techniques to alleviate problems
137 caused by limits:
138 
139 #### Getting the right minimum with limits.
140 
141 If MIGRAD converges normally to a point where no parameter is near one of
142 its limits, then the existence of limits has probably not prevented MINUIT
143 from finding the right minimum. On the other hand, if one or more
144 parameters is near its limit at the minimum, this may be because the true
145 minimum is indeed at a limit, or it may be because the minimizer has
146 become ``blocked'' at a limit. This may normally happen only if the
147 parameter is so close to a limit (internal value at an odd multiple of
148 \f$\pm \frac{\pi}{2}\f$
149 that MINUIT prints a warning to this effect when it prints
150 the parameter values.
151 
152 The minimizer can become blocked at a limit, because at a limit
153 the derivative seen by the minimizer
154 \f$\partial F / \partial P_{\mathrm{int}}\f$
155 is zero no matter what the real derivative
156 \f$\partial F / \partial P_{\mathrm{ext}}\f$ is.
157 
158 \f[
159 \frac{\partial F}{\partial P_{\mathrm{int}}} =
160 \frac{\partial F}{\partial P_{\mathrm{ext}}}
161 \frac{\partial P_{\mathrm{ext}}}{\partial P_{\mathrm{int}}} =
162 \frac{\partial F}{\partial P_{\mathrm{ext}}} = 0
163 \f]
164 
165 #### Getting the right parameter errors with limits.
166 
167 In the best case, where the minimum is far from any limits, MINUIT will
168 correctly transform the error matrix, and the parameter errors it reports
169 should be accurate and very close to those you would have got without
170 limits. In other cases (which should be more common, since otherwise you
171 wouldn't need limits), the very meaning of parameter errors becomes
172 problematic. Mathematically, since the limit is an absolute constraint on
173 the parameter, a parameter at its limit has no error, at least in one
174 direction. The error matrix, which can assign only symmetric errors, then
175 becomes essentially meaningless.
176 
177 ### Interpretation of Parameter Errors:
178 
179 There are two kinds of problems that can arise: the reliability of
180 MINUIT's error estimates, and their statistical interpretation, assuming
181 they are accurate.
182 
183 ### Statistical interpretation:
184 
185 For discussion of basic concepts, such as the meaning of the elements of
186 the error matrix, or setting of exact confidence levels see:
187 
188  1. F.James.
189  Determining the statistical Significance of experimental Results.
190  Technical Report DD/81/02 and CERN Report 81-03, CERN, 1981.</li>
191 
192  2. W.T.Eadie, D.Drijard, F.James, M.Roos, and B.Sadoulet.
193  Statistical Methods in Experimental Physics.
194  North-Holland, 1971.</li>
195 
196 ### Reliability of MINUIT error estimates.
197 
198 MINUIT always carries around its own current estimates of the parameter
199 errors, which it will print out on request, no matter how accurate they
200 are at any given point in the execution. For example, at initialization,
201 these estimates are just the starting step sizes as specified by the user.
202 After a HESSE step, the errors are usually quite accurate,
203 unless there has been a problem. MINUIT, when it prints out error values,
204 also gives some indication of how reliable it thinks they are. For
205 example, those marked <TT>CURRENT GUESS ERROR</TT> are only working values
206 not to be believed, and <TT>APPROXIMATE ERROR</TT> means that they have
207 been calculated but there is reason to believe that they may not be
208 accurate.
209 
210 If no mitigating adjective is given, then at least MINUIT believes the
211 errors are accurate, although there is always a small chance that MINUIT
212 has been fooled. Some visible signs that MINUIT may have been fooled are:
213 
214 
215  1. Warning messages produced during the minimization or error analysis.
216 
217  2. Failure to find new minimum.
218 
219  3. Value of <TT>EDM</TT> too big (estimated Distance to Minimum).
220 
221  4. Correlation coefficients exactly equal to zero, unless some parameters
222  are known to be uncorrelated with the others.
223 
224  5. Correlation coefficients very close to one (greater than 0.99). This
225  indicates both an exceptionally difficult problem, and one which has been
226  badly parameterised so that individual errors are not very meaningful
227  because they are so highly correlated.
228 
229  6. Parameter at limit. This condition, signalled by a MINUIT warning
230  message, may make both the function minimum and parameter errors
231  unreliable. See the discussion above ``Getting the right parameter errors
232  with limits''.
233 
234 
235 The best way to be absolutely sure of the errors, is to use
236 ``independent'' calculations and compare them, or compare the calculated
237 errors with a picture of the function. Theoretically, the covariance
238 matrix for a ``physical'' function must be positive-definite at the
239 minimum, although it may not be so for all points far away from the
240 minimum, even for a well-determined physical problem. Therefore, if MIGRAD
241 reports that it has found a non-positive-definite covariance matrix, this
242 may be a sign of one or more of the following:
243 
244 ##### A non-physical region:
245 
246 On its way to the minimum, MIGRAD may have traversed a region which has
247 unphysical behaviour, which is of course not a serious problem as long as
248 it recovers and leaves such a region.
249 
250 ##### An underdetermined problem:
251 
252 If the matrix is not positive-definite even at the minimum, this may mean
253 that the solution is not well-defined, for example that there are more
254 unknowns than there are data points, or that the parameterisation of the
255 fit contains a linear dependence. If this is the case, then MINUIT (or any
256 other program) cannot solve your problem uniquely, and the error matrix
257 will necessarily be largely meaningless, so the user must remove the
258 under-determinedness by reformulating the parameterisation. MINUIT cannot
259 do this itself.
260 
261 ##### Numerical inaccuracies:
262 
263 It is possible that the apparent lack of positive-definiteness is in fact
264 only due to excessive roundoff errors in numerical calculations in the
265 user function or not enough precision. This is unlikely in general, but
266 becomes more likely if the number of free parameters is very large, or if
267 
268 the parameters are badly scaled (not all of the same order of magnitude),
269 and correlations are also large. In any case, whether the
270 non-positive-definiteness is real or only numerical is largely irrelevant,
271 since in both cases the error matrix will be unreliable and the minimum
272 suspicious.
273 
274 ##### An ill-posed problem:
275 
276 For questions of parameter dependence, see the discussion above on
277 positive-definiteness.
278 
279 Possible other mathematical problems are the following:
280 
281 ##### Excessive numerical roundoff:
282 
283 Be especially careful of exponential and factorial functions which get big
284 very quickly and lose accuracy.
285 
286 ##### Starting too far from the solution:
287 
288 The function may have unphysical local minima, especially at infinity in
289 some variables.
290 
291 ##### Minuit parameter errors in the presence of limits
292 This concerns the way Minuit reports the symmetric (or parabolic) errors
293 on parameters. It does not apply to the errors reported from Minos, which
294 are in general asymmetric.
295 
296 The symmetric errors reported by Minuit are always calculated from
297 the covariance matrix, assuming that this matrix has been calculated,
298 usually as the result of a Migrad minimization or a direct
299 calculation by Hesse which inverts the second derivative matrix.
300 
301 When there are no limits on the parameter in question, the error reported
302 by Minuit should therefore be exactly equal to the square root of the
303 corresponding diagonal element of the error matrix reported by Minuit.
304 
305 However, when there are limits on the parameter, there is a transformation
306 between the internal parameter values seen by Minuit (which are unbounded)
307 and the external parameter values seen by the user in FCN (which remain
308 inside the desired limits). Therefore the internal error matrix kept by
309 Minuit must be transformed to an external error matrix for the user.
310 This is done by multiplying the (I,J)th element by DEXDIN(I)*DEXDIN(J),
311 where DEXDIN is the derivative of the external value with respect to the
312 internal value at the minimum. This is a linearisation of the
313 transformation, and is the only way to produce an error matrix in external
314 coordinates meaningful to the user. But when reporting the individual
315 parabolic errors for limited parameters, Minuit can do a little better, so
316 it does. In this case, Minuit actually transforms the ends of the
317 internal "error bar" to external coordinates and reports the length of
318 this transformed interval. Strictly speaking, it is now asymmetric, but
319 since the origin of the asymmetry is only an artificial transformation it
320 does not make much sense, so the transformed errors are symmetrized.
321 
322 The result of all the above is that for parameters with limits, the error
323 reported by Minuit is not exactly equal to the square root of the diagonal
324 element of the error matrix. The difference is a measure of how much the
325 limits deform the problem. If possible, it is suggested not to use limits
326 on parameters, and the problem goes away. If for some reason limits are
327 necessary, and you are sensitive to the difference between the two ways of
328 calculating the errors, it is suggested to use Minos errors which take
329 into account the non-linearities much more precisely.
330 
331 @ingroup MinuitOld
332 */
333 
334 #include <stdlib.h>
335 #include <stdio.h>
336 
337 #include "TROOT.h"
338 #include "TMinuit.h"
339 #include "TMath.h"
340 #include "TError.h"
341 #include "TPluginManager.h"
342 #include "TClass.h"
343 
344 #include <atomic>
345 
347 
348 static const char charal[29] = " .ABCDEFGHIJKLMNOPQRSTUVWXYZ";
349 
351 
352 ////////////////////////////////////////////////////////////////////////////////
353 /// Minuit normal constructor
354 ///
355 
356 TMinuit::TMinuit(): TNamed("MINUIT","The Minimization package")
357 {
358  if (TMinuit::Class()->IsCallingNew() != TClass::kRealNew) {
359  //preset all pointers to null
360  fCpnam = 0;
361  fU = 0;
362  fAlim = 0;
363  fBlim = 0;
364  fPstar = 0;
365  fGin = 0;
366  fNvarl = 0;
367  fNiofex = 0;
368 
369  fNexofi = 0;
370  fIpfix = 0;
371  fErp = 0;
372  fErn = 0;
373  fWerr = 0;
374  fGlobcc = 0;
375  fX = 0;
376  fXt = 0;
377  fDirin = 0;
378  fXs = 0;
379  fXts = 0;
380  fDirins = 0;
381  fGrd = 0;
382  fG2 = 0;
383  fGstep = 0;
384  fDgrd = 0;
385  fGrds = 0;
386  fG2s = 0;
387  fGsteps = 0;
388  fPstst = 0;
389  fPbar = 0;
390  fPrho = 0;
391  fWord7 = 0;
392  fVhmat = 0;
393  fVthmat = 0;
394  fP = 0;
395  fXpt = 0;
396  fYpt = 0;
397  fChpt = 0;
398  fCONTgcc = 0;
399  fCONTw = 0;
400  fFIXPyy = 0;
401  fGRADgf = 0;
402  fHESSyy = 0;
403  fIMPRdsav = 0;
404  fIMPRy = 0;
405  fMATUvline = 0;
406  fMIGRflnu = 0;
407  fMIGRstep = 0;
408  fMIGRgs = 0;
409  fMIGRvg = 0;
410  fMIGRxxs = 0;
411  fMNOTxdev = 0;
412  fMNOTw = 0;
413  fMNOTgcc = 0;
414  fPSDFs = 0;
415  fSEEKxmid = 0;
416  fSEEKxbest = 0;
417  fSIMPy = 0;
418  fVERTq = 0;
419  fVERTs = 0;
420  fVERTpp = 0;
421  fCOMDplist = 0;
422  fPARSplist = 0;
423 
424  fUp = 0;
425  fEpsi = 0;
426  fApsi = 0;
427  fXmidcr = 0;
428  fYmidcr = 0;
429  fXdircr = 0;
430  fYdircr = 0;
431 
432  fStatus = 0;
433  fEmpty = 0;
434  fObjectFit = 0;
435  fMethodCall = 0;
436  fPlot = 0;
437  fGraphicsMode = kTRUE;
438 
439  } else {
440  BuildArrays(25);
441 
442  fUp = 0;
443  fEpsi = 0;
444  fApsi = 0;
445  fXmidcr = 0;
446  fYmidcr = 0;
447  fXdircr = 0;
448  fYdircr = 0;
449 
450  fStatus = 0;
451  fEmpty = 0;
452  fObjectFit = 0;
453  fMethodCall = 0;
454  fPlot = 0;
455  fGraphicsMode = kTRUE;
456  SetMaxIterations();
457  mninit(5,6,7);
458  }
459 
460  fFCN = 0;
461  {
463  gROOT->GetListOfSpecials()->Add(this);
464  }
465  gMinuit = this;
466 }
467 
468 ////////////////////////////////////////////////////////////////////////////////
469 /// Minuit normal constructor
470 ///
471 /// maxpar is the maximum number of parameters used with this TMinuit object.
472 
473 TMinuit::TMinuit(Int_t maxpar): TNamed("MINUIT","The Minimization package")
474 {
475  fFCN = 0;
476 
477  BuildArrays(maxpar);
478 
479  fStatus = 0;
480  fEmpty = 0;
481  fObjectFit = 0;
482  fMethodCall = 0;
483  fPlot = 0;
486 
487  mninit(5,6,7);
488  {
490  gROOT->GetListOfSpecials()->Add(this);
491  }
492  gMinuit = this;
493 }
494 
495 ////////////////////////////////////////////////////////////////////////////////
496 /// Private TMinuit copy ctor. TMinuit can not be copied.
497 
498 TMinuit::TMinuit(const TMinuit &minuit) : TNamed(minuit)
499 {
500  Error("TMinuit", "can not copy construct TMinuit");
501 }
502 
503 ////////////////////////////////////////////////////////////////////////////////
504 /// Minuit default destructor
505 
507 {
508  DeleteArrays();
509  delete fPlot;
510  delete fMethodCall;
511  {
513  if (gROOT != 0 && gROOT->GetListOfSpecials() != 0) gROOT->GetListOfSpecials()->Remove(this);
514  }
515  if (gMinuit == this) gMinuit = nullptr;
516 }
517 
518 ////////////////////////////////////////////////////////////////////////////////
519 /// Create internal Minuit arrays for the maxpar parameters
520 
522 {
523  fMaxpar = 25;
524  if (maxpar >= fMaxpar) fMaxpar = maxpar+1;
525  fMaxpar1= fMaxpar*(fMaxpar+1);
526  fMaxpar2= 2*fMaxpar;
527  fMaxpar5= fMaxpar1/2;
528  fMaxcpt = 101;
529  fCpnam = new TString[fMaxpar2];
530  fU = new Double_t[fMaxpar2];
531  fAlim = new Double_t[fMaxpar2];
532  fBlim = new Double_t[fMaxpar2];
533  fPstar = new Double_t[fMaxpar2];
534  fGin = new Double_t[fMaxpar2];
535  fNvarl = new Int_t[fMaxpar2];
536  fNiofex = new Int_t[fMaxpar2];
537 
538  fNexofi = new Int_t[fMaxpar];
539  fIpfix = new Int_t[fMaxpar];
540  fErp = new Double_t[fMaxpar];
541  fErn = new Double_t[fMaxpar];
542  fWerr = new Double_t[fMaxpar];
543  fGlobcc = new Double_t[fMaxpar];
544  fX = new Double_t[fMaxpar];
545  fXt = new Double_t[fMaxpar];
546  fDirin = new Double_t[fMaxpar];
547  fXs = new Double_t[fMaxpar];
548  fXts = new Double_t[fMaxpar];
549  fDirins = new Double_t[fMaxpar];
550  fGrd = new Double_t[fMaxpar];
551  fG2 = new Double_t[fMaxpar];
552  fGstep = new Double_t[fMaxpar];
553  fDgrd = new Double_t[fMaxpar];
554  fGrds = new Double_t[fMaxpar];
555  fG2s = new Double_t[fMaxpar];
556  fGsteps = new Double_t[fMaxpar];
557  fPstst = new Double_t[fMaxpar];
558  fPbar = new Double_t[fMaxpar];
559  fPrho = new Double_t[fMaxpar];
560  fWord7 = new Double_t[fMaxpar];
561  fVhmat = new Double_t[fMaxpar5];
562  fVthmat = new Double_t[fMaxpar5];
563  fP = new Double_t[fMaxpar1];
564  fXpt = new Double_t[fMaxcpt];
565  fYpt = new Double_t[fMaxcpt];
566  fChpt = new char[fMaxcpt+1];
567  // initialisation of dynamic arrays used internally in some functions
568  // these arrays had a fix dimension in Minuit
569  fCONTgcc = new Double_t[fMaxpar];
570  fCONTw = new Double_t[fMaxpar];
571  fFIXPyy = new Double_t[fMaxpar];
572  fGRADgf = new Double_t[fMaxpar];
573  fHESSyy = new Double_t[fMaxpar];
574  fIMPRdsav = new Double_t[fMaxpar];
575  fIMPRy = new Double_t[fMaxpar];
576  fMATUvline = new Double_t[fMaxpar];
577  fMIGRflnu = new Double_t[fMaxpar];
578  fMIGRstep = new Double_t[fMaxpar];
579  fMIGRgs = new Double_t[fMaxpar];
580  fMIGRvg = new Double_t[fMaxpar];
581  fMIGRxxs = new Double_t[fMaxpar];
582  fMNOTxdev = new Double_t[fMaxpar];
583  fMNOTw = new Double_t[fMaxpar];
584  fMNOTgcc = new Double_t[fMaxpar];
585  fPSDFs = new Double_t[fMaxpar];
586  fSEEKxmid = new Double_t[fMaxpar];
587  fSEEKxbest = new Double_t[fMaxpar];
588  fSIMPy = new Double_t[fMaxpar];
589  fVERTq = new Double_t[fMaxpar];
590  fVERTs = new Double_t[fMaxpar];
591  fVERTpp = new Double_t[fMaxpar];
592  fCOMDplist = new Double_t[fMaxpar];
593  fPARSplist = new Double_t[fMaxpar];
594 
595  for (int i = 0; i < fMaxpar; i++) {
596  fErp[i] = 0;
597  fErn[i] = 0;
598  }
599 }
600 
601 ////////////////////////////////////////////////////////////////////////////////
602 /// Make a clone of an object using the Streamer facility.
603 /// Function pointer is copied to Clone
604 
605 TObject *TMinuit::Clone(const char *newname) const
606 {
607  TMinuit *named = (TMinuit*)TNamed::Clone(newname);
608  named->fFCN=fFCN;
609  return named;
610 }
611 
612 ////////////////////////////////////////////////////////////////////////////////
613 /// Execute a Minuit command
614 ///
615 /// Equivalent to MNEXCM except that the command is given as a character string.
616 /// See TMinuit::mnhelp for the full list of available commands
617 /// See also the
618 /// [complete documentation of all the available commands](https://root.cern.ch/sites/d35c7d8c.web.cern.ch/files/minuit.pdf)
619 ///
620 /// Returns the status of the execution:
621 /// - 0: command executed normally
622 /// - 1: command is blank, ignored
623 /// - 2: command line unreadable, ignored
624 /// - 3: unknown command, ignored
625 /// - 4: abnormal termination (e.g., MIGRAD not converged)
626 /// - 5: command is a request to read PARAMETER definitions
627 /// - 6: 'SET INPUT' command
628 /// - 7: 'SET TITLE' command
629 /// - 8: 'SET COVAR' command
630 /// - 9: reserved
631 /// - 10: END command
632 /// - 11: EXIT or STOP command
633 /// - 12: RETURN command
634 
635 Int_t TMinuit::Command(const char *command)
636 {
637  Int_t status = 0;
638  mncomd(command,status);
639  return status;
640 }
641 
642 ////////////////////////////////////////////////////////////////////////////////
643 /// Creates a TGraph object describing the n-sigma contour of a
644 /// TMinuit fit. The contour of the parameters pa1 and pa2 is calculated
645 /// using npoints (>=4) points. The TMinuit status will be
646 /// - 0 on success and
647 /// - -1 if errors in the calling sequence (pa1, pa2 not variable)
648 /// - 1 if less than four points can be found
649 /// - 2 if npoints<4
650 /// - n>3 if only n points can be found (n < npoints)
651 /// The status can be obtained via TMinuit::GetStatus().
652 ///
653 /// To get the n-sigma contour the ERRDEF parameter in Minuit has to set
654 /// to n^2. The fcn function has to be set before the routine is called.
655 ///
656 /// The TGraph object is created via the interpreter. The user must cast it
657 /// to a TGraph*. Note that the TGraph is created with npoints+1 in order to
658 /// close the contour (setting last point equal to first point).
659 ///
660 /// You can find an example in $ROOTSYS/tutorials/fit/fitcont.C
661 
663 {
664  if (npoints<4) {
665  // we need at least 4 points
666  fStatus= 2;
667  return (TObject *)0;
668  }
669  Int_t npfound;
670  Double_t *xcoor = new Double_t[npoints+1];
671  Double_t *ycoor = new Double_t[npoints+1];
672  mncont(pa1,pa2,npoints,xcoor,ycoor,npfound);
673  if (npfound<4) {
674  // mncont did go wrong
675  Warning("Contour","Cannot find more than 4 points, no TGraph returned");
676  fStatus= (npfound==0 ? 1 : npfound);
677  delete [] xcoor;
678  delete [] ycoor;
679  return (TObject *)0;
680  }
681  if (npfound!=npoints) {
682  // mncont did go wrong
683  Warning("Contour","Returning a TGraph with %d points only",npfound);
684  npoints = npfound;
685  }
686  fStatus=0;
687  // create graph via the PluginManager
688  xcoor[npoints] = xcoor[0]; // add first point at end to get closed polyline
689  ycoor[npoints] = ycoor[0];
690  TObject *gr = 0;
691  TPluginHandler *h;
692  if ((h = gROOT->GetPluginManager()->FindHandler("TMinuitGraph"))) {
693  if (h->LoadPlugin() != -1)
694  gr = (TObject*)h->ExecPlugin(3,npoints+1,xcoor,ycoor);
695  }
696  delete [] xcoor;
697  delete [] ycoor;
698  return gr;
699 }
700 
701 ////////////////////////////////////////////////////////////////////////////////
702 /// Define a parameter
703 
704 Int_t TMinuit::DefineParameter( Int_t parNo, const char *name, Double_t initVal, Double_t initErr, Double_t lowerLimit, Double_t upperLimit )
705 {
706  Int_t err;
707 
708  TString sname = name;
709  mnparm( parNo, sname, initVal, initErr, lowerLimit, upperLimit, err);
710 
711  return err;
712 }
713 
714 ////////////////////////////////////////////////////////////////////////////////
715 /// Delete internal Minuit arrays
716 
718 {
719  if (fEmpty) return;
720  delete [] fCpnam;
721  delete [] fU;
722  delete [] fAlim;
723  delete [] fBlim;
724  delete [] fErp;
725  delete [] fErn;
726  delete [] fWerr;
727  delete [] fGlobcc;
728  delete [] fNvarl;
729  delete [] fNiofex;
730  delete [] fNexofi;
731  delete [] fX;
732  delete [] fXt;
733  delete [] fDirin;
734  delete [] fXs;
735  delete [] fXts;
736  delete [] fDirins;
737  delete [] fGrd;
738  delete [] fG2;
739  delete [] fGstep;
740  delete [] fGin;
741  delete [] fDgrd;
742  delete [] fGrds;
743  delete [] fG2s;
744  delete [] fGsteps;
745  delete [] fIpfix;
746  delete [] fVhmat;
747  delete [] fVthmat;
748  delete [] fP;
749  delete [] fPstar;
750  delete [] fPstst;
751  delete [] fPbar;
752  delete [] fPrho;
753  delete [] fWord7;
754  delete [] fXpt;
755  delete [] fYpt;
756  delete [] fChpt;
757 
758  delete [] fCONTgcc;
759  delete [] fCONTw;
760  delete [] fFIXPyy;
761  delete [] fGRADgf;
762  delete [] fHESSyy;
763  delete [] fIMPRdsav;
764  delete [] fIMPRy;
765  delete [] fMATUvline;
766  delete [] fMIGRflnu;
767  delete [] fMIGRstep;
768  delete [] fMIGRgs;
769  delete [] fMIGRvg;
770  delete [] fMIGRxxs;
771  delete [] fMNOTxdev;
772  delete [] fMNOTw;
773  delete [] fMNOTgcc;
774  delete [] fPSDFs;
775  delete [] fSEEKxmid;
776  delete [] fSEEKxbest;
777  delete [] fSIMPy;
778  delete [] fVERTq;
779  delete [] fVERTs;
780  delete [] fVERTpp;
781  delete [] fCOMDplist;
782  delete [] fPARSplist;
783 
784  fEmpty = 1;
785 }
786 
787 ////////////////////////////////////////////////////////////////////////////////
788 /// Evaluate the minimisation function
789 /// Input parameters:
790 /// - npar: number of currently variable parameters
791 /// - par: array of (constant and variable) parameters
792 /// - flag: Indicates what is to be calculated (see example below)
793 /// - grad: array of gradients
794 /// Output parameters:
795 /// - fval: The calculated function value.
796 /// - grad: The (optional) vector of first derivatives).
797 ///
798 /// The meaning of the parameters par is of course defined by the user,
799 /// who uses the values of those parameters to calculate their function value.
800 /// The starting values must be specified by the user.
801 /// Later values are determined by Minuit as it searches for the minimum
802 /// or performs whatever analysis is requested by the user.
803 ///
804 /// Note that this virtual function may be redefined in a class derived from TMinuit.
805 /// The default function calls the function specified in SetFCN
806 ///
807 /// Example of Minimisation function:
808 
810 {
811 /*
812  if (flag == 1) {
813  read input data,
814  calculate any necessary constants, etc.
815  }
816  if (flag == 2) {
817  calculate GRAD, the first derivatives of FVAL
818  (this is optional)
819  }
820  Always calculate the value of the function, FVAL,
821  which is usually a chisquare or log likelihood.
822  if (iflag == 3) {
823  will come here only after the fit is finished.
824  Perform any final calculations, output fitted data, etc.
825  }
826 */
827 // See concrete examples in TH1::H1FitChisquare, H1FitLikelihood
828 
829  if (fFCN) (*fFCN)(npar,grad,fval,par,flag);
830  return 0;
831 }
832 
833 ////////////////////////////////////////////////////////////////////////////////
834 /// fix a parameter
835 
837 {
838  Int_t err;
839  Double_t tmp[1];
840  tmp[0] = parNo+1; //set internal Minuit numbering
841 
842  mnexcm( "FIX", tmp, 1, err );
843 
844  return err;
845 }
846 
847 ////////////////////////////////////////////////////////////////////////////////
848 /// return parameter value and error
849 
850 Int_t TMinuit::GetParameter( Int_t parNo, Double_t &currentValue, Double_t &currentError ) const
851 {
852  Int_t err;
853  TString name; // ignored
854  Double_t bnd1, bnd2; // ignored
855 
856  mnpout( parNo, name, currentValue, currentError, bnd1, bnd2, err );
857 
858  return err;
859 }
860 
861 ////////////////////////////////////////////////////////////////////////////////
862 /// returns the number of currently fixed parameters
863 
865 {
866  return fNpfix;
867 }
868 
869 ////////////////////////////////////////////////////////////////////////////////
870 /// returns the number of currently free parameters
871 
873 {
874  return fNpar;
875 }
876 
877 ////////////////////////////////////////////////////////////////////////////////
878 /// returns the total number of parameters that have been defined
879 /// as fixed or free. The constant parameters are not counted.
880 
882 {
883  return fNpar + fNpfix;
884 }
885 
886 ////////////////////////////////////////////////////////////////////////////////
887 /// invokes the MIGRAD minimizer
888 
890 {
891  Int_t err;
892  Double_t tmp[1];
893  tmp[0] = 0;
894 
895  mnexcm( "MIGRAD", tmp, 0, err );
896 
897  return err;
898 }
899 
900 ////////////////////////////////////////////////////////////////////////////////
901 /// release a parameter
902 
904 {
905  Int_t err;
906  Double_t tmp[1];
907  tmp[0] = parNo+1; //set internal Minuit numbering
908 
909  mnexcm( "RELEASE", tmp, 1, err );
910 
911  return err;
912 }
913 
914 ////////////////////////////////////////////////////////////////////////////////
915 /// To get the n-sigma contour the error def parameter "up" has to set to n^2.
916 
918 {
919  Int_t err;
920 
921  mnexcm( "SET ERRDEF", &up, 1, err );
922 
923  return err;
924 }
925 
926 ////////////////////////////////////////////////////////////////////////////////
927 /// To set the address of the minimization function
928 
929 void TMinuit::SetFCN(void (*fcn)(Int_t &, Double_t *, Double_t &f, Double_t *, Int_t))
930 {
931  fFCN = fcn;
932 }
933 
934 ////////////////////////////////////////////////////////////////////////////////
935 /// Static function called when SetFCN is called in interactive mode
936 
937 void InteractiveFCNm(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag)
938 {
939  TMethodCall *m = gMinuit->GetMethodCall();
940  if (!m) return;
941 
942  Long_t args[5];
943  args[0] = (Long_t)&npar;
944  args[1] = (Long_t)gin;
945  args[2] = (Long_t)&f;
946  args[3] = (Long_t)u;
947  args[4] = (Long_t)flag;
948  m->SetParamPtrs(args);
950  m->Execute(result);
951 }
952 
953 ////////////////////////////////////////////////////////////////////////////////
954 /// To set the address of the minimization function
955 ///
956 /// this function is called by the interpretor instead of the function above
957 
958 void TMinuit::SetFCN(void *fcn)
959 {
960  if (!fcn) return;
961 
962  Error("SetFCN", "Not used anymore.");
963 
965  gMinuit = this; //required by InteractiveFCNm
966 }
967 
968 ////////////////////////////////////////////////////////////////////////////////
969 /// set Minuit print level.
970 ///
971 /// printlevel:
972 /// - = -1 quiet (also suppress all warnings)
973 /// - = 0 normal
974 /// - = 1 verbose
975 
977 {
978  Int_t err;
979  Double_t tmp[1];
980  tmp[0] = printLevel;
981 
982  mnexcm( "SET PRINT", tmp, 1, err );
983 
984  if (printLevel <=-1) mnexcm("SET NOWarnings",tmp,0,err);
985 
986  return err;
987 }
988 
989 ////////////////////////////////////////////////////////////////////////////////
990 /// Initialize AMIN
991 ///
992 /// Called from many places. Initializes the value of AMIN by
993 /// calling the user function. Prints out the function value and
994 /// parameter values if Print Flag value is high enough.
995 
997 {
998  /* Local variables */
999  Double_t fnew;
1000  Int_t nparx;
1001 
1002  nparx = fNpar;
1003  if (fISW[4] >= 1) {
1004  Printf(" FIRST CALL TO USER FUNCTION AT NEW START POINT, WITH IFLAG=4.");
1005  }
1006  mnexin(fX);
1007  Eval(nparx, fGin, fnew, fU, 4); ++fNfcn;
1008  fAmin = fnew;
1009  fEDM = fBigedm;
1010 }
1011 
1012 ////////////////////////////////////////////////////////////////////////////////
1013 /// Compute reasonable histogram intervals
1014 ///
1015 /// Function TO DETERMINE REASONABLE HISTOGRAM INTERVALS
1016 /// GIVEN ABSOLUTE UPPER AND LOWER BOUNDS A1 AND A2
1017 /// AND DESIRED MAXIMUM NUMBER OF BINS NAA
1018 /// PROGRAM MAKES REASONABLE BINNING FROM BL TO BH OF WIDTH BWID
1019 /// F. JAMES, AUGUST, 1974 , stolen for Minuit, 1988
1020 
1021 void TMinuit::mnbins(Double_t a1, Double_t a2, Int_t naa, Double_t &bl, Double_t &bh, Int_t &nb, Double_t &bwid)
1022 {
1023  /* Local variables */
1024  Double_t awid,ah, al, sigfig, sigrnd, alb;
1025  Int_t kwid, lwid, na=0, log_;
1026 
1027  al = TMath::Min(a1,a2);
1028  ah = TMath::Max(a1,a2);
1029  if (al == ah) ah = al + 1;
1030 
1031 // IF NAA .EQ. -1 , PROGRAM USES BWID INPUT FROM CALLING ROUTINE
1032  if (naa == -1) goto L150;
1033 L10:
1034  na = naa - 1;
1035  if (na < 1) na = 1;
1036 
1037 // GET NOMINAL BIN WIDTH IN EXPON FORM
1038 L20:
1039  awid = (ah-al) / Double_t(na);
1040  log_ = Int_t(TMath::Log10(awid));
1041  if (awid <= 1) --log_;
1042  sigfig = awid*TMath::Power(10, -log_);
1043 // ROUND MANTISSA UP TO 2, 2.5, 5, OR 10
1044  if (sigfig > 2) goto L40;
1045  sigrnd = 2;
1046  goto L100;
1047 L40:
1048  if (sigfig > 2.5) goto L50;
1049  sigrnd = 2.5;
1050  goto L100;
1051 L50:
1052  if (sigfig > 5) goto L60;
1053  sigrnd = 5;
1054  goto L100;
1055 L60:
1056  sigrnd = 1;
1057  ++log_;
1058 L100:
1059  bwid = sigrnd*TMath::Power(10, log_);
1060  goto L200;
1061 // GET NEW BOUNDS FROM NEW WIDTH BWID
1062 L150:
1063  if (bwid <= 0) goto L10;
1064 L200:
1065  alb = al / bwid;
1066  lwid = Int_t(alb);
1067  if (alb < 0) --lwid;
1068  bl = bwid*Double_t(lwid);
1069  alb = ah / bwid + 1;
1070  kwid = Int_t(alb);
1071  if (alb < 0) --kwid;
1072  bh = bwid*Double_t(kwid);
1073  nb = kwid - lwid;
1074  if (naa > 5) goto L240;
1075  if (naa == -1) return;
1076 // REQUEST FOR ONE BIN IS DIFFICULT CASE
1077  if (naa > 1 || nb == 1) return;
1078  bwid *= 2;
1079  nb = 1;
1080  return;
1081 L240:
1082  if (nb << 1 != naa) return;
1083  ++na;
1084  goto L20;
1085 }
1086 
1087 ////////////////////////////////////////////////////////////////////////////////
1088 /// Transform FCN to find further minima
1089 ///
1090 /// Called only from MNIMPR. Transforms the function FCN
1091 /// by dividing out the quadratic part in order to find further
1092 /// minima. Calculates `ycalf = (f-fmin)/(x-xmin)*v*(x-xmin)`
1093 
1094 void TMinuit::mncalf(Double_t *pvec, Double_t &ycalf)
1095 {
1096  /* Local variables */
1097  Int_t ndex, i, j, m, n, nparx;
1098  Double_t denom, f;
1099 
1100  nparx = fNpar;
1101  mninex(&pvec[0]);
1102  Eval(nparx, fGin, f, fU, 4); ++fNfcn;
1103  for (i = 1; i <= fNpar; ++i) {
1104  fGrd[i-1] = 0;
1105  for (j = 1; j <= fNpar; ++j) {
1106  m = TMath::Max(i,j);
1107  n = TMath::Min(i,j);
1108  ndex = m*(m-1) / 2 + n;
1109  fGrd[i-1] += fVthmat[ndex-1]*(fXt[j-1] - pvec[j-1]);
1110  }
1111  }
1112  denom = 0;
1113  for (i = 1; i <= fNpar; ++i) {denom += fGrd[i-1]*(fXt[i-1] - pvec[i-1]); }
1114  if (denom <= 0) {
1115  fDcovar = 1;
1116  fISW[1] = 0;
1117  denom = 1;
1118  }
1119  ycalf = (f - fApsi) / denom;
1120 }
1121 
1122 ////////////////////////////////////////////////////////////////////////////////
1123 /// Resets the parameter list to UNDEFINED
1124 ///
1125 /// Called from MINUIT and by option from MNEXCM
1126 
1128 {
1129  Int_t i;
1130 
1131  fNpfix = 0;
1132  fNu = 0;
1133  fNpar = 0;
1134  fNfcn = 0;
1135  fNwrmes[0] = 0;
1136  fNwrmes[1] = 0;
1137  for (i = 1; i <= fMaxext; ++i) {
1138  fU[i-1] = 0;
1139  fCpnam[i-1] = fCundef;
1140  fNvarl[i-1] = -1;
1141  fNiofex[i-1] = 0;
1142  }
1143  mnrset(1);
1144  fCfrom = "CLEAR ";
1145  fNfcnfr = fNfcn;
1146  fCstatu = "UNDEFINED ";
1147  fLnolim = kTRUE;
1148  fLphead = kTRUE;
1149 }
1150 
1151 ////////////////////////////////////////////////////////////////////////////////
1152 /// Print function contours in two variables, on line printer
1153 ///
1154 /// input arguments: parx, pary, devs, ngrid
1155 
1156 void TMinuit::mncntr(Int_t ike1, Int_t ike2, Int_t &ierrf)
1157 {
1158  static const char *const clabel = "0123456789ABCDEFGHIJ";
1159 
1160  /* Local variables */
1161  Double_t d__1, d__2;
1162  Double_t fcna[115], fcnb[115], contur[20];
1163  Double_t ylabel, fmn, fmx, xlo, ylo, xup, yup;
1164  Double_t devs, xsav, ysav, bwidx, bwidy, unext, ff, xb4;
1165  Int_t i, ngrid, ixmid, nparx, ix, nx, ny, ki1, ki2, ixzero, iy, ics;
1166  TString chmid, chln, chzero;
1167 
1168  Int_t ke1 = ike1+1;
1169  Int_t ke2 = ike2+1;
1170  if (ke1 <= 0 || ke2 <= 0) goto L1350;
1171  if (ke1 > fNu || ke2 > fNu) goto L1350;
1172  ki1 = fNiofex[ke1-1];
1173  ki2 = fNiofex[ke2-1];
1174  if (ki1 <= 0 || ki2 <= 0) goto L1350;
1175  if (ki1 == ki2) goto L1350;
1176 
1177  if (fISW[1] < 1) {
1178  mnhess();
1179  mnwerr();
1180  }
1181  nparx = fNpar;
1182  xsav = fU[ke1-1];
1183  ysav = fU[ke2-1];
1184  devs = fWord7[2];
1185  if (devs <= 0) devs = 2;
1186  xlo = fU[ke1-1] - devs*fWerr[ki1-1];
1187  xup = fU[ke1-1] + devs*fWerr[ki1-1];
1188  ylo = fU[ke2-1] - devs*fWerr[ki2-1];
1189  yup = fU[ke2-1] + devs*fWerr[ki2-1];
1190  ngrid = Int_t(fWord7[3]);
1191  if (ngrid <= 0) {
1192  ngrid = 25;
1193 // Computing MIN
1194  nx = TMath::Min(fNpagwd - 15,ngrid);
1195 // Computing MIN
1196  ny = TMath::Min(fNpagln - 7,ngrid);
1197  } else {
1198  nx = ngrid;
1199  ny = ngrid;
1200  }
1201  if (nx < 11) nx = 11;
1202  if (ny < 11) ny = 11;
1203  if (nx >= 115) nx = 114;
1204 
1205 // ask if parameter outside limits
1206  if (fNvarl[ke1-1] > 1) {
1207  if (xlo < fAlim[ke1-1]) xlo = fAlim[ke1-1];
1208  if (xup > fBlim[ke1-1]) xup = fBlim[ke1-1];
1209  }
1210  if (fNvarl[ke2-1] > 1) {
1211  if (ylo < fAlim[ke2-1]) ylo = fAlim[ke2-1];
1212  if (yup > fBlim[ke2-1]) yup = fBlim[ke2-1];
1213  }
1214  bwidx = (xup - xlo) / Double_t(nx);
1215  bwidy = (yup - ylo) / Double_t(ny);
1216  ixmid = Int_t(((xsav - xlo)*Double_t(nx) / (xup - xlo)) + 1);
1217  if (ixmid < 1) ixmid = 1;
1218  if (fAmin == fUndefi) mnamin();
1219 
1220  for (i = 1; i <= 20; ++i) { contur[i-1] = fAmin + fUp*(i-1)*(i-1); }
1221  contur[0] += fUp*.01;
1222 // fill FCNB to prepare first row, and find column zero/
1223  fU[ke2-1] = yup;
1224  ixzero = 0;
1225  xb4 = 1;
1226 //TH
1227  chmid.Resize(nx+1);
1228  chzero.Resize(nx+1);
1229  chln.Resize(nx+1);
1230  for (ix = 1; ix <= nx + 1; ++ix) {
1231  fU[ke1-1] = xlo + Double_t(ix-1)*bwidx;
1232  Eval(nparx, fGin, ff, fU, 4);
1233  fcnb[ix-1] = ff;
1234  if (xb4 < 0 && fU[ke1-1] > 0) ixzero = ix - 1;
1235  xb4 = fU[ke1-1];
1236  chmid[ix-1] = '*';
1237  chzero[ix-1] = '-';
1238  }
1239  Printf(" Y-AXIS: PARAMETER %3d: %s",ke2,(const char*)fCpnam[ke2-1]);
1240  if (ixzero > 0) {
1241  chzero[ixzero-1] = '+';
1242  chln = " ";
1243  Printf(" X=0");
1244  }
1245 // loop over rows
1246  for (iy = 1; iy <= ny; ++iy) {
1247  unext = fU[ke2-1] - bwidy;
1248 // prepare this line background pattern for contour
1249  chln = " ";
1250 // TH
1251  chln.Resize(nx+1);
1252  chln[ixmid-1] = '*';
1253  if (ixzero != 0) chln[ixzero-1] = ':';
1254  if (fU[ke2-1] > ysav && unext < ysav) chln = chmid;
1255  if (fU[ke2-1] > 0 && unext < 0) chln = chzero;
1256  fU[ke2-1] = unext;
1257  ylabel = fU[ke2-1] + bwidy*.5;
1258 // move FCNB to FCNA and fill FCNB with next row
1259  for (ix = 1; ix <= nx + 1; ++ix) {
1260  fcna[ix-1] = fcnb[ix-1];
1261  fU[ke1-1] = xlo + Double_t(ix-1)*bwidx;
1262  Eval(nparx, fGin, ff, fU, 4);
1263  fcnb[ix-1] = ff;
1264  }
1265 // look for contours crossing the FCNxy squares
1266  for (ix = 1; ix <= nx; ++ix) {
1267  d__1 = TMath::Max(fcna[ix-1],fcnb[ix-1]),
1268  d__2 = TMath::Max(fcna[ix],fcnb[ix]);
1269  fmx = TMath::Max(d__1,d__2);
1270  d__1 = TMath::Min(fcna[ix-1],fcnb[ix-1]),
1271  d__2 = TMath::Min(fcna[ix],fcnb[ix]);
1272  fmn = TMath::Min(d__1,d__2);
1273  for (ics = 1; ics <= 20; ++ics) {
1274  if (contur[ics-1] > fmn) goto L240;
1275  }
1276  continue;
1277 L240:
1278  if (contur[ics-1] < fmx) chln[ix-1] = clabel[ics-1];
1279  }
1280 // print a row of the contour plot
1281  Printf(" %12.4g %s",ylabel,(const char*)chln);
1282  }
1283 // contours printed, label x-axis
1284  chln = " ";
1285  chln(0,1) = 'I';
1286  chln(ixmid-1,1) = 'I';
1287  chln(nx-1,1) = 'I';
1288  Printf(" %s",(const char*)chln);
1289 
1290 // the hardest of all: print x-axis scale!
1291  chln = " ";
1292  if (nx <= 26) {
1293  Printf(" %12.4g%s%12.4g",xlo,(const char*)chln,xup);
1294  Printf(" %s%12.4g",(const char*)chln,xsav);
1295  } else {
1296  Printf(" %12.4g%s%12.4g%s%12.4g",xlo,(const char*)chln,xsav,(const char*)chln,xup);
1297  }
1298  Printf(" X-AXIS: PARAMETER %3d %s ONE COLUMN=%12.4g"
1299  ,ke1,(const char*)fCpnam[ke1-1],bwidx);
1300  Printf(" FUNCTION VALUES: F(I)=%12.4g +%12.4g *I**2",fAmin,fUp);
1301 // finished. reset input values
1302  fU[ke1-1] = xsav;
1303  fU[ke2-1] = ysav;
1304  ierrf = 0;
1305  return;
1306 L1350:
1307  Printf(" INVALID PARAMETER NUMBER(S) REQUESTED. IGNORED.");
1308  ierrf = 1;
1309 }
1310 
1311 ////////////////////////////////////////////////////////////////////////////////
1312 /// Reads a command string and executes
1313 ///
1314 /// Called by user. 'Reads' a command string and executes.
1315 /// Equivalent to MNEXCM except that the command is given as a
1316 /// character string.
1317 ///
1318 /// ICONDN =
1319 /// - 0: command executed normally
1320 /// - 1: command is blank, ignored
1321 /// - 2: command line unreadable, ignored
1322 /// - 3: unknown command, ignored
1323 /// - 4: abnormal termination (e.g., MIGRAD not converged)
1324 /// - 5: command is a request to read PARAMETER definitions
1325 /// - 6: 'SET INPUT' command
1326 /// - 7: 'SET TITLE' command
1327 /// - 8: 'SET COVAR' command
1328 /// - 9: reserved
1329 /// - 10: END command
1330 /// - 11: EXIT or STOP command
1331 /// - 12: RETURN command
1332 ///
1333 
1334 void TMinuit::mncomd(const char *crdbin, Int_t &icondn)
1335 {
1336  /* Local variables */
1337  Int_t ierr, ipos, i, llist, lenbuf, lnc;
1338  Bool_t leader;
1339  TString comand, crdbuf, ctemp;
1340 
1341  crdbuf = crdbin;
1342  crdbuf.ToUpper();
1343  lenbuf = crdbuf.Length();
1344  icondn = 0;
1345 // record not case-sensitive, get upper case, strip leading blanks
1346  leader = kTRUE;
1347  ipos = 1;
1348  for (i = 1; i <= TMath::Min(20,lenbuf); ++i) {
1349  if (crdbuf[i-1] == '\'') break;
1350  if (crdbuf[i-1] == ' ') {
1351  if (leader) ++ipos;
1352  continue;
1353  }
1354  leader = kFALSE;
1355  }
1356 
1357 // blank or null command
1358  if (ipos > lenbuf) {
1359  Printf(" BLANK COMMAND IGNORED.");
1360  icondn = 1;
1361  return;
1362  }
1363 // preemptive commands
1364 // if command is 'PARAMETER'
1365  if (crdbuf(ipos-1,3) == "PAR") {
1366  icondn = 5;
1367  fLphead = kTRUE;
1368  return;
1369  }
1370 // if command is 'SET INPUT'
1371  if (crdbuf(ipos-1,3) == "SET INP") {
1372  icondn = 6;
1373  fLphead = kTRUE;
1374  return;
1375  }
1376 // if command is 'SET TITLE'
1377  if (crdbuf(ipos-1,7) == "SET TIT") {
1378  icondn = 7;
1379  fLphead = kTRUE;
1380  return;
1381  }
1382 // if command is 'SET COVARIANCE'
1383  if (crdbuf(ipos-1,7) == "SET COV") {
1384  icondn = 8;
1385  fLphead = kTRUE;
1386  return;
1387  }
1388 // crack the command
1389  ctemp = crdbuf(ipos-1,lenbuf-ipos+1);
1390  mncrck(ctemp, 20, comand, lnc, fMaxpar, fCOMDplist, llist, ierr, fIsyswr);
1391  if (ierr > 0) {
1392  Printf(" COMMAND CANNOT BE INTERPRETED");
1393  icondn = 2;
1394  return;
1395  }
1396 
1397  mnexcm(comand.Data(), fCOMDplist, llist, ierr);
1398  icondn = ierr;
1399 }
1400 
1401 ////////////////////////////////////////////////////////////////////////////////
1402 /// Find points along a contour where FCN is minimum
1403 ///
1404 /// Find NPTU points along a contour where the function
1405 ///
1406 /// FMIN (X(KE1),X(KE2)) = AMIN+UP
1407 ///
1408 /// where FMIN is the minimum of FCN with respect to all
1409 /// the other NPAR-2 variable parameters (if any).
1410 ///
1411 /// IERRF on return will be equal to the number of points found:
1412 /// - NPTU if normal termination with NPTU points found
1413 /// - -1 if errors in the calling sequence (KE1, KE2 not variable)
1414 /// - 0 if less than four points can be found (using MNMNOT)
1415 /// - n>3 if only n points can be found (n < NPTU)
1416 ///
1417 /// input arguments: parx, pary, devs, ngrid
1418 
1419 void TMinuit::mncont(Int_t ike1, Int_t ike2, Int_t nptu, Double_t *xptu, Double_t *yptu, Int_t &ierrf)
1420 {
1421  /* System generated locals */
1422  Int_t i__1;
1423 
1424  /* Local variables */
1425  Double_t d__1, d__2;
1426  Double_t dist, xdir, ydir, aopt, u1min, u2min;
1427  Double_t abest, scalx, scaly;
1428  Double_t a1, a2, val2mi, val2pl, dc, sclfac, bigdis, sigsav;
1429  Int_t nall, iold, line, mpar, ierr, inew, move, next, i, j, nfcol, iercr;
1430  Int_t idist=0, npcol, kints, i2, i1, lr, nfcnco=0, ki1, ki2, ki3, ke3;
1431  Int_t nowpts, istrav, nfmxin, isw2, isw4;
1432  Bool_t ldebug;
1433 
1434  /* Function Body */
1435  Int_t ke1 = ike1+1;
1436  Int_t ke2 = ike2+1;
1437  ldebug = fIdbg[6] >= 1;
1438  if (ke1 <= 0 || ke2 <= 0) goto L1350;
1439  if (ke1 > fNu || ke2 > fNu) goto L1350;
1440  ki1 = fNiofex[ke1-1];
1441  ki2 = fNiofex[ke2-1];
1442  if (ki1 <= 0 || ki2 <= 0) goto L1350;
1443  if (ki1 == ki2) goto L1350;
1444  if (nptu < 4) goto L1400;
1445 
1446  nfcnco = fNfcn;
1447  fNfcnmx = (nptu + 5)*100*(fNpar + 1);
1448 // The minimum
1449  mncuve();
1450  u1min = fU[ke1-1];
1451  u2min = fU[ke2-1];
1452  ierrf = 0;
1453  fCfrom = "MNContour ";
1454  fNfcnfr = nfcnco;
1455  if (fISW[4] >= 0) {
1456  Printf(" START MNCONTOUR CALCULATION OF %4d POINTS ON CONTOUR.",nptu);
1457  if (fNpar > 2) {
1458  if (fNpar == 3) {
1459  ki3 = 6 - ki1 - ki2;
1460  ke3 = fNexofi[ki3-1];
1461  Printf(" EACH POINT IS A MINIMUM WITH RESPECT TO PARAMETER %3d %s",ke3,(const char*)fCpnam[ke3-1]);
1462  } else {
1463  Printf(" EACH POINT IS A MINIMUM WITH RESPECT TO THE OTHER %3d VARIABLE PARAMETERS.",fNpar - 2);
1464  }
1465  }
1466  }
1467 
1468 // Find the first four points using MNMNOT
1469 // first two points
1470  mnmnot(ke1, ke2, val2pl, val2mi);
1471  if (fErn[ki1-1] == fUndefi) {
1472  xptu[0] = fAlim[ke1-1];
1473  mnwarn("W", "MNContour ", "Contour squeezed by parameter limits.");
1474  } else {
1475  if (fErn[ki1-1] >= 0) goto L1500;
1476  xptu[0] = u1min + fErn[ki1-1];
1477  }
1478  yptu[0] = val2mi;
1479 
1480  if (fErp[ki1-1] == fUndefi) {
1481  xptu[2] = fBlim[ke1-1];
1482  mnwarn("W", "MNContour ", "Contour squeezed by parameter limits.");
1483  } else {
1484  if (fErp[ki1-1] <= 0) goto L1500;
1485  xptu[2] = u1min + fErp[ki1-1];
1486  }
1487  yptu[2] = val2pl;
1488  scalx = 1 / (xptu[2] - xptu[0]);
1489 // next two points
1490  mnmnot(ke2, ke1, val2pl, val2mi);
1491  if (fErn[ki2-1] == fUndefi) {
1492  yptu[1] = fAlim[ke2-1];
1493  mnwarn("W", "MNContour ", "Contour squeezed by parameter limits.");
1494  } else {
1495  if (fErn[ki2-1] >= 0) goto L1500;
1496  yptu[1] = u2min + fErn[ki2-1];
1497  }
1498  xptu[1] = val2mi;
1499  if (fErp[ki2-1] == fUndefi) {
1500  yptu[3] = fBlim[ke2-1];
1501  mnwarn("W", "MNContour ", "Contour squeezed by parameter limits.");
1502  } else {
1503  if (fErp[ki2-1] <= 0) goto L1500;
1504  yptu[3] = u2min + fErp[ki2-1];
1505  }
1506  xptu[3] = val2pl;
1507  scaly = 1 / (yptu[3] - yptu[1]);
1508  nowpts = 4;
1509  next = 5;
1510  if (ldebug) {
1511  Printf(" Plot of four points found by MINOS");
1512  fXpt[0] = u1min;
1513  fYpt[0] = u2min;
1514  fChpt[0] = ' ';
1515 // Computing MIN
1516  nall = TMath::Min(nowpts + 1,101);
1517  for (i = 2; i <= nall; ++i) {
1518  fXpt[i-1] = xptu[i-2];
1519  fYpt[i-1] = yptu[i-2];
1520  }
1521  sprintf(fChpt,"%s"," ABCD");
1522  mnplot(fXpt, fYpt, fChpt, nall, fNpagwd, fNpagln);
1523  }
1524 
1525 // save some values before fixing
1526  isw2 = fISW[1];
1527  isw4 = fISW[3];
1528  sigsav = fEDM;
1529  istrav = fIstrat;
1530  dc = fDcovar;
1531  fApsi = fEpsi*.5;
1532  abest = fAmin;
1533  mpar = fNpar;
1534  nfmxin = fNfcnmx;
1535  for (i = 1; i <= mpar; ++i) { fXt[i-1] = fX[i-1]; }
1536  i__1 = mpar*(mpar + 1) / 2;
1537  for (j = 1; j <= i__1; ++j) { fVthmat[j-1] = fVhmat[j-1]; }
1538  for (i = 1; i <= mpar; ++i) {
1539  fCONTgcc[i-1] = fGlobcc[i-1];
1540  fCONTw[i-1] = fWerr[i-1];
1541  }
1542 // fix the two parameters in question
1543  kints = fNiofex[ke1-1];
1544  mnfixp(kints-1, ierr);
1545  kints = fNiofex[ke2-1];
1546  mnfixp(kints-1, ierr);
1547 // Fill in the rest of the points
1548  for (inew = next; inew <= nptu; ++inew) {
1549 // find the two neighbouring points with largest separation
1550  bigdis = 0;
1551  for (iold = 1; iold <= inew - 1; ++iold) {
1552  i2 = iold + 1;
1553  if (i2 == inew) i2 = 1;
1554  d__1 = scalx*(xptu[iold-1] - xptu[i2-1]);
1555  d__2 = scaly*(yptu[iold-1] - yptu[i2-1]);
1556  dist = d__1*d__1 + d__2*d__2;
1557  if (dist > bigdis) {
1558  bigdis = dist;
1559  idist = iold;
1560  }
1561  }
1562  i1 = idist;
1563  i2 = i1 + 1;
1564  if (i2 == inew) i2 = 1;
1565 // next point goes between I1 and I2
1566  a1 = .5;
1567  a2 = .5;
1568 L300:
1569  fXmidcr = a1*xptu[i1-1] + a2*xptu[i2-1];
1570  fYmidcr = a1*yptu[i1-1] + a2*yptu[i2-1];
1571  xdir = yptu[i2-1] - yptu[i1-1];
1572  ydir = xptu[i1-1] - xptu[i2-1];
1573  sclfac = TMath::Max(TMath::Abs(xdir*scalx),TMath::Abs(ydir*scaly));
1574  fXdircr = xdir / sclfac;
1575  fYdircr = ydir / sclfac;
1576  fKe1cr = ke1;
1577  fKe2cr = ke2;
1578 // Find the contour crossing point along DIR
1579  fAmin = abest;
1580  mncros(aopt, iercr);
1581  if (iercr > 1) {
1582 // If cannot find mid-point, try closer to point 1
1583  if (a1 > .5) {
1584  if (fISW[4] >= 0) {
1585  Printf(" MNCONT CANNOT FIND NEXT POINT ON CONTOUR. ONLY %3d POINTS FOUND.",nowpts);
1586  }
1587  goto L950;
1588  }
1589  mnwarn("W", "MNContour ", "Cannot find midpoint, try closer.");
1590  a1 = .75;
1591  a2 = .25;
1592  goto L300;
1593  }
1594 // Contour has been located, insert new point in list
1595  for (move = nowpts; move >= i1 + 1; --move) {
1596  xptu[move] = xptu[move-1];
1597  yptu[move] = yptu[move-1];
1598  }
1599  ++nowpts;
1600  xptu[i1] = fXmidcr + fXdircr*aopt;
1601  yptu[i1] = fYmidcr + fYdircr*aopt;
1602  }
1603 L950:
1604 
1605  ierrf = nowpts;
1606  fCstatu = "SUCCESSFUL";
1607  if (nowpts < nptu) fCstatu = "INCOMPLETE";
1608 
1609 // make a lineprinter plot of the contour
1610  if (fISW[4] >= 0) {
1611  fXpt[0] = u1min;
1612  fYpt[0] = u2min;
1613  fChpt[0] = ' ';
1614  nall = TMath::Min(nowpts + 1,101);
1615  for (i = 2; i <= nall; ++i) {
1616  fXpt[i-1] = xptu[i-2];
1617  fYpt[i-1] = yptu[i-2];
1618  fChpt[i-1] = 'X';
1619  }
1620  fChpt[nall] = 0;
1621  Printf(" Y-AXIS: PARAMETER %3d %s",ke2,(const char*)fCpnam[ke2-1]);
1622 
1623  mnplot(fXpt, fYpt, fChpt, nall, fNpagwd, fNpagln);
1624 
1625  Printf(" X-AXIS: PARAMETER %3d %s",ke1,(const char*)fCpnam[ke1-1]);
1626  }
1627 // print out the coordinates around the contour
1628  if (fISW[4] >= 1) {
1629  npcol = (nowpts + 1) / 2;
1630  nfcol = nowpts / 2;
1631  Printf("%5d POINTS ON CONTOUR. FMIN=%13.5e ERRDEF=%11.3g",nowpts,abest,fUp);
1632  Printf(" %s%s%s%s",(const char*)fCpnam[ke1-1],
1633  (const char*)fCpnam[ke2-1],
1634  (const char*)fCpnam[ke1-1],
1635  (const char*)fCpnam[ke2-1]);
1636  for (line = 1; line <= nfcol; ++line) {
1637  lr = line + npcol;
1638  Printf(" %5d%13.5e%13.5e %5d%13.5e%13.5e",line,xptu[line-1],yptu[line-1],lr,xptu[lr-1],yptu[lr-1]);
1639  }
1640  if (nfcol < npcol) {
1641  Printf(" %5d%13.5e%13.5e",npcol,xptu[npcol-1],yptu[npcol-1]);
1642  }
1643  }
1644 // contour finished. reset v
1645  fItaur = 1;
1646  mnfree(1);
1647  mnfree(1);
1648  i__1 = mpar*(mpar + 1) / 2;
1649  for (j = 1; j <= i__1; ++j) { fVhmat[j-1] = fVthmat[j-1]; }
1650  for (i = 1; i <= mpar; ++i) {
1651  fGlobcc[i-1] = fCONTgcc[i-1];
1652  fWerr[i-1] = fCONTw[i-1];
1653  fX[i-1] = fXt[i-1];
1654  }
1655  mninex(fX);
1656  fEDM = sigsav;
1657  fAmin = abest;
1658  fISW[1] = isw2;
1659  fISW[3] = isw4;
1660  fDcovar = dc;
1661  fItaur = 0;
1662  fNfcnmx = nfmxin;
1663  fIstrat = istrav;
1664  fU[ke1-1] = u1min;
1665  fU[ke2-1] = u2min;
1666  goto L2000;
1667 // Error returns
1668 L1350:
1669  Printf(" INVALID PARAMETER NUMBERS.");
1670  goto L1450;
1671 L1400:
1672  Printf(" LESS THAN FOUR POINTS REQUESTED.");
1673 L1450:
1674  ierrf = -1;
1675  fCstatu = "USER ERROR";
1676  goto L2000;
1677 L1500:
1678  Printf(" MNCONT UNABLE TO FIND FOUR POINTS.");
1679  fU[ke1-1] = u1min;
1680  fU[ke2-1] = u2min;
1681  ierrf = 0;
1682  fCstatu = "FAILED";
1683 L2000:
1684  fCfrom = "MNContour ";
1685  fNfcnfr = nfcnco;
1686 }
1687 
1688 ////////////////////////////////////////////////////////////////////////////////
1689 /// Cracks the free-format input
1690 ///
1691 /// Cracks the free-format input, expecting zero or more
1692 /// alphanumeric fields (which it joins into COMAND(1:LNC))
1693 /// followed by one or more numeric fields separated by
1694 /// blanks and/or one comma. The numeric fields are put into
1695 /// the LLIST (but at most MXP) elements of PLIST.
1696 ///
1697 /// IERR :
1698 /// - = 0 if no errors,
1699 /// - = 1 if error(s).
1700 
1701 void TMinuit::mncrck(TString cardbuf, Int_t maxcwd, TString &comand, Int_t &lnc,
1702  Int_t mxp, Double_t *plist, Int_t &llist, Int_t &ierr, Int_t)
1703 {
1704  /* Initialized data */
1705 
1706  char *cnull = 0;
1707  const char *cnumer = "123456789-.0+";
1708 
1709  /* Local variables */
1710  Int_t ifld, iend, lend, left, nreq, ipos, kcmnd, nextb, ic, ibegin, ltoadd;
1711  Int_t ielmnt, lelmnt[25], nelmnt;
1712  TString ctemp;
1713  char *celmnt[25];
1714  char command[25];
1715 
1716  /* Function Body */
1717  char *crdbuf = (char*)cardbuf.Data();
1718  lend = cardbuf.Length();
1719  ielmnt = 0;
1720  nextb = 1;
1721  ierr = 0;
1722 // loop over words CELMNT
1723 L10:
1724  for (ipos = nextb; ipos <= lend; ++ipos) {
1725  ibegin = ipos;
1726  if (crdbuf[ipos-1] == ' ') continue;
1727  if (crdbuf[ipos-1] == ',') goto L250;
1728  goto L150;
1729  }
1730  goto L300;
1731 L150:
1732 // found beginning of word, look for end
1733  for (ipos = ibegin + 1; ipos <= lend; ++ipos) {
1734  if (crdbuf[ipos-1] == ' ') goto L250;
1735  if (crdbuf[ipos-1] == ',') goto L250;
1736  }
1737  ipos = lend + 1;
1738 L250:
1739  iend = ipos - 1;
1740  ++ielmnt;
1741  if (iend >= ibegin) celmnt[ielmnt-1] = &crdbuf[ibegin-1];
1742  else celmnt[ielmnt-1] = cnull;
1743  lelmnt[ielmnt-1] = iend - ibegin + 1;
1744  if (lelmnt[ielmnt-1] > 19) {
1745  Printf(" MINUIT WARNING: INPUT DATA WORD TOO LONG.");
1746  ctemp = cardbuf(ibegin-1,iend-ibegin+1);
1747  Printf(" ORIGINAL:%s",ctemp.Data());
1748  Printf(" TRUNCATED TO:%s",celmnt[ielmnt-1]);
1749  lelmnt[ielmnt-1] = 19;
1750  }
1751  if (ipos >= lend) goto L300;
1752  if (ielmnt >= 25) goto L300;
1753 // look for comma or beginning of next word
1754  for (ipos = iend + 1; ipos <= lend; ++ipos) {
1755  if (crdbuf[ipos-1] == ' ') continue;
1756  nextb = ipos;
1757  if (crdbuf[ipos-1] == ',') nextb = ipos + 1;
1758  goto L10;
1759  }
1760 // All elements found, join the alphabetic ones to
1761 // form a command
1762 L300:
1763  nelmnt = ielmnt;
1764  command[0] = ' '; command[1] = 0;
1765  lnc = 1;
1766  plist[0] = 0;
1767  llist = 0;
1768  if (ielmnt == 0) goto L900;
1769  kcmnd = 0;
1770  for (ielmnt = 1; ielmnt <= nelmnt; ++ielmnt) {
1771  if ( celmnt[ielmnt-1] == cnull) goto L450;
1772  for (ic = 1; ic <= 13; ++ic) {
1773  if (*celmnt[ielmnt-1] == cnumer[ic-1]) goto L450;
1774  }
1775  if (kcmnd >= maxcwd) continue;
1776  left = maxcwd - kcmnd;
1777  ltoadd = lelmnt[ielmnt-1];
1778  if (ltoadd > left) ltoadd = left;
1779  strncpy(&command[kcmnd],celmnt[ielmnt-1],ltoadd);
1780  kcmnd += ltoadd;
1781  if (kcmnd == maxcwd) continue;
1782  command[kcmnd] = ' ';
1783  ++kcmnd;
1784  command[kcmnd] = 0;
1785  }
1786  lnc = kcmnd;
1787  goto L900;
1788 L450:
1789  lnc = kcmnd;
1790 // we have come to a numeric field
1791  llist = 0;
1792  for (ifld = ielmnt; ifld <= nelmnt; ++ifld) {
1793  ++llist;
1794  if (llist > mxp) {
1795  nreq = nelmnt - ielmnt + 1;
1796  Printf(" MINUIT WARNING IN MNCRCK: ");
1797  Printf(" COMMAND HAS INPUT %5d NUMERIC FIELDS, BUT MINUIT CAN ACCEPT ONLY%3d",nreq,mxp);
1798  goto L900;
1799  }
1800  if (celmnt[ifld-1] == cnull) plist[llist-1] = 0;
1801  else {
1802  sscanf(celmnt[ifld-1],"%lf",&plist[llist-1]);
1803  }
1804  }
1805 // end loop over numeric fields
1806 L900:
1807  if (lnc <= 0) lnc = 1;
1808  comand = command;
1809 }
1810 
1811 ////////////////////////////////////////////////////////////////////////////////
1812 /// Find point where MNEVAL=AMIN+UP
1813 ///
1814 /// Find point where MNEVAL=AMIN+UP, along the line through
1815 /// XMIDCR,YMIDCR with direction XDIRCR,YDIRCR, where X and Y
1816 /// are parameters KE1CR and KE2CR. If KE2CR=0 (from MINOS),
1817 /// only KE1CR is varied. From MNCONT, both are varied.
1818 /// Crossing point is at
1819 ///
1820 /// (U(KE1),U(KE2)) = (XMID,YMID) + AOPT*(XDIR,YDIR)
1821 
1822 void TMinuit::mncros(Double_t &aopt, Int_t &iercr)
1823 {
1824  /* Local variables */
1825  Double_t alsb[3], flsb[3], bmin, bmax, zmid, sdev, zdir, zlim;
1826  Double_t coeff[3], aleft, aulim, fdist, adist, aminsv;
1827  Double_t anext, fnext, slope, s1, s2, x1, x2, ecarmn, ecarmx;
1828  Double_t determ, rt, smalla, aright, aim, tla, tlf, dfda,ecart;
1829  Int_t iout=0, i, ileft, ierev, maxlk, ibest, ik, it;
1830  Int_t noless, iworst=0, iright, itoohi, kex, ipt;
1831  Bool_t ldebug;
1832  const char *chsign;
1833  x2 = 0;
1834 
1835  ldebug = fIdbg[6] >= 1;
1836  aminsv = fAmin;
1837 // convergence when F is within TLF of AIM and next prediction
1838 // of AOPT is within TLA of previous value of AOPT
1839  aim = fAmin + fUp;
1840  tlf = fUp*.01;
1841  tla = .01;
1842  fXpt[0] = 0;
1843  fYpt[0] = aim;
1844  fChpt[0] = ' ';
1845  ipt = 1;
1846  if (fKe2cr == 0) {
1847  fXpt[1] = -1;
1848  fYpt[1] = fAmin;
1849  fChpt[1] = '.';
1850  ipt = 2;
1851  }
1852 // find the largest allowed A
1853  aulim = 100;
1854  for (ik = 1; ik <= 2; ++ik) {
1855  if (ik == 1) {
1856  kex = fKe1cr;
1857  zmid = fXmidcr;
1858  zdir = fXdircr;
1859  } else {
1860  if (fKe2cr == 0) continue;
1861  kex = fKe2cr;
1862  zmid = fYmidcr;
1863  zdir = fYdircr;
1864  }
1865  if (fNvarl[kex-1] <= 1) continue;
1866  if (zdir == 0) continue;
1867  zlim = fAlim[kex-1];
1868  if (zdir > 0) zlim = fBlim[kex-1];
1869  aulim = TMath::Min(aulim,(zlim - zmid) / zdir);
1870  }
1871 // LSB = Line Search Buffer
1872 // first point
1873  anext = 0;
1874  aopt = anext;
1875  fLimset = kFALSE;
1876  if (aulim < aopt + tla) fLimset = kTRUE;
1877  mneval(anext, fnext, ierev);
1878 // debug printout:
1879  if (ldebug) {
1880  Printf(" MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt);
1881  }
1882  if (ierev > 0) goto L900;
1883  if (fLimset && fnext <= aim) goto L930;
1884  ++ipt;
1885  fXpt[ipt-1] = anext;
1886  fYpt[ipt-1] = fnext;
1887  fChpt[ipt-1] = charal[ipt-1];
1888  alsb[0] = anext;
1889  flsb[0] = fnext;
1890  fnext = TMath::Max(fnext,aminsv + fUp*.1);
1891  aopt = TMath::Sqrt(fUp / (fnext - aminsv)) - 1;
1892  if (TMath::Abs(fnext - aim) < tlf) goto L800;
1893 
1894  if (aopt < -.5)aopt = -.5;
1895  if (aopt > 1) aopt = 1;
1896  fLimset = kFALSE;
1897  if (aopt > aulim) {
1898  aopt = aulim;
1899  fLimset = kTRUE;
1900  }
1901  mneval(aopt, fnext, ierev);
1902 // debug printout:
1903  if (ldebug) {
1904  Printf(" MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt);
1905  }
1906  if (ierev > 0) goto L900;
1907  if (fLimset && fnext <= aim) goto L930;
1908  alsb[1] = aopt;
1909  ++ipt;
1910  fXpt[ipt-1] = alsb[1];
1911  fYpt[ipt-1] = fnext;
1912  fChpt[ipt-1] = charal[ipt-1];
1913  flsb[1] = fnext;
1914  dfda = (flsb[1] - flsb[0]) / (alsb[1] - alsb[0]);
1915 // DFDA must be positive on the contour
1916  if (dfda > 0) goto L460;
1917 L300:
1918  mnwarn("D", "MNCROS ", "Looking for slope of the right sign");
1919  maxlk = 15 - ipt;
1920  for (it = 1; it <= maxlk; ++it) {
1921  alsb[0] = alsb[1];
1922  flsb[0] = flsb[1];
1923  aopt = alsb[0] + Double_t(it)*.2;
1924  fLimset = kFALSE;
1925  if (aopt > aulim) {
1926  aopt = aulim;
1927  fLimset = kTRUE;
1928  }
1929  mneval(aopt, fnext, ierev);
1930 // debug printout:
1931  if (ldebug) {
1932  Printf(" MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt);
1933  }
1934  if (ierev > 0) goto L900;
1935  if (fLimset && fnext <= aim) goto L930;
1936  alsb[1] = aopt;
1937  ++ipt;
1938  fXpt[ipt-1] = alsb[1];
1939  fYpt[ipt-1] = fnext;
1940  fChpt[ipt-1] = charal[ipt-1];
1941  flsb[1] = fnext;
1942  dfda = (flsb[1] - flsb[0]) / (alsb[1] - alsb[0]);
1943  if (dfda > 0) goto L450;
1944  }
1945  mnwarn("W", "MNCROS ", "Cannot find slope of the right sign");
1946  goto L950;
1947 L450:
1948 // we have two points with the right slope
1949 L460:
1950  aopt = alsb[1] + (aim - flsb[1]) / dfda;
1951  fdist = TMath::Min(TMath::Abs(aim - flsb[0]),TMath::Abs(aim - flsb[1]));
1952  adist = TMath::Min(TMath::Abs(aopt - alsb[0]),TMath::Abs(aopt - alsb[1]));
1953  tla = .01;
1954  if (TMath::Abs(aopt) > 1) tla = TMath::Abs(aopt)*.01;
1955  if (adist < tla && fdist < tlf) goto L800;
1956  if (ipt >= 15) goto L950;
1957  bmin = TMath::Min(alsb[0],alsb[1]) - 1;
1958  if (aopt < bmin) aopt = bmin;
1959  bmax = TMath::Max(alsb[0],alsb[1]) + 1;
1960  if (aopt > bmax) aopt = bmax;
1961 // Try a third point
1962  fLimset = kFALSE;
1963  if (aopt > aulim) {
1964  aopt = aulim;
1965  fLimset = kTRUE;
1966  }
1967  mneval(aopt, fnext, ierev);
1968 // debug printout:
1969  if (ldebug) {
1970  Printf(" MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt);
1971  }
1972  if (ierev > 0) goto L900;
1973  if (fLimset && fnext <= aim) goto L930;
1974  alsb[2] = aopt;
1975  ++ipt;
1976  fXpt[ipt-1] = alsb[2];
1977  fYpt[ipt-1] = fnext;
1978  fChpt[ipt-1] = charal[ipt-1];
1979  flsb[2] = fnext;
1980 // now we have three points, ask how many <AIM
1981  ecarmn = TMath::Abs(fnext-aim);
1982  ibest = 3;
1983  ecarmx = 0;
1984  noless = 0;
1985  for (i = 1; i <= 3; ++i) {
1986  ecart = TMath::Abs(flsb[i-1] - aim);
1987  if (ecart > ecarmx) { ecarmx = ecart; iworst = i; }
1988  if (ecart < ecarmn) { ecarmn = ecart; ibest = i; }
1989  if (flsb[i-1] < aim) ++noless;
1990  }
1991 // if at least one on each side of AIM, fit a parabola
1992  if (noless == 1 || noless == 2) goto L500;
1993 // if all three are above AIM, third must be closest to AIM
1994  if (noless == 0 && ibest != 3) goto L950;
1995 // if all three below, and third is not best, then slope
1996 // has again gone negative, look for positive slope.
1997  if (noless == 3 && ibest != 3) {
1998  alsb[1] = alsb[2];
1999  flsb[1] = flsb[2];
2000  goto L300;
2001  }
2002 // in other cases, new straight line thru last two points
2003  alsb[iworst-1] = alsb[2];
2004  flsb[iworst-1] = flsb[2];
2005  dfda = (flsb[1] - flsb[0]) / (alsb[1] - alsb[0]);
2006  goto L460;
2007 // parabola fit
2008 L500:
2009  mnpfit(alsb, flsb, 3, coeff, sdev);
2010  if (coeff[2] <= 0) {
2011  mnwarn("D", "MNCROS ", "Curvature is negative near contour line.");
2012  }
2013  determ = coeff[1]*coeff[1] - coeff[2]*4*(coeff[0] - aim);
2014  if (determ <= 0) {
2015  mnwarn("D", "MNCROS ", "Problem 2, impossible determinant");
2016  goto L950;
2017  }
2018 // Find which root is the right one
2019  rt = TMath::Sqrt(determ);
2020  x1 = (-coeff[1] + rt) / (coeff[2]*2);
2021  x2 = (-coeff[1] - rt) / (coeff[2]*2);
2022  s1 = coeff[1] + x1*2*coeff[2];
2023  s2 = coeff[1] + x2*2*coeff[2];
2024  if (s1*s2 > 0) {
2025  Printf(" MNCONTour problem 1");
2026  }
2027  aopt = x1;
2028  slope = s1;
2029  if (s2 > 0) {
2030  aopt = x2;
2031  slope = s2;
2032  }
2033 // ask if converged
2034  tla = .01;
2035  if (TMath::Abs(aopt) > 1) tla = TMath::Abs(aopt)*.01;
2036  if (TMath::Abs(aopt - alsb[ibest-1]) < tla && TMath::Abs(flsb[ibest-1] - aim) < tlf) {
2037  goto L800;
2038  }
2039  if (ipt >= 15) goto L950;
2040 
2041 // see if proposed point is in acceptable zone between L and R
2042 // first find ILEFT, IRIGHT, IOUT and IBEST
2043  ileft = 0;
2044  iright = 0;
2045  ibest = 1;
2046  ecarmx = 0;
2047  ecarmn = TMath::Abs(aim - flsb[0]);
2048  for (i = 1; i <= 3; ++i) {
2049  ecart = TMath::Abs(flsb[i-1] - aim);
2050  if (ecart < ecarmn) { ecarmn = ecart; ibest = i; }
2051  if (ecart > ecarmx) { ecarmx = ecart; }
2052  if (flsb[i-1] > aim) {
2053  if (iright == 0) iright = i;
2054  else if (flsb[i-1] > flsb[iright-1]) iout = i;
2055  else { iout = iright; iright = i; }
2056  }
2057  else if (ileft == 0) ileft = i;
2058  else if (flsb[i-1] < flsb[ileft-1]) iout = i;
2059  else { iout = ileft; ileft = i; }
2060  }
2061 // avoid keeping a very bad point next time around
2062  if (ecarmx > TMath::Abs(flsb[iout-1] - aim)*10) {
2063  aopt = aopt*.5 + (alsb[iright-1] + alsb[ileft-1])*.25;
2064  }
2065 // knowing ILEFT and IRIGHT, get acceptable window
2066  smalla = tla*.1;
2067  if (slope*smalla > tlf) smalla = tlf / slope;
2068  aleft = alsb[ileft-1] + smalla;
2069  aright = alsb[iright-1] - smalla;
2070 // move proposed point AOPT into window if necessary
2071  if (aopt < aleft) aopt = aleft;
2072  if (aopt > aright) aopt = aright;
2073  if (aleft > aright) aopt = (aleft + aright)*.5;
2074 
2075 // see if proposed point outside limits (should be impossible!)
2076  fLimset = kFALSE;
2077  if (aopt > aulim) {
2078  aopt = aulim;
2079  fLimset = kTRUE;
2080  }
2081 // Evaluate function at new point AOPT
2082  mneval(aopt, fnext, ierev);
2083 // debug printout:
2084  if (ldebug) {
2085  Printf(" MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt);
2086  }
2087  if (ierev > 0) goto L900;
2088  if (fLimset && fnext <= aim) goto L930;
2089  ++ipt;
2090  fXpt[ipt-1] = aopt;
2091  fYpt[ipt-1] = fnext;
2092  fChpt[ipt-1] = charal[ipt-1];
2093 // Replace odd point by new one
2094  alsb[iout-1] = aopt;
2095  flsb[iout-1] = fnext;
2096 // the new point may not be the best, but it is the only one
2097 // which could be good enough to pass convergence criteria
2098  ibest = iout;
2099  goto L500;
2100 
2101 // Contour has been located, return point to MNCONT OR MINOS
2102 L800:
2103  iercr = 0;
2104  goto L1000;
2105 // error in the minimization
2106 L900:
2107  if (ierev == 1) goto L940;
2108  goto L950;
2109 // parameter up against limit
2110 L930:
2111  iercr = 1;
2112  goto L1000;
2113 // too many calls to FCN
2114 L940:
2115  iercr = 2;
2116  goto L1000;
2117 // cannot find next point
2118 L950:
2119  iercr = 3;
2120 // in any case
2121 L1000:
2122  if (ldebug) {
2123  itoohi = 0;
2124  for (i = 1; i <= ipt; ++i) {
2125  if (fYpt[i-1] > aim + fUp) {
2126  fYpt[i-1] = aim + fUp;
2127  fChpt[i-1] = '+';
2128  itoohi = 1;
2129  }
2130  }
2131  fChpt[ipt] = 0;
2132  chsign = "POSI";
2133  if (fXdircr < 0) chsign = "NEGA";
2134  if (fKe2cr == 0) {
2135  Printf(" %sTIVE MINOS ERROR, PARAMETER %3d",chsign,fKe1cr);
2136  }
2137  if (itoohi == 1) {
2138  Printf("POINTS LABELLED '+' WERE TOO HIGH TO PLOT.");
2139  }
2140  if (iercr == 1) {
2141  Printf("RIGHTMOST POINT IS UP AGAINST LIMIT.");
2142  }
2143  mnplot(fXpt, fYpt, fChpt, ipt, fNpagwd, fNpagln);
2144  }
2145 }
2146 
2147 ////////////////////////////////////////////////////////////////////////////////
2148 /// Makes sure that the current point is a local minimum
2149 ///
2150 /// Makes sure that the current point is a local
2151 /// minimum and that the error matrix exists,
2152 /// or at least something good enough for MINOS and MNCONT
2153 
2155 {
2156  /* Local variables */
2157  Double_t dxdi, wint;
2158  Int_t ndex, iext, i, j;
2159 
2160  if (fISW[3] < 1) {
2161  Printf(" FUNCTION MUST BE MINIMIZED BEFORE CALLING %s",(const char*)fCfrom);
2162  fApsi = fEpsi;
2163  mnmigr();
2164  }
2165  if (fISW[1] < 3) {
2166  mnhess();
2167  if (fISW[1] < 1) {
2168  mnwarn("W", fCfrom, "NO ERROR MATRIX. WILL IMPROVISE.");
2169  for (i = 1; i <= fNpar; ++i) {
2170  ndex = i*(i-1) / 2;
2171  for (j = 1; j <= i-1; ++j) {
2172  ++ndex;
2173  fVhmat[ndex-1] = 0;
2174  }
2175  ++ndex;
2176  if (fG2[i-1] <= 0) {
2177  wint = fWerr[i-1];
2178  iext = fNexofi[i-1];
2179  if (fNvarl[iext-1] > 1) {
2180  mndxdi(fX[i-1], i-1, dxdi);
2181  if (TMath::Abs(dxdi) < .001) wint = .01;
2182  else wint /= TMath::Abs(dxdi);
2183  }
2184  fG2[i-1] = fUp / (wint*wint);
2185  }
2186  fVhmat[ndex-1] = 2 / fG2[i-1];
2187  }
2188  fISW[1] = 1;
2189  fDcovar = 1;
2190  } else mnwerr();
2191  }
2192 }
2193 
2194 ////////////////////////////////////////////////////////////////////////////////
2195 /// Calculates the first derivatives of FCN (GRD)
2196 ///
2197 /// Calculates the first derivatives of FCN (GRD),
2198 /// either by finite differences or by transforming the user-
2199 /// supplied derivatives to internal coordinates,
2200 /// according to whether fISW[2] is zero or one.
2201 
2203 {
2204  /* Local variables */
2205  Double_t step, dfmin, stepb4, dd, df, fs1;
2206  Double_t tlrstp, tlrgrd, epspri, optstp, stpmax, stpmin, fs2, grbfor=0, d1d2, xtf;
2207  Int_t icyc, ncyc, iint, iext, i, nparx;
2208  Bool_t ldebug;
2209 
2210  nparx = fNpar;
2211  ldebug = fIdbg[2] >= 1;
2212  if (fAmin == fUndefi) mnamin();
2213  if (fISW[2] == 1) goto L100;
2214 
2215  if (ldebug) {
2216 // make sure starting at the right place
2217  mninex(fX);
2218  nparx = fNpar;
2219  Eval(nparx, fGin, fs1, fU, 4); ++fNfcn;
2220  if (fs1 != fAmin) {
2221  df = fAmin - fs1;
2222  mnwarn("D", "MNDERI", TString::Format("function value differs from AMIN by %12.3g",df));
2223  fAmin = fs1;
2224  }
2225  Printf(" FIRST DERIVATIVE DEBUG PRINTOUT. MNDERI");
2226  Printf(" PAR DERIV STEP MINSTEP OPTSTEP D1-D2 2ND DRV");
2227  }
2228  dfmin = fEpsma2*8*(TMath::Abs(fAmin) + fUp);
2229  if (fIstrat <= 0) {
2230  ncyc = 2;
2231  tlrstp = .5;
2232  tlrgrd = .1;
2233  } else if (fIstrat == 1) {
2234  ncyc = 3;
2235  tlrstp = .3;
2236  tlrgrd = .05;
2237  } else {
2238  ncyc = 5;
2239  tlrstp = .1;
2240  tlrgrd = .02;
2241  }
2242 // loop over variable parameters
2243  for (i = 1; i <= fNpar; ++i) {
2244  epspri = fEpsma2 + TMath::Abs(fGrd[i-1]*fEpsma2);
2245 // two-point derivatives always assumed necessary
2246 // maximum number of cycles over step size depends on strategy
2247  xtf = fX[i-1];
2248  stepb4 = 0;
2249 // loop as little as possible here!/
2250  for (icyc = 1; icyc <= ncyc; ++icyc) {
2251 // theoretically best step
2252  optstp = TMath::Sqrt(dfmin / (TMath::Abs(fG2[i-1]) + epspri));
2253 // step cannot decrease by more than a factor of ten
2254  step = TMath::Max(optstp,TMath::Abs(fGstep[i-1]*.1));
2255 // but if parameter has limits, max step size = 0.5
2256  if (fGstep[i-1] < 0 && step > .5) step = .5;
2257 // and not more than ten times the previous step
2258  stpmax = TMath::Abs(fGstep[i-1])*10;
2259  if (step > stpmax) step = stpmax;
2260 // minimum step size allowed by machine precision
2261  stpmin = TMath::Abs(fEpsma2*fX[i-1])*8;
2262  if (step < stpmin) step = stpmin;
2263 // end of iterations if step change less than factor 2
2264  if (TMath::Abs((step - stepb4) / step) < tlrstp) goto L50;
2265 // take step positive
2266  stepb4 = step;
2267  if (fGstep[i-1] > 0) fGstep[i-1] = TMath::Abs(step);
2268  else fGstep[i-1] = -TMath::Abs(step);
2269  stepb4 = step;
2270  fX[i-1] = xtf + step;
2271  mninex(fX);
2272  Eval(nparx, fGin, fs1, fU, 4); ++fNfcn;
2273 // take step negative
2274  fX[i-1] = xtf - step;
2275  mninex(fX);
2276  Eval(nparx, fGin, fs2, fU, 4); ++fNfcn;
2277  grbfor = fGrd[i-1];
2278  fGrd[i-1] = (fs1 - fs2) / (step*2);
2279  fG2[i-1] = (fs1 + fs2 - fAmin*2) / (step*step);
2280  fX[i-1] = xtf;
2281  if (ldebug) {
2282  d1d2 = (fs1 + fs2 - fAmin*2) / step;
2283  Printf("%4d%11.3g%11.3g%10.2g%10.2g%10.2g%10.2g",i,fGrd[i-1],step,stpmin,optstp,d1d2,fG2[i-1]);
2284  }
2285 // see if another iteration is necessary
2286  if (TMath::Abs(grbfor - fGrd[i-1]) / (TMath::Abs(fGrd[i-1]) + dfmin/step) < tlrgrd)
2287  goto L50;
2288  }
2289 // end of ICYC loop. too many iterations
2290  if (ncyc == 1) goto L50;
2291  mnwarn("D", "MNDERI", TString::Format("First derivative not converged. %g%g",fGrd[i-1],grbfor));
2292 L50:
2293  ;
2294  }
2295  mninex(fX);
2296  return;
2297 // derivatives calc by fcn
2298 L100:
2299  for (iint = 1; iint <= fNpar; ++iint) {
2300  iext = fNexofi[iint-1];
2301  if (fNvarl[iext-1] <= 1) {
2302  fGrd[iint-1] = fGin[iext-1];
2303  } else {
2304  dd = (fBlim[iext-1] - fAlim[iext-1])*.5*TMath::Cos(fX[iint-1]);
2305  fGrd[iint-1] = fGin[iext-1]*dd;
2306  }
2307  }
2308 }
2309 
2310 ////////////////////////////////////////////////////////////////////////////////
2311 /// Calculates the transformation factor between ext/internal values
2312 ///
2313 /// calculates the transformation factor between external and
2314 /// internal parameter values. this factor is one for
2315 /// parameters which are not limited. called from MNEMAT.
2316 
2317 void TMinuit::mndxdi(Double_t pint, Int_t ipar, Double_t &dxdi)
2318 {
2319  Int_t i = fNexofi[ipar];
2320  dxdi = 1;
2321  if (fNvarl[i-1] > 1) {
2322  dxdi = TMath::Abs((fBlim[i-1] - fAlim[i-1])*TMath::Cos(pint))*.5;
2323  }
2324 }
2325 
2326 ////////////////////////////////////////////////////////////////////////////////
2327 /// Compute matrix eigen values
2328 
2329 void TMinuit::mneig(Double_t *a, Int_t ndima, Int_t n, Int_t mits, Double_t *work, Double_t precis, Int_t &ifault)
2330 {
2331  /* System generated locals */
2332  Int_t a_offset;
2333  Double_t d__1;
2334 
2335  /* Local variables */
2336  Double_t b, c, f, h, r, s, hh, gl, pr, pt;
2337  Int_t i, j, k, l, m=0, i0, i1, j1, m1, n1;
2338 
2339 // PRECIS is the machine precision EPSMAC
2340  /* Parameter adjustments */
2341  a_offset = ndima + 1;
2342  a -= a_offset;
2343  --work;
2344 
2345  /* Function Body */
2346  ifault = 1;
2347 
2348  i = n;
2349  for (i1 = 2; i1 <= n; ++i1) {
2350  l = i-2;
2351  f = a[i + (i-1)*ndima];
2352  gl = 0;
2353 
2354  if (l < 1) goto L25;
2355 
2356  for (k = 1; k <= l; ++k) {
2357  d__1 = a[i + k*ndima];
2358  gl += d__1*d__1;
2359  }
2360 L25:
2361  h = gl + f*f;
2362 
2363  if (gl > 1e-35) goto L30;
2364 
2365  work[i] = 0;
2366  work[n + i] = f;
2367  goto L65;
2368 L30:
2369  ++l;
2370  gl = TMath::Sqrt(h);
2371  if (f >= 0) gl = -gl;
2372  work[n + i] = gl;
2373  h -= f*gl;
2374  a[i + (i-1)*ndima] = f - gl;
2375  f = 0;
2376  for (j = 1; j <= l; ++j) {
2377  a[j + i*ndima] = a[i + j*ndima] / h;
2378  gl = 0;
2379  for (k = 1; k <= j; ++k) { gl += a[j + k*ndima]*a[i + k*ndima]; }
2380  if (j >= l) goto L47;
2381  j1 = j + 1;
2382  for (k = j1; k <= l; ++k) { gl += a[k + j*ndima]*a[i + k*ndima]; }
2383 L47:
2384  work[n + j] = gl / h;
2385  f += gl*a[j + i*ndima];
2386  }
2387  hh = f / (h + h);
2388  for (j = 1; j <= l; ++j) {
2389  f = a[i + j*ndima];
2390  gl = work[n + j] - hh*f;
2391  work[n + j] = gl;
2392  for (k = 1; k <= j; ++k) {
2393  a[j + k*ndima] = a[j + k*ndima] - f*work[n + k] - gl*a[i + k*ndima];
2394  }
2395  }
2396  work[i] = h;
2397 L65:
2398  --i;
2399  }
2400  work[1] = 0;
2401  work[n + 1] = 0;
2402  for (i = 1; i <= n; ++i) {
2403  l = i-1;
2404  if (work[i] == 0 || l == 0) goto L100;
2405 
2406  for (j = 1; j <= l; ++j) {
2407  gl = 0;
2408  for (k = 1; k <= l; ++k) { gl += a[i + k*ndima]*a[k + j*ndima]; }
2409  for (k = 1; k <= l; ++k) { a[k + j*ndima] -= gl*a[k + i*ndima]; }
2410  }
2411 L100:
2412  work[i] = a[i + i*ndima];
2413  a[i + i*ndima] = 1;
2414  if (l == 0) continue;
2415 
2416  for (j = 1; j <= l; ++j) {
2417  a[i + j*ndima] = 0;
2418  a[j + i*ndima] = 0;
2419  }
2420  }
2421 
2422  n1 = n - 1;
2423  for (i = 2; i <= n; ++i) {
2424  i0 = n + i-1;
2425  work[i0] = work[i0 + 1];
2426  }
2427  work[n + n] = 0;
2428  b = 0;
2429  f = 0;
2430  for (l = 1; l <= n; ++l) {
2431  j = 0;
2432  h = precis*(TMath::Abs(work[l]) + TMath::Abs(work[n + l]));
2433  if (b < h) b = h;
2434  for (m1 = l; m1 <= n; ++m1) {
2435  m = m1;
2436  if (TMath::Abs(work[n + m]) <= b) goto L150;
2437  }
2438 
2439 L150:
2440  if (m == l) goto L205;
2441 
2442 L160:
2443  if (j == mits) return;
2444  ++j;
2445  pt = (work[l + 1] - work[l]) / (work[n + l]*2);
2446  r = TMath::Sqrt(pt*pt + 1);
2447  pr = pt + r;
2448  if (pt < 0) pr = pt - r;
2449 
2450  h = work[l] - work[n + l] / pr;
2451  for (i = l; i <= n; ++i) { work[i] -= h; }
2452  f += h;
2453  pt = work[m];
2454  c = 1;
2455  s = 0;
2456  m1 = m - 1;
2457  i = m;
2458  for (i1 = l; i1 <= m1; ++i1) {
2459  j = i;
2460  --i;
2461  gl = c*work[n + i];
2462  h = c*pt;
2463  if (TMath::Abs(pt) >= TMath::Abs(work[n + i])) goto L180;
2464 
2465  c = pt / work[n + i];
2466  r = TMath::Sqrt(c*c + 1);
2467  work[n + j] = s*work[n + i]*r;
2468  s = 1 / r;
2469  c /= r;
2470  goto L190;
2471 L180:
2472  c = work[n + i] / pt;
2473  r = TMath::Sqrt(c*c + 1);
2474  work[n + j] = s*pt*r;
2475  s = c / r;
2476  c = 1 / r;
2477 L190:
2478  pt = c*work[i] - s*gl;
2479  work[j] = h + s*(c*gl + s*work[i]);
2480  for (k = 1; k <= n; ++k) {
2481  h = a[k + j*ndima];
2482  a[k + j*ndima] = s*a[k + i*ndima] + c*h;
2483  a[k + i*ndima] = c*a[k + i*ndima] - s*h;
2484  }
2485  }
2486  work[n + l] = s*pt;
2487  work[l] = c*pt;
2488 
2489  if (TMath::Abs(work[n + l]) > b) goto L160;
2490 
2491 L205:
2492  work[l] += f;
2493  }
2494  for (i = 1; i <= n1; ++i) {
2495  k = i;
2496  pt = work[i];
2497  i1 = i + 1;
2498  for (j = i1; j <= n; ++j) {
2499  if (work[j] >= pt) continue;
2500  k = j;
2501  pt = work[j];
2502  }
2503 
2504  if (k == i) continue;
2505 
2506  work[k] = work[i];
2507  work[i] = pt;
2508  for (j = 1; j <= n; ++j) {
2509  pt = a[j + i*ndima];
2510  a[j + i*ndima] = a[j + k*ndima];
2511  a[j + k*ndima] = pt;
2512  }
2513  }
2514  ifault = 0;
2515 }
2516 
2517 ////////////////////////////////////////////////////////////////////////////////
2518 /// Calculates the external error matrix from the internal matrix
2519 ///
2520 /// Note that if the matrix is declared like Double_t matrix[5][5]
2521 /// in the calling program, one has to call mnemat with, eg
2522 ///
2523 /// gMinuit->mnemat(&matrix[0][0],5);
2524 
2525 void TMinuit::mnemat(Double_t *emat, Int_t ndim)
2526 {
2527  /* System generated locals */
2528  Int_t emat_dim1, emat_offset;
2529 
2530  /* Local variables */
2531  Double_t dxdi, dxdj;
2532  Int_t i, j, k, npard, k2, kk, iz, nperln, kga, kgb;
2533  TString ctemp;
2534 
2535  /* Parameter adjustments */
2536  emat_dim1 = ndim;
2537  emat_offset = emat_dim1 + 1;
2538  emat -= emat_offset;
2539 
2540  /* Function Body */
2541  if (fISW[1] < 1) return;
2542  if (fISW[4] >= 2) {
2543  Printf(" EXTERNAL ERROR MATRIX. NDIM=%4d NPAR=%3d ERR DEF=%g",ndim,fNpar,fUp);
2544  }
2545 // size of matrix to be printed
2546  npard = fNpar;
2547  if (ndim < fNpar) {
2548  npard = ndim;
2549  if (fISW[4] >= 0) {
2550  Printf(" USER-DIMENSIONED ARRAY EMAT NOT BIG ENOUGH. REDUCED MATRIX CALCULATED.");
2551  }
2552  }
2553 // NPERLN is the number of elements that fit on one line
2554 
2555  nperln = (fNpagwd - 5) / 10;
2556  nperln = TMath::Min(nperln,13);
2557  if (fISW[4] >= 1 && npard > nperln) {
2558  Printf(" ELEMENTS ABOVE DIAGONAL ARE NOT PRINTED.");
2559  }
2560 // I counts the rows of the matrix
2561  for (i = 1; i <= npard; ++i) {
2562  mndxdi(fX[i-1], i-1, dxdi);
2563  kga = i*(i-1) / 2;
2564  for (j = 1; j <= i; ++j) {
2565  mndxdi(fX[j-1], j-1, dxdj);
2566  kgb = kga + j;
2567  emat[i + j*emat_dim1] = dxdi*fVhmat[kgb-1]*dxdj*fUp;
2568  emat[j + i*emat_dim1] = emat[i + j*emat_dim1];
2569  }
2570  }
2571 // IZ is number of columns to be printed in row I
2572  if (fISW[4] >= 2) {
2573  for (i = 1; i <= npard; ++i) {
2574  iz = npard;
2575  if (npard >= nperln) iz = i;
2576  ctemp = " ";
2577  for (k = 1; nperln < 0 ? k >= iz : k <= iz; k += nperln) {
2578  k2 = k + nperln - 1;
2579  if (k2 > iz) k2 = iz;
2580  for (kk = k; kk <= k2; ++kk) {
2581  ctemp += TString::Format("%10.3e ",emat[i + kk*emat_dim1]);
2582  }
2583  Printf("%s",(const char*)ctemp);
2584  }
2585  }
2586  }
2587 }
2588 
2589 ////////////////////////////////////////////////////////////////////////////////
2590 /// Utility routine to get MINOS errors
2591 ///
2592 /// Called by user.
2593 ///
2594 /// NUMBER is the parameter number
2595 ///
2596 /// values returned by MNERRS:
2597 /// - EPLUS, EMINUS are MINOS errors of parameter NUMBER,
2598 /// - EPARAB is 'parabolic' error (from error matrix).
2599 /// (Errors not calculated are set = 0)
2600 /// - GCC is global correlation coefficient from error matrix
2601 
2602 void TMinuit::mnerrs(Int_t number, Double_t &eplus, Double_t &eminus, Double_t &eparab, Double_t &gcc)
2603 {
2604  Double_t dxdi;
2605  Int_t ndiag, iin, iex;
2606 
2607  iex = number+1;
2608 
2609  if (iex > fNu || iex <= 0) goto L900;
2610  iin = fNiofex[iex-1];
2611  if (iin <= 0) goto L900;
2612 
2613 // IEX is external number, IIN is internal number
2614  eplus = fErp[iin-1];
2615  if (eplus == fUndefi) eplus = 0;
2616  eminus = fErn[iin-1];
2617  if (eminus == fUndefi) eminus = 0;
2618  mndxdi(fX[iin-1], iin-1, dxdi);
2619  ndiag = iin*(iin + 1) / 2;
2620  eparab = TMath::Abs(dxdi*TMath::Sqrt(TMath::Abs(fUp*fVhmat[ndiag- 1])));
2621 // global correlation coefficient
2622  gcc = 0;
2623  if (fISW[1] < 2) return;
2624  gcc = fGlobcc[iin-1];
2625  return;
2626 // ERROR. parameter number not valid
2627 L900:
2628  eplus = 0;
2629  eminus = 0;
2630  eparab = 0;
2631  gcc = 0;
2632 }
2633 
2634 ////////////////////////////////////////////////////////////////////////////////
2635 /// Evaluates the function being analysed by MNCROS
2636 ///
2637 /// Evaluates the function being analysed by MNCROS, which is
2638 /// generally the minimum of FCN with respect to all remaining
2639 /// variable parameters. The class data members contains the
2640 /// data necessary to know the values of U(KE1CR) and U(KE2CR)
2641 /// to be used, namely U(KE1CR) = XMIDCR + ANEXT*XDIRCR
2642 /// and (if KE2CR .NE. 0) U(KE2CR) = YMIDCR + ANEXT*YDIRCR
2643 
2644 void TMinuit::mneval(Double_t anext, Double_t &fnext, Int_t &ierev)
2645 {
2646  Int_t nparx;
2647 
2648  fU[fKe1cr-1] = fXmidcr + anext*fXdircr;
2649  if (fKe2cr != 0) fU[fKe2cr-1] = fYmidcr + anext*fYdircr;
2650  mninex(fX);
2651  nparx = fNpar;
2652  Eval(nparx, fGin, fnext, fU, 4); ++fNfcn;
2653  ierev = 0;
2654  if (fNpar > 0) {
2655  fItaur = 1;
2656  fAmin = fnext;
2657  fISW[0] = 0;
2658  mnmigr();
2659  fItaur = 0;
2660  fnext = fAmin;
2661  if (fISW[0] >= 1) ierev = 1;
2662  if (fISW[3] < 1) ierev = 2;
2663  }
2664 }
2665 
2666 ////////////////////////////////////////////////////////////////////////////////
2667 /// Interprets a command and takes appropriate action
2668 ///
2669 /// either directly by skipping to the corresponding code in
2670 /// MNEXCM, or by setting up a call to a function
2671 ///
2672 /// recognized MINUIT commands:
2673 /// obsolete commands:
2674 /// IERFLG is now (94.5) defined the same as ICONDN in MNCOMD =
2675 /// - 0: command executed normally
2676 /// - 1: command is blank, ignored
2677 /// - 2: command line unreadable, ignored
2678 /// - 3: unknown command, ignored
2679 /// - 4: abnormal termination (e.g., MIGRAD not converged)
2680 /// - 9: reserved
2681 /// - 10: END command
2682 /// - 11: EXIT or STOP command
2683 /// - 12: RETURN command
2684 ///
2685 /// see also
2686 /// [the possible list of all Minuit commands](https://root.cern.ch/sites/d35c7d8c.web.cern.ch/files/minuit.pdf).
2687 
2688 void TMinuit::mnexcm(const char *command, Double_t *plist, Int_t llist, Int_t &ierflg)
2689 {
2690  /* Initialized data */
2691 
2692  TString comand = command;
2693  static const char *const cname[40] = {
2694  "MINImize ",
2695  "SEEk ",
2696  "SIMplex ",
2697  "MIGrad ",
2698  "MINOs ",
2699  "SET xxx ",
2700  "SHOw xxx ",
2701  "TOP of pag",
2702  "FIX ",
2703  "REStore ",
2704  "RELease ",
2705  "SCAn ",
2706  "CONtour ",
2707  "HESse ",
2708  "SAVe ",
2709  "IMProve ",
2710  "CALl fcn ",
2711  "STAndard ",
2712  "END ",
2713  "EXIt ",
2714  "RETurn ",
2715  "CLEar ",
2716  "HELP ",
2717  "MNContour ",
2718  "STOp ",
2719  "JUMp ",
2720  " ",
2721  " ",
2722  " ",
2723  " ",
2724  " ",
2725  " ",
2726  " ",
2727  "COVARIANCE",
2728  "PRINTOUT ",
2729  "GRADIENT ",
2730  "MATOUT ",
2731  "ERROR DEF ",
2732  "LIMITS ",
2733  "PUNCH "};
2734 
2735  Int_t nntot = 40;
2736 
2737  /* Local variables */
2738  Double_t step, xptu[101], yptu[101], f, rno;
2739  Int_t icol, kcol, ierr, iint, iext, lnow, nptu, i, iflag, ierrf;
2740  Int_t ilist, nparx, izero, nf, lk, it, iw, inonde, nsuper;
2741  Int_t it2, ke1, ke2, nowprt, kll, krl;
2742  TString chwhy, c26, cvblnk, cneway, comd;
2743  TString ctemp;
2744  Bool_t lfreed, ltofix, lfixed;
2745 
2746 // alphabetical order of command names!
2747 
2748  /* Function Body */
2749 
2750  lk = comand.Length();
2751  if (lk > 20) lk = 20;
2752  fCword = comand;
2753  fCword.ToUpper();
2754 // Copy the first MAXP arguments into WORD7, making
2755 // sure that WORD7(1)=0 if LLIST=0
2756  for (iw = 1; iw <= fMaxpar; ++iw) {
2757  fWord7[iw-1] = 0;
2758  if (iw <= llist) fWord7[iw-1] = plist[iw-1];
2759  }
2760  ++fIcomnd;
2761  fNfcnlc = fNfcn;
2762  if (fCword(0,7) != "SET PRI" || fWord7[0] >= 0) {
2763  if (fISW[4] >= 0) {
2764  lnow = llist;
2765  if (lnow > 4) lnow = 4;
2766  Printf(" **********");
2767  ctemp.Form(" **%5d **%s",fIcomnd,(const char*)fCword);
2768  for (i = 1; i <= lnow; ++i) {
2769  ctemp += TString::Format("%12.4g",plist[i-1]);
2770  }
2771  Printf("%s",(const char*)ctemp);
2772  inonde = 0;
2773  if (llist > lnow) {
2774  kll = llist;
2775  if (llist > fMaxpar) {
2776  inonde = 1;
2777  kll = fMaxpar;
2778  }
2779  Printf(" ***********");
2780  for (i = lnow + 1; i <= kll; ++i) {
2781  Printf("%12.4g",plist[i-1]);
2782  }
2783  }
2784  Printf(" **********");
2785  if (inonde > 0) {
2786  Printf(" ERROR: ABOVE CALL TO MNEXCM TRIED TO PASS MORE THAN %d PARAMETERS.", fMaxpar);
2787  }
2788  }
2789  }
2790  fNfcnmx = Int_t(fWord7[0]);
2791  if (fNfcnmx <= 0) {
2792  fNfcnmx = fNpar*100 + 200 + fNpar*fNpar*5;
2793  }
2794  fEpsi = fWord7[1];
2795  if (fEpsi <= 0) {
2796  fEpsi = fUp*.1;
2797  }
2798  fLnewmn = kFALSE;
2799  fLphead = kTRUE;
2800  fISW[0] = 0;
2801  ierflg = 0;
2802 // look for command in list CNAME
2803  ctemp = fCword(0,3);
2804  for (i = 1; i <= nntot; ++i) {
2805  if (strncmp(ctemp.Data(),cname[i-1],3) == 0) goto L90;
2806  }
2807  Printf("UNKNOWN COMMAND IGNORED:%s", comand.Data());
2808  ierflg = 3;
2809  return;
2810 // normal case: recognized MINUIT command
2811 L90:
2812  if (fCword(0,4) == "MINO") i = 5;
2813  if (i != 6 && i != 7 && i != 8 && i != 23) {
2814  fCfrom = cname[i-1];
2815  fNfcnfr = fNfcn;
2816  }
2817 // 1 2 3 4 5 6 7 8 9 10
2818  switch (i) {
2819  case 1: goto L400;
2820  case 2: goto L200;
2821  case 3: goto L300;
2822  case 4: goto L400;
2823  case 5: goto L500;
2824  case 6: goto L700;
2825  case 7: goto L700;
2826  case 8: goto L800;
2827  case 9: goto L900;
2828  case 10: goto L1000;
2829  case 11: goto L1100;
2830  case 12: goto L1200;
2831  case 13: goto L1300;
2832  case 14: goto L1400;
2833  case 15: goto L1500;
2834  case 16: goto L1600;
2835  case 17: goto L1700;
2836  case 18: goto L1800;
2837  case 19: goto L1900;
2838  case 20: goto L1900;
2839  case 21: goto L1900;
2840  case 22: goto L2200;
2841  case 23: goto L2300;
2842  case 24: goto L2400;
2843  case 25: goto L1900;
2844  case 26: goto L2600;
2845  case 27: goto L3300;
2846  case 28: goto L3300;
2847  case 29: goto L3300;
2848  case 30: goto L3300;
2849  case 31: goto L3300;
2850  case 32: goto L3300;
2851  case 33: goto L3300;
2852  case 34: goto L3400;
2853  case 35: goto L3500;
2854  case 36: goto L3600;
2855  case 37: goto L3700;
2856  case 38: goto L3800;
2857  case 39: goto L3900;
2858  case 40: goto L4000;
2859  }
2860 // seek
2861 L200:
2862  mnseek();
2863  return;
2864 // simplex
2865 L300:
2866  mnsimp();
2867  if (fISW[3] < 1) ierflg = 4;
2868  return;
2869 // migrad, minimize
2870 L400:
2871  nf = fNfcn;
2872  fApsi = fEpsi;
2873  mnmigr();
2874  mnwerr();
2875  if (fISW[3] >= 1) return;
2876  ierflg = 4;
2877  if (fISW[0] == 1) return;
2878  if (fCword(0,3) == "MIG") return;
2879 
2880  fNfcnmx = fNfcnmx + nf - fNfcn;
2881  nf = fNfcn;
2882  mnsimp();
2883  if (fISW[0] == 1) return;
2884  fNfcnmx = fNfcnmx + nf - fNfcn;
2885  mnmigr();
2886  if (fISW[3] >= 1) ierflg = 0;
2887  mnwerr();
2888  return;
2889 // minos
2890 L500:
2891  nsuper = fNfcn + ((fNpar + 1) << 1)*fNfcnmx;
2892 // possible loop over new minima
2893  fEpsi = fUp*.1;
2894 L510:
2895  fCfrom = cname[i-1]; // ensure that mncuve complains about MINOS not MIGRAD
2896  mncuve();
2897  mnmnos();
2898  if (! fLnewmn) return;
2899  mnrset(0);
2900  mnmigr();
2901  mnwerr();
2902  if (fNfcn < nsuper) goto L510;
2903  Printf(" TOO MANY FUNCTION CALLS. MINOS GIVES UP");
2904  ierflg = 4;
2905  return;
2906 // set, show
2907 L700:
2908  mnset();
2909  return;
2910 // top of page
2911 
2912 L800:
2913  Printf("1");
2914  return;
2915 // fix
2916 L900:
2917  ltofix = kTRUE;
2918 // (also release)
2919 L901:
2920  lfreed = kFALSE;
2921  lfixed = kFALSE;
2922  if (llist == 0) {
2923  Printf("%s: NO PARAMETERS REQUESTED ",(const char*)fCword);
2924  return;
2925  }
2926  for (ilist = 1; ilist <= llist; ++ilist) {
2927  iext = Int_t(plist[ilist-1]);
2928  chwhy = " IS UNDEFINED.";
2929  if (iext <= 0) goto L930;
2930  if (iext > fNu) goto L930;
2931  if (fNvarl[iext-1] < 0) goto L930;
2932  chwhy = " IS CONSTANT. ";
2933  if (fNvarl[iext-1] == 0) goto L930;
2934  iint = fNiofex[iext-1];
2935  if (ltofix) {
2936  chwhy = " ALREADY FIXED.";
2937  if (iint == 0) goto L930;
2938  mnfixp(iint-1, ierr);
2939  if (ierr == 0) lfixed = kTRUE;
2940  else ierflg = 4;
2941  } else {
2942  chwhy = " ALREADY VARIABLE.";
2943  if (iint > 0) goto L930;
2944  krl = -abs(iext);
2945  mnfree(krl);
2946  lfreed = kTRUE;
2947  }
2948  continue;
2949 L930:
2950  if (fISW[4] >= 0) Printf(" PARAMETER %4d %s IGNORED.",iext,(const char*)chwhy);
2951  }
2952  if (lfreed || lfixed) mnrset(0);
2953  if (lfreed) {
2954  fISW[1] = 0;
2955  fDcovar = 1;
2956  fEDM = fBigedm;
2957  fISW[3] = 0;
2958  }
2959  mnwerr();
2960  if (fISW[4] > 1) mnprin(5, fAmin);
2961  return;
2962 // restore
2963 L1000:
2964  it = Int_t(fWord7[0]);
2965  if (it > 1 || it < 0) goto L1005;
2966  lfreed = fNpfix > 0;
2967  mnfree(it);
2968  if (lfreed) {
2969  mnrset(0);
2970  fISW[1] = 0;
2971  fDcovar = 1;
2972  fEDM = fBigedm;
2973  }
2974  return;
2975 L1005:
2976  Printf(" IGNORED. UNKNOWN ARGUMENT:%4d",it);
2977  ierflg = 3;
2978  return;
2979 // release
2980 L1100:
2981  ltofix = kFALSE;
2982  goto L901;
2983 // scan
2984 L1200:
2985  iext = Int_t(fWord7[0]);
2986  if (iext <= 0) goto L1210;
2987  it2 = 0;
2988  if (iext <= fNu) it2 = fNiofex[iext-1];
2989  if (it2 <= 0) goto L1250;
2990 
2991 L1210:
2992  mnscan();
2993  return;
2994 L1250:
2995  Printf(" PARAMETER %4d NOT VARIABLE.",iext);
2996  ierflg = 3;
2997  return;
2998 // contour
2999 L1300:
3000  ke1 = Int_t(fWord7[0]);
3001  ke2 = Int_t(fWord7[1]);
3002  if (ke1 == 0) {
3003  if (fNpar == 2) {
3004  ke1 = fNexofi[0];
3005  ke2 = fNexofi[1];
3006  } else {
3007  Printf("%s: NO PARAMETERS REQUESTED ",(const char*)fCword);
3008  ierflg = 3;
3009  return;
3010  }
3011  }
3012  fNfcnmx = 1000;
3013  mncntr(ke1-1, ke2-1, ierrf);
3014  if (ierrf > 0) ierflg = 3;
3015  return;
3016 // hesse
3017 L1400:
3018  mnhess();
3019  mnwerr();
3020  if (fISW[4] >= 0) mnprin(2, fAmin);
3021  if (fISW[4] >= 1) mnmatu(1);
3022  return;
3023 // save
3024 L1500:
3025  mnsave();
3026  return;
3027 // improve
3028 L1600:
3029  mncuve();
3030  mnimpr();
3031  if (fLnewmn) goto L400;
3032  ierflg = 4;
3033  return;
3034 // call fcn
3035 L1700:
3036  iflag = Int_t(fWord7[0]);
3037  nparx = fNpar;
3038  f = fUndefi;
3039  Eval(nparx, fGin, f, fU, iflag); ++fNfcn;
3040  nowprt = 0;
3041  if (f != fUndefi) {
3042  if (fAmin == fUndefi) {
3043  fAmin = f;
3044  nowprt = 1;
3045  } else if (f < fAmin) {
3046  fAmin = f;
3047  nowprt = 1;
3048  }
3049  if (fISW[4] >= 0 && iflag <= 5 && nowprt == 1) {
3050  mnprin(5, fAmin);
3051  }
3052  if (iflag == 3) fFval3 = f;
3053  }
3054  if (iflag > 5) mnrset(1);
3055  return;
3056 // standard
3057 L1800:
3058 // stand();
3059  return;
3060 // return, stop, end, exit
3061 L1900:
3062  it = Int_t(fWord7[0]);
3063  if (fFval3 != fAmin && it == 0) {
3064  iflag = 3;
3065  if (fISW[4] >= 0) Printf(" CALL TO USER FUNCTION WITH IFLAG = 3");
3066  nparx = fNpar;
3067  Eval(nparx, fGin, f, fU, iflag); ++fNfcn;
3068  }
3069  ierflg = 11;
3070  if (fCword(0,3) == "END") ierflg = 10;
3071  if (fCword(0,3) == "RET") ierflg = 12;
3072  return;
3073 // clear
3074 L2200:
3075  mncler();
3076  if (fISW[4] >= 1) {
3077  Printf(" MINUIT MEMORY CLEARED. NO PARAMETERS NOW DEFINED.");
3078  }
3079  return;
3080 // help
3081 L2300:
3082  kcol = 0;
3083  for (icol = 5; icol <= lk; ++icol) {
3084  if (fCword[icol-1] == ' ') continue;
3085  kcol = icol;
3086  goto L2320;
3087  }
3088 L2320:
3089  if (kcol == 0) comd = "* ";
3090  else comd = fCword(kcol-1,lk-kcol+1);
3091  mnhelp(comd);
3092  return;
3093 // MNContour
3094 L2400:
3095  fEpsi = fUp*.05;
3096  ke1 = Int_t(fWord7[0]);
3097  ke2 = Int_t(fWord7[1]);
3098  if (ke1 == 0 && fNpar == 2) {
3099  ke1 = fNexofi[0];
3100  ke2 = fNexofi[1];
3101  }
3102  nptu = Int_t(fWord7[2]);
3103  if (nptu <= 0) nptu = 20;
3104  if (nptu > 101) nptu = 101;
3105  fNfcnmx = (nptu + 5)*100*(fNpar + 1);
3106  mncont(ke1-1, ke2-1, nptu, xptu, yptu, ierrf);
3107  if (ierrf < nptu) ierflg = 4;
3108  if (ierrf == -1) ierflg = 3;
3109  return;
3110 // jump
3111 L2600:
3112  step = fWord7[0];
3113  if (step <= 0) step = 2;
3114  rno = 0;
3115  izero = 0;
3116  for (i = 1; i <= fNpar; ++i) {
3117  mnrn15(rno, izero);
3118  rno = rno*2 - 1;
3119  fX[i-1] += rno*step*fWerr[i-1];
3120  }
3121  mninex(fX);
3122  mnamin();
3123  mnrset(0);
3124  return;
3125 // blank line
3126 L3300:
3127  Printf(" BLANK COMMAND IGNORED.");
3128  ierflg = 1;
3129  return;
3130 // obsolete commands
3131 // covariance
3132 L3400:
3133  Printf(" 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*");
3134  ierflg = 3;
3135  return;
3136 // printout
3137 L3500:
3138  cneway = "SET PRInt ";
3139  goto L3100;
3140 // gradient
3141 L3600:
3142  cneway = "SET GRAd ";
3143  goto L3100;
3144 // matout
3145 L3700:
3146  cneway = "SHOW COVar";
3147  goto L3100;
3148 // error def
3149 L3800:
3150  cneway = "SET ERRdef";
3151  goto L3100;
3152 // limits
3153 L3900:
3154  cneway = "SET LIMits";
3155  goto L3100;
3156 // punch
3157 L4000:
3158  cneway = "SAVE ";
3159 // come from obsolete commands
3160 L3100:
3161  Printf(" OBSOLETE COMMAND:%s PLEASE USE:%s",(const char*)fCword
3162  ,(const char*)cneway);
3163  fCword = cneway;
3164  if (fCword == "SAVE ") goto L1500;
3165  goto L700;
3166 //
3167 }
3168 
3169 ////////////////////////////////////////////////////////////////////////////////
3170 /// Transforms the external parameter values U to internal values
3171 ///
3172 /// Transforms the external parameter values U to internal
3173 /// values in the dense array PINT.
3174 
3176 {
3177  Double_t pinti;
3178  Int_t iint, iext;
3179 
3180  fLimset = kFALSE;
3181  for (iint = 1; iint <= fNpar; ++iint) {
3182  iext = fNexofi[iint-1];
3183  mnpint(fU[iext-1], iext-1, pinti);
3184  pint[iint-1] = pinti;
3185  }
3186 }
3187 
3188 ////////////////////////////////////////////////////////////////////////////////
3189 /// Removes parameter IINT from the internal parameter list
3190 ///
3191 /// and arranges the rest of the list to fill the hole.
3192 
3193 void TMinuit::mnfixp(Int_t iint1, Int_t &ierr)
3194 {
3195  /* Local variables */
3196  Double_t yyover;
3197  Int_t kold, nold, ndex, knew, iext, i, j, m, n, lc, ik;
3198 
3199 // first see if it can be done
3200  ierr = 0;
3201  Int_t iint = iint1+1;
3202  if (iint > fNpar || iint <= 0) {
3203  ierr = 1;
3204  Printf(" MINUIT ERROR. ARGUMENT TO MNFIXP=%4d",iint);
3205  return;
3206  }
3207  iext = fNexofi[iint-1];
3208  if (fNpfix >= fMaxpar) {
3209  ierr = 1;
3210  Printf(" MINUIT CANNOT FIX PARAMETER %4d MAXIMUM NUMBER THAT CAN BE FIXED IS %d",iext,fMaxpar);
3211  return;
3212  }
3213 // reduce number of variable parameters by one
3214 
3215  fNiofex[iext-1] = 0;
3216  nold = fNpar;
3217  --fNpar;
3218 // save values in case parameter is later restored
3219 
3220  ++fNpfix;
3221  fIpfix[fNpfix-1] = iext;
3222  lc = iint;
3223  fXs[fNpfix-1] = fX[lc-1];
3224  fXts[fNpfix-1] = fXt[lc-1];
3225  fDirins[fNpfix-1] = fWerr[lc-1];
3226  fGrds[fNpfix-1] = fGrd[lc-1];
3227  fG2s[fNpfix-1] = fG2[lc-1];
3228  fGsteps[fNpfix-1] = fGstep[lc-1];
3229 // shift values for other parameters to fill hole
3230  for (ik = iext + 1; ik <= fNu; ++ik) {
3231  if (fNiofex[ik-1] > 0) {
3232  lc = fNiofex[ik-1] - 1;
3233  fNiofex[ik-1] = lc;
3234  fNexofi[lc-1] = ik;
3235  fX[lc-1] = fX[lc];
3236  fXt[lc-1] = fXt[lc];
3237  fDirin[lc-1] = fDirin[lc];
3238  fWerr[lc-1] = fWerr[lc];
3239  fGrd[lc-1] = fGrd[lc];
3240  fG2[lc-1] = fG2[lc];
3241  fGstep[lc-1] = fGstep[lc];
3242  }
3243  }
3244  if (fISW[1] <= 0) return;
3245 // remove one row and one column from variance matrix
3246  if (fNpar <= 0) return;
3247  for (i = 1; i <= nold; ++i) {
3248  m = TMath::Max(i,iint);
3249  n = TMath::Min(i,iint);
3250  ndex = m*(m-1) / 2 + n;
3251  fFIXPyy[i-1] = fVhmat[ndex-1];
3252  }
3253  yyover = 1 / fFIXPyy[iint-1];
3254  knew = 0;
3255  kold = 0;
3256  for (i = 1; i <= nold; ++i) {
3257  for (j = 1; j <= i; ++j) {
3258  ++kold;
3259  if (j == iint || i == iint) continue;
3260  ++knew;
3261  fVhmat[knew-1] = fVhmat[kold-1] - fFIXPyy[j-1]*fFIXPyy[i-1]*yyover;
3262  }
3263  }
3264 }
3265 
3266 ////////////////////////////////////////////////////////////////////////////////
3267 /// Restores one or more fixed parameter(s) to variable status
3268 ///
3269 /// Restores one or more fixed parameter(s) to variable status
3270 /// by inserting it into the internal parameter list at the
3271 /// appropriate place.
3272 ///
3273 /// - K = 0 means restore all parameters
3274 /// - K = 1 means restore the last parameter fixed
3275 /// - K = -I means restore external parameter I (if possible)
3276 /// - IQ = fix-location where internal parameters were stored
3277 /// - IR = external number of parameter being restored
3278 /// - IS = internal number of parameter being restored
3279 
3281 {
3282  /* Local variables */
3283  Double_t grdv, xv, dirinv, g2v, gstepv, xtv;
3284  Int_t i, ipsav, ka, lc, ik, iq, ir, is;
3285 
3286  if (k > 1) {
3287  Printf(" CALL TO MNFREE IGNORED. ARGUMENT GREATER THAN ONE");
3288  }
3289  if (fNpfix < 1) {
3290  Printf(" CALL TO MNFREE IGNORED. THERE ARE NO FIXED PARAMETERS");
3291  }
3292  if (k == 1 || k == 0) goto L40;
3293 
3294 // release parameter with specified external number
3295  ka = abs(k);
3296  if (fNiofex[ka-1] == 0) goto L15;
3297  Printf(" IGNORED. PARAMETER SPECIFIED IS ALREADY VARIABLE.");
3298  return;
3299 L15:
3300  if (fNpfix < 1) goto L21;
3301  for (ik = 1; ik <= fNpfix; ++ik) { if (fIpfix[ik-1] == ka) goto L24; }
3302 L21:
3303  Printf(" PARAMETER %4d NOT FIXED. CANNOT BE RELEASED.",ka);
3304  return;
3305 L24:
3306  if (ik == fNpfix) goto L40;
3307 
3308 // move specified parameter to end of list
3309  ipsav = ka;
3310  xv = fXs[ik-1];
3311  xtv = fXts[ik-1];
3312  dirinv = fDirins[ik-1];
3313  grdv = fGrds[ik-1];
3314  g2v = fG2s[ik-1];
3315  gstepv = fGsteps[ik-1];
3316  for (i = ik + 1; i <= fNpfix; ++i) {
3317  fIpfix[i-2] = fIpfix[i-1];
3318  fXs[i-2] = fXs[i-1];
3319  fXts[i-2] = fXts[i-1];
3320  fDirins[i-2] = fDirins[i-1];
3321  fGrds[i-2] = fGrds[i-1];
3322  fG2s[i-2] = fG2s[i-1];
3323  fGsteps[i-2] = fGsteps[i-1];
3324  }
3325  fIpfix[fNpfix-1] = ipsav;
3326  fXs[fNpfix-1] = xv;
3327  fXts[fNpfix-1] = xtv;
3328  fDirins[fNpfix-1] = dirinv;
3329  fGrds[fNpfix-1] = grdv;
3330  fG2s[fNpfix-1] = g2v;
3331  fGsteps[fNpfix-1] = gstepv;
3332 // restore last parameter in fixed list -- IPFIX(NPFIX)
3333 L40:
3334  if (fNpfix < 1) goto L300;
3335  ir = fIpfix[fNpfix-1];
3336  is = 0;
3337  for (ik = fNu; ik >= ir; --ik) {
3338  if (fNiofex[ik-1] > 0) {
3339  lc = fNiofex[ik-1] + 1;
3340  is = lc - 1;
3341  fNiofex[ik-1] = lc;
3342  fNexofi[lc-1] = ik;
3343  fX[lc-1] = fX[lc-2];
3344  fXt[lc-1] = fXt[lc-2];
3345  fDirin[lc-1] = fDirin[lc-2];
3346  fWerr[lc-1] = fWerr[lc-2];
3347  fGrd[lc-1] = fGrd[lc-2];
3348  fG2[lc-1] = fG2[lc-2];
3349  fGstep[lc-1] = fGstep[lc-2];
3350  }
3351  }
3352  ++fNpar;
3353  if (is == 0) is = fNpar;
3354  fNiofex[ir-1] = is;
3355  fNexofi[is-1] = ir;
3356  iq = fNpfix;
3357  fX[is-1] = fXs[iq-1];
3358  fXt[is-1] = fXts[iq-1];
3359  fDirin[is-1] = fDirins[iq-1];
3360  fWerr[is-1] = fDirins[iq-1];
3361  fGrd[is-1] = fGrds[iq-1];
3362  fG2[is-1] = fG2s[iq-1];
3363  fGstep[is-1] = fGsteps[iq-1];
3364  --fNpfix;
3365  fISW[1] = 0;
3366  fDcovar = 1;
3367  if (fISW[4] - fItaur >= 1) {
3368  Printf(" PARAMETER %4d %s RESTORED TO VARIABLE.",ir,
3369  (const char*)fCpnam[ir-1]);
3370  }
3371  if (k == 0) goto L40;
3372 L300:
3373 // if different from internal, external values are taken
3374  mnexin(fX);
3375 }
3376 
3377 ////////////////////////////////////////////////////////////////////////////////
3378 /// Interprets the SET GRAD command
3379 ///
3380 /// - Called from MNSET
3381 /// - Interprets the SET GRAD command, which informs MINUIT whether
3382 /// - the first derivatives of FCN will be calculated by the user
3383 /// - inside FCN. It can check the user derivative calculation
3384 /// - by comparing it with a finite difference approximation.
3385 
3387 {
3388  /* Local variables */
3389  Double_t fzero, err;
3390  Int_t i, nparx, lc, istsav;
3391  Bool_t lnone;
3392 
3393  fISW[2] = 1;
3394  nparx = fNpar;
3395  if (fWord7[0] > 0) goto L2000;
3396 
3397 // get user-calculated first derivatives from FCN
3398  for (i = 1; i <= fNu; ++i) { fGin[i-1] = fUndefi; }
3399  mninex(fX);
3400  Eval(nparx, fGin, fzero, fU, 2); ++fNfcn;
3401  mnderi();
3402  for (i = 1; i <= fNpar; ++i) { fGRADgf[i-1] = fGrd[i-1]; }
3403 // get MINUIT-calculated first derivatives
3404  fISW[2] = 0;
3405  istsav = fIstrat;
3406  fIstrat = 2;
3407  mnhes1();
3408  fIstrat = istsav;
3409  Printf(" CHECK OF GRADIENT CALCULATION IN FCN");
3410  Printf(" PARAMETER G(IN FCN) G(MINUIT) DG(MINUIT) AGREEMENT");
3411  fISW[2] = 1;
3412  lnone = kFALSE;
3413  for (lc = 1; lc <= fNpar; ++lc) {
3414  i = fNexofi[lc-1];
3415  const char *cwd = "GOOD";
3416  err = fDgrd[lc-1];
3417  if (TMath::Abs(fGRADgf[lc-1] - fGrd[lc-1]) > err) {
3418  cwd = " BAD";
3419  fISW[2] = 0;
3420  }
3421  if (fGin[i-1] == fUndefi) {
3422  cwd = "NONE";
3423  lnone = kTRUE;
3424  fGRADgf[lc-1] = 0;
3425  fISW[2] = 0;
3426  }
3427  Printf(" %5d %10s%12.4e%12.4e%12.4e %s",i
3428  ,(const char*)fCpnam[i-1]
3429  ,fGRADgf[lc-1],fGrd[lc-1],err,cwd);
3430  }
3431  if (lnone) {
3432  Printf(" AGREEMENT=NONE MEANS FCN DID NOT CALCULATE THE DERIVATIVE");
3433  }
3434  if (fISW[2] == 0) {
3435  Printf(" MINUIT DOES NOT ACCEPT DERIVATIVE CALCULATIONS BY FCN");
3436  Printf(" TO FORCE ACCEPTANCE, ENTER *SET GRAD 1*");
3437  }
3438 
3439 L2000:
3440  return;
3441 }
3442 
3443 ////////////////////////////////////////////////////////////////////////////////
3444 /// interface to Minuit help
3445 
3446 void TMinuit::mnhelp(const char *command)
3447 {
3448  TString comd = command;
3449  mnhelp(comd);
3450 }
3451 
3452 ////////////////////////////////////////////////////////////////////////////////
3453 /// HELP routine for MINUIT interactive commands
3454 ///
3455 /// - COMD ='*' or "" prints a global help for all commands
3456 /// - COMD =Command_name: print detailed help for one command.
3457 /// Note that at least 3 characters must be given for the command
3458 /// name.
3459 ///
3460 /// Author: Rene Brun
3461 /// comments extracted from the MINUIT documentation file.
3462 
3464 {
3465 //______________________________________________________________________________
3466 //
3467 // Global HELP: Summary of all commands
3468 //
3469  comd.ToUpper();
3470  if( comd.Length() == 0 || comd[0] == '*' || comd[0] == '?' || comd[0] == 0 || comd=="HELP" ) {
3471  Printf(" ==>List of MINUIT Interactive commands:");
3472  Printf(" CLEar Reset all parameter names and values undefined");
3473  Printf(" CONtour Make contour map of the user function");
3474  Printf(" EXIT Exit from Interactive Minuit");
3475  Printf(" FIX Cause parameter(s) to remain constant");
3476  Printf(" HESse Calculate the Hessian or error matrix.");
3477  Printf(" IMPROVE Search for a new minimum around current minimum");
3478  Printf(" MIGrad Minimize by the method of Migrad");
3479  Printf(" MINImize MIGRAD + SIMPLEX method if Migrad fails");
3480  Printf(" MINOs Exact (non-linear) parameter error analysis");
3481  Printf(" MNContour Calculate one MINOS function contour");
3482  Printf(" PARameter Define or redefine new parameters and values");
3483  Printf(" RELease Make previously FIXed parameters variable again");
3484  Printf(" REStore Release last parameter fixed");
3485  Printf(" SAVe Save current parameter values on a file");
3486  Printf(" SCAn Scan the user function by varying parameters");
3487  Printf(" SEEk Minimize by the method of Monte Carlo");
3488  Printf(" SET Set various MINUIT constants or conditions");
3489  Printf(" SHOw Show values of current constants or conditions");
3490  Printf(" SIMplex Minimize by the method of Simplex");
3491  goto L99;
3492  }
3493 
3494 //______________________________________________________________________________
3495 //
3496 // Command CLEAR
3497 //
3498  if( !strncmp(comd.Data(),"CLE",3) ) {
3499  Printf(" ***>CLEAR");
3500  Printf(" Resets all parameter names and values to undefined.");
3501  Printf(" Must normally be followed by a PARameters command or ");
3502  Printf(" equivalent, in order to define parameter values.");
3503  goto L99;
3504  }
3505 //______________________________________________________________________________
3506 //
3507 // Command CONTOUR
3508 //
3509  if( !strncmp(comd.Data(),"CON",3) ) {
3510  Printf(" ***>CONTOUR <par1> <par2> [devs] [ngrid]");
3511  Printf(" Instructs Minuit to trace contour lines of the user function");
3512  Printf(" with respect to the two parameters whose external numbers");
3513  Printf(" are <par1> and <par2>.");
3514  Printf(" Other variable parameters of the function, if any, will have");
3515  Printf(" their values fixed at the current values during the contour");
3516  Printf(" tracing. The optional parameter [devs] (default value 2.)");
3517  Printf(" gives the number of standard deviations in each parameter");
3518  Printf(" which should lie entirely within the plotting area.");
3519  Printf(" Optional parameter [ngrid] (default value 25 unless page");
3520  Printf(" size is too small) determines the resolution of the plot,");
3521  Printf(" i.e. the number of rows and columns of the grid at which the");
3522  Printf(" function will be evaluated. [See also MNContour.]");
3523  goto L99;
3524  }
3525 //______________________________________________________________________________
3526 //
3527 // Command END
3528 //
3529  if( !strncmp(comd.Data(),"END",3) ) {
3530  Printf(" ***>END");
3531  Printf(" Signals the end of a data block (i.e., the end of a fit),");
3532  Printf(" and implies that execution should continue, because another");
3533  Printf(" Data Block follows. A Data Block is a set of Minuit data");
3534  Printf(" consisting of");
3535  Printf(" (1) A Title,");
3536  Printf(" (2) One or more Parameter Definitions,");
3537  Printf(" (3) A blank line, and");
3538  Printf(" (4) A set of Minuit Commands.");
3539  Printf(" The END command is used when more than one Data Block is to");
3540  Printf(" be used with the same FCN function. It first causes Minuit");
3541  Printf(" to issue a CALL FCN with IFLAG=3, in order to allow FCN to");
3542  Printf(" perform any calculations associated with the final fitted");
3543  Printf(" parameter values, unless a CALL FCN 3 command has already");
3544  Printf(" been executed at the current FCN value.");
3545  goto L99;
3546  }
3547 //______________________________________________________________________________
3548 //
3549 // Command EXIT
3550 //
3551  if( !strncmp(comd.Data(),"EXI",3) ) {
3552  Printf(" ***>EXIT");
3553  Printf(" Signals the end of execution.");
3554  Printf(" The EXIT command first causes Minuit to issue a CALL FCN");
3555  Printf(" with IFLAG=3, to allow FCN to perform any calculations");
3556  Printf(" associated with the final fitted parameter values, unless a");
3557  Printf(" CALL FCN 3 command has already been executed.");
3558  goto L99;
3559  }
3560 //______________________________________________________________________________
3561 //
3562 // Command FIX
3563 //
3564  if( !strncmp(comd.Data(),"FIX",3) ) {
3565  Printf(" ***>FIX} <parno> [parno] ... [parno]");
3566  Printf(" Causes parameter(s) <parno> to be removed from the list of");
3567  Printf(" variable parameters, and their value(s) will remain constant");
3568  Printf(" during subsequent minimizations, etc., until another command");
3569  Printf(" changes their value(s) or status.");
3570  goto L99;
3571  }
3572 //______________________________________________________________________________
3573 //
3574 // Command HESSE
3575 //
3576  if( !strncmp(comd.Data(),"HES",3) ) {
3577  Printf(" ***>HESse [maxcalls]");
3578  Printf(" Calculate, by finite differences, the Hessian or error matrix.");
3579  Printf(" That is, it calculates the full matrix of second derivatives");
3580  Printf(" of the function with respect to the currently variable");
3581  Printf(" parameters, and inverts it, printing out the resulting error");
3582  Printf(" matrix. The optional argument [maxcalls] specifies the");
3583  Printf(" (approximate) maximum number of function calls after which");
3584  Printf(" the calculation will be stopped.");
3585  goto L99;
3586  }
3587 //______________________________________________________________________________
3588 //
3589 // Command IMPROVE
3590 //
3591  if( !strncmp(comd.Data(),"IMP",3) ) {
3592  Printf(" ***>IMPROVE [maxcalls]");
3593  Printf(" If a previous minimization has converged, and the current");
3594  Printf(" values of the parameters therefore correspond to a local");
3595  Printf(" minimum of the function, this command requests a search for");
3596  Printf(" additional distinct local minima.");
3597  Printf(" The optional argument [maxcalls] specifies the (approximate");
3598  Printf(" maximum number of function calls after which the calculation");
3599  Printf(" will be stopped.");
3600  goto L99;
3601  }
3602 //______________________________________________________________________________
3603 //
3604 // Command MIGRAD
3605 //
3606  if( !strncmp(comd.Data(),"MIG",3) ) {
3607  Printf(" ***>MIGrad [maxcalls] [tolerance]");
3608  Printf(" Causes minimization of the function by the method of Migrad,");
3609  Printf(" the most efficient and complete single method, recommended");
3610  Printf(" for general functions (see also MINImize).");
3611  Printf(" The minimization produces as a by-product the error matrix");
3612  Printf(" of the parameters, which is usually reliable unless warning");
3613  Printf(" messages are produced.");
3614  Printf(" The optional argument [maxcalls] specifies the (approximate)");
3615  Printf(" maximum number of function calls after which the calculation");
3616  Printf(" will be stopped even if it has not yet converged.");
3617  Printf(" The optional argument [tolerance] specifies required tolerance");
3618  Printf(" on the function value at the minimum.");
3619  Printf(" The default tolerance is 0.1, and the minimization will stop");
3620  Printf(" when the estimated vertical distance to the minimum (EDM) is");
3621  Printf(" less than 0.001*[tolerance]*UP (see [SET ERRordef]).");
3622  goto L99;
3623  }
3624 //______________________________________________________________________________
3625 //
3626 // Command MINIMIZE
3627 //
3628  if( !strncmp(comd.Data(),"MINI",4) ) {
3629  Printf(" ***>MINImize [maxcalls] [tolerance]");
3630  Printf(" Causes minimization of the function by the method of Migrad,");
3631  Printf(" as does the MIGrad command, but switches to the SIMplex method");
3632  Printf(" if Migrad fails to converge. Arguments are as for MIGrad.");
3633  Printf(" Note that command requires four characters to be unambiguous.");
3634  goto L99;
3635  }
3636 //______________________________________________________________________________
3637 //
3638 // Command MINOS
3639 //
3640  if( !strncmp(comd.Data(),"MIN0",4) ) {
3641  Printf(" ***>MINOs [maxcalls] [parno] [parno] ...");
3642  Printf(" Causes a Minos error analysis to be performed on the parameters");
3643  Printf(" whose numbers [parno] are specified. If none are specified,");
3644  Printf(" Minos errors are calculated for all variable parameters.");
3645  Printf(" Minos errors may be expensive to calculate, but are very");
3646  Printf(" reliable since they take account of non-linearities in the");
3647  Printf(" problem as well as parameter correlations, and are in general");
3648  Printf(" asymmetric.");
3649  Printf(" The optional argument [maxcalls] specifies the (approximate)");
3650  Printf(" maximum number of function calls per parameter requested,");
3651  Printf(" after which the calculation will stop for that parameter.");
3652  goto L99;
3653  }
3654 //______________________________________________________________________________
3655 //
3656 // Command MNCONTOUR
3657 //
3658  if( !strncmp(comd.Data(),"MNC",3) ) {
3659  Printf(" ***>MNContour <par1> <par2> [npts]");
3660  Printf(" Calculates one function contour of FCN with respect to");
3661  Printf(" parameters par1 and par2, with FCN minimized always with");
3662  Printf(" respect to all other NPAR-2 variable parameters (if any).");
3663  Printf(" Minuit will try to find npts points on the contour (default 20)");
3664  Printf(" If only two parameters are variable at the time, it is not");
3665  Printf(" necessary to specify their numbers. To calculate more than");
3666  Printf(" one contour, it is necessary to SET ERRordef to the appropriate");
3667  Printf(" value and issue the MNContour command for each contour.");
3668  goto L99;
3669  }
3670 //______________________________________________________________________________
3671 //
3672 // Command PARAMETER
3673 //
3674  if( !strncmp(comd.Data(),"PAR",3) ) {
3675  Printf(" ***>PARameters");
3676  Printf(" followed by one or more parameter definitions.");
3677  Printf(" Parameter definitions are of the form:");
3678  Printf(" <number> ''name'' <value> <step> [lolim] [uplim] ");
3679  Printf(" for example:");
3680  Printf(" 3 ''K width'' 1.2 0.1");
3681  Printf(" the last definition is followed by a blank line or a zero.");
3682  goto L99;
3683  }
3684 //______________________________________________________________________________
3685 //
3686 // Command RELEASE
3687 //
3688  if( !strncmp(comd.Data(),"REL",3) ) {
3689  Printf(" ***>RELease <parno> [parno] ... [parno]");
3690  Printf(" If <parno> is the number of a previously variable parameter");
3691  Printf(" which has been fixed by a command: FIX <parno>, then that");
3692  Printf(" parameter will return to variable status. Otherwise a warning");
3693  Printf(" message is printed and the command is ignored.");
3694  Printf(" Note that this command operates only on parameters which were");
3695  Printf(" at one time variable and have been FIXed. It cannot make");
3696  Printf(" constant parameters variable; that must be done by redefining");
3697  Printf(" the parameter with a PARameters command.");
3698  goto L99;
3699  }
3700 //______________________________________________________________________________
3701 //
3702 // Command RESTORE
3703 //
3704  if( !strncmp(comd.Data(),"RES",3) ) {
3705  Printf(" ***>REStore [code]");
3706  Printf(" If no [code] is specified, this command restores all previously");
3707  Printf(" FIXed parameters to variable status. If [code]=1, then only");
3708  Printf(" the last parameter FIXed is restored to variable status.");
3709  Printf(" If code is neither zero nor one, the command is ignored.");
3710  goto L99;
3711  }
3712 //______________________________________________________________________________
3713 //
3714 // Command RETURN
3715 //
3716  if( !strncmp(comd.Data(),"RET",3) ) {
3717  Printf(" ***>RETURN");
3718  Printf(" Signals the end of a data block, and instructs Minuit to return");
3719  Printf(" to the program which called it. The RETurn command first");
3720  Printf(" causes Minuit to CALL FCN with IFLAG=3, in order to allow FCN");
3721  Printf(" to perform any calculations associated with the final fitted");
3722  Printf(" parameter values, unless a CALL FCN 3 command has already been");
3723  Printf(" executed at the current FCN value.");
3724  goto L99;
3725  }
3726 //______________________________________________________________________________
3727 //
3728 // Command SAVE
3729 //
3730  if( !strncmp(comd.Data(),"SAV",3) ) {
3731  Printf(" ***>SAVe");
3732  Printf(" Causes the current parameter values to be saved on a file in");
3733  Printf(" such a format that they can be read in again as Minuit");
3734  Printf(" parameter definitions. If the covariance matrix exists, it is");
3735  Printf(" also output in such a format. The unit number is by default 7,");
3736  Printf(" or that specified by the user in their call to MINTIO or");
3737  Printf(" MNINIT. The user is responsible for opening the file previous");
3738  Printf(" to issuing the [SAVe] command (except where this can be done");
3739  Printf(" interactively).");
3740  goto L99;
3741  }
3742 //______________________________________________________________________________
3743 //
3744 // Command SCAN
3745 //
3746  if( !strncmp(comd.Data(),"SCA",3) ) {
3747  Printf(" ***>SCAn [parno] [numpts] [from] [to]");
3748  Printf(" Scans the value of the user function by varying parameter");
3749  Printf(" number [parno], leaving all other parameters fixed at the");
3750  Printf(" current value. If [parno] is not specified, all variable");
3751  Printf(" parameters are scanned in sequence.");
3752  Printf(" The number of points [numpts] in the scan is 40 by default,");
3753  Printf(" and cannot exceed 100. The range of the scan is by default");
3754  Printf(" 2 standard deviations on each side of the current best value,");
3755  Printf(" but can be specified as from [from] to [to].");
3756  Printf(" After each scan, if a new minimum is found, the best parameter");
3757  Printf(" values are retained as start values for future scans or");
3758  Printf(" minimizations. The curve resulting from each scan is plotted");
3759  Printf(" on the output unit in order to show the approximate behaviour");
3760  Printf(" of the function.");
3761  Printf(" This command is not intended for minimization, but is sometimes");
3762  Printf(" useful for debugging the user function or finding a");
3763  Printf(" reasonable starting point.");
3764  goto L99;
3765  }
3766 //______________________________________________________________________________
3767 //
3768 // Command SEEK
3769 //
3770  if( !strncmp(comd.Data(),"SEE",3) ) {
3771  Printf(" ***>SEEk [maxcalls] [devs]");
3772  Printf(" Causes a Monte Carlo minimization of the function, by choosing");
3773  Printf(" random values of the variable parameters, chosen uniformly");
3774  Printf(" over a hypercube centered at the current best value.");
3775  Printf(" The region size is by default 3 standard deviations on each");
3776  Printf(" side, but can be changed by specifying the value of [devs].");
3777  goto L99;
3778  }
3779 //______________________________________________________________________________
3780 //
3781 // Command SET
3782 //
3783  if( !strncmp(comd.Data(),"SET",3) ) {
3784  Printf(" ***>SET <option_name>");
3785  Printf(" SET BATch");
3786  Printf(" Informs Minuit that it is running in batch mode.");
3787 
3788  Printf(" ");
3789  Printf(" SET EPSmachine <accuracy>");
3790  Printf(" Informs Minuit that the relative floating point arithmetic");
3791  Printf(" precision is <accuracy>. Minuit determines the nominal");
3792  Printf(" precision itself, but the SET EPSmachine command can be");
3793  Printf(" used to override Minuit own determination, when the user");
3794  Printf(" knows that the FCN function value is not calculated to");
3795  Printf(" the nominal machine accuracy. Typical values of <accuracy>");
3796  Printf(" are between 10**-5 and 10**-14.");
3797 
3798  Printf(" ");
3799  Printf(" SET ERRordef <up>");
3800  Printf(" Sets the value of UP (default value= 1.), defining parameter");
3801  Printf(" errors. Minuit defines parameter errors as the change");
3802  Printf(" in parameter value required to change the function value");
3803  Printf(" by UP. Normally, for chisquared fits UP=1, and for negative");
3804  Printf(" log likelihood, UP=0.5.");
3805 
3806  Printf(" ");
3807  Printf(" SET GRAdient [force]");
3808  Printf(" Informs Minuit that the user function is prepared to");
3809  Printf(" calculate its own first derivatives and return their values");
3810  Printf(" in the array GRAD when IFLAG=2 (see specs of FCN).");
3811  Printf(" If [force] is not specified, Minuit will calculate");
3812  Printf(" the FCN derivatives by finite differences at the current");
3813  Printf(" point and compare with the user calculation at that point,");
3814  Printf(" accepting the user values only if they agree.");
3815  Printf(" If [force]=1, Minuit does not do its own derivative");
3816  Printf(" calculation, and uses the derivatives calculated in FCN.");
3817 
3818  Printf(" ");
3819  Printf(" SET INPut [unitno] [filename]");
3820  Printf(" Causes Minuit, in data-driven mode only, to read subsequent");
3821  Printf(" commands (or parameter definitions) from a different input");
3822  Printf(" file. If no [unitno] is specified, reading reverts to the");
3823  Printf(" previous input file, assuming that there was one.");
3824  Printf(" If [unitno] is specified, and that unit has not been opened,");
3825  Printf(" then Minuit attempts to open the file [filename]} if a");
3826  Printf(" name is specified. If running in interactive mode and");
3827  Printf(" [filename] is not specified and [unitno] is not opened,");
3828  Printf(" Minuit prompts the user to enter a file name.");
3829  Printf(" If the word REWIND is added to the command (note:no blanks");
3830  Printf(" between INPUT and REWIND), the file is rewound before");
3831  Printf(" reading. Note that this command is implemented in standard");
3832  Printf(" Fortran 77 and the results may depend on the system;");
3833  Printf(" for example, if a filename is given under VM/CMS, it must");
3834  Printf(" be preceded by a slash.");
3835 
3836  Printf(" ");
3837  Printf(" SET INTeractive");
3838  Printf(" Informs Minuit that it is running interactively.");
3839 
3840  Printf(" ");
3841  Printf(" SET LIMits [parno] [lolim] [uplim]");
3842  Printf(" Allows the user to change the limits on one or all");
3843  Printf(" parameters. If no arguments are specified, all limits are");
3844  Printf(" removed from all parameters. If [parno] alone is specified,");
3845  Printf(" limits are removed from parameter [parno].");
3846  Printf(" If all arguments are specified, then parameter [parno] will");
3847  Printf(" be bounded between [lolim] and [uplim].");
3848  Printf(" Limits can be specified in either order, Minuit will take");
3849  Printf(" the smaller as [lolim] and the larger as [uplim].");
3850  Printf(" However, if [lolim] is equal to [uplim], an error condition");
3851  Printf(" results.");
3852 
3853  Printf(" ");
3854  Printf(" SET LINesperpage");
3855  Printf(" Sets the number of lines for one page of output.");
3856  Printf(" Default value is 24 for interactive mode");
3857 
3858  Printf(" ");
3859  Printf(" SET NOGradient");
3860  Printf(" The inverse of SET GRAdient, instructs Minuit not to");
3861  Printf(" use the first derivatives calculated by the user in FCN.");
3862 
3863  Printf(" ");
3864  Printf(" SET NOWarnings");
3865  Printf(" Supresses Minuit warning messages.");
3866 
3867  Printf(" ");
3868  Printf(" SET OUTputfile <unitno>");
3869  Printf(" Instructs Minuit to write further output to unit <unitno>.");
3870 
3871  Printf(" ");
3872  Printf(" SET PAGethrow <integer>");
3873  Printf(" Sets the carriage control character for ``new page'' to");
3874  Printf(" <integer>. Thus the value 1 produces a new page, and 0");
3875  Printf(" produces a blank line, on some devices (see TOPofpage)");
3876 
3877 
3878  Printf(" ");
3879  Printf(" SET PARameter <parno> <value>");
3880  Printf(" Sets the value of parameter <parno> to <value>.");
3881  Printf(" The parameter in question may be variable, fixed, or");
3882  Printf(" constant, but must be defined.");
3883 
3884  Printf(" ");
3885  Printf(" SET PRIntout <level>");
3886  Printf(" Sets the print level, determining how much output will be");
3887  Printf(" produced. Allowed values and their meanings are displayed");
3888  Printf(" after a SHOw PRInt command, and are currently <level>=:");
3889  Printf(" [-1] no output except from SHOW commands");
3890  Printf(" [0] minimum output");
3891  Printf(" [1] default value, normal output");
3892  Printf(" [2] additional output giving intermediate results.");
3893  Printf(" [3] maximum output, showing progress of minimizations.");
3894  Printf(" Note: See also the SET WARnings command.");
3895 
3896  Printf(" ");
3897  Printf(" SET RANdomgenerator <seed>");
3898  Printf(" Sets the seed of the random number generator used in SEEk.");
3899  Printf(" This can be any integer between 10000 and 900000000, for");
3900  Printf(" example one which was output from a SHOw RANdom command of");
3901  Printf(" a previous run.");
3902 
3903  Printf(" ");
3904  Printf(" SET STRategy <level>");
3905  Printf(" Sets the strategy to be used in calculating first and second");
3906  Printf(" derivatives and in certain minimization methods.");
3907  Printf(" In general, low values of <level> mean fewer function calls");
3908  Printf(" and high values mean more reliable minimization.");
3909  Printf(" Currently allowed values are 0, 1 (default), and 2.");
3910 
3911  Printf(" ");
3912  Printf(" SET TITle");
3913  Printf(" Informs Minuit that the next input line is to be considered");
3914  Printf(" the (new) title for this task or sub-task. This is for");
3915  Printf(" the convenience of the user in reading their output.");
3916 
3917  Printf(" ");
3918  Printf(" SET WARnings");
3919  Printf(" Instructs Minuit to output warning messages when suspicious");
3920  Printf(" conditions arise which may indicate unreliable results.");
3921  Printf(" This is the default.");
3922 
3923  Printf(" ");
3924  Printf(" SET WIDthpage");
3925  Printf(" Informs Minuit of the output page width.");
3926  Printf(" Default values are 80 for interactive jobs");
3927  goto L99;
3928  }
3929 //______________________________________________________________________________
3930 //
3931 // Command SHOW
3932 //
3933  if( !strncmp(comd.Data(),"SHO",3) ) {
3934  Printf(" ***>SHOw <option_name>");
3935  Printf(" All SET XXXX commands have a corresponding SHOw XXXX command.");
3936  Printf(" In addition, the SHOw commands listed starting here have no");
3937  Printf(" corresponding SET command for obvious reasons.");
3938 
3939  Printf(" ");
3940  Printf(" SHOw CORrelations");
3941  Printf(" Calculates and prints the parameter correlations from the");
3942  Printf(" error matrix.");
3943 
3944  Printf(" ");
3945  Printf(" SHOw COVariance");
3946  Printf(" Prints the (external) covariance (error) matrix.");
3947 
3948  Printf(" ");
3949  Printf(" SHOw EIGenvalues");
3950  Printf(" Calculates and prints the eigenvalues of the covariance");
3951  Printf(" matrix.");
3952 
3953  Printf(" ");
3954  Printf(" SHOw FCNvalue");
3955  Printf(" Prints the current value of FCN.");
3956  goto L99;
3957  }
3958 //______________________________________________________________________________
3959 //
3960 // Command SIMPLEX
3961 //
3962  if( !strncmp(comd.Data(),"SIM",3) ) {
3963  Printf(" ***>SIMplex [maxcalls] [tolerance]");
3964  Printf(" Performs a function minimization using the simplex method of");
3965  Printf(" Nelder and Mead. Minimization terminates either when the");
3966  Printf(" function has been called (approximately) [maxcalls] times,");
3967  Printf(" or when the estimated vertical distance to minimum (EDM) is");
3968  Printf(" less than [tolerance].");
3969  Printf(" The default value of [tolerance] is 0.1*UP(see SET ERRordef).");
3970  goto L99;
3971  }
3972 //______________________________________________________________________________
3973 //
3974 // Command STANDARD
3975 //
3976  if( !strncmp(comd.Data(),"STA",3) ) {
3977  Printf(" ***>STAndard");
3978  goto L99;
3979  }
3980 //______________________________________________________________________________
3981 //
3982 // Command STOP
3983 //
3984  if( !strncmp(comd.Data(),"STO",3) ) {
3985  Printf(" ***>STOP");
3986  Printf(" Same as EXIT.");
3987  goto L99;
3988  }
3989 //______________________________________________________________________________
3990 //
3991 // Command TOPOFPAGE
3992 //
3993  if( !strncmp(comd.Data(),"TOP",3) ) {
3994  Printf(" ***>TOPofpage");
3995  Printf(" Causes Minuit to write the character specified in a");
3996  Printf(" SET PAGethrow command (default = 1) to column 1 of the output");
3997  Printf(" file, which may or may not position your output medium to");
3998  Printf(" the top of a page depending on the device and system.");
3999  goto L99;
4000  }
4001 //______________________________________________________________________________
4002  Printf(" Unknown MINUIT command. Type HELP for list of commands.");
4003 
4004 L99:
4005  return;
4006 }
4007 
4008 ////////////////////////////////////////////////////////////////////////////////
4009 /// Calculates the full second-derivative matrix of FCN
4010 ///
4011 /// by taking finite differences. When calculating diagonal
4012 /// elements, it may iterate so that step size is nearly that
4013 /// which gives function change= UP/10. The first derivatives
4014 /// of course come as a free side effect, but with a smaller
4015 /// step size in order to obtain a known accuracy.
4016 
4018 {
4019  /* Local variables */
4020  Double_t dmin_, dxdi, elem, wint, tlrg2, d, dlast, ztemp, g2bfor;
4021  Double_t df, aimsag, fs1, tlrstp, fs2, stpinm, g2i, sag=0, xtf, xti, xtj;
4022  Int_t icyc, ncyc, ndex, idrv, iext, npar2, i, j, ifail, npard, nparx, id, multpy;
4023  Bool_t ldebug;
4024 
4025  ldebug = fIdbg[3] >= 1;
4026  if (fAmin == fUndefi) {
4027  mnamin();
4028  }
4029  if (fIstrat <= 0) {
4030  ncyc = 3;
4031  tlrstp = .5;
4032  tlrg2 = .1;
4033  } else if (fIstrat == 1) {
4034  ncyc = 5;
4035  tlrstp = .3;
4036  tlrg2 = .05;
4037  } else {
4038  ncyc = 7;
4039  tlrstp = .1;
4040  tlrg2 = .02;
4041  }
4042  if (fISW[4] >= 2 || ldebug) {
4043  Printf(" START COVARIANCE MATRIX CALCULATION.");
4044  }
4045  fCfrom = "HESSE ";
4046  fNfcnfr = fNfcn;
4047  fCstatu = "OK ";
4048  npard = fNpar;
4049 // make sure starting at the right place
4050  mninex(fX);
4051  nparx = fNpar;
4052  Eval(nparx, fGin, fs1, fU, 4); ++fNfcn;
4053  if (fs1 != fAmin) {
4054  df = fAmin - fs1;
4055  mnwarn("D", "MNHESS", TString::Format("function value differs from AMIN by %g",df));
4056  }
4057  fAmin = fs1;
4058  if (ldebug) {
4059  Printf(" PAR D GSTEP D G2 GRD SAG ");
4060  }
4061 // diagonal elements .
4062 
4063 // fISW[1] = 1 if approx, 2 if not posdef, 3 if ok
4064 // AIMSAG is the sagitta we are aiming for in second deriv calc.
4065 
4066  aimsag = TMath::Sqrt(fEpsma2)*(TMath::Abs(fAmin) + fUp);
4067 // Zero the second derivative matrix
4068  npar2 = fNpar*(fNpar + 1) / 2;
4069  for (i = 1; i <= npar2; ++i) { fVhmat[i-1] = 0; }
4070 
4071 // Loop over variable parameters for second derivatives
4072  idrv = 2;
4073  for (id = 1; id <= npard; ++id) {
4074  i = id + fNpar - npard;
4075  iext = fNexofi[i-1];
4076  if (fG2[i-1] == 0) {
4077  mnwarn("W", "HESSE", Form("Second derivative enters zero, param %d",iext));
4078  wint = fWerr[i-1];
4079  if (fNvarl[iext-1] > 1) {
4080  mndxdi(fX[i-1], i-1, dxdi);
4081  if (TMath::Abs(dxdi) < .001) wint = .01;
4082  else wint /= TMath::Abs(dxdi);
4083  }
4084  fG2[i-1] = fUp / (wint*wint);
4085  }
4086  xtf = fX[i-1];
4087  dmin_ = fEpsma2*8*TMath::Abs(xtf);
4088 
4089 // find step which gives sagitta = AIMSAG
4090  d = TMath::Abs(fGstep[i-1]);
4091  int skip50 = 0;
4092  for (icyc = 1; icyc <= ncyc; ++icyc) {
4093 // loop here only if SAG=0
4094  for (multpy = 1; multpy <= 5; ++multpy) {
4095 // take two steps
4096  fX[i-1] = xtf + d;
4097  mninex(fX);
4098  nparx = fNpar;
4099  Eval(nparx, fGin, fs1, fU, 4); ++fNfcn;
4100  fX[i-1] = xtf - d;
4101  mninex(fX);
4102  Eval(nparx, fGin, fs2, fU, 4); ++fNfcn;
4103  fX[i-1] = xtf;
4104  sag = (fs1 + fs2 - fAmin*2)*.5;
4105  if (sag != 0) goto L30;
4106  if (fGstep[i-1] < 0) {
4107  if (d >= .5) goto L26;
4108  d *= 10;
4109  if (d > .5) d = .51;
4110  continue;
4111  }
4112  d *= 10;
4113  }
4114 L26:
4115  mnwarn("W", "HESSE", TString::Format("Second derivative zero for parameter%d",iext));
4116  goto L390;
4117 // SAG is not zero
4118 L30:
4119  g2bfor = fG2[i-1];
4120  fG2[i-1] = sag*2 / (d*d);
4121  fGrd[i-1] = (fs1 - fs2) / (d*2);
4122  if (ldebug) {
4123  Printf("%4d%2d%12.5g%12.5g%12.5g%12.5g%12.5g",i,idrv,fGstep[i-1],d,fG2[i-1],fGrd[i-1],sag);
4124  }
4125  if (fGstep[i-1] > 0) fGstep[i-1] = TMath::Abs(d);
4126  else fGstep[i-1] = -TMath::Abs(d);
4127  fDirin[i-1] = d;
4128  fHESSyy[i-1]= fs1;
4129  dlast = d;
4130  d = TMath::Sqrt(aimsag*2 / TMath::Abs(fG2[i-1]));
4131 // if parameter has limits, max int step size = 0.5
4132  stpinm = .5;
4133  if (fGstep[i-1] < 0) d = TMath::Min(d,stpinm);
4134  if (d < dmin_) d = dmin_;
4135 // see if converged
4136  if (TMath::Abs((d - dlast) / d) < tlrstp ||
4137  TMath::Abs((fG2[i-1] - g2bfor) / fG2[i-1]) < tlrg2) {
4138  skip50 = 1;
4139  break;
4140  }
4141  d = TMath::Min(d,dlast*102);
4142  d = TMath::Max(d,dlast*.1);
4143  }
4144 // end of step size loop
4145  if (!skip50)
4146  mnwarn("D", "MNHESS", TString::Format("Second Deriv. SAG,AIM= %d%g%g",iext,sag,aimsag));
4147 
4148  ndex = i*(i + 1) / 2;
4149  fVhmat[ndex-1] = fG2[i-1];
4150  }
4151 // end of diagonal second derivative loop
4152  mninex(fX);
4153 // refine the first derivatives
4154  if (fIstrat > 0) mnhes1();
4155  fISW[1] = 3;
4156  fDcovar = 0;
4157 // off-diagonal elements
4158 
4159  if (fNpar == 1) goto L214;
4160  for (i = 1; i <= fNpar; ++i) {
4161  for (j = 1; j <= i-1; ++j) {
4162  xti = fX[i-1];
4163  xtj = fX[j-1];
4164  fX[i-1] = xti + fDirin[i-1];
4165  fX[j-1] = xtj + fDirin[j-1];
4166  mninex(fX);
4167  Eval(nparx, fGin, fs1, fU, 4); ++fNfcn;
4168  fX[i-1] = xti;
4169  fX[j-1] = xtj;
4170  elem = (fs1 + fAmin - fHESSyy[i-1] - fHESSyy[j-1]) / (
4171  fDirin[i-1]*fDirin[j-1]);
4172  ndex = i*(i-1) / 2 + j;
4173  fVhmat[ndex-1] = elem;
4174  }
4175  }
4176 L214:
4177  mninex(fX);
4178 // verify matrix positive-definite
4179  mnpsdf();
4180  for (i = 1; i <= fNpar; ++i) {
4181  for (j = 1; j <= i; ++j) {
4182  ndex = i*(i-1) / 2 + j;
4183  fP[i + j*fMaxpar - fMaxpar-1] = fVhmat[ndex-1];
4184  fP[j + i*fMaxpar - fMaxpar-1] = fP[i + j*fMaxpar - fMaxpar-1];
4185  }
4186  }
4187  mnvert(fP, fMaxint, fMaxint, fNpar, ifail);
4188  if (ifail > 0) {
4189  mnwarn("W", "HESSE", "Matrix inversion fails.");
4190  goto L390;
4191  }
4192 // calculate e d m
4193  fEDM = 0;
4194 
4195  for (i = 1; i <= fNpar; ++i) {
4196 // off-diagonal elements
4197  ndex = i*(i-1) / 2;
4198  for (j = 1; j <= i-1; ++j) {
4199  ++ndex;
4200  ztemp = fP[i + j*fMaxpar - fMaxpar-1]*2;
4201  fEDM += fGrd[i-1]*ztemp*fGrd[j-1];
4202  fVhmat[ndex-1] = ztemp;
4203  }
4204 // diagonal elements
4205  ++ndex;
4206  fVhmat[ndex-1] = fP[i + i*fMaxpar - fMaxpar-1]*2;
4207  fEDM += fP[i + i*fMaxpar - fMaxpar-1]*(fGrd[i-1]*fGrd[i-1]);
4208  }
4209  if (fISW[4] >= 1 && fISW[1] == 3 && fItaur == 0) {
4210  Printf(" COVARIANCE MATRIX CALCULATED SUCCESSFULLY");
4211  }
4212  goto L900;
4213 // failure to invert 2nd deriv matrix
4214 L390:
4215  fISW[1] = 1;
4216  fDcovar = 1;
4217  fCstatu = "FAILED ";
4218  if (fISW[4] >= 0) {
4219  Printf(" MNHESS FAILS AND WILL RETURN DIAGONAL MATRIX. ");
4220  }
4221  for (i = 1; i <= fNpar; ++i) {
4222  ndex = i*(i-1) / 2;
4223  for (j = 1; j <= i-1; ++j) {
4224  ++ndex;
4225  fVhmat[ndex-1] = 0;
4226  }
4227  ++ndex;
4228  g2i = fG2[i-1];
4229  if (g2i <= 0) g2i = 1;
4230  fVhmat[ndex-1] = 2 / g2i;
4231  }
4232 L900:
4233  return;
4234 }
4235 
4236 ////////////////////////////////////////////////////////////////////////////////
4237 /// Calculate first derivatives (GRD) and uncertainties (DGRD)
4238 ///
4239 /// and appropriate step sizes GSTEP
4240 /// Called from MNHESS and MNGRAD
4241 
4243 {
4244  /* Local variables */
4245  Double_t dmin_, d, dfmin, dgmin=0, change, chgold, grdold=0, epspri;
4246  Double_t fs1, optstp, fs2, grdnew=0, sag, xtf;
4247  Int_t icyc, ncyc=0, idrv, i, nparx;
4248  Bool_t ldebug;
4249 
4250  ldebug = fIdbg[5] >= 1;
4251  if (fIstrat <= 0) ncyc = 1;
4252  if (fIstrat == 1) ncyc = 2;
4253  if (fIstrat > 1) ncyc = 6;
4254  idrv = 1;
4255  nparx = fNpar;
4256  dfmin = fEpsma2*4*(TMath::Abs(fAmin) + fUp);
4257 // main loop over parameters
4258  for (i = 1; i <= fNpar; ++i) {
4259  xtf = fX[i-1];
4260  dmin_ = fEpsma2*4*TMath::Abs(xtf);
4261  epspri = fEpsma2 + TMath::Abs(fGrd[i-1]*fEpsma2);
4262  optstp = TMath::Sqrt(dfmin / (TMath::Abs(fG2[i-1]) + epspri));
4263  d = TMath::Abs(fGstep[i-1])*.2;
4264  if (d > optstp) d = optstp;
4265  if (d < dmin_) d = dmin_;
4266  chgold = 1e4;
4267 // iterate reducing step size
4268  for (icyc = 1; icyc <= ncyc; ++icyc) {
4269  fX[i-1] = xtf + d;
4270  mninex(fX);
4271  Eval(nparx, fGin, fs1, fU, 4); ++fNfcn;
4272  fX[i-1] = xtf - d;
4273  mninex(fX);
4274  Eval(nparx, fGin, fs2, fU, 4); ++fNfcn;
4275  fX[i-1] = xtf;
4276 // check if step sizes appropriate
4277  sag = (fs1 + fs2 - fAmin*2)*.5;
4278  grdold = fGrd[i-1];
4279  grdnew = (fs1 - fs2) / (d*2);
4280  dgmin = fEpsmac*(TMath::Abs(fs1) + TMath::Abs(fs2)) / d;
4281  if (ldebug) {
4282  Printf("%4d%2d%12.5g%12.5g%12.5g%12.5g%12.5g",i,idrv,fGstep[i-1],d,fG2[i-1],grdnew,sag);
4283  }
4284  if (grdnew == 0) goto L60;
4285  change = TMath::Abs((grdold - grdnew) / grdnew);
4286  if (change > chgold && icyc > 1) goto L60;
4287  chgold = change;
4288  fGrd[i-1] = grdnew;
4289  if (fGstep[i-1] > 0) fGstep[i-1] = TMath::Abs(d);
4290  else fGstep[i-1] = -TMath::Abs(d);
4291 // decrease step until first derivative changes by <5%
4292  if (change < .05) goto L60;
4293  if (TMath::Abs(grdold - grdnew) < dgmin) goto L60;
4294  if (d < dmin_) {
4295  mnwarn("D", "MNHES1", "Step size too small for 1st drv.");
4296  goto L60;
4297  }
4298  d *= .2;
4299  }
4300 // loop satisfied = too many iter
4301  mnwarn("D", "MNHES1", TString::Format("Too many iterations on D1.%g%g",grdold,grdnew));
4302 L60:
4303  fDgrd[i-1] = TMath::Max(dgmin,TMath::Abs(grdold - grdnew));
4304  }
4305 // end of first deriv. loop
4306  mninex(fX);
4307 }
4308 
4309 ////////////////////////////////////////////////////////////////////////////////
4310 /// Attempts to improve on a good local minimum
4311 ///
4312 /// Attempts to improve on a good local minimum by finding a
4313 /// better one. The quadratic part of FCN is removed by MNCALF
4314 /// and this transformed function is minimised using the simplex
4315 /// method from several random starting points.
4316 ///
4317 /// ref. -- Goldstein and Price, Math.Comp. 25, 569 (1971)
4318 
4320 {
4321  /* Initialized data */
4322 
4323  Double_t rnum = 0;
4324 
4325  /* Local variables */
4326  Double_t amax, ycalf, ystar, ystst;
4327  Double_t pb, ep, wg, xi, sigsav, reg, sig2;
4328  Int_t npfn, ndex, loop=0, i, j, ifail, iseed=0;
4329  Int_t jhold, nloop, nparx, nparp1, jh, jl, iswtr;
4330 
4331  if (fNpar <= 0) return;
4332  if (fAmin == fUndefi) mnamin();
4333  fCstatu = "UNCHANGED ";
4334  fItaur = 1;
4335  fEpsi = fUp*.1;
4336  npfn = fNfcn;
4337  nloop = Int_t(fWord7[1]);
4338  if (nloop <= 0) nloop = fNpar + 4;
4339  nparx = fNpar;
4340  nparp1 = fNpar + 1;
4341  wg = 1 / Double_t(fNpar);
4342  sigsav = fEDM;
4343  fApsi = fAmin;
4344  iswtr = fISW[4] - 2*fItaur;
4345  for (i = 1; i <= fNpar; ++i) {
4346  fXt[i-1] = fX[i-1];
4347  fIMPRdsav[i-1] = fWerr[i-1];
4348  for (j = 1; j <= i; ++j) {
4349  ndex = i*(i-1) / 2 + j;
4350  fP[i + j*fMaxpar - fMaxpar-1] = fVhmat[ndex-1];
4351  fP[j + i*fMaxpar - fMaxpar-1] = fP[i + j*fMaxpar - fMaxpar-1];
4352  }
4353  }
4354  mnvert(fP, fMaxint, fMaxint, fNpar, ifail);
4355  if (ifail >= 1) goto L280;
4356 // Save inverted matrix in VT
4357  for (i = 1; i <= fNpar; ++i) {
4358  ndex = i*(i-1) / 2;
4359  for (j = 1; j <= i; ++j) {
4360  ++ndex;
4361  fVthmat[ndex-1] = fP[i + j*fMaxpar - fMaxpar-1];
4362  }
4363  }
4364  loop = 0;
4365 
4366 L20:
4367  for (i = 1; i <= fNpar; ++i) {
4368  fDirin[i-1] = fIMPRdsav[i-1]*2;
4369  mnrn15(rnum, iseed);
4370  fX[i-1] = fXt[i-1] + fDirin[i-1]*2*(rnum - .5);
4371  }
4372  ++loop;
4373  reg = 2;
4374  if (fISW[4] >= 0) {
4375  Printf("START ATTEMPT NO.%2d TO FIND NEW MINIMUM",loop);
4376  }
4377 L30:
4378  mncalf(fX, ycalf);
4379  fAmin = ycalf;
4380 // set up random simplex
4381  jl = nparp1;
4382  jh = nparp1;
4383  fIMPRy[nparp1-1] = fAmin;
4384  amax = fAmin;
4385  for (i = 1; i <= fNpar; ++i) {
4386  xi = fX[i-1];
4387  mnrn15(rnum, iseed);
4388  fX[i-1] = xi - fDirin[i-1]*(rnum - .5);
4389  mncalf(fX, ycalf);
4390  fIMPRy[i-1] = ycalf;
4391  if (fIMPRy[i-1] < fAmin) {
4392  fAmin = fIMPRy[i-1];
4393  jl = i;
4394  } else if (fIMPRy[i-1] > amax) {
4395  amax = fIMPRy[i-1];
4396  jh = i;
4397  }
4398  for (j = 1; j <= fNpar; ++j) { fP[j + i*fMaxpar - fMaxpar-1] = fX[j-1]; }
4399  fP[i + nparp1*fMaxpar - fMaxpar-1] = xi;
4400  fX[i-1] = xi;
4401  }
4402 
4403  fEDM = fAmin;
4404  sig2 = fEDM;
4405 // start main loop
4406 L50:
4407  if (fAmin < 0) goto L95;
4408  if (fISW[1] <= 2) goto L280;
4409  ep = fAmin*.1;
4410  if (sig2 < ep && fEDM < ep) goto L100;
4411  sig2 = fEDM;
4412  if (fNfcn - npfn > fNfcnmx) goto L300;
4413 // calculate new point * by reflection
4414  for (i = 1; i <= fNpar; ++i) {
4415  pb = 0;
4416  for (j = 1; j <= nparp1; ++j) { pb += wg*fP[i + j*fMaxpar - fMaxpar-1]; }
4417  fPbar[i-1] = pb - wg*fP[i + jh*fMaxpar - fMaxpar-1];
4418  fPstar[i-1] = fPbar[i-1]*2 - fP[i + jh*fMaxpar - fMaxpar-1]*1;
4419  }
4420  mncalf(fPstar, ycalf);
4421  ystar = ycalf;
4422  if (ystar >= fAmin) goto L70;
4423 // point * better than jl, calculate new point **
4424  for (i = 1; i <= fNpar; ++i) {
4425  fPstst[i-1] = fPstar[i-1]*2 + fPbar[i- 1]*-1;
4426  }
4427  mncalf(fPstst, ycalf);
4428  ystst = ycalf;
4429  if (ystst < fIMPRy[jl-1]) goto L67;
4430  mnrazz(ystar, fPstar, fIMPRy, jh, jl);
4431  goto L50;
4432 L67:
4433  mnrazz(ystst, fPstst, fIMPRy, jh, jl);
4434  goto L50;
4435 // point * is not as good as jl
4436 L70:
4437  if (ystar >= fIMPRy[jh-1]) goto L73;
4438  jhold = jh;
4439  mnrazz(ystar, fPstar, fIMPRy, jh, jl);
4440  if (jhold != jh) goto L50;
4441 // calculate new point **
4442 L73:
4443  for (i = 1; i <= fNpar; ++i) {
4444  fPstst[i-1] = fP[i + jh*fMaxpar - fMaxpar-1]*.5 + fPbar[i-1]*.5;
4445  }
4446  mncalf(fPstst, ycalf);
4447  ystst = ycalf;
4448  if (ystst > fIMPRy[jh-1]) goto L30;
4449 // point ** is better than jh
4450  if (ystst < fAmin) goto L67;
4451  mnrazz(ystst, fPstst, fIMPRy, jh, jl);
4452  goto L50;
4453 // end main loop
4454 L95:
4455  if (fISW[4] >= 0) {
4456  Printf(" AN IMPROVEMENT ON THE PREVIOUS MINIMUM HAS BEEN FOUND");
4457  }
4458  reg = .1;
4459 // ask if point is new
4460 L100:
4461  mninex(fX);
4462  Eval(nparx, fGin, fAmin, fU, 4); ++fNfcn;
4463  for (i = 1; i <= fNpar; ++i) {
4464  fDirin[i-1] = reg*fIMPRdsav[i-1];
4465  if (TMath::Abs(fX[i-1] - fXt[i-1]) > fDirin[i-1]) goto L150;
4466  }
4467  goto L230;
4468 L150:
4469  fNfcnmx = fNfcnmx + npfn - fNfcn;
4470  npfn = fNfcn;
4471  mnsimp();
4472  if (fAmin >= fApsi) goto L325;
4473  for (i = 1; i <= fNpar; ++i) {
4474  fDirin[i-1] = fIMPRdsav[i-1]*.1;
4475  if (TMath::Abs(fX[i-1] - fXt[i-1]) > fDirin[i-1]) goto L250;
4476  }
4477 L230:
4478  if (fAmin < fApsi) goto L350;
4479  goto L325;
4480 /* truly new minimum */
4481 L250:
4482  fLnewmn = kTRUE;
4483  if (fISW[1] >= 1) {
4484  fISW[1] = 1;
4485  fDcovar = TMath::Max(fDcovar,.5);
4486  } else fDcovar = 1;
4487  fItaur = 0;
4488  fNfcnmx = fNfcnmx + npfn - fNfcn;
4489  fCstatu = "NEW MINIMU";
4490  if (fISW[4] >= 0) {
4491  Printf(" IMPROVE HAS FOUND A TRULY NEW MINIMUM");
4492  Printf(" *************************************");
4493  }
4494  return;
4495 // return to previous region
4496 L280:
4497  if (fISW[4] > 0) {
4498  Printf(" COVARIANCE MATRIX WAS NOT POSITIVE-DEFINITE");
4499  }
4500  goto L325;
4501 L300:
4502  fISW[0] = 1;
4503 L325:
4504  for (i = 1; i <= fNpar; ++i) {
4505  fDirin[i-1] = fIMPRdsav[i-1]*.01;
4506  fX[i-1] = fXt[i-1];
4507  }
4508  fAmin = fApsi;
4509  fEDM = sigsav;
4510 L350:
4511  mninex(fX);
4512  if (fISW[4] > 0) {
4513  Printf(" IMPROVE HAS RETURNED TO REGION OF ORIGINAL MINIMUM");
4514  }
4515  fCstatu = "UNCHANGED ";
4516  mnrset(0);
4517  if (fISW[1] < 2) goto L380;
4518  if (loop < nloop && fISW[0] < 1) goto L20;
4519 L380:
4520  if (iswtr >= 0) mnprin(5, fAmin);
4521  fItaur = 0;
4522 }
4523 
4524 ////////////////////////////////////////////////////////////////////////////////
4525 /// Transforms from internal coordinates (PINT) to external (U)
4526 ///
4527 /// The minimising routines which work in
4528 /// internal coordinates call this routine before calling FCN.
4529 
4531 {
4532  Int_t i, j;
4533 
4534  for (j = 0; j < fNpar; ++j) {
4535  i = fNexofi[j]-1;
4536  if (fNvarl[i] == 1) {
4537  fU[i] = pint[j];
4538  } else {
4539  fU[i] = fAlim[i] + (TMath::Sin(pint[j]) + 1)*.5*(fBlim[i] - fAlim[i]);
4540  }
4541  }
4542 }
4543 
4544 ////////////////////////////////////////////////////////////////////////////////
4545 /// Main initialization member function for MINUIT
4546 ///
4547 /// It initializes some constants
4548 /// (including the logical I/O unit nos.),
4549 
4551 {
4552  /* Local variables */
4553  volatile Double_t epsp1;
4554  Double_t piby2, epstry, epsbak, distnn;
4555  Int_t i, idb;
4556 
4557 // I/O unit numbers
4558  fIsysrd = i1;
4559  fIsyswr = i2;
4560  fIstkwr[0] = fIsyswr;
4561  fNstkwr = 1;
4562  fIsyssa = i3;
4563  fNstkrd = 0;
4564 // version identifier
4565  fCvrsn = "95.03++ ";
4566 // some CONSTANT
4567  fMaxint = fMaxpar;
4568  fMaxext = 2*fMaxpar;
4569  fUndefi = -54321;
4570  fBigedm = 123456;
4571  fCundef = ")UNDEFINED";
4572  fCovmes[0] = "NO ERROR MATRIX ";
4573  fCovmes[1] = "ERR MATRIX APPROXIMATE";
4574  fCovmes[2] = "ERR MATRIX NOT POS-DEF";
4575  fCovmes[3] = "ERROR MATRIX ACCURATE ";
4576 // some starting values
4577  fNblock = 0;
4578  fIcomnd = 0;
4579  fCtitl = fCundef;
4580  fCfrom = "INPUT ";
4581  fNfcn = 0;
4582  fNfcnfr = fNfcn;
4583  fCstatu = "INITIALIZE";
4584  fISW[2] = 0;
4585  fISW[3] = 0;
4586  fISW[4] = 1;
4587 // fISW[5]=0 for batch jobs, =1 for interactive jobs
4588 // =-1 for originally interactive temporarily batch
4589 
4590  fISW[5] = 0;
4591 // if (intrac(&dummy)) fISW[5] = 1;
4592 // DEBUG options set to default values
4593  for (idb = 0; idb <= 10; ++idb) { fIdbg[idb] = 0; }
4594  fLrepor = kFALSE;
4595  fLwarn = kTRUE;
4596  fLimset = kFALSE;
4597  fLnewmn = kFALSE;
4598  fIstrat = 1;
4599  fItaur = 0;
4600 // default page dimensions and 'new page' carriage control integer
4601  fNpagwd = 120;
4602  fNpagln = 56;
4603  fNewpag = 1;
4604  if (fISW[5] > 0) {
4605  fNpagwd = 80;
4606  fNpagln = 30;
4607  fNewpag = 0;
4608  }
4609  fUp = 1;
4610  fUpdflt = fUp;
4611 // determine machine accuracy epsmac
4612  epstry = .5;
4613  for (i = 1; i <= 100; ++i) {
4614  epstry *= .5;
4615  epsp1 = epstry + 1;
4616  mntiny(epsp1, epsbak);
4617  if (epsbak < epstry) goto L35;
4618  }
4619  epstry = 1e-7;
4620  fEpsmac = epstry*4;
4621  Printf(" MNINIT UNABLE TO DETERMINE ARITHMETIC PRECISION. WILL ASSUME:%g",fEpsmac);
4622 L35:
4623  fEpsmac = epstry*8;
4625 // the vlims are a non-negligible distance from pi/2
4626 // used by MNPINT to set variables "near" the physical limits
4627  piby2 = TMath::ATan(1)*2;
4628  distnn = TMath::Sqrt(fEpsma2)*8;
4629  fVlimhi = piby2 - distnn;
4630  fVlimlo = -piby2 + distnn;
4631  mncler();
4632 // Printf(" MINUIT RELEASE %s INITIALIZED. DIMENSIONS 100/50 EPSMAC=%g",(const char*)fCvrsn,fEpsmac);
4633 }
4634 
4635 ////////////////////////////////////////////////////////////////////////////////
4636 /// Interprets the SET LIM command, to reset the parameter limits
4637 ///
4638 /// Called from MNSET
4639 
4641 {
4642  /* Local variables */
4643  Double_t dxdi, snew;
4644  Int_t kint, i2, newcod, ifx=0, inu;
4645 
4646  fCfrom = "SET LIM ";
4647  fNfcnfr = fNfcn;
4648  fCstatu = "NO CHANGE ";
4649  i2 = Int_t(fWord7[0]);
4650  if (i2 > fMaxext || i2 < 0) goto L900;
4651  if (i2 > 0) goto L30;
4652 // set limits on all parameters
4653  newcod = 4;
4654  if (fWord7[1] == fWord7[2]) newcod = 1;
4655  for (inu = 1; inu <= fNu; ++inu) {
4656  if (fNvarl[inu-1] <= 0) continue;
4657  if (fNvarl[inu-1] == 1 && newcod == 1) continue;
4658  kint = fNiofex[inu-1];
4659 // see if parameter has been fixed
4660  if (kint <= 0) {
4661  if (fISW[4] >= 0) {
4662  Printf(" LIMITS NOT CHANGED FOR FIXED PARAMETER:%4d",inu);
4663  }
4664  continue;
4665  }
4666  if (newcod == 1) {
4667 // remove limits from parameter
4668  if (fISW[4] > 0) {
4669  Printf(" LIMITS REMOVED FROM PARAMETER :%3d",inu);
4670  }
4671  fCstatu = "NEW LIMITS";
4672  mndxdi(fX[kint-1], kint-1, dxdi);
4673  snew = fGstep[kint-1]*dxdi;
4674  fGstep[kint-1] = TMath::Abs(snew);
4675  fNvarl[inu-1] = 1;
4676  } else {
4677 // put limits on parameter
4678  fAlim[inu-1] = TMath::Min(fWord7[1],fWord7[2]);
4679  fBlim[inu-1] = TMath::Max(fWord7[1],fWord7[2]);
4680  if (fISW[4] > 0) {
4681  Printf(" PARAMETER %3d LIMITS SET TO %15.5g%15.5g",inu,fAlim[inu-1],fBlim[inu-1]);
4682  }
4683  fNvarl[inu-1] = 4;
4684  fCstatu = "NEW LIMITS";
4685  fGstep[kint-1] = -.1;
4686  }
4687  }
4688  goto L900;
4689 // set limits on one parameter
4690 L30:
4691  if (fNvarl[i2-1] <= 0) {
4692  Printf(" PARAMETER %3d IS NOT VARIABLE.", i2);
4693  goto L900;
4694  }
4695  kint = fNiofex[i2-1];
4696 // see if parameter was fixed
4697  if (kint == 0) {
4698  Printf(" REQUEST TO CHANGE LIMITS ON FIXED PARAMETER:%3d",i2);
4699  for (ifx = 1; ifx <= fNpfix; ++ifx) {
4700  if (i2 == fIpfix[ifx-1]) goto L92;
4701  }
4702  Printf(" MINUIT BUG IN MNLIMS. SEE F. JAMES");
4703 L92:
4704  ;
4705  }
4706  if (fWord7[1] != fWord7[2]) goto L235;
4707 // remove limits
4708  if (fNvarl[i2-1] != 1) {
4709  if (fISW[4] > 0) {
4710  Printf(" LIMITS REMOVED FROM PARAMETER %2d",i2);
4711  }
4712  fCstatu = "NEW LIMITS";
4713  if (kint <= 0) {
4714  fGsteps[ifx-1] = TMath::Abs(fGsteps[ifx-1]);
4715  } else {
4716  mndxdi(fX[kint-1], kint-1, dxdi);
4717  if (TMath::Abs(dxdi) < .01) dxdi = .01;
4718  fGstep[kint-1] = TMath::Abs(fGstep[kint-1]*dxdi);
4719  fGrd[kint-1] *= dxdi;
4720  }
4721  fNvarl[i2-1] = 1;
4722  } else {
4723  Printf(" NO LIMITS SPECIFIED. PARAMETER %3d IS ALREADY UNLIMITED. NO CHANGE.",i2);
4724  }
4725  goto L900;
4726 // put on limits
4727 L235:
4728  fAlim[i2-1] = TMath::Min(fWord7[1],fWord7[2]);
4729  fBlim[i2-1] = TMath::Max(fWord7[1],fWord7[2]);
4730  fNvarl[i2-1] = 4;
4731  if (fISW[4] > 0) {
4732  Printf(" PARAMETER %3d LIMITS SET TO %15.5g%15.5g",i2,fAlim[i2-1],fBlim[i2-1]);
4733  }
4734  fCstatu = "NEW LIMITS";
4735  if (kint <= 0) fGsteps[ifx-1] = -.1;
4736  else fGstep[kint-1] = -.1;
4737 
4738 L900:
4739  if (fCstatu != "NO CHANGE ") {
4740  mnexin(fX);
4741  mnrset(1);
4742  }
4743 }
4744 
4745 ////////////////////////////////////////////////////////////////////////////////
4746 /// Perform a line search from position START
4747 ///
4748 /// along direction STEP, where the length of vector STEP
4749 /// gives the expected position of minimum.
4750 /// - FSTART is value of function at START
4751 /// - SLOPE (if non-zero) is df/dx along STEP at START
4752 /// - TOLER is initial tolerance of minimum in direction STEP
4753 ///
4754 /// SLAMBG and ALPHA control the maximum individual steps allowed.
4755 /// The first step is always =1. The max length of second step is SLAMBG.
4756 /// The max size of subsequent steps is the maximum previous successful
4757 /// step multiplied by ALPHA + the size of most recent successful step,
4758 /// but cannot be smaller than SLAMBG.
4759 
4760 void TMinuit::mnline(Double_t *start, Double_t fstart, Double_t *step, Double_t slope, Double_t toler)
4761 {
4762  /* Local variables */
4763  Double_t xpq[12], ypq[12], slam, sdev, coeff[3], denom, flast;
4764  Double_t fvals[3], xvals[3], f1, fvmin, xvmin, ratio, f2, f3 = 0., fvmax;
4765  Double_t toler8, toler9, overal, undral, slamin, slamax, slopem;
4766  Int_t i, nparx=0, nvmax=0, nxypt, kk, ipt;
4767  Bool_t ldebug;
4768  TString cmess;
4769  char chpq[13];
4770  int l65, l70, l80;
4771 
4772  /* Function Body */
4773  l65 = 0; l70 = 0; l80 = 0;
4774  ldebug = fIdbg[1] >= 1;
4775 // starting values for overall limits on total step SLAM
4776  overal = 1e3;
4777  undral = -100;
4778 // debug check if start is ok
4779  if (ldebug) {
4780  mninex(&start[0]);
4781  Eval(nparx, fGin, f1, fU, 4); ++fNfcn;
4782  if (f1 != fstart) {
4783  Printf(" MNLINE start point not consistent, F values, parameters=");
4784  for (kk = 1; kk <= fNpar; ++kk) {
4785  Printf(" %14.5e",fX[kk-1]);
4786  }
4787  }
4788  }
4789 // set up linear search along STEP
4790  fvmin = fstart;
4791  xvmin = 0;
4792  nxypt = 1;
4793  chpq[0] = charal[0];
4794  xpq[0] = 0;
4795  ypq[0] = fstart;
4796 // SLAMIN = smallest possible value of ABS(SLAM)
4797  slamin = 0;
4798  for (i = 1; i <= fNpar; ++i) {
4799  if (step[i-1] != 0) {
4800  ratio = TMath::Abs(start[i-1] / step[i-1]);
4801  if (slamin == 0) slamin = ratio;
4802  if (ratio < slamin) slamin = ratio;
4803  }
4804  fX[i-1] = start[i-1] + step[i-1];
4805  }
4806  if (slamin == 0) slamin = fEpsmac;
4807  slamin *= fEpsma2;
4808  nparx = fNpar;
4809 
4810  mninex(fX);
4811  Eval(nparx, fGin, f1, fU, 4); ++fNfcn;
4812  ++nxypt;
4813  chpq[nxypt-1] = charal[nxypt-1];
4814  xpq[nxypt-1] = 1;
4815  ypq[nxypt-1] = f1;
4816  if (f1 < fstart) {
4817  fvmin = f1;
4818  xvmin = 1;
4819  }
4820 // quadr interp using slope GDEL and two points
4821  slam = 1;
4822  toler8 = toler;
4823  slamax = 5;
4824  flast = f1;
4825 // can iterate on two-points (cut) if no imprvmnt
4826 
4827  do {
4828  denom = (flast - fstart - slope*slam)*2 / (slam*slam);
4829  slam = 1;
4830  if (denom != 0) slam = -slope / denom;
4831  if (slam < 0) slam = slamax;
4832  if (slam > slamax) slam = slamax;
4833  if (slam < toler8) slam = toler8;
4834  if (slam < slamin) {
4835  l80 = 1;
4836  break;
4837  }
4838  if (TMath::Abs(slam - 1) < toler8 && f1 < fstart) {
4839  l70 = 1;
4840  break;
4841  }
4842  if (TMath::Abs(slam - 1) < toler8) slam = toler8 + 1;
4843  if (nxypt >= 12) {
4844  l65 = 1;
4845  break;
4846  }
4847  for (i = 1; i <= fNpar; ++i) { fX[i-1] = start[i-1] + slam*step[i-1]; }
4848  mninex(fX);
4849  nparx = fNpar;
4850  Eval(nparx, fGin, f2, fU, 4); ++fNfcn;
4851  ++nxypt;
4852  chpq[nxypt-1] = charal[nxypt-1];
4853  xpq[nxypt-1] = slam;
4854  ypq[nxypt-1] = f2;
4855  if (f2 < fvmin) {
4856  fvmin = f2;
4857  xvmin = slam;
4858  }
4859  if (fstart == fvmin) {
4860  flast = f2;
4861  toler8 = toler*slam;
4862  overal = slam - toler8;
4863  slamax = overal;
4864  }
4865  } while (fstart == fvmin);
4866 
4867  if (!l65 && !l70 && !l80) {
4868 // quadr interp using 3 points
4869  xvals[0] = xpq[0];
4870  fvals[0] = ypq[0];
4871  xvals[1] = xpq[nxypt-2];
4872  fvals[1] = ypq[nxypt-2];
4873  xvals[2] = xpq[nxypt-1];
4874  fvals[2] = ypq[nxypt-1];
4875 // begin iteration, calculate desired step
4876  do {
4877  slamax = TMath::Max(slamax,TMath::Abs(xvmin)*2);
4878  mnpfit(xvals, fvals, 3, coeff, sdev);
4879  if (coeff[2] <= 0) {
4880  slopem = coeff[2]*2*xvmin + coeff[1];
4881  if (slopem <= 0) slam = xvmin + slamax;
4882  else slam = xvmin - slamax;
4883  } else {
4884  slam = -coeff[1] / (coeff[2]*2);
4885  if (slam > xvmin + slamax) slam = xvmin + slamax;
4886  if (slam < xvmin - slamax) slam = xvmin - slamax;
4887  }
4888  if (slam > 0) {
4889  if (slam > overal)
4890  slam = overal;
4891  else if (slam < undral)
4892  slam = undral;
4893  }
4894 
4895 // come here if step was cut below
4896  do {
4897  toler9 = TMath::Max(toler8,TMath::Abs(toler8*slam));
4898  for (ipt = 1; ipt <= 3; ++ipt) {
4899  if (TMath::Abs(slam - xvals[ipt-1]) < toler9) {
4900  l70 = 1;
4901  break;
4902  }
4903  }
4904  if (l70) break;
4905 // take the step
4906  if (nxypt >= 12) {
4907  l65 = 1;
4908  break;
4909  }
4910  for (i = 1; i <= fNpar; ++i) { fX[i-1] = start[i-1] + slam*step[i-1]; }
4911  mninex(fX);
4912  Eval(nparx, fGin, f3, fU, 4); ++fNfcn;
4913  ++nxypt;
4914  chpq[nxypt-1] = charal[nxypt-1];
4915  xpq[nxypt-1] = slam;
4916  ypq[nxypt-1] = f3;
4917 // find worst previous point out of three
4918  fvmax = fvals[0];
4919  nvmax = 1;
4920  if (fvals[1] > fvmax) {
4921  fvmax = fvals[1];
4922  nvmax = 2;
4923  }
4924  if (fvals[2] > fvmax) {
4925  fvmax = fvals[2];
4926  nvmax = 3;
4927  }
4928 // if latest point worse than all three previous, cut step
4929  if (f3 >= fvmax) {
4930  if (nxypt >= 12) {
4931  l65 = 1;
4932  break;
4933  }
4934  if (slam > xvmin) overal = TMath::Min(overal,slam - toler8);
4935  if (slam < xvmin) undral = TMath::Max(undral,slam + toler8);
4936  slam = (slam + xvmin)*.5;
4937  }
4938  } while (f3 >= fvmax);
4939 
4940 // prepare another iteration, replace worst previous point
4941  if (l65 || l70) break;
4942 
4943  xvals[nvmax-1] = slam;
4944  fvals[nvmax-1] = f3;
4945  if (f3 < fvmin) {
4946  fvmin = f3;
4947  xvmin = slam;
4948  } else {
4949  if (slam > xvmin) overal = TMath::Min(overal,slam - toler8);
4950  if (slam < xvmin) undral = TMath::Max(undral,slam + toler8);
4951  }
4952  } while (nxypt < 12);
4953  }
4954 
4955 // end of iteration
4956 // stop because too many iterations
4957  if (!l70 && !l80) {
4958  cmess = " LINE SEARCH HAS EXHAUSTED THE LIMIT OF FUNCTION CALLS ";
4959  if (ldebug) {
4960  Printf(" MNLINE DEBUG: steps=");
4961  for (kk = 1; kk <= fNpar; ++kk) {
4962  Printf(" %12.4g",step[kk-1]);
4963  }
4964  }
4965  }
4966 // stop because within tolerance
4967  if (l70) cmess = " LINE SEARCH HAS ATTAINED TOLERANCE ";
4968  if (l80) cmess = " STEP SIZE AT ARITHMETICALLY ALLOWED MINIMUM";
4969 
4970  fAmin = fvmin;
4971  for (i = 1; i <= fNpar; ++i) {
4972  fDirin[i-1] = step[i-1]*xvmin;
4973  fX[i-1] = start[i-1] + fDirin[i-1];
4974  }
4975  mninex(fX);
4976  if (xvmin < 0) {
4977  mnwarn("D", "MNLINE", " LINE MINIMUM IN BACKWARDS DIRECTION");
4978  }
4979  if (fvmin == fstart) {
4980  mnwarn("D", "MNLINE", " LINE SEARCH FINDS NO IMPROVEMENT ");
4981  }
4982  if (ldebug) {
4983  Printf(" AFTER %3d POINTS,%s",nxypt,(const char*)cmess);
4984  mnplot(xpq, ypq, chpq, nxypt, fNpagwd, fNpagln);
4985  }
4986 }
4987 
4988 ////////////////////////////////////////////////////////////////////////////////
4989 /// Prints the covariance matrix v when KODE=1
4990 ///
4991 /// always prints the global correlations, and
4992 /// calculates and prints the individual correlation coefficients
4993 
4995 {
4996  /* Local variables */
4997  Int_t ndex, i, j, m, n, ncoef, nparm, id, it, ix;
4998  Int_t nsofar, ndi, ndj, iso, isw2, isw5;
4999  TString ctemp;
5000 
5001  isw2 = fISW[1];
5002  if (isw2 < 1) {
5003  Printf("%s",(const char*)fCovmes[isw2]);
5004  return;
5005  }
5006  if (fNpar == 0) {
5007  Printf(" MNMATU: NPAR=0");
5008  return;
5009  }
5010 // external error matrix
5011  if (kode == 1) {
5012  isw5 = fISW[4];
5013  fISW[4] = 2;
5014  mnemat(fP, fMaxint);
5015  if (isw2 < 3) {
5016  Printf("%s",(const char*)fCovmes[isw2]);
5017  }
5018  fISW[4] = isw5;
5019  }
5020 // correlation coeffs
5021  if (fNpar <= 1) return;
5022  mnwerr();
5023 // NCOEF is number of coeff. that fit on one line, not to exceed 20
5024  ncoef = (fNpagwd - 19) / 6;
5025  ncoef = TMath::Min(ncoef,20);
5026  nparm = TMath::Min(fNpar,ncoef);
5027  Printf(" PARAMETER CORRELATION COEFFICIENTS ");
5028  ctemp = " NO. GLOBAL";
5029  for (id = 1; id <= nparm; ++id) {
5030  ctemp += TString::Format(" %6d",fNexofi[id-1]);
5031  }
5032  Printf("%s",(const char*)ctemp);
5033  for (i = 1; i <= fNpar; ++i) {
5034  ix = fNexofi[i-1];
5035  ndi = i*(i + 1) / 2;
5036  for (j = 1; j <= fNpar; ++j) {
5037  m = TMath::Max(i,j);
5038  n = TMath::Min(i,j);
5039  ndex = m*(m-1) / 2 + n;
5040  ndj = j*(j + 1) / 2;
5041  fMATUvline[j-1] = fVhmat[ndex-1] / TMath::Sqrt(TMath::Abs(fVhmat[ndi-1]*fVhmat[ndj-1]));
5042  }
5043  nparm = TMath::Min(fNpar,ncoef);
5044  ctemp.Form(" %3d %7.5f ",ix,fGlobcc[i-1]);
5045  for (it = 1; it <= nparm; ++it) {
5046  ctemp += TString::Format(" %6.3f",fMATUvline[it-1]);
5047  }
5048  Printf("%s",(const char*)ctemp);
5049  if (i <= nparm) continue;
5050  ctemp = " ";
5051  for (iso = 1; iso <= 10; ++iso) {
5052  nsofar = nparm;
5053  nparm = TMath::Min(fNpar,nsofar + ncoef);
5054  for (it = nsofar + 1; it <= nparm; ++it) {
5055  ctemp = ctemp + TString::Format(" %6.3f",fMATUvline[it-1]);
5056  }
5057  Printf("%s",(const char*)ctemp);
5058  if (i <= nparm) break;
5059  }
5060  }
5061  if (isw2 < 3) {
5062  Printf(" %s",(const char*)fCovmes[isw2]);
5063  }
5064 }
5065 
5066 ////////////////////////////////////////////////////////////////////////////////
5067 /// Performs a local function minimization
5068 ///
5069 /// Performs a local function minimization using basically the
5070 /// method of Davidon-Fletcher-Powell as modified by Fletcher
5071 ///
5072 /// ref. -- Fletcher, Comp.J. 13,317 (1970) "switching method"
5073 
5075 {
5076  /* Local variables */
5077  Double_t gdel, gami, vlen, dsum, gssq, vsum, d;
5078  Double_t fzero, fs, ri, delgam, rhotol;
5079  Double_t gdgssq, gvg, vgi;
5080  Int_t npfn, ndex, iext, i, j, m, n, npsdf, nparx;
5081  Int_t iswtr, lined2, kk, nfcnmg, nrstrt,iter;
5082  Bool_t ldebug;
5083  Double_t toler = 0.05;
5084 
5085  if (fNpar <= 0) return;
5086  if (fAmin == fUndefi) mnamin();
5087  ldebug = kFALSE; if ( fIdbg[4] >= 1) ldebug = kTRUE;
5088  fCfrom = "MIGRAD ";
5089  fNfcnfr = fNfcn;
5090  nfcnmg = fNfcn;
5091  fCstatu = "INITIATE ";
5092  iswtr = fISW[4] - 2*fItaur;
5093  npfn = fNfcn;
5094  nparx = fNpar;
5095  vlen = (Double_t) (fNpar*(fNpar + 1) / 2);
5096  nrstrt = 0;
5097  npsdf = 0;
5098  lined2 = 0;
5099  fISW[3] = -1;
5100  rhotol = fApsi*.001;
5101  if (iswtr >= 1) {
5102  Printf(" START MIGRAD MINIMIZATION. STRATEGY %2d. CONVERGENCE WHEN EDM .LT.%9.2e",fIstrat,rhotol);
5103  }
5104 // initialization strategy
5105  if (fIstrat < 2 || fISW[1] >= 3) goto L2;
5106 // come (back) here to restart completely
5107 L1:
5108  if (nrstrt > fIstrat) {
5109  fCstatu = "FAILED ";
5110  fISW[3] = -1;
5111  goto L230;
5112  }
5113 // get full covariance and gradient
5114  mnhess();
5115  mnwerr();
5116  npsdf = 0;
5117  if (fISW[1] >= 1) goto L10;
5118 // get gradient at start point
5119 L2:
5120  mninex(fX);
5121  if (fISW[2] == 1) {
5122  Eval(nparx, fGin, fzero, fU, 2); ++fNfcn;
5123  }
5124  mnderi();
5125  if (fISW[1] >= 1) goto L10;
5126 // sometimes start with diagonal matrix
5127  for (i = 1; i <= fNpar; ++i) {
5128  fMIGRxxs[i-1] = fX[i-1];
5129  fMIGRstep[i-1] = 0;
5130  }
5131 // do line search if second derivative negative
5132  ++lined2;
5133  if (lined2 < (fIstrat + 1)*fNpar) {
5134  for (i = 1; i <= fNpar; ++i) {
5135  if (fG2[i-1] > 0) continue;
5136  if (fGrd[i-1] > 0) fMIGRstep[i-1] = -TMath::Abs(fGstep[i-1]);
5137  else fMIGRstep[i-1] = TMath::Abs(fGstep[i-1]);
5138  gdel = fMIGRstep[i-1]*fGrd[i-1];
5139  fs = fAmin;
5140  mnline(fMIGRxxs, fs, fMIGRstep, gdel, toler);
5141  mnwarn("D", "MNMIGR", "Negative G2 line search");
5142  iext = fNexofi[i-1];
5143  if (ldebug) {
5144  Printf(" Negative G2 line search, param %3d %13.3g%13.3g",iext,fs,fAmin);
5145  }
5146  goto L2;
5147  }
5148  }
5149 // make diagonal error matrix
5150  for (i = 1; i <= fNpar; ++i) {
5151  ndex = i*(i-1) / 2;
5152  for (j = 1; j <= i-1; ++j) {
5153  ++ndex;
5154  fVhmat[ndex-1] = 0;
5155  }
5156  ++ndex;
5157  if (fG2[i-1] <= 0) fG2[i-1] = 1;
5158  fVhmat[ndex-1] = 2 / fG2[i-1];
5159  }
5160  fDcovar = 1;
5161  if (ldebug) {
5162  Printf(" DEBUG MNMIGR, STARTING MATRIX DIAGONAL, VHMAT=");
5163  for (kk = 1; kk <= Int_t(vlen); ++kk) {
5164  Printf(" %10.2g",fVhmat[kk-1]);
5165  }
5166  }
5167 // ready to start first iteration
5168 L10:
5169  ++nrstrt;
5170  if (nrstrt > fIstrat + 1) {
5171  fCstatu = "FAILED ";
5172  goto L230;
5173  }
5174  fs = fAmin;
5175 // get EDM and set up loop
5176  fEDM = 0;
5177  for (i = 1; i <= fNpar; ++i) {
5178  fMIGRgs[i-1] = fGrd[i-1];
5179  fMIGRxxs[i-1] = fX[i-1];
5180  ndex = i*(i-1) / 2;
5181  for (j = 1; j <= i-1; ++j) {
5182  ++ndex;
5183  fEDM += fMIGRgs[i-1]*fVhmat[ndex-1]*fMIGRgs[j-1];
5184  }
5185  ++ndex;
5186  fEDM += fMIGRgs[i-1]*fMIGRgs[i-1]*.5*fVhmat[ndex-1];
5187  }
5188  fEDM = fEDM*.5*(fDcovar*3 + 1);
5189  if (fEDM < 0) {
5190  mnwarn("W", "MIGRAD", "STARTING MATRIX NOT POS-DEFINITE.");
5191  fISW[1] = 0;
5192  fDcovar = 1;
5193  goto L2;
5194  }
5195  if (fISW[1] == 0) fEDM = fBigedm;
5196  iter = 0;
5197  mninex(fX);
5198  mnwerr();
5199  if (iswtr >= 1) mnprin(3, fAmin);
5200  if (iswtr >= 2) mnmatu(0);
5201 // start main loop
5202 L24:
5203  if (fNfcn - npfn >= fNfcnmx) goto L190;
5204  gdel = 0;
5205  gssq = 0;
5206  for (i = 1; i <= fNpar; ++i) {
5207  ri = 0;
5208  gssq += fMIGRgs[i-1]*fMIGRgs[i-1];
5209  for (j = 1; j <= fNpar; ++j) {
5210  m = TMath::Max(i,j);
5211  n = TMath::Min(i,j);
5212  ndex = m*(m-1) / 2 + n;
5213  ri += fVhmat[ndex-1]*fMIGRgs[j-1];
5214  }
5215  fMIGRstep[i-1] = ri*-.5;
5216  gdel += fMIGRstep[i-1]*fMIGRgs[i-1];
5217  }
5218  if (gssq == 0) {
5219  mnwarn("D", "MIGRAD", " FIRST DERIVATIVES OF FCN ARE ALL ZERO");
5220  goto L300;
5221  }
5222 // if gdel positive, V not posdef
5223  if (gdel >= 0) {
5224  mnwarn("D", "MIGRAD", " NEWTON STEP NOT DESCENT.");
5225  if (npsdf == 1) goto L1;
5226  mnpsdf();
5227  npsdf = 1;
5228  goto L24;
5229  }
5230 // do line search
5231  mnline(fMIGRxxs, fs, fMIGRstep, gdel, toler);
5232  if (fAmin == fs) goto L200;
5233  fCfrom = "MIGRAD ";
5234  fNfcnfr = nfcnmg;
5235  fCstatu = "PROGRESS ";
5236 // get gradient at new point
5237  mninex(fX);
5238  if (fISW[2] == 1) {
5239  Eval(nparx, fGin, fzero, fU, 2); ++fNfcn;
5240  }
5241  mnderi();
5242 // calculate new EDM
5243  npsdf = 0;
5244 L81:
5245  fEDM = 0;
5246  gvg = 0;
5247  delgam = 0;
5248  gdgssq = 0;
5249  for (i = 1; i <= fNpar; ++i) {
5250  ri = 0;
5251  vgi = 0;
5252  for (j = 1; j <= fNpar; ++j) {
5253  m = TMath::Max(i,j);
5254  n = TMath::Min(i,j);
5255  ndex = m*(m-1) / 2 + n;
5256  vgi += fVhmat[ndex-1]*(fGrd[j-1] - fMIGRgs[j-1]);
5257  ri += fVhmat[ndex-1]*fGrd[j-1];
5258  }
5259  fMIGRvg[i-1] = vgi*.5;
5260  gami = fGrd[i-1] - fMIGRgs[i-1];
5261  gdgssq += gami*gami;
5262  gvg += gami*fMIGRvg[i-1];
5263  delgam += fDirin[i-1]*gami;
5264  fEDM += fGrd[i-1]*ri*.5;
5265  }
5266  fEDM = fEDM*.5*(fDcovar*3 + 1);
5267 // if EDM negative, not positive-definite
5268  if (fEDM < 0 || gvg <= 0) {
5269  mnwarn("D", "MIGRAD", "NOT POS-DEF. EDM OR GVG NEGATIVE.");
5270  fCstatu = "NOT POSDEF";
5271  if (npsdf == 1) goto L230;
5272  mnpsdf();
5273  npsdf = 1;
5274  goto L81;
5275  }
5276 // print information about this iteration
5277  ++iter;
5278  if (iswtr >= 3 || (iswtr == 2 && iter % 10 == 1)) {
5279  mnwerr();
5280  mnprin(3, fAmin);
5281  }
5282  if (gdgssq == 0) {
5283  mnwarn("D", "MIGRAD", "NO CHANGE IN FIRST DERIVATIVES OVER LAST STEP");
5284  }
5285  if (delgam < 0) {
5286  mnwarn("D", "MIGRAD", "FIRST DERIVATIVES INCREASING ALONG SEARCH LINE");
5287  }
5288 // update covariance matrix
5289  fCstatu = "IMPROVEMNT";
5290  if (ldebug) {
5291  Printf(" VHMAT 1 =");
5292  for (kk = 1; kk <= 10; ++kk) {
5293  Printf(" %10.2g",fVhmat[kk-1]);
5294  }
5295  }
5296  dsum = 0;
5297  vsum = 0;
5298  for (i = 1; i <= fNpar; ++i) {
5299  for (j = 1; j <= i; ++j) {
5300  if(delgam == 0 || gvg == 0) d = 0;
5301  else d = fDirin[i-1]*fDirin[j-1] / delgam - fMIGRvg[i-1]*fMIGRvg[j-1] / gvg;
5302  dsum += TMath::Abs(d);
5303  ndex = i*(i-1) / 2 + j;
5304  fVhmat[ndex-1] += d*2;
5305  vsum += TMath::Abs(fVhmat[ndex-1]);
5306  }
5307  }
5308 // smooth local fluctuations by averaging DCOVAR
5309  fDcovar = (fDcovar + dsum / vsum)*.5;
5310  if (iswtr >= 3 || ldebug) {
5311  Printf(" RELATIVE CHANGE IN COV. MATRIX=%5.1f per cent",fDcovar*100);
5312  }
5313  if (ldebug) {
5314  Printf(" VHMAT 2 =");
5315  for (kk = 1; kk <= 10; ++kk) {
5316  Printf(" %10.3g",fVhmat[kk-1]);
5317  }
5318  }
5319  if (delgam <= gvg) goto L135;
5320  for (i = 1; i <= fNpar; ++i) {
5321  fMIGRflnu[i-1] = fDirin[i-1] / delgam - fMIGRvg[i-1] / gvg;
5322  }
5323  for (i = 1; i <= fNpar; ++i) {
5324  for (j = 1; j <= i; ++j) {
5325  ndex = i*(i-1) / 2 + j;
5326  fVhmat[ndex-1] += gvg*2*fMIGRflnu[i-1]*fMIGRflnu[j-1];
5327  }
5328  }
5329 L135:
5330 // and see if converged
5331  if (fEDM < rhotol*.1) goto L300;
5332 // if not, prepare next iteration
5333  for (i = 1; i <= fNpar; ++i) {
5334  fMIGRxxs[i-1] = fX[i-1];
5335  fMIGRgs[i-1] = fGrd[i-1];
5336  }
5337  fs = fAmin;
5338  if (fISW[1] == 0 && fDcovar < .5) fISW[1] = 1;
5339  if (fISW[1] == 3 && fDcovar > .1) fISW[1] = 1;
5340  if (fISW[1] == 1 && fDcovar < .05) fISW[1] = 3;
5341  goto L24;
5342 // end main loop
5343 // call limit in MNMIGR
5344 L190:
5345  fISW[0] = 1;
5346  if (fISW[4] >= 0) {
5347  Printf(" CALL LIMIT EXCEEDED IN MIGRAD.");
5348  }
5349  fCstatu = "CALL LIMIT";
5350  goto L230;
5351 // fails to improve
5352 L200:
5353  if (iswtr >= 1) {
5354  Printf(" MIGRAD FAILS TO FIND IMPROVEMENT");
5355  }
5356  for (i = 1; i <= fNpar; ++i) { fX[i-1] = fMIGRxxs[i-1]; }
5357  if (fEDM < rhotol) goto L300;
5358  if (fEDM < TMath::Abs(fEpsma2*fAmin)) {
5359  if (iswtr >= 0) {
5360  Printf(" MACHINE ACCURACY LIMITS FURTHER IMPROVEMENT.");
5361  }
5362  goto L300;
5363  }
5364  if (fIstrat < 1) {
5365  if (fISW[4] >= 0) {
5366  Printf(" MIGRAD FAILS WITH STRATEGY=0. WILL TRY WITH STRATEGY=1.");
5367  }
5368  fIstrat = 1;
5369  }
5370  goto L1;
5371 // fails to converge
5372 L230:
5373  if (iswtr >= 0) {
5374  Printf(" MIGRAD TERMINATED WITHOUT CONVERGENCE.");
5375  }
5376  if (fISW[1] == 3) fISW[1] = 1;
5377  fISW[3] = -1;
5378  goto L400;
5379 // apparent convergence
5380 L300:
5381  if (iswtr >= 0) {
5382  Printf(" MIGRAD MINIMIZATION HAS CONVERGED.");
5383  }
5384  if (fItaur == 0) {
5385  if (fIstrat >= 2 || (fIstrat == 1 && fISW[1] < 3)) {
5386  if (fISW[4] >= 0) {
5387  Printf(" MIGRAD WILL VERIFY CONVERGENCE AND ERROR MATRIX.");
5388  }
5389  mnhess();
5390  mnwerr();
5391  npsdf = 0;
5392  if (fEDM > rhotol) goto L10;
5393  }
5394  }
5395  fCstatu = "CONVERGED ";
5396  fISW[3] = 1;
5397 // come here in any case
5398 L400:
5399  fCfrom = "MIGRAD ";
5400  fNfcnfr = nfcnmg;
5401  mninex(fX);
5402  mnwerr();
5403  if (iswtr >= 0) mnprin(3, fAmin);
5404  if (iswtr >= 1) mnmatu(1);
5405 }
5406 
5407 ////////////////////////////////////////////////////////////////////////////////
5408 /// Performs a MINOS error analysis
5409 ///
5410 /// Performs a MINOS error analysis on those parameters for
5411 /// which it is requested on the MINOS command by calling
5412 /// MNMNOT for each parameter requested.
5413 
5415 {
5416  /* Local variables */
5417  Double_t val2mi, val2pl;
5418  Int_t nbad, ilax, ilax2, ngood, nfcnmi, iin, knt;
5419 
5420  if (fNpar <= 0) goto L700;
5421  ngood = 0;
5422  nbad = 0;
5423  nfcnmi = fNfcn;
5424 // loop over parameters requested
5425  for (knt = 1; knt <= fNpar; ++knt) {
5426  if (Int_t(fWord7[1]) == 0) {
5427  ilax = fNexofi[knt-1];
5428  } else {
5429  if (knt >= 7) break;
5430  ilax = Int_t(fWord7[knt]);
5431  if (ilax == 0) break;
5432  if (ilax > 0 && ilax <= fNu) {
5433  if (fNiofex[ilax-1] > 0) goto L565;
5434  }
5435  Printf(" PARAMETER NUMBER %3d NOT A VARIABLE. IGNORED.",ilax);
5436  continue;
5437  }
5438 L565:
5439 // calculate one pair of M E s
5440  ilax2 = 0;
5441  mnmnot(ilax, ilax2, val2pl, val2mi);
5442  if (fLnewmn) goto L650;
5443 // update NGOOD and NBAD
5444  iin = fNiofex[ilax-1];
5445  if (fErp[iin-1] > 0) ++ngood;
5446  else ++nbad;
5447  if (fErn[iin-1] < 0) ++ngood;
5448  else ++nbad;
5449  }
5450 // end of loop
5451 // printout final values
5452  fCfrom = "MINOS ";
5453  fNfcnfr = nfcnmi;
5454  fCstatu = "UNCHANGED ";
5455  if (ngood == 0 && nbad == 0) goto L700;
5456  if (ngood > 0 && nbad == 0) fCstatu = "SUCCESSFUL";
5457  if (ngood == 0 && nbad > 0) fCstatu = "FAILURE ";
5458  if (ngood > 0 && nbad > 0) fCstatu = "PROBLEMS ";
5459  if (fISW[4] >= 0) mnprin(4, fAmin);
5460  if (fISW[4] >= 2) mnmatu(0);
5461  return;
5462 // new minimum found
5463 L650:
5464  fCfrom = "MINOS ";
5465  fNfcnfr = nfcnmi;
5466  fCstatu = "NEW MINIMU";
5467  if (fISW[4] >= 0) mnprin(4, fAmin);
5468  Printf(" NEW MINIMUM FOUND. GO BACK TO MINIMIZATION STEP.");
5469  Printf(" =================================================");
5470  Printf(" V");
5471  Printf(" V");
5472  Printf(" V");
5473  Printf(" VVVVVVV");
5474  Printf(" VVVVV");
5475  Printf(" VVV");
5476  Printf(" V\n");
5477  return;
5478 L700:
5479  Printf(" THERE ARE NO MINOS ERRORS TO CALCULATE.");
5480 }
5481 
5482 ////////////////////////////////////////////////////////////////////////////////
5483 /// Performs a MINOS error analysis on one parameter
5484 ///
5485 /// The parameter ILAX is varied, and the minimum of the
5486 /// function with respect to the other parameters is followed
5487 /// until it crosses the value FMIN+UP.
5488 
5489 void TMinuit::mnmnot(Int_t ilax, Int_t ilax2, Double_t &val2pl, Double_t &val2mi)
5490 {
5491  /* System generated locals */
5492  Int_t i__1;
5493 
5494  /* Local variables */
5495  Double_t delu, aopt, eros;
5496  Double_t abest, xunit, dc, ut, sigsav, du1;
5497  Double_t fac, sig, sav;
5498  Int_t marc, isig, mpar, ndex, imax, indx, ierr, i, j;
5499  Int_t iercr, it, istrav, nfmxin, nlimit, isw2, isw4;
5500  TString csig;
5501 
5502 // save and prepare start vals
5503  isw2 = fISW[1];
5504  isw4 = fISW[3];
5505  sigsav = fEDM;
5506  istrav = fIstrat;
5507  dc = fDcovar;
5508  fLnewmn = kFALSE;
5509  fApsi = fEpsi*.5;
5510  abest = fAmin;
5511  mpar = fNpar;
5512  nfmxin = fNfcnmx;
5513  for (i = 1; i <= mpar; ++i) { fXt[i-1] = fX[i-1]; }
5514  i__1 = mpar*(mpar + 1) / 2;
5515  for (j = 1; j <= i__1; ++j) { fVthmat[j-1] = fVhmat[j-1]; }
5516  for (i = 1; i <= mpar; ++i) {
5517  fMNOTgcc[i-1] = fGlobcc[i-1];
5518  fMNOTw[i-1] = fWerr[i-1];
5519  }
5520  it = fNiofex[ilax-1];
5521  fErp[it-1] = 0;
5522  fErn[it-1] = 0;
5523  mninex(fXt);
5524  ut = fU[ilax-1];
5525  if (fNvarl[ilax-1] == 1) {
5526  fAlim[ilax-1] = ut - fMNOTw[it-1]*100;
5527  fBlim[ilax-1] = ut + fMNOTw[it-1]*100;
5528  }
5529  ndex = it*(it + 1) / 2;
5530  xunit = TMath::Sqrt(fUp / fVthmat[ndex-1]);
5531  marc = 0;
5532  for (i = 1; i <= mpar; ++i) {
5533  if (i == it) continue;
5534  ++marc;
5535  imax = TMath::Max(it,i);
5536  indx = imax*(imax-1) / 2 + TMath::Min(it,i);
5537  fMNOTxdev[marc-1] = xunit*fVthmat[indx-1];
5538  }
5539 // fix the parameter in question
5540  mnfixp(it-1, ierr);
5541  if (ierr > 0) {
5542  Printf(" MINUIT ERROR. CANNOT FIX PARAMETER %4d INTERNAL %3d",ilax,it);
5543  goto L700;
5544  }
5545 // Nota Bene: from here on, NPAR=MPAR-1
5546 // Remember: MNFIXP squeezes IT out of X, XT, WERR, and VHMAT,
5547 // not W, VTHMAT
5548  for (isig = 1; isig <= 2; ++isig) {
5549  if (isig == 1) {
5550  sig = 1;
5551  csig = "POSI";
5552  } else {
5553  sig = -1;
5554  csig = "NEGA";
5555  }
5556 // sig=sign of error being calcd
5557  if (fISW[4] > 1) {
5558  Printf(" DETERMINATION OF %sTIVE MINOS ERROR FOR PARAMETER %d %s"
5559  ,(const char*)csig,ilax
5560  ,(const char*)fCpnam[ilax-1]);
5561  }
5562  if (fISW[1] <= 0) {
5563  mnwarn("D", "MINOS", "NO COVARIANCE MATRIX.");
5564  }
5565  nlimit = fNfcn + nfmxin;
5566  fIstrat = TMath::Max(istrav-1,0);
5567  du1 = fMNOTw[it-1];
5568  fU[ilax-1] = ut + sig*du1;
5569  fU[ilax-1] = TMath::Min(fU[ilax-1],fBlim[ilax-1]);
5570  fU[ilax-1] = TMath::Max(fU[ilax-1],fAlim[ilax-1]);
5571  delu = fU[ilax-1] - ut;
5572 // stop if already at limit with negligible step size
5573  if (TMath::Abs(delu) / (TMath::Abs(ut) + TMath::Abs(fU[ilax-1])) < fEpsmac) goto L440;
5574  fac = delu / fMNOTw[it-1];
5575  for (i = 1; i <= fNpar; ++i) {
5576  fX[i-1] = fXt[i-1] + fac*fMNOTxdev[i-1];
5577  }
5578  if (fISW[4] > 1) {
5579  Printf(" PARAMETER %4d SET TO%11.3e + %10.3e = %12.3e",ilax,ut,delu,fU[ilax-1]);
5580  }
5581 // loop to hit AMIN+UP
5582  fKe1cr = ilax;
5583  fKe2cr = 0;
5584  fXmidcr = fU[ilax-1];
5585  fXdircr = delu;
5586 
5587  fAmin = abest;
5588  fNfcnmx = nlimit - fNfcn;
5589  mncros(aopt, iercr);
5590  if (abest - fAmin > fUp*.01) goto L650;
5591  if (iercr == 1) goto L440;
5592  if (iercr == 2) goto L450;
5593  if (iercr == 3) goto L460;
5594 // error successfully calculated
5595  eros = fXmidcr - ut + aopt*fXdircr;
5596  if (fISW[4] > 1) {
5597  Printf(" THE %4sTIVE MINOS ERROR OF PARAMETER %3d %10s, IS %12.4e"
5598  ,(const char*)csig,ilax
5599  ,(const char*)fCpnam[ilax-1],eros);
5600  }
5601  goto L480;
5602 // failure returns
5603 L440:
5604  if (fISW[4] >= 1) {
5605  Printf(" THE %4sTIVE MINOS ERROR OF PARAMETER %3d, %s EXCEEDS ITS LIMIT."
5606  ,(const char*)csig,ilax
5607  ,(const char*)fCpnam[ilax-1]);
5608  }
5609  eros = fUndefi;
5610  goto L480;
5611 L450:
5612  if (fISW[4] >= 1) {
5613  Printf(" THE %4sTIVE MINOS ERROR %4d REQUIRES MORE THAN %5d FUNCTION CALLS."
5614  ,(const char*)csig,ilax,nfmxin);
5615  }
5616  eros = 0;
5617  goto L480;
5618 L460:
5619  if (fISW[4] >= 1) {
5620  Printf(" %4sTIVE MINOS ERROR NOT CALCULATED FOR PARAMETER %d"
5621  ,(const char*)csig,ilax);
5622  }
5623  eros = 0;
5624 
5625 L480:
5626  if (fISW[4] > 1)