Logo ROOT   6.14/05
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;
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;
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 
809 Int_t TMinuit::Eval(Int_t npar, Double_t *grad, Double_t &fval, Double_t *par, Int_t flag)
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);
949  Double_t result;
950  m->Execute(result);
951 }
952 
953 ////////////////////////////////////////////////////////////////////////////////
954 /// set Minuit print level.
955 ///
956 /// printlevel:
957 /// - = -1 quiet (also suppress all warnings)
958 /// - = 0 normal
959 /// - = 1 verbose
960 
962 {
963  Int_t err;
964  Double_t tmp[1];
965  tmp[0] = printLevel;
966 
967  mnexcm( "SET PRINT", tmp, 1, err );
968 
969  if (printLevel <=-1) mnexcm("SET NOWarnings",tmp,0,err);
970 
971  return err;
972 }
973 
974 ////////////////////////////////////////////////////////////////////////////////
975 /// Initialize AMIN
976 ///
977 /// Called from many places. Initializes the value of AMIN by
978 /// calling the user function. Prints out the function value and
979 /// parameter values if Print Flag value is high enough.
980 
982 {
983  /* Local variables */
984  Double_t fnew;
985  Int_t nparx;
986 
987  nparx = fNpar;
988  if (fISW[4] >= 1) {
989  Printf(" FIRST CALL TO USER FUNCTION AT NEW START POINT, WITH IFLAG=4.");
990  }
991  mnexin(fX);
992  Eval(nparx, fGin, fnew, fU, 4); ++fNfcn;
993  fAmin = fnew;
994  fEDM = fBigedm;
995 }
996 
997 ////////////////////////////////////////////////////////////////////////////////
998 /// Compute reasonable histogram intervals
999 ///
1000 /// Function TO DETERMINE REASONABLE HISTOGRAM INTERVALS
1001 /// GIVEN ABSOLUTE UPPER AND LOWER BOUNDS A1 AND A2
1002 /// AND DESIRED MAXIMUM NUMBER OF BINS NAA
1003 /// PROGRAM MAKES REASONABLE BINNING FROM BL TO BH OF WIDTH BWID
1004 /// F. JAMES, AUGUST, 1974 , stolen for Minuit, 1988
1005 
1006 void TMinuit::mnbins(Double_t a1, Double_t a2, Int_t naa, Double_t &bl, Double_t &bh, Int_t &nb, Double_t &bwid)
1007 {
1008  /* Local variables */
1009  Double_t awid,ah, al, sigfig, sigrnd, alb;
1010  Int_t kwid, lwid, na=0, log_;
1011 
1012  al = TMath::Min(a1,a2);
1013  ah = TMath::Max(a1,a2);
1014  if (al == ah) ah = al + 1;
1015 
1016 // IF NAA .EQ. -1 , PROGRAM USES BWID INPUT FROM CALLING ROUTINE
1017  if (naa == -1) goto L150;
1018 L10:
1019  na = naa - 1;
1020  if (na < 1) na = 1;
1021 
1022 // GET NOMINAL BIN WIDTH IN EXPON FORM
1023 L20:
1024  awid = (ah-al) / Double_t(na);
1025  log_ = Int_t(TMath::Log10(awid));
1026  if (awid <= 1) --log_;
1027  sigfig = awid*TMath::Power(10, -log_);
1028 // ROUND MANTISSA UP TO 2, 2.5, 5, OR 10
1029  if (sigfig > 2) goto L40;
1030  sigrnd = 2;
1031  goto L100;
1032 L40:
1033  if (sigfig > 2.5) goto L50;
1034  sigrnd = 2.5;
1035  goto L100;
1036 L50:
1037  if (sigfig > 5) goto L60;
1038  sigrnd = 5;
1039  goto L100;
1040 L60:
1041  sigrnd = 1;
1042  ++log_;
1043 L100:
1044  bwid = sigrnd*TMath::Power(10, log_);
1045  goto L200;
1046 // GET NEW BOUNDS FROM NEW WIDTH BWID
1047 L150:
1048  if (bwid <= 0) goto L10;
1049 L200:
1050  alb = al / bwid;
1051  lwid = Int_t(alb);
1052  if (alb < 0) --lwid;
1053  bl = bwid*Double_t(lwid);
1054  alb = ah / bwid + 1;
1055  kwid = Int_t(alb);
1056  if (alb < 0) --kwid;
1057  bh = bwid*Double_t(kwid);
1058  nb = kwid - lwid;
1059  if (naa > 5) goto L240;
1060  if (naa == -1) return;
1061 // REQUEST FOR ONE BIN IS DIFFICULT CASE
1062  if (naa > 1 || nb == 1) return;
1063  bwid *= 2;
1064  nb = 1;
1065  return;
1066 L240:
1067  if (nb << 1 != naa) return;
1068  ++na;
1069  goto L20;
1070 }
1071 
1072 ////////////////////////////////////////////////////////////////////////////////
1073 /// Transform FCN to find further minima
1074 ///
1075 /// Called only from MNIMPR. Transforms the function FCN
1076 /// by dividing out the quadratic part in order to find further
1077 /// minima. Calculates `ycalf = (f-fmin)/(x-xmin)*v*(x-xmin)`
1078 
1079 void TMinuit::mncalf(Double_t *pvec, Double_t &ycalf)
1080 {
1081  /* Local variables */
1082  Int_t ndex, i, j, m, n, nparx;
1083  Double_t denom, f;
1084 
1085  nparx = fNpar;
1086  mninex(&pvec[0]);
1087  Eval(nparx, fGin, f, fU, 4); ++fNfcn;
1088  for (i = 1; i <= fNpar; ++i) {
1089  fGrd[i-1] = 0;
1090  for (j = 1; j <= fNpar; ++j) {
1091  m = TMath::Max(i,j);
1092  n = TMath::Min(i,j);
1093  ndex = m*(m-1) / 2 + n;
1094  fGrd[i-1] += fVthmat[ndex-1]*(fXt[j-1] - pvec[j-1]);
1095  }
1096  }
1097  denom = 0;
1098  for (i = 1; i <= fNpar; ++i) {denom += fGrd[i-1]*(fXt[i-1] - pvec[i-1]); }
1099  if (denom <= 0) {
1100  fDcovar = 1;
1101  fISW[1] = 0;
1102  denom = 1;
1103  }
1104  ycalf = (f - fApsi) / denom;
1105 }
1106 
1107 ////////////////////////////////////////////////////////////////////////////////
1108 /// Resets the parameter list to UNDEFINED
1109 ///
1110 /// Called from MINUIT and by option from MNEXCM
1111 
1113 {
1114  Int_t i;
1115 
1116  fNpfix = 0;
1117  fNu = 0;
1118  fNpar = 0;
1119  fNfcn = 0;
1120  fNwrmes[0] = 0;
1121  fNwrmes[1] = 0;
1122  for (i = 1; i <= fMaxext; ++i) {
1123  fU[i-1] = 0;
1124  fCpnam[i-1] = fCundef;
1125  fNvarl[i-1] = -1;
1126  fNiofex[i-1] = 0;
1127  }
1128  mnrset(1);
1129  fCfrom = "CLEAR ";
1130  fNfcnfr = fNfcn;
1131  fCstatu = "UNDEFINED ";
1132  fLnolim = kTRUE;
1133  fLphead = kTRUE;
1134 }
1135 
1136 ////////////////////////////////////////////////////////////////////////////////
1137 /// Print function contours in two variables, on line printer
1138 ///
1139 /// input arguments: parx, pary, devs, ngrid
1140 
1141 void TMinuit::mncntr(Int_t ike1, Int_t ike2, Int_t &ierrf)
1142 {
1143  static const char *const clabel = "0123456789ABCDEFGHIJ";
1144 
1145  /* Local variables */
1146  Double_t d__1, d__2;
1147  Double_t fcna[115], fcnb[115], contur[20];
1148  Double_t ylabel, fmn, fmx, xlo, ylo, xup, yup;
1149  Double_t devs, xsav, ysav, bwidx, bwidy, unext, ff, xb4;
1150  Int_t i, ngrid, ixmid, nparx, ix, nx, ny, ki1, ki2, ixzero, iy, ics;
1151  TString chmid, chln, chzero;
1152 
1153  Int_t ke1 = ike1+1;
1154  Int_t ke2 = ike2+1;
1155  if (ke1 <= 0 || ke2 <= 0) goto L1350;
1156  if (ke1 > fNu || ke2 > fNu) goto L1350;
1157  ki1 = fNiofex[ke1-1];
1158  ki2 = fNiofex[ke2-1];
1159  if (ki1 <= 0 || ki2 <= 0) goto L1350;
1160  if (ki1 == ki2) goto L1350;
1161 
1162  if (fISW[1] < 1) {
1163  mnhess();
1164  mnwerr();
1165  }
1166  nparx = fNpar;
1167  xsav = fU[ke1-1];
1168  ysav = fU[ke2-1];
1169  devs = fWord7[2];
1170  if (devs <= 0) devs = 2;
1171  xlo = fU[ke1-1] - devs*fWerr[ki1-1];
1172  xup = fU[ke1-1] + devs*fWerr[ki1-1];
1173  ylo = fU[ke2-1] - devs*fWerr[ki2-1];
1174  yup = fU[ke2-1] + devs*fWerr[ki2-1];
1175  ngrid = Int_t(fWord7[3]);
1176  if (ngrid <= 0) {
1177  ngrid = 25;
1178 // Computing MIN
1179  nx = TMath::Min(fNpagwd - 15,ngrid);
1180 // Computing MIN
1181  ny = TMath::Min(fNpagln - 7,ngrid);
1182  } else {
1183  nx = ngrid;
1184  ny = ngrid;
1185  }
1186  if (nx < 11) nx = 11;
1187  if (ny < 11) ny = 11;
1188  if (nx >= 115) nx = 114;
1189 
1190 // ask if parameter outside limits
1191  if (fNvarl[ke1-1] > 1) {
1192  if (xlo < fAlim[ke1-1]) xlo = fAlim[ke1-1];
1193  if (xup > fBlim[ke1-1]) xup = fBlim[ke1-1];
1194  }
1195  if (fNvarl[ke2-1] > 1) {
1196  if (ylo < fAlim[ke2-1]) ylo = fAlim[ke2-1];
1197  if (yup > fBlim[ke2-1]) yup = fBlim[ke2-1];
1198  }
1199  bwidx = (xup - xlo) / Double_t(nx);
1200  bwidy = (yup - ylo) / Double_t(ny);
1201  ixmid = Int_t(((xsav - xlo)*Double_t(nx) / (xup - xlo)) + 1);
1202  if (ixmid < 1) ixmid = 1;
1203  if (fAmin == fUndefi) mnamin();
1204 
1205  for (i = 1; i <= 20; ++i) { contur[i-1] = fAmin + fUp*(i-1)*(i-1); }
1206  contur[0] += fUp*.01;
1207 // fill FCNB to prepare first row, and find column zero/
1208  fU[ke2-1] = yup;
1209  ixzero = 0;
1210  xb4 = 1;
1211 //TH
1212  chmid.Resize(nx+1);
1213  chzero.Resize(nx+1);
1214  chln.Resize(nx+1);
1215  for (ix = 1; ix <= nx + 1; ++ix) {
1216  fU[ke1-1] = xlo + Double_t(ix-1)*bwidx;
1217  Eval(nparx, fGin, ff, fU, 4);
1218  fcnb[ix-1] = ff;
1219  if (xb4 < 0 && fU[ke1-1] > 0) ixzero = ix - 1;
1220  xb4 = fU[ke1-1];
1221  chmid[ix-1] = '*';
1222  chzero[ix-1] = '-';
1223  }
1224  Printf(" Y-AXIS: PARAMETER %3d: %s",ke2,(const char*)fCpnam[ke2-1]);
1225  if (ixzero > 0) {
1226  chzero[ixzero-1] = '+';
1227  chln = " ";
1228  Printf(" X=0");
1229  }
1230 // loop over rows
1231  for (iy = 1; iy <= ny; ++iy) {
1232  unext = fU[ke2-1] - bwidy;
1233 // prepare this line background pattern for contour
1234  chln = " ";
1235 // TH
1236  chln.Resize(nx+1);
1237  chln[ixmid-1] = '*';
1238  if (ixzero != 0) chln[ixzero-1] = ':';
1239  if (fU[ke2-1] > ysav && unext < ysav) chln = chmid;
1240  if (fU[ke2-1] > 0 && unext < 0) chln = chzero;
1241  fU[ke2-1] = unext;
1242  ylabel = fU[ke2-1] + bwidy*.5;
1243 // move FCNB to FCNA and fill FCNB with next row
1244  for (ix = 1; ix <= nx + 1; ++ix) {
1245  fcna[ix-1] = fcnb[ix-1];
1246  fU[ke1-1] = xlo + Double_t(ix-1)*bwidx;
1247  Eval(nparx, fGin, ff, fU, 4);
1248  fcnb[ix-1] = ff;
1249  }
1250 // look for contours crossing the FCNxy squares
1251  for (ix = 1; ix <= nx; ++ix) {
1252  d__1 = TMath::Max(fcna[ix-1],fcnb[ix-1]),
1253  d__2 = TMath::Max(fcna[ix],fcnb[ix]);
1254  fmx = TMath::Max(d__1,d__2);
1255  d__1 = TMath::Min(fcna[ix-1],fcnb[ix-1]),
1256  d__2 = TMath::Min(fcna[ix],fcnb[ix]);
1257  fmn = TMath::Min(d__1,d__2);
1258  for (ics = 1; ics <= 20; ++ics) {
1259  if (contur[ics-1] > fmn) goto L240;
1260  }
1261  continue;
1262 L240:
1263  if (contur[ics-1] < fmx) chln[ix-1] = clabel[ics-1];
1264  }
1265 // print a row of the contour plot
1266  Printf(" %12.4g %s",ylabel,(const char*)chln);
1267  }
1268 // contours printed, label x-axis
1269  chln = " ";
1270  chln(0,1) = 'I';
1271  chln(ixmid-1,1) = 'I';
1272  chln(nx-1,1) = 'I';
1273  Printf(" %s",(const char*)chln);
1274 
1275 // the hardest of all: print x-axis scale!
1276  chln = " ";
1277  if (nx <= 26) {
1278  Printf(" %12.4g%s%12.4g",xlo,(const char*)chln,xup);
1279  Printf(" %s%12.4g",(const char*)chln,xsav);
1280  } else {
1281  Printf(" %12.4g%s%12.4g%s%12.4g",xlo,(const char*)chln,xsav,(const char*)chln,xup);
1282  }
1283  Printf(" X-AXIS: PARAMETER %3d %s ONE COLUMN=%12.4g"
1284  ,ke1,(const char*)fCpnam[ke1-1],bwidx);
1285  Printf(" FUNCTION VALUES: F(I)=%12.4g +%12.4g *I**2",fAmin,fUp);
1286 // finished. reset input values
1287  fU[ke1-1] = xsav;
1288  fU[ke2-1] = ysav;
1289  ierrf = 0;
1290  return;
1291 L1350:
1292  Printf(" INVALID PARAMETER NUMBER(S) REQUESTED. IGNORED.");
1293  ierrf = 1;
1294 }
1295 
1296 ////////////////////////////////////////////////////////////////////////////////
1297 /// Reads a command string and executes
1298 ///
1299 /// Called by user. 'Reads' a command string and executes.
1300 /// Equivalent to MNEXCM except that the command is given as a
1301 /// character string.
1302 ///
1303 /// ICONDN =
1304 /// - 0: command executed normally
1305 /// - 1: command is blank, ignored
1306 /// - 2: command line unreadable, ignored
1307 /// - 3: unknown command, ignored
1308 /// - 4: abnormal termination (e.g., MIGRAD not converged)
1309 /// - 5: command is a request to read PARAMETER definitions
1310 /// - 6: 'SET INPUT' command
1311 /// - 7: 'SET TITLE' command
1312 /// - 8: 'SET COVAR' command
1313 /// - 9: reserved
1314 /// - 10: END command
1315 /// - 11: EXIT or STOP command
1316 /// - 12: RETURN command
1317 ///
1318 
1319 void TMinuit::mncomd(const char *crdbin, Int_t &icondn)
1320 {
1321  /* Local variables */
1322  Int_t ierr, ipos, i, llist, lenbuf, lnc;
1323  Bool_t leader;
1324  TString comand, crdbuf, ctemp;
1325 
1326  crdbuf = crdbin;
1327  crdbuf.ToUpper();
1328  lenbuf = crdbuf.Length();
1329  icondn = 0;
1330 // record not case-sensitive, get upper case, strip leading blanks
1331  leader = kTRUE;
1332  ipos = 1;
1333  for (i = 1; i <= TMath::Min(20,lenbuf); ++i) {
1334  if (crdbuf[i-1] == '\'') break;
1335  if (crdbuf[i-1] == ' ') {
1336  if (leader) ++ipos;
1337  continue;
1338  }
1339  leader = kFALSE;
1340  }
1341 
1342 // blank or null command
1343  if (ipos > lenbuf) {
1344  Printf(" BLANK COMMAND IGNORED.");
1345  icondn = 1;
1346  return;
1347  }
1348 // preemptive commands
1349 // if command is 'PARAMETER'
1350  if (crdbuf(ipos-1,3) == "PAR") {
1351  icondn = 5;
1352  fLphead = kTRUE;
1353  return;
1354  }
1355 // if command is 'SET INPUT'
1356  if (crdbuf(ipos-1,3) == "SET INP") {
1357  icondn = 6;
1358  fLphead = kTRUE;
1359  return;
1360  }
1361 // if command is 'SET TITLE'
1362  if (crdbuf(ipos-1,7) == "SET TIT") {
1363  icondn = 7;
1364  fLphead = kTRUE;
1365  return;
1366  }
1367 // if command is 'SET COVARIANCE'
1368  if (crdbuf(ipos-1,7) == "SET COV") {
1369  icondn = 8;
1370  fLphead = kTRUE;
1371  return;
1372  }
1373 // crack the command
1374  ctemp = crdbuf(ipos-1,lenbuf-ipos+1);
1375  mncrck(ctemp, 20, comand, lnc, fMaxpar, fCOMDplist, llist, ierr, fIsyswr);
1376  if (ierr > 0) {
1377  Printf(" COMMAND CANNOT BE INTERPRETED");
1378  icondn = 2;
1379  return;
1380  }
1381 
1382  mnexcm(comand.Data(), fCOMDplist, llist, ierr);
1383  icondn = ierr;
1384 }
1385 
1386 ////////////////////////////////////////////////////////////////////////////////
1387 /// Find points along a contour where FCN is minimum
1388 ///
1389 /// Find NPTU points along a contour where the function
1390 ///
1391 /// FMIN (X(KE1),X(KE2)) = AMIN+UP
1392 ///
1393 /// where FMIN is the minimum of FCN with respect to all
1394 /// the other NPAR-2 variable parameters (if any).
1395 ///
1396 /// IERRF on return will be equal to the number of points found:
1397 /// - NPTU if normal termination with NPTU points found
1398 /// - -1 if errors in the calling sequence (KE1, KE2 not variable)
1399 /// - 0 if less than four points can be found (using MNMNOT)
1400 /// - n>3 if only n points can be found (n < NPTU)
1401 ///
1402 /// input arguments: parx, pary, devs, ngrid
1403 
1404 void TMinuit::mncont(Int_t ike1, Int_t ike2, Int_t nptu, Double_t *xptu, Double_t *yptu, Int_t &ierrf)
1405 {
1406  /* System generated locals */
1407  Int_t i__1;
1408 
1409  /* Local variables */
1410  Double_t d__1, d__2;
1411  Double_t dist, xdir, ydir, aopt, u1min, u2min;
1412  Double_t abest, scalx, scaly;
1413  Double_t a1, a2, val2mi, val2pl, dc, sclfac, bigdis, sigsav;
1414  Int_t nall, iold, line, mpar, ierr, inew, move, next, i, j, nfcol, iercr;
1415  Int_t idist=0, npcol, kints, i2, i1, lr, nfcnco=0, ki1, ki2, ki3, ke3;
1416  Int_t nowpts, istrav, nfmxin, isw2, isw4;
1417  Bool_t ldebug;
1418 
1419  /* Function Body */
1420  Int_t ke1 = ike1+1;
1421  Int_t ke2 = ike2+1;
1422  ldebug = fIdbg[6] >= 1;
1423  if (ke1 <= 0 || ke2 <= 0) goto L1350;
1424  if (ke1 > fNu || ke2 > fNu) goto L1350;
1425  ki1 = fNiofex[ke1-1];
1426  ki2 = fNiofex[ke2-1];
1427  if (ki1 <= 0 || ki2 <= 0) goto L1350;
1428  if (ki1 == ki2) goto L1350;
1429  if (nptu < 4) goto L1400;
1430 
1431  nfcnco = fNfcn;
1432  fNfcnmx = (nptu + 5)*100*(fNpar + 1);
1433 // The minimum
1434  mncuve();
1435  u1min = fU[ke1-1];
1436  u2min = fU[ke2-1];
1437  ierrf = 0;
1438  fCfrom = "MNContour ";
1439  fNfcnfr = nfcnco;
1440  if (fISW[4] >= 0) {
1441  Printf(" START MNCONTOUR CALCULATION OF %4d POINTS ON CONTOUR.",nptu);
1442  if (fNpar > 2) {
1443  if (fNpar == 3) {
1444  ki3 = 6 - ki1 - ki2;
1445  ke3 = fNexofi[ki3-1];
1446  Printf(" EACH POINT IS A MINIMUM WITH RESPECT TO PARAMETER %3d %s",ke3,(const char*)fCpnam[ke3-1]);
1447  } else {
1448  Printf(" EACH POINT IS A MINIMUM WITH RESPECT TO THE OTHER %3d VARIABLE PARAMETERS.",fNpar - 2);
1449  }
1450  }
1451  }
1452 
1453 // Find the first four points using MNMNOT
1454 // first two points
1455  mnmnot(ke1, ke2, val2pl, val2mi);
1456  if (fErn[ki1-1] == fUndefi) {
1457  xptu[0] = fAlim[ke1-1];
1458  mnwarn("W", "MNContour ", "Contour squeezed by parameter limits.");
1459  } else {
1460  if (fErn[ki1-1] >= 0) goto L1500;
1461  xptu[0] = u1min + fErn[ki1-1];
1462  }
1463  yptu[0] = val2mi;
1464 
1465  if (fErp[ki1-1] == fUndefi) {
1466  xptu[2] = fBlim[ke1-1];
1467  mnwarn("W", "MNContour ", "Contour squeezed by parameter limits.");
1468  } else {
1469  if (fErp[ki1-1] <= 0) goto L1500;
1470  xptu[2] = u1min + fErp[ki1-1];
1471  }
1472  yptu[2] = val2pl;
1473  scalx = 1 / (xptu[2] - xptu[0]);
1474 // next two points
1475  mnmnot(ke2, ke1, val2pl, val2mi);
1476  if (fErn[ki2-1] == fUndefi) {
1477  yptu[1] = fAlim[ke2-1];
1478  mnwarn("W", "MNContour ", "Contour squeezed by parameter limits.");
1479  } else {
1480  if (fErn[ki2-1] >= 0) goto L1500;
1481  yptu[1] = u2min + fErn[ki2-1];
1482  }
1483  xptu[1] = val2mi;
1484  if (fErp[ki2-1] == fUndefi) {
1485  yptu[3] = fBlim[ke2-1];
1486  mnwarn("W", "MNContour ", "Contour squeezed by parameter limits.");
1487  } else {
1488  if (fErp[ki2-1] <= 0) goto L1500;
1489  yptu[3] = u2min + fErp[ki2-1];
1490  }
1491  xptu[3] = val2pl;
1492  scaly = 1 / (yptu[3] - yptu[1]);
1493  nowpts = 4;
1494  next = 5;
1495  if (ldebug) {
1496  Printf(" Plot of four points found by MINOS");
1497  fXpt[0] = u1min;
1498  fYpt[0] = u2min;
1499  fChpt[0] = ' ';
1500 // Computing MIN
1501  nall = TMath::Min(nowpts + 1,101);
1502  for (i = 2; i <= nall; ++i) {
1503  fXpt[i-1] = xptu[i-2];
1504  fYpt[i-1] = yptu[i-2];
1505  }
1506  sprintf(fChpt,"%s"," ABCD");
1507  mnplot(fXpt, fYpt, fChpt, nall, fNpagwd, fNpagln);
1508  }
1509 
1510 // save some values before fixing
1511  isw2 = fISW[1];
1512  isw4 = fISW[3];
1513  sigsav = fEDM;
1514  istrav = fIstrat;
1515  dc = fDcovar;
1516  fApsi = fEpsi*.5;
1517  abest = fAmin;
1518  mpar = fNpar;
1519  nfmxin = fNfcnmx;
1520  for (i = 1; i <= mpar; ++i) { fXt[i-1] = fX[i-1]; }
1521  i__1 = mpar*(mpar + 1) / 2;
1522  for (j = 1; j <= i__1; ++j) { fVthmat[j-1] = fVhmat[j-1]; }
1523  for (i = 1; i <= mpar; ++i) {
1524  fCONTgcc[i-1] = fGlobcc[i-1];
1525  fCONTw[i-1] = fWerr[i-1];
1526  }
1527 // fix the two parameters in question
1528  kints = fNiofex[ke1-1];
1529  mnfixp(kints-1, ierr);
1530  kints = fNiofex[ke2-1];
1531  mnfixp(kints-1, ierr);
1532 // Fill in the rest of the points
1533  for (inew = next; inew <= nptu; ++inew) {
1534 // find the two neighbouring points with largest separation
1535  bigdis = 0;
1536  for (iold = 1; iold <= inew - 1; ++iold) {
1537  i2 = iold + 1;
1538  if (i2 == inew) i2 = 1;
1539  d__1 = scalx*(xptu[iold-1] - xptu[i2-1]);
1540  d__2 = scaly*(yptu[iold-1] - yptu[i2-1]);
1541  dist = d__1*d__1 + d__2*d__2;
1542  if (dist > bigdis) {
1543  bigdis = dist;
1544  idist = iold;
1545  }
1546  }
1547  i1 = idist;
1548  i2 = i1 + 1;
1549  if (i2 == inew) i2 = 1;
1550 // next point goes between I1 and I2
1551  a1 = .5;
1552  a2 = .5;
1553 L300:
1554  fXmidcr = a1*xptu[i1-1] + a2*xptu[i2-1];
1555  fYmidcr = a1*yptu[i1-1] + a2*yptu[i2-1];
1556  xdir = yptu[i2-1] - yptu[i1-1];
1557  ydir = xptu[i1-1] - xptu[i2-1];
1558  sclfac = TMath::Max(TMath::Abs(xdir*scalx),TMath::Abs(ydir*scaly));
1559  fXdircr = xdir / sclfac;
1560  fYdircr = ydir / sclfac;
1561  fKe1cr = ke1;
1562  fKe2cr = ke2;
1563 // Find the contour crossing point along DIR
1564  fAmin = abest;
1565  mncros(aopt, iercr);
1566  if (iercr > 1) {
1567 // If cannot find mid-point, try closer to point 1
1568  if (a1 > .5) {
1569  if (fISW[4] >= 0) {
1570  Printf(" MNCONT CANNOT FIND NEXT POINT ON CONTOUR. ONLY %3d POINTS FOUND.",nowpts);
1571  }
1572  goto L950;
1573  }
1574  mnwarn("W", "MNContour ", "Cannot find midpoint, try closer.");
1575  a1 = .75;
1576  a2 = .25;
1577  goto L300;
1578  }
1579 // Contour has been located, insert new point in list
1580  for (move = nowpts; move >= i1 + 1; --move) {
1581  xptu[move] = xptu[move-1];
1582  yptu[move] = yptu[move-1];
1583  }
1584  ++nowpts;
1585  xptu[i1] = fXmidcr + fXdircr*aopt;
1586  yptu[i1] = fYmidcr + fYdircr*aopt;
1587  }
1588 L950:
1589 
1590  ierrf = nowpts;
1591  fCstatu = "SUCCESSFUL";
1592  if (nowpts < nptu) fCstatu = "INCOMPLETE";
1593 
1594 // make a lineprinter plot of the contour
1595  if (fISW[4] >= 0) {
1596  fXpt[0] = u1min;
1597  fYpt[0] = u2min;
1598  fChpt[0] = ' ';
1599  nall = TMath::Min(nowpts + 1,101);
1600  for (i = 2; i <= nall; ++i) {
1601  fXpt[i-1] = xptu[i-2];
1602  fYpt[i-1] = yptu[i-2];
1603  fChpt[i-1] = 'X';
1604  }
1605  fChpt[nall] = 0;
1606  Printf(" Y-AXIS: PARAMETER %3d %s",ke2,(const char*)fCpnam[ke2-1]);
1607 
1608  mnplot(fXpt, fYpt, fChpt, nall, fNpagwd, fNpagln);
1609 
1610  Printf(" X-AXIS: PARAMETER %3d %s",ke1,(const char*)fCpnam[ke1-1]);
1611  }
1612 // print out the coordinates around the contour
1613  if (fISW[4] >= 1) {
1614  npcol = (nowpts + 1) / 2;
1615  nfcol = nowpts / 2;
1616  Printf("%5d POINTS ON CONTOUR. FMIN=%13.5e ERRDEF=%11.3g",nowpts,abest,fUp);
1617  Printf(" %s%s%s%s",(const char*)fCpnam[ke1-1],
1618  (const char*)fCpnam[ke2-1],
1619  (const char*)fCpnam[ke1-1],
1620  (const char*)fCpnam[ke2-1]);
1621  for (line = 1; line <= nfcol; ++line) {
1622  lr = line + npcol;
1623  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]);
1624  }
1625  if (nfcol < npcol) {
1626  Printf(" %5d%13.5e%13.5e",npcol,xptu[npcol-1],yptu[npcol-1]);
1627  }
1628  }
1629 // contour finished. reset v
1630  fItaur = 1;
1631  mnfree(1);
1632  mnfree(1);
1633  i__1 = mpar*(mpar + 1) / 2;
1634  for (j = 1; j <= i__1; ++j) { fVhmat[j-1] = fVthmat[j-1]; }
1635  for (i = 1; i <= mpar; ++i) {
1636  fGlobcc[i-1] = fCONTgcc[i-1];
1637  fWerr[i-1] = fCONTw[i-1];
1638  fX[i-1] = fXt[i-1];
1639  }
1640  mninex(fX);
1641  fEDM = sigsav;
1642  fAmin = abest;
1643  fISW[1] = isw2;
1644  fISW[3] = isw4;
1645  fDcovar = dc;
1646  fItaur = 0;
1647  fNfcnmx = nfmxin;
1648  fIstrat = istrav;
1649  fU[ke1-1] = u1min;
1650  fU[ke2-1] = u2min;
1651  goto L2000;
1652 // Error returns
1653 L1350:
1654  Printf(" INVALID PARAMETER NUMBERS.");
1655  goto L1450;
1656 L1400:
1657  Printf(" LESS THAN FOUR POINTS REQUESTED.");
1658 L1450:
1659  ierrf = -1;
1660  fCstatu = "USER ERROR";
1661  goto L2000;
1662 L1500:
1663  Printf(" MNCONT UNABLE TO FIND FOUR POINTS.");
1664  fU[ke1-1] = u1min;
1665  fU[ke2-1] = u2min;
1666  ierrf = 0;
1667  fCstatu = "FAILED";
1668 L2000:
1669  fCfrom = "MNContour ";
1670  fNfcnfr = nfcnco;
1671 }
1672 
1673 ////////////////////////////////////////////////////////////////////////////////
1674 /// Cracks the free-format input
1675 ///
1676 /// Cracks the free-format input, expecting zero or more
1677 /// alphanumeric fields (which it joins into COMAND(1:LNC))
1678 /// followed by one or more numeric fields separated by
1679 /// blanks and/or one comma. The numeric fields are put into
1680 /// the LLIST (but at most MXP) elements of PLIST.
1681 ///
1682 /// IERR :
1683 /// - = 0 if no errors,
1684 /// - = 1 if error(s).
1685 
1686 void TMinuit::mncrck(TString cardbuf, Int_t maxcwd, TString &comand, Int_t &lnc,
1687  Int_t mxp, Double_t *plist, Int_t &llist, Int_t &ierr, Int_t)
1688 {
1689  /* Initialized data */
1690 
1691  char *cnull = 0;
1692  const char *cnumer = "123456789-.0+";
1693 
1694  /* Local variables */
1695  Int_t ifld, iend, lend, left, nreq, ipos, kcmnd, nextb, ic, ibegin, ltoadd;
1696  Int_t ielmnt, lelmnt[25], nelmnt;
1697  TString ctemp;
1698  char *celmnt[25];
1699  char command[25];
1700 
1701  /* Function Body */
1702  char *crdbuf = (char*)cardbuf.Data();
1703  lend = cardbuf.Length();
1704  ielmnt = 0;
1705  nextb = 1;
1706  ierr = 0;
1707 // loop over words CELMNT
1708 L10:
1709  for (ipos = nextb; ipos <= lend; ++ipos) {
1710  ibegin = ipos;
1711  if (crdbuf[ipos-1] == ' ') continue;
1712  if (crdbuf[ipos-1] == ',') goto L250;
1713  goto L150;
1714  }
1715  goto L300;
1716 L150:
1717 // found beginning of word, look for end
1718  for (ipos = ibegin + 1; ipos <= lend; ++ipos) {
1719  if (crdbuf[ipos-1] == ' ') goto L250;
1720  if (crdbuf[ipos-1] == ',') goto L250;
1721  }
1722  ipos = lend + 1;
1723 L250:
1724  iend = ipos - 1;
1725  ++ielmnt;
1726  if (iend >= ibegin) celmnt[ielmnt-1] = &crdbuf[ibegin-1];
1727  else celmnt[ielmnt-1] = cnull;
1728  lelmnt[ielmnt-1] = iend - ibegin + 1;
1729  if (lelmnt[ielmnt-1] > 19) {
1730  Printf(" MINUIT WARNING: INPUT DATA WORD TOO LONG.");
1731  ctemp = cardbuf(ibegin-1,iend-ibegin+1);
1732  Printf(" ORIGINAL:%s",ctemp.Data());
1733  Printf(" TRUNCATED TO:%s",celmnt[ielmnt-1]);
1734  lelmnt[ielmnt-1] = 19;
1735  }
1736  if (ipos >= lend) goto L300;
1737  if (ielmnt >= 25) goto L300;
1738 // look for comma or beginning of next word
1739  for (ipos = iend + 1; ipos <= lend; ++ipos) {
1740  if (crdbuf[ipos-1] == ' ') continue;
1741  nextb = ipos;
1742  if (crdbuf[ipos-1] == ',') nextb = ipos + 1;
1743  goto L10;
1744  }
1745 // All elements found, join the alphabetic ones to
1746 // form a command
1747 L300:
1748  nelmnt = ielmnt;
1749  command[0] = ' '; command[1] = 0;
1750  lnc = 1;
1751  plist[0] = 0;
1752  llist = 0;
1753  if (ielmnt == 0) goto L900;
1754  kcmnd = 0;
1755  for (ielmnt = 1; ielmnt <= nelmnt; ++ielmnt) {
1756  if ( celmnt[ielmnt-1] == cnull) goto L450;
1757  for (ic = 1; ic <= 13; ++ic) {
1758  if (*celmnt[ielmnt-1] == cnumer[ic-1]) goto L450;
1759  }
1760  if (kcmnd >= maxcwd) continue;
1761  left = maxcwd - kcmnd;
1762  ltoadd = lelmnt[ielmnt-1];
1763  if (ltoadd > left) ltoadd = left;
1764  strncpy(&command[kcmnd],celmnt[ielmnt-1],ltoadd);
1765  kcmnd += ltoadd;
1766  if (kcmnd == maxcwd) continue;
1767  command[kcmnd] = ' ';
1768  ++kcmnd;
1769  command[kcmnd] = 0;
1770  }
1771  lnc = kcmnd;
1772  goto L900;
1773 L450:
1774  lnc = kcmnd;
1775 // we have come to a numeric field
1776  llist = 0;
1777  for (ifld = ielmnt; ifld <= nelmnt; ++ifld) {
1778  ++llist;
1779  if (llist > mxp) {
1780  nreq = nelmnt - ielmnt + 1;
1781  Printf(" MINUIT WARNING IN MNCRCK: ");
1782  Printf(" COMMAND HAS INPUT %5d NUMERIC FIELDS, BUT MINUIT CAN ACCEPT ONLY%3d",nreq,mxp);
1783  goto L900;
1784  }
1785  if (celmnt[ifld-1] == cnull) plist[llist-1] = 0;
1786  else {
1787  sscanf(celmnt[ifld-1],"%lf",&plist[llist-1]);
1788  }
1789  }
1790 // end loop over numeric fields
1791 L900:
1792  if (lnc <= 0) lnc = 1;
1793  comand = command;
1794 }
1795 
1796 ////////////////////////////////////////////////////////////////////////////////
1797 /// Find point where MNEVAL=AMIN+UP
1798 ///
1799 /// Find point where MNEVAL=AMIN+UP, along the line through
1800 /// XMIDCR,YMIDCR with direction XDIRCR,YDIRCR, where X and Y
1801 /// are parameters KE1CR and KE2CR. If KE2CR=0 (from MINOS),
1802 /// only KE1CR is varied. From MNCONT, both are varied.
1803 /// Crossing point is at
1804 ///
1805 /// (U(KE1),U(KE2)) = (XMID,YMID) + AOPT*(XDIR,YDIR)
1806 
1807 void TMinuit::mncros(Double_t &aopt, Int_t &iercr)
1808 {
1809  /* Local variables */
1810  Double_t alsb[3], flsb[3], bmin, bmax, zmid, sdev, zdir, zlim;
1811  Double_t coeff[3], aleft, aulim, fdist, adist, aminsv;
1812  Double_t anext, fnext, slope, s1, s2, x1, x2, ecarmn, ecarmx;
1813  Double_t determ, rt, smalla, aright, aim, tla, tlf, dfda,ecart;
1814  Int_t iout=0, i, ileft, ierev, maxlk, ibest, ik, it;
1815  Int_t noless, iworst=0, iright, itoohi, kex, ipt;
1816  Bool_t ldebug;
1817  const char *chsign;
1818  x2 = 0;
1819 
1820  ldebug = fIdbg[6] >= 1;
1821  aminsv = fAmin;
1822 // convergence when F is within TLF of AIM and next prediction
1823 // of AOPT is within TLA of previous value of AOPT
1824  aim = fAmin + fUp;
1825  tlf = fUp*.01;
1826  tla = .01;
1827  fXpt[0] = 0;
1828  fYpt[0] = aim;
1829  fChpt[0] = ' ';
1830  ipt = 1;
1831  if (fKe2cr == 0) {
1832  fXpt[1] = -1;
1833  fYpt[1] = fAmin;
1834  fChpt[1] = '.';
1835  ipt = 2;
1836  }
1837 // find the largest allowed A
1838  aulim = 100;
1839  for (ik = 1; ik <= 2; ++ik) {
1840  if (ik == 1) {
1841  kex = fKe1cr;
1842  zmid = fXmidcr;
1843  zdir = fXdircr;
1844  } else {
1845  if (fKe2cr == 0) continue;
1846  kex = fKe2cr;
1847  zmid = fYmidcr;
1848  zdir = fYdircr;
1849  }
1850  if (fNvarl[kex-1] <= 1) continue;
1851  if (zdir == 0) continue;
1852  zlim = fAlim[kex-1];
1853  if (zdir > 0) zlim = fBlim[kex-1];
1854  aulim = TMath::Min(aulim,(zlim - zmid) / zdir);
1855  }
1856 // LSB = Line Search Buffer
1857 // first point
1858  anext = 0;
1859  aopt = anext;
1860  fLimset = kFALSE;
1861  if (aulim < aopt + tla) fLimset = kTRUE;
1862  mneval(anext, fnext, ierev);
1863 // debug printout:
1864  if (ldebug) {
1865  Printf(" MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt);
1866  }
1867  if (ierev > 0) goto L900;
1868  if (fLimset && fnext <= aim) goto L930;
1869  ++ipt;
1870  fXpt[ipt-1] = anext;
1871  fYpt[ipt-1] = fnext;
1872  fChpt[ipt-1] = charal[ipt-1];
1873  alsb[0] = anext;
1874  flsb[0] = fnext;
1875  fnext = TMath::Max(fnext,aminsv + fUp*.1);
1876  aopt = TMath::Sqrt(fUp / (fnext - aminsv)) - 1;
1877  if (TMath::Abs(fnext - aim) < tlf) goto L800;
1878 
1879  if (aopt < -.5)aopt = -.5;
1880  if (aopt > 1) aopt = 1;
1881  fLimset = kFALSE;
1882  if (aopt > aulim) {
1883  aopt = aulim;
1884  fLimset = kTRUE;
1885  }
1886  mneval(aopt, fnext, ierev);
1887 // debug printout:
1888  if (ldebug) {
1889  Printf(" MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt);
1890  }
1891  if (ierev > 0) goto L900;
1892  if (fLimset && fnext <= aim) goto L930;
1893  alsb[1] = aopt;
1894  ++ipt;
1895  fXpt[ipt-1] = alsb[1];
1896  fYpt[ipt-1] = fnext;
1897  fChpt[ipt-1] = charal[ipt-1];
1898  flsb[1] = fnext;
1899  dfda = (flsb[1] - flsb[0]) / (alsb[1] - alsb[0]);
1900 // DFDA must be positive on the contour
1901  if (dfda > 0) goto L460;
1902 L300:
1903  mnwarn("D", "MNCROS ", "Looking for slope of the right sign");
1904  maxlk = 15 - ipt;
1905  for (it = 1; it <= maxlk; ++it) {
1906  alsb[0] = alsb[1];
1907  flsb[0] = flsb[1];
1908  aopt = alsb[0] + Double_t(it)*.2;
1909  fLimset = kFALSE;
1910  if (aopt > aulim) {
1911  aopt = aulim;
1912  fLimset = kTRUE;
1913  }
1914  mneval(aopt, fnext, ierev);
1915 // debug printout:
1916  if (ldebug) {
1917  Printf(" MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt);
1918  }
1919  if (ierev > 0) goto L900;
1920  if (fLimset && fnext <= aim) goto L930;
1921  alsb[1] = aopt;
1922  ++ipt;
1923  fXpt[ipt-1] = alsb[1];
1924  fYpt[ipt-1] = fnext;
1925  fChpt[ipt-1] = charal[ipt-1];
1926  flsb[1] = fnext;
1927  dfda = (flsb[1] - flsb[0]) / (alsb[1] - alsb[0]);
1928  if (dfda > 0) goto L450;
1929  }
1930  mnwarn("W", "MNCROS ", "Cannot find slope of the right sign");
1931  goto L950;
1932 L450:
1933 // we have two points with the right slope
1934 L460:
1935  aopt = alsb[1] + (aim - flsb[1]) / dfda;
1936  fdist = TMath::Min(TMath::Abs(aim - flsb[0]),TMath::Abs(aim - flsb[1]));
1937  adist = TMath::Min(TMath::Abs(aopt - alsb[0]),TMath::Abs(aopt - alsb[1]));
1938  tla = .01;
1939  if (TMath::Abs(aopt) > 1) tla = TMath::Abs(aopt)*.01;
1940  if (adist < tla && fdist < tlf) goto L800;
1941  if (ipt >= 15) goto L950;
1942  bmin = TMath::Min(alsb[0],alsb[1]) - 1;
1943  if (aopt < bmin) aopt = bmin;
1944  bmax = TMath::Max(alsb[0],alsb[1]) + 1;
1945  if (aopt > bmax) aopt = bmax;
1946 // Try a third point
1947  fLimset = kFALSE;
1948  if (aopt > aulim) {
1949  aopt = aulim;
1950  fLimset = kTRUE;
1951  }
1952  mneval(aopt, fnext, ierev);
1953 // debug printout:
1954  if (ldebug) {
1955  Printf(" MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt);
1956  }
1957  if (ierev > 0) goto L900;
1958  if (fLimset && fnext <= aim) goto L930;
1959  alsb[2] = aopt;
1960  ++ipt;
1961  fXpt[ipt-1] = alsb[2];
1962  fYpt[ipt-1] = fnext;
1963  fChpt[ipt-1] = charal[ipt-1];
1964  flsb[2] = fnext;
1965 // now we have three points, ask how many <AIM
1966  ecarmn = TMath::Abs(fnext-aim);
1967  ibest = 3;
1968  ecarmx = 0;
1969  noless = 0;
1970  for (i = 1; i <= 3; ++i) {
1971  ecart = TMath::Abs(flsb[i-1] - aim);
1972  if (ecart > ecarmx) { ecarmx = ecart; iworst = i; }
1973  if (ecart < ecarmn) { ecarmn = ecart; ibest = i; }
1974  if (flsb[i-1] < aim) ++noless;
1975  }
1976 // if at least one on each side of AIM, fit a parabola
1977  if (noless == 1 || noless == 2) goto L500;
1978 // if all three are above AIM, third must be closest to AIM
1979  if (noless == 0 && ibest != 3) goto L950;
1980 // if all three below, and third is not best, then slope
1981 // has again gone negative, look for positive slope.
1982  if (noless == 3 && ibest != 3) {
1983  alsb[1] = alsb[2];
1984  flsb[1] = flsb[2];
1985  goto L300;
1986  }
1987 // in other cases, new straight line thru last two points
1988  alsb[iworst-1] = alsb[2];
1989  flsb[iworst-1] = flsb[2];
1990  dfda = (flsb[1] - flsb[0]) / (alsb[1] - alsb[0]);
1991  goto L460;
1992 // parabola fit
1993 L500:
1994  mnpfit(alsb, flsb, 3, coeff, sdev);
1995  if (coeff[2] <= 0) {
1996  mnwarn("D", "MNCROS ", "Curvature is negative near contour line.");
1997  }
1998  determ = coeff[1]*coeff[1] - coeff[2]*4*(coeff[0] - aim);
1999  if (determ <= 0) {
2000  mnwarn("D", "MNCROS ", "Problem 2, impossible determinant");
2001  goto L950;
2002  }
2003 // Find which root is the right one
2004  rt = TMath::Sqrt(determ);
2005  x1 = (-coeff[1] + rt) / (coeff[2]*2);
2006  x2 = (-coeff[1] - rt) / (coeff[2]*2);
2007  s1 = coeff[1] + x1*2*coeff[2];
2008  s2 = coeff[1] + x2*2*coeff[2];
2009  if (s1*s2 > 0) {
2010  Printf(" MNCONTour problem 1");
2011  }
2012  aopt = x1;
2013  slope = s1;
2014  if (s2 > 0) {
2015  aopt = x2;
2016  slope = s2;
2017  }
2018 // ask if converged
2019  tla = .01;
2020  if (TMath::Abs(aopt) > 1) tla = TMath::Abs(aopt)*.01;
2021  if (TMath::Abs(aopt - alsb[ibest-1]) < tla && TMath::Abs(flsb[ibest-1] - aim) < tlf) {
2022  goto L800;
2023  }
2024  if (ipt >= 15) goto L950;
2025 
2026 // see if proposed point is in acceptable zone between L and R
2027 // first find ILEFT, IRIGHT, IOUT and IBEST
2028  ileft = 0;
2029  iright = 0;
2030  ibest = 1;
2031  ecarmx = 0;
2032  ecarmn = TMath::Abs(aim - flsb[0]);
2033  for (i = 1; i <= 3; ++i) {
2034  ecart = TMath::Abs(flsb[i-1] - aim);
2035  if (ecart < ecarmn) { ecarmn = ecart; ibest = i; }
2036  if (ecart > ecarmx) { ecarmx = ecart; }
2037  if (flsb[i-1] > aim) {
2038  if (iright == 0) iright = i;
2039  else if (flsb[i-1] > flsb[iright-1]) iout = i;
2040  else { iout = iright; iright = i; }
2041  }
2042  else if (ileft == 0) ileft = i;
2043  else if (flsb[i-1] < flsb[ileft-1]) iout = i;
2044  else { iout = ileft; ileft = i; }
2045  }
2046 // avoid keeping a very bad point next time around
2047  if (ecarmx > TMath::Abs(flsb[iout-1] - aim)*10) {
2048  aopt = aopt*.5 + (alsb[iright-1] + alsb[ileft-1])*.25;
2049  }
2050 // knowing ILEFT and IRIGHT, get acceptable window
2051  smalla = tla*.1;
2052  if (slope*smalla > tlf) smalla = tlf / slope;
2053  aleft = alsb[ileft-1] + smalla;
2054  aright = alsb[iright-1] - smalla;
2055 // move proposed point AOPT into window if necessary
2056  if (aopt < aleft) aopt = aleft;
2057  if (aopt > aright) aopt = aright;
2058  if (aleft > aright) aopt = (aleft + aright)*.5;
2059 
2060 // see if proposed point outside limits (should be impossible!)
2061  fLimset = kFALSE;
2062  if (aopt > aulim) {
2063  aopt = aulim;
2064  fLimset = kTRUE;
2065  }
2066 // Evaluate function at new point AOPT
2067  mneval(aopt, fnext, ierev);
2068 // debug printout:
2069  if (ldebug) {
2070  Printf(" MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt);
2071  }
2072  if (ierev > 0) goto L900;
2073  if (fLimset && fnext <= aim) goto L930;
2074  ++ipt;
2075  fXpt[ipt-1] = aopt;
2076  fYpt[ipt-1] = fnext;
2077  fChpt[ipt-1] = charal[ipt-1];
2078 // Replace odd point by new one
2079  alsb[iout-1] = aopt;
2080  flsb[iout-1] = fnext;
2081 // the new point may not be the best, but it is the only one
2082 // which could be good enough to pass convergence criteria
2083  ibest = iout;
2084  goto L500;
2085 
2086 // Contour has been located, return point to MNCONT OR MINOS
2087 L800:
2088  iercr = 0;
2089  goto L1000;
2090 // error in the minimization
2091 L900:
2092  if (ierev == 1) goto L940;
2093  goto L950;
2094 // parameter up against limit
2095 L930:
2096  iercr = 1;
2097  goto L1000;
2098 // too many calls to FCN
2099 L940:
2100  iercr = 2;
2101  goto L1000;
2102 // cannot find next point
2103 L950:
2104  iercr = 3;
2105 // in any case
2106 L1000:
2107  if (ldebug) {
2108  itoohi = 0;
2109  for (i = 1; i <= ipt; ++i) {
2110  if (fYpt[i-1] > aim + fUp) {
2111  fYpt[i-1] = aim + fUp;
2112  fChpt[i-1] = '+';
2113  itoohi = 1;
2114  }
2115  }
2116  fChpt[ipt] = 0;
2117  chsign = "POSI";
2118  if (fXdircr < 0) chsign = "NEGA";
2119  if (fKe2cr == 0) {
2120  Printf(" %sTIVE MINOS ERROR, PARAMETER %3d",chsign,fKe1cr);
2121  }
2122  if (itoohi == 1) {
2123  Printf("POINTS LABELLED '+' WERE TOO HIGH TO PLOT.");
2124  }
2125  if (iercr == 1) {
2126  Printf("RIGHTMOST POINT IS UP AGAINST LIMIT.");
2127  }
2128  mnplot(fXpt, fYpt, fChpt, ipt, fNpagwd, fNpagln);
2129  }
2130 }
2131 
2132 ////////////////////////////////////////////////////////////////////////////////
2133 /// Makes sure that the current point is a local minimum
2134 ///
2135 /// Makes sure that the current point is a local
2136 /// minimum and that the error matrix exists,
2137 /// or at least something good enough for MINOS and MNCONT
2138 
2140 {
2141  /* Local variables */
2142  Double_t dxdi, wint;
2143  Int_t ndex, iext, i, j;
2144 
2145  if (fISW[3] < 1) {
2146  Printf(" FUNCTION MUST BE MINIMIZED BEFORE CALLING %s",(const char*)fCfrom);
2147  fApsi = fEpsi;
2148  mnmigr();
2149  }
2150  if (fISW[1] < 3) {
2151  mnhess();
2152  if (fISW[1] < 1) {
2153  mnwarn("W", fCfrom, "NO ERROR MATRIX. WILL IMPROVISE.");
2154  for (i = 1; i <= fNpar; ++i) {
2155  ndex = i*(i-1) / 2;
2156  for (j = 1; j <= i-1; ++j) {
2157  ++ndex;
2158  fVhmat[ndex-1] = 0;
2159  }
2160  ++ndex;
2161  if (fG2[i-1] <= 0) {
2162  wint = fWerr[i-1];
2163  iext = fNexofi[i-1];
2164  if (fNvarl[iext-1] > 1) {
2165  mndxdi(fX[i-1], i-1, dxdi);
2166  if (TMath::Abs(dxdi) < .001) wint = .01;
2167  else wint /= TMath::Abs(dxdi);
2168  }
2169  fG2[i-1] = fUp / (wint*wint);
2170  }
2171  fVhmat[ndex-1] = 2 / fG2[i-1];
2172  }
2173  fISW[1] = 1;
2174  fDcovar = 1;
2175  } else mnwerr();
2176  }
2177 }
2178 
2179 ////////////////////////////////////////////////////////////////////////////////
2180 /// Calculates the first derivatives of FCN (GRD)
2181 ///
2182 /// Calculates the first derivatives of FCN (GRD),
2183 /// either by finite differences or by transforming the user-
2184 /// supplied derivatives to internal coordinates,
2185 /// according to whether fISW[2] is zero or one.
2186 
2188 {
2189  /* Local variables */
2190  Double_t step, dfmin, stepb4, dd, df, fs1;
2191  Double_t tlrstp, tlrgrd, epspri, optstp, stpmax, stpmin, fs2, grbfor=0, d1d2, xtf;
2192  Int_t icyc, ncyc, iint, iext, i, nparx;
2193  Bool_t ldebug;
2194 
2195  nparx = fNpar;
2196  ldebug = fIdbg[2] >= 1;
2197  if (fAmin == fUndefi) mnamin();
2198  if (fISW[2] == 1) goto L100;
2199 
2200  if (ldebug) {
2201 // make sure starting at the right place
2202  mninex(fX);
2203  nparx = fNpar;
2204  Eval(nparx, fGin, fs1, fU, 4); ++fNfcn;
2205  if (fs1 != fAmin) {
2206  df = fAmin - fs1;
2207  mnwarn("D", "MNDERI", TString::Format("function value differs from AMIN by %12.3g",df));
2208  fAmin = fs1;
2209  }
2210  Printf(" FIRST DERIVATIVE DEBUG PRINTOUT. MNDERI");
2211  Printf(" PAR DERIV STEP MINSTEP OPTSTEP D1-D2 2ND DRV");
2212  }
2213  dfmin = fEpsma2*8*(TMath::Abs(fAmin) + fUp);
2214  if (fIstrat <= 0) {
2215  ncyc = 2;
2216  tlrstp = .5;
2217  tlrgrd = .1;
2218  } else if (fIstrat == 1) {
2219  ncyc = 3;
2220  tlrstp = .3;
2221  tlrgrd = .05;
2222  } else {
2223  ncyc = 5;
2224  tlrstp = .1;
2225  tlrgrd = .02;
2226  }
2227 // loop over variable parameters
2228  for (i = 1; i <= fNpar; ++i) {
2229  epspri = fEpsma2 + TMath::Abs(fGrd[i-1]*fEpsma2);
2230 // two-point derivatives always assumed necessary
2231 // maximum number of cycles over step size depends on strategy
2232  xtf = fX[i-1];
2233  stepb4 = 0;
2234 // loop as little as possible here!/
2235  for (icyc = 1; icyc <= ncyc; ++icyc) {
2236 // theoretically best step
2237  optstp = TMath::Sqrt(dfmin / (TMath::Abs(fG2[i-1]) + epspri));
2238 // step cannot decrease by more than a factor of ten
2239  step = TMath::Max(optstp,TMath::Abs(fGstep[i-1]*.1));
2240 // but if parameter has limits, max step size = 0.5
2241  if (fGstep[i-1] < 0 && step > .5) step = .5;
2242 // and not more than ten times the previous step
2243  stpmax = TMath::Abs(fGstep[i-1])*10;
2244  if (step > stpmax) step = stpmax;
2245 // minimum step size allowed by machine precision
2246  stpmin = TMath::Abs(fEpsma2*fX[i-1])*8;
2247  if (step < stpmin) step = stpmin;
2248 // end of iterations if step change less than factor 2
2249  if (TMath::Abs((step - stepb4) / step) < tlrstp) goto L50;
2250 // take step positive
2251  stepb4 = step;
2252  if (fGstep[i-1] > 0) fGstep[i-1] = TMath::Abs(step);
2253  else fGstep[i-1] = -TMath::Abs(step);
2254  stepb4 = step;
2255  fX[i-1] = xtf + step;
2256  mninex(fX);
2257  Eval(nparx, fGin, fs1, fU, 4); ++fNfcn;
2258 // take step negative
2259  fX[i-1] = xtf - step;
2260  mninex(fX);
2261  Eval(nparx, fGin, fs2, fU, 4); ++fNfcn;
2262  grbfor = fGrd[i-1];
2263  fGrd[i-1] = (fs1 - fs2) / (step*2);
2264  fG2[i-1] = (fs1 + fs2 - fAmin*2) / (step*step);
2265  fX[i-1] = xtf;
2266  if (ldebug) {
2267  d1d2 = (fs1 + fs2 - fAmin*2) / step;
2268  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]);
2269  }
2270 // see if another iteration is necessary
2271  if (TMath::Abs(grbfor - fGrd[i-1]) / (TMath::Abs(fGrd[i-1]) + dfmin/step) < tlrgrd)
2272  goto L50;
2273  }
2274 // end of ICYC loop. too many iterations
2275  if (ncyc == 1) goto L50;
2276  mnwarn("D", "MNDERI", TString::Format("First derivative not converged. %g%g",fGrd[i-1],grbfor));
2277 L50:
2278  ;
2279  }
2280  mninex(fX);
2281  return;
2282 // derivatives calc by fcn
2283 L100:
2284  for (iint = 1; iint <= fNpar; ++iint) {
2285  iext = fNexofi[iint-1];
2286  if (fNvarl[iext-1] <= 1) {
2287  fGrd[iint-1] = fGin[iext-1];
2288  } else {
2289  dd = (fBlim[iext-1] - fAlim[iext-1])*.5*TMath::Cos(fX[iint-1]);
2290  fGrd[iint-1] = fGin[iext-1]*dd;
2291  }
2292  }
2293 }
2294 
2295 ////////////////////////////////////////////////////////////////////////////////
2296 /// Calculates the transformation factor between ext/internal values
2297 ///
2298 /// calculates the transformation factor between external and
2299 /// internal parameter values. this factor is one for
2300 /// parameters which are not limited. called from MNEMAT.
2301 
2302 void TMinuit::mndxdi(Double_t pint, Int_t ipar, Double_t &dxdi)
2303 {
2304  Int_t i = fNexofi[ipar];
2305  dxdi = 1;
2306  if (fNvarl[i-1] > 1) {
2307  dxdi = TMath::Abs((fBlim[i-1] - fAlim[i-1])*TMath::Cos(pint))*.5;
2308  }
2309 }
2310 
2311 ////////////////////////////////////////////////////////////////////////////////
2312 /// Compute matrix eigen values
2313 
2314 void TMinuit::mneig(Double_t *a, Int_t ndima, Int_t n, Int_t mits, Double_t *work, Double_t precis, Int_t &ifault)
2315 {
2316  /* System generated locals */
2317  Int_t a_offset;
2318  Double_t d__1;
2319 
2320  /* Local variables */
2321  Double_t b, c, f, h, r, s, hh, gl, pr, pt;
2322  Int_t i, j, k, l, m=0, i0, i1, j1, m1, n1;
2323 
2324 // PRECIS is the machine precision EPSMAC
2325  /* Parameter adjustments */
2326  a_offset = ndima + 1;
2327  a -= a_offset;
2328  --work;
2329 
2330  /* Function Body */
2331  ifault = 1;
2332 
2333  i = n;
2334  for (i1 = 2; i1 <= n; ++i1) {
2335  l = i-2;
2336  f = a[i + (i-1)*ndima];
2337  gl = 0;
2338 
2339  if (l < 1) goto L25;
2340 
2341  for (k = 1; k <= l; ++k) {
2342  d__1 = a[i + k*ndima];
2343  gl += d__1*d__1;
2344  }
2345 L25:
2346  h = gl + f*f;
2347 
2348  if (gl > 1e-35) goto L30;
2349 
2350  work[i] = 0;
2351  work[n + i] = f;
2352  goto L65;
2353 L30:
2354  ++l;
2355  gl = TMath::Sqrt(h);
2356  if (f >= 0) gl = -gl;
2357  work[n + i] = gl;
2358  h -= f*gl;
2359  a[i + (i-1)*ndima] = f - gl;
2360  f = 0;
2361  for (j = 1; j <= l; ++j) {
2362  a[j + i*ndima] = a[i + j*ndima] / h;
2363  gl = 0;
2364  for (k = 1; k <= j; ++k) { gl += a[j + k*ndima]*a[i + k*ndima]; }
2365  if (j >= l) goto L47;
2366  j1 = j + 1;
2367  for (k = j1; k <= l; ++k) { gl += a[k + j*ndima]*a[i + k*ndima]; }
2368 L47:
2369  work[n + j] = gl / h;
2370  f += gl*a[j + i*ndima];
2371  }
2372  hh = f / (h + h);
2373  for (j = 1; j <= l; ++j) {
2374  f = a[i + j*ndima];
2375  gl = work[n + j] - hh*f;
2376  work[n + j] = gl;
2377  for (k = 1; k <= j; ++k) {
2378  a[j + k*ndima] = a[j + k*ndima] - f*work[n + k] - gl*a[i + k*ndima];
2379  }
2380  }
2381  work[i] = h;
2382 L65:
2383  --i;
2384  }
2385  work[1] = 0;
2386  work[n + 1] = 0;
2387  for (i = 1; i <= n; ++i) {
2388  l = i-1;
2389  if (work[i] == 0 || l == 0) goto L100;
2390 
2391  for (j = 1; j <= l; ++j) {
2392  gl = 0;
2393  for (k = 1; k <= l; ++k) { gl += a[i + k*ndima]*a[k + j*ndima]; }
2394  for (k = 1; k <= l; ++k) { a[k + j*ndima] -= gl*a[k + i*ndima]; }
2395  }
2396 L100:
2397  work[i] = a[i + i*ndima];
2398  a[i + i*ndima] = 1;
2399  if (l == 0) continue;
2400 
2401  for (j = 1; j <= l; ++j) {
2402  a[i + j*ndima] = 0;
2403  a[j + i*ndima] = 0;
2404  }
2405  }
2406 
2407  n1 = n - 1;
2408  for (i = 2; i <= n; ++i) {
2409  i0 = n + i-1;
2410  work[i0] = work[i0 + 1];
2411  }
2412  work[n + n] = 0;
2413  b = 0;
2414  f = 0;
2415  for (l = 1; l <= n; ++l) {
2416  j = 0;
2417  h = precis*(TMath::Abs(work[l]) + TMath::Abs(work[n + l]));
2418  if (b < h) b = h;
2419  for (m1 = l; m1 <= n; ++m1) {
2420  m = m1;
2421  if (TMath::Abs(work[n + m]) <= b) goto L150;
2422  }
2423 
2424 L150:
2425  if (m == l) goto L205;
2426 
2427 L160:
2428  if (j == mits) return;
2429  ++j;
2430  pt = (work[l + 1] - work[l]) / (work[n + l]*2);
2431  r = TMath::Sqrt(pt*pt + 1);
2432  pr = pt + r;
2433  if (pt < 0) pr = pt - r;
2434 
2435  h = work[l] - work[n + l] / pr;
2436  for (i = l; i <= n; ++i) { work[i] -= h; }
2437  f += h;
2438  pt = work[m];
2439  c = 1;
2440  s = 0;
2441  m1 = m - 1;
2442  i = m;
2443  for (i1 = l; i1 <= m1; ++i1) {
2444  j = i;
2445  --i;
2446  gl = c*work[n + i];
2447  h = c*pt;
2448  if (TMath::Abs(pt) >= TMath::Abs(work[n + i])) goto L180;
2449 
2450  c = pt / work[n + i];
2451  r = TMath::Sqrt(c*c + 1);
2452  work[n + j] = s*work[n + i]*r;
2453  s = 1 / r;
2454  c /= r;
2455  goto L190;
2456 L180:
2457  c = work[n + i] / pt;
2458  r = TMath::Sqrt(c*c + 1);
2459  work[n + j] = s*pt*r;
2460  s = c / r;
2461  c = 1 / r;
2462 L190:
2463  pt = c*work[i] - s*gl;
2464  work[j] = h + s*(c*gl + s*work[i]);
2465  for (k = 1; k <= n; ++k) {
2466  h = a[k + j*ndima];
2467  a[k + j*ndima] = s*a[k + i*ndima] + c*h;
2468  a[k + i*ndima] = c*a[k + i*ndima] - s*h;
2469  }
2470  }
2471  work[n + l] = s*pt;
2472  work[l] = c*pt;
2473 
2474  if (TMath::Abs(work[n + l]) > b) goto L160;
2475 
2476 L205:
2477  work[l] += f;
2478  }
2479  for (i = 1; i <= n1; ++i) {
2480  k = i;
2481  pt = work[i];
2482  i1 = i + 1;
2483  for (j = i1; j <= n; ++j) {
2484  if (work[j] >= pt) continue;
2485  k = j;
2486  pt = work[j];
2487  }
2488 
2489  if (k == i) continue;
2490 
2491  work[k] = work[i];
2492  work[i] = pt;
2493  for (j = 1; j <= n; ++j) {
2494  pt = a[j + i*ndima];
2495  a[j + i*ndima] = a[j + k*ndima];
2496  a[j + k*ndima] = pt;
2497  }
2498  }
2499  ifault = 0;
2500 }
2501 
2502 ////////////////////////////////////////////////////////////////////////////////
2503 /// Calculates the external error matrix from the internal matrix
2504 ///
2505 /// Note that if the matrix is declared like Double_t matrix[5][5]
2506 /// in the calling program, one has to call mnemat with, eg
2507 ///
2508 /// gMinuit->mnemat(&matrix[0][0],5);
2509 
2510 void TMinuit::mnemat(Double_t *emat, Int_t ndim)
2511 {
2512  /* System generated locals */
2513  Int_t emat_dim1, emat_offset;
2514 
2515  /* Local variables */
2516  Double_t dxdi, dxdj;
2517  Int_t i, j, k, npard, k2, kk, iz, nperln, kga, kgb;
2518  TString ctemp;
2519 
2520  /* Parameter adjustments */
2521  emat_dim1 = ndim;
2522  emat_offset = emat_dim1 + 1;
2523  emat -= emat_offset;
2524 
2525  /* Function Body */
2526  if (fISW[1] < 1) return;
2527  if (fISW[4] >= 2) {
2528  Printf(" EXTERNAL ERROR MATRIX. NDIM=%4d NPAR=%3d ERR DEF=%g",ndim,fNpar,fUp);
2529  }
2530 // size of matrix to be printed
2531  npard = fNpar;
2532  if (ndim < fNpar) {
2533  npard = ndim;
2534  if (fISW[4] >= 0) {
2535  Printf(" USER-DIMENSIONED ARRAY EMAT NOT BIG ENOUGH. REDUCED MATRIX CALCULATED.");
2536  }
2537  }
2538 // NPERLN is the number of elements that fit on one line
2539 
2540  nperln = (fNpagwd - 5) / 10;
2541  nperln = TMath::Min(nperln,13);
2542  if (fISW[4] >= 1 && npard > nperln) {
2543  Printf(" ELEMENTS ABOVE DIAGONAL ARE NOT PRINTED.");
2544  }
2545 // I counts the rows of the matrix
2546  for (i = 1; i <= npard; ++i) {
2547  mndxdi(fX[i-1], i-1, dxdi);
2548  kga = i*(i-1) / 2;
2549  for (j = 1; j <= i; ++j) {
2550  mndxdi(fX[j-1], j-1, dxdj);
2551  kgb = kga + j;
2552  emat[i + j*emat_dim1] = dxdi*fVhmat[kgb-1]*dxdj*fUp;
2553  emat[j + i*emat_dim1] = emat[i + j*emat_dim1];
2554  }
2555  }
2556 // IZ is number of columns to be printed in row I
2557  if (fISW[4] >= 2) {
2558  for (i = 1; i <= npard; ++i) {
2559  iz = npard;
2560  if (npard >= nperln) iz = i;
2561  ctemp = " ";
2562  for (k = 1; nperln < 0 ? k >= iz : k <= iz; k += nperln) {
2563  k2 = k + nperln - 1;
2564  if (k2 > iz) k2 = iz;
2565  for (kk = k; kk <= k2; ++kk) {
2566  ctemp += TString::Format("%10.3e ",emat[i + kk*emat_dim1]);
2567  }
2568  Printf("%s",(const char*)ctemp);
2569  }
2570  }
2571  }
2572 }
2573 
2574 ////////////////////////////////////////////////////////////////////////////////
2575 /// Utility routine to get MINOS errors
2576 ///
2577 /// Called by user.
2578 ///
2579 /// NUMBER is the parameter number
2580 ///
2581 /// values returned by MNERRS:
2582 /// - EPLUS, EMINUS are MINOS errors of parameter NUMBER,
2583 /// - EPARAB is 'parabolic' error (from error matrix).
2584 /// (Errors not calculated are set = 0)
2585 /// - GCC is global correlation coefficient from error matrix
2586 
2587 void TMinuit::mnerrs(Int_t number, Double_t &eplus, Double_t &eminus, Double_t &eparab, Double_t &gcc)
2588 {
2589  Double_t dxdi;
2590  Int_t ndiag, iin, iex;
2591 
2592  iex = number+1;
2593 
2594  if (iex > fNu || iex <= 0) goto L900;
2595  iin = fNiofex[iex-1];
2596  if (iin <= 0) goto L900;
2597 
2598 // IEX is external number, IIN is internal number
2599  eplus = fErp[iin-1];
2600  if (eplus == fUndefi) eplus = 0;
2601  eminus = fErn[iin-1];
2602  if (eminus == fUndefi) eminus = 0;
2603  mndxdi(fX[iin-1], iin-1, dxdi);
2604  ndiag = iin*(iin + 1) / 2;
2605  eparab = TMath::Abs(dxdi*TMath::Sqrt(TMath::Abs(fUp*fVhmat[ndiag- 1])));
2606 // global correlation coefficient
2607  gcc = 0;
2608  if (fISW[1] < 2) return;
2609  gcc = fGlobcc[iin-1];
2610  return;
2611 // ERROR. parameter number not valid
2612 L900:
2613  eplus = 0;
2614  eminus = 0;
2615  eparab = 0;
2616  gcc = 0;
2617 }
2618 
2619 ////////////////////////////////////////////////////////////////////////////////
2620 /// Evaluates the function being analysed by MNCROS
2621 ///
2622 /// Evaluates the function being analysed by MNCROS, which is
2623 /// generally the minimum of FCN with respect to all remaining
2624 /// variable parameters. The class data members contains the
2625 /// data necessary to know the values of U(KE1CR) and U(KE2CR)
2626 /// to be used, namely U(KE1CR) = XMIDCR + ANEXT*XDIRCR
2627 /// and (if KE2CR .NE. 0) U(KE2CR) = YMIDCR + ANEXT*YDIRCR
2628 
2629 void TMinuit::mneval(Double_t anext, Double_t &fnext, Int_t &ierev)
2630 {
2631  Int_t nparx;
2632 
2633  fU[fKe1cr-1] = fXmidcr + anext*fXdircr;
2634  if (fKe2cr != 0) fU[fKe2cr-1] = fYmidcr + anext*fYdircr;
2635  mninex(fX);
2636  nparx = fNpar;
2637  Eval(nparx, fGin, fnext, fU, 4); ++fNfcn;
2638  ierev = 0;
2639  if (fNpar > 0) {
2640  fItaur = 1;
2641  fAmin = fnext;
2642  fISW[0] = 0;
2643  mnmigr();
2644  fItaur = 0;
2645  fnext = fAmin;
2646  if (fISW[0] >= 1) ierev = 1;
2647  if (fISW[3] < 1) ierev = 2;
2648  }
2649 }
2650 
2651 ////////////////////////////////////////////////////////////////////////////////
2652 /// Interprets a command and takes appropriate action
2653 ///
2654 /// either directly by skipping to the corresponding code in
2655 /// MNEXCM, or by setting up a call to a function
2656 ///
2657 /// recognized MINUIT commands:
2658 /// obsolete commands:
2659 /// IERFLG is now (94.5) defined the same as ICONDN in MNCOMD =
2660 /// - 0: command executed normally
2661 /// - 1: command is blank, ignored
2662 /// - 2: command line unreadable, ignored
2663 /// - 3: unknown command, ignored
2664 /// - 4: abnormal termination (e.g., MIGRAD not converged)
2665 /// - 9: reserved
2666 /// - 10: END command
2667 /// - 11: EXIT or STOP command
2668 /// - 12: RETURN command
2669 ///
2670 /// see also
2671 /// [the possible list of all Minuit commands](https://root.cern.ch/sites/d35c7d8c.web.cern.ch/files/minuit.pdf).
2672 
2673 void TMinuit::mnexcm(const char *command, Double_t *plist, Int_t llist, Int_t &ierflg)
2674 {
2675  /* Initialized data */
2676 
2677  TString comand = command;
2678  static const char *const cname[40] = {
2679  "MINImize ",
2680  "SEEk ",
2681  "SIMplex ",
2682  "MIGrad ",
2683  "MINOs ",
2684  "SET xxx ",
2685  "SHOw xxx ",
2686  "TOP of pag",
2687  "FIX ",
2688  "REStore ",
2689  "RELease ",
2690  "SCAn ",
2691  "CONtour ",
2692  "HESse ",
2693  "SAVe ",
2694  "IMProve ",
2695  "CALl fcn ",
2696  "STAndard ",
2697  "END ",
2698  "EXIt ",
2699  "RETurn ",
2700  "CLEar ",
2701  "HELP ",
2702  "MNContour ",
2703  "STOp ",
2704  "JUMp ",
2705  " ",
2706  " ",
2707  " ",
2708  " ",
2709  " ",
2710  " ",
2711  " ",
2712  "COVARIANCE",
2713  "PRINTOUT ",
2714  "GRADIENT ",
2715  "MATOUT ",
2716  "ERROR DEF ",
2717  "LIMITS ",
2718  "PUNCH "};
2719 
2720  Int_t nntot = 40;
2721 
2722  /* Local variables */
2723  Double_t step, xptu[101], yptu[101], f, rno;
2724  Int_t icol, kcol, ierr, iint, iext, lnow, nptu, i, iflag, ierrf;
2725  Int_t ilist, nparx, izero, nf, lk, it, iw, inonde, nsuper;
2726  Int_t it2, ke1, ke2, nowprt, kll, krl;
2727  TString chwhy, c26, cvblnk, cneway, comd;
2728  TString ctemp;
2729  Bool_t lfreed, ltofix, lfixed;
2730 
2731 // alphabetical order of command names!
2732 
2733  /* Function Body */
2734 
2735  lk = comand.Length();
2736  if (lk > 20) lk = 20;
2737  fCword = comand;
2738  fCword.ToUpper();
2739 // Copy the first MAXP arguments into WORD7, making
2740 // sure that WORD7(1)=0 if LLIST=0
2741  for (iw = 1; iw <= fMaxpar; ++iw) {
2742  fWord7[iw-1] = 0;
2743  if (iw <= llist) fWord7[iw-1] = plist[iw-1];
2744  }
2745  ++fIcomnd;
2746  fNfcnlc = fNfcn;
2747  if (fCword(0,7) != "SET PRI" || fWord7[0] >= 0) {
2748  if (fISW[4] >= 0) {
2749  lnow = llist;
2750  if (lnow > 4) lnow = 4;
2751  Printf(" **********");
2752  ctemp.Form(" **%5d **%s",fIcomnd,(const char*)fCword);
2753  for (i = 1; i <= lnow; ++i) {
2754  ctemp += TString::Format("%12.4g",plist[i-1]);
2755  }
2756  Printf("%s",(const char*)ctemp);
2757  inonde = 0;
2758  if (llist > lnow) {
2759  kll = llist;
2760  if (llist > fMaxpar) {
2761  inonde = 1;
2762  kll = fMaxpar;
2763  }
2764  Printf(" ***********");
2765  for (i = lnow + 1; i <= kll; ++i) {
2766  Printf("%12.4g",plist[i-1]);
2767  }
2768  }
2769  Printf(" **********");
2770  if (inonde > 0) {
2771  Printf(" ERROR: ABOVE CALL TO MNEXCM TRIED TO PASS MORE THAN %d PARAMETERS.", fMaxpar);
2772  }
2773  }
2774  }
2775  fNfcnmx = Int_t(fWord7[0]);
2776  if (fNfcnmx <= 0) {
2777  fNfcnmx = fNpar*100 + 200 + fNpar*fNpar*5;
2778  }
2779  fEpsi = fWord7[1];
2780  if (fEpsi <= 0) {
2781  fEpsi = fUp*.1;
2782  }
2783  fLnewmn = kFALSE;
2784  fLphead = kTRUE;
2785  fISW[0] = 0;
2786  ierflg = 0;
2787 // look for command in list CNAME
2788  ctemp = fCword(0,3);
2789  for (i = 1; i <= nntot; ++i) {
2790  if (strncmp(ctemp.Data(),cname[i-1],3) == 0) goto L90;
2791  }
2792  Printf("UNKNOWN COMMAND IGNORED:%s", comand.Data());
2793  ierflg = 3;
2794  return;
2795 // normal case: recognized MINUIT command
2796 L90:
2797  if (fCword(0,4) == "MINO") i = 5;
2798  if (i != 6 && i != 7 && i != 8 && i != 23) {
2799  fCfrom = cname[i-1];
2800  fNfcnfr = fNfcn;
2801  }
2802 // 1 2 3 4 5 6 7 8 9 10
2803  switch (i) {
2804  case 1: goto L400;
2805  case 2: goto L200;
2806  case 3: goto L300;
2807  case 4: goto L400;
2808  case 5: goto L500;
2809  case 6: goto L700;
2810  case 7: goto L700;
2811  case 8: goto L800;
2812  case 9: goto L900;
2813  case 10: goto L1000;
2814  case 11: goto L1100;
2815  case 12: goto L1200;
2816  case 13: goto L1300;
2817  case 14: goto L1400;
2818  case 15: goto L1500;
2819  case 16: goto L1600;
2820  case 17: goto L1700;
2821  case 18: goto L1800;
2822  case 19: goto L1900;
2823  case 20: goto L1900;
2824  case 21: goto L1900;
2825  case 22: goto L2200;
2826  case 23: goto L2300;
2827  case 24: goto L2400;
2828  case 25: goto L1900;
2829  case 26: goto L2600;
2830  case 27: goto L3300;
2831  case 28: goto L3300;
2832  case 29: goto L3300;
2833  case 30: goto L3300;
2834  case 31: goto L3300;
2835  case 32: goto L3300;
2836  case 33: goto L3300;
2837  case 34: goto L3400;
2838  case 35: goto L3500;
2839  case 36: goto L3600;
2840  case 37: goto L3700;
2841  case 38: goto L3800;
2842  case 39: goto L3900;
2843  case 40: goto L4000;
2844  }
2845 // seek
2846 L200:
2847  mnseek();
2848  return;
2849 // simplex
2850 L300:
2851  mnsimp();
2852  if (fISW[3] < 1) ierflg = 4;
2853  return;
2854 // migrad, minimize
2855 L400:
2856  nf = fNfcn;
2857  fApsi = fEpsi;
2858  mnmigr();
2859  mnwerr();
2860  if (fISW[3] >= 1) return;
2861  ierflg = 4;
2862  if (fISW[0] == 1) return;
2863  if (fCword(0,3) == "MIG") return;
2864 
2865  fNfcnmx = fNfcnmx + nf - fNfcn;
2866  nf = fNfcn;
2867  mnsimp();
2868  if (fISW[0] == 1) return;
2869  fNfcnmx = fNfcnmx + nf - fNfcn;
2870  mnmigr();
2871  if (fISW[3] >= 1) ierflg = 0;
2872  mnwerr();
2873  return;
2874 // minos
2875 L500:
2876  nsuper = fNfcn + ((fNpar + 1) << 1)*fNfcnmx;
2877 // possible loop over new minima
2878  fEpsi = fUp*.1;
2879 L510:
2880  fCfrom = cname[i-1]; // ensure that mncuve complains about MINOS not MIGRAD
2881  mncuve();
2882  mnmnos();
2883  if (! fLnewmn) return;
2884  mnrset(0);
2885  mnmigr();
2886  mnwerr();
2887  if (fNfcn < nsuper) goto L510;
2888  Printf(" TOO MANY FUNCTION CALLS. MINOS GIVES UP");
2889  ierflg = 4;
2890  return;
2891 // set, show
2892 L700:
2893  mnset();
2894  return;
2895 // top of page
2896 
2897 L800:
2898  Printf("1");
2899  return;
2900 // fix
2901 L900:
2902  ltofix = kTRUE;
2903 // (also release)
2904 L901:
2905  lfreed = kFALSE;
2906  lfixed = kFALSE;
2907  if (llist == 0) {
2908  Printf("%s: NO PARAMETERS REQUESTED ",(const char*)fCword);
2909  return;
2910  }
2911  for (ilist = 1; ilist <= llist; ++ilist) {
2912  iext = Int_t(plist[ilist-1]);
2913  chwhy = " IS UNDEFINED.";
2914  if (iext <= 0) goto L930;
2915  if (iext > fNu) goto L930;
2916  if (fNvarl[iext-1] < 0) goto L930;
2917  chwhy = " IS CONSTANT. ";
2918  if (fNvarl[iext-1] == 0) goto L930;
2919  iint = fNiofex[iext-1];
2920  if (ltofix) {
2921  chwhy = " ALREADY FIXED.";
2922  if (iint == 0) goto L930;
2923  mnfixp(iint-1, ierr);
2924  if (ierr == 0) lfixed = kTRUE;
2925  else ierflg = 4;
2926  } else {
2927  chwhy = " ALREADY VARIABLE.";
2928  if (iint > 0) goto L930;
2929  krl = -abs(iext);
2930  mnfree(krl);
2931  lfreed = kTRUE;
2932  }
2933  continue;
2934 L930:
2935  if (fISW[4] >= 0) Printf(" PARAMETER %4d %s IGNORED.",iext,(const char*)chwhy);
2936  }
2937  if (lfreed || lfixed) mnrset(0);
2938  if (lfreed) {
2939  fISW[1] = 0;
2940  fDcovar = 1;
2941  fEDM = fBigedm;
2942  fISW[3] = 0;
2943  }
2944  mnwerr();
2945  if (fISW[4] > 1) mnprin(5, fAmin);
2946  return;
2947 // restore
2948 L1000:
2949  it = Int_t(fWord7[0]);
2950  if (it > 1 || it < 0) goto L1005;
2951  lfreed = fNpfix > 0;
2952  mnfree(it);
2953  if (lfreed) {
2954  mnrset(0);
2955  fISW[1] = 0;
2956  fDcovar = 1;
2957  fEDM = fBigedm;
2958  }
2959  return;
2960 L1005:
2961  Printf(" IGNORED. UNKNOWN ARGUMENT:%4d",it);
2962  ierflg = 3;
2963  return;
2964 // release
2965 L1100:
2966  ltofix = kFALSE;
2967  goto L901;
2968 // scan
2969 L1200:
2970  iext = Int_t(fWord7[0]);
2971  if (iext <= 0) goto L1210;
2972  it2 = 0;
2973  if (iext <= fNu) it2 = fNiofex[iext-1];
2974  if (it2 <= 0) goto L1250;
2975 
2976 L1210:
2977  mnscan();
2978  return;
2979 L1250:
2980  Printf(" PARAMETER %4d NOT VARIABLE.",iext);
2981  ierflg = 3;
2982  return;
2983 // contour
2984 L1300:
2985  ke1 = Int_t(fWord7[0]);
2986  ke2 = Int_t(fWord7[1]);
2987  if (ke1 == 0) {
2988  if (fNpar == 2) {
2989  ke1 = fNexofi[0];
2990  ke2 = fNexofi[1];
2991  } else {
2992  Printf("%s: NO PARAMETERS REQUESTED ",(const char*)fCword);
2993  ierflg = 3;
2994  return;
2995  }
2996  }
2997  fNfcnmx = 1000;
2998  mncntr(ke1-1, ke2-1, ierrf);
2999  if (ierrf > 0) ierflg = 3;
3000  return;
3001 // hesse
3002 L1400:
3003  mnhess();
3004  mnwerr();
3005  if (fISW[4] >= 0) mnprin(2, fAmin);
3006  if (fISW[4] >= 1) mnmatu(1);
3007  return;
3008 // save
3009 L1500:
3010  mnsave();
3011  return;
3012 // improve
3013 L1600:
3014  mncuve();
3015  mnimpr();
3016  if (fLnewmn) goto L400;
3017  ierflg = 4;
3018  return;
3019 // call fcn
3020 L1700:
3021  iflag = Int_t(fWord7[0]);
3022  nparx = fNpar;
3023  f = fUndefi;
3024  Eval(nparx, fGin, f, fU, iflag); ++fNfcn;
3025  nowprt = 0;
3026  if (f != fUndefi) {
3027  if (fAmin == fUndefi) {
3028  fAmin = f;
3029  nowprt = 1;
3030  } else if (f < fAmin) {
3031  fAmin = f;
3032  nowprt = 1;
3033  }
3034  if (fISW[4] >= 0 && iflag <= 5 && nowprt == 1) {
3035  mnprin(5, fAmin);
3036  }
3037  if (iflag == 3) fFval3 = f;
3038  }
3039  if (iflag > 5) mnrset(1);
3040  return;
3041 // standard
3042 L1800:
3043 // stand();
3044  return;
3045 // return, stop, end, exit
3046 L1900:
3047  it = Int_t(fWord7[0]);
3048  if (fFval3 != fAmin && it == 0) {
3049  iflag = 3;
3050  if (fISW[4] >= 0) Printf(" CALL TO USER FUNCTION WITH IFLAG = 3");
3051  nparx = fNpar;
3052  Eval(nparx, fGin, f, fU, iflag); ++fNfcn;
3053  }
3054  ierflg = 11;
3055  if (fCword(0,3) == "END") ierflg = 10;
3056  if (fCword(0,3) == "RET") ierflg = 12;
3057  return;
3058 // clear
3059 L2200:
3060  mncler();
3061  if (fISW[4] >= 1) {
3062  Printf(" MINUIT MEMORY CLEARED. NO PARAMETERS NOW DEFINED.");
3063  }
3064  return;
3065 // help
3066 L2300:
3067  kcol = 0;
3068  for (icol = 5; icol <= lk; ++icol) {
3069  if (fCword[icol-1] == ' ') continue;
3070  kcol = icol;
3071  goto L2320;
3072  }
3073 L2320:
3074  if (kcol == 0) comd = "* ";
3075  else comd = fCword(kcol-1,lk-kcol+1);
3076  mnhelp(comd);
3077  return;
3078 // MNContour
3079 L2400:
3080  fEpsi = fUp*.05;
3081  ke1 = Int_t(fWord7[0]);
3082  ke2 = Int_t(fWord7[1]);
3083  if (ke1 == 0 && fNpar == 2) {
3084  ke1 = fNexofi[0];
3085  ke2 = fNexofi[1];
3086  }
3087  nptu = Int_t(fWord7[2]);
3088  if (nptu <= 0) nptu = 20;
3089  if (nptu > 101) nptu = 101;
3090  fNfcnmx = (nptu + 5)*100*(fNpar + 1);
3091  mncont(ke1-1, ke2-1, nptu, xptu, yptu, ierrf);
3092  if (ierrf < nptu) ierflg = 4;
3093  if (ierrf == -1) ierflg = 3;
3094  return;
3095 // jump
3096 L2600:
3097  step = fWord7[0];
3098  if (step <= 0) step = 2;
3099  rno = 0;
3100  izero = 0;
3101  for (i = 1; i <= fNpar; ++i) {
3102  mnrn15(rno, izero);
3103  rno = rno*2 - 1;
3104  fX[i-1] += rno*step*fWerr[i-1];
3105  }
3106  mninex(fX);
3107  mnamin();
3108  mnrset(0);
3109  return;
3110 // blank line
3111 L3300:
3112  Printf(" BLANK COMMAND IGNORED.");
3113  ierflg = 1;
3114  return;
3115 // obsolete commands
3116 // covariance
3117 L3400:
3118  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*");
3119  ierflg = 3;
3120  return;
3121 // printout
3122 L3500:
3123  cneway = "SET PRInt ";
3124  goto L3100;
3125 // gradient
3126 L3600:
3127  cneway = "SET GRAd ";
3128  goto L3100;
3129 // matout
3130 L3700:
3131  cneway = "SHOW COVar";
3132  goto L3100;
3133 // error def
3134 L3800:
3135  cneway = "SET ERRdef";
3136  goto L3100;
3137 // limits
3138 L3900:
3139  cneway = "SET LIMits";
3140  goto L3100;
3141 // punch
3142 L4000:
3143  cneway = "SAVE ";
3144 // come from obsolete commands
3145 L3100:
3146  Printf(" OBSOLETE COMMAND:%s PLEASE USE:%s",(const char*)fCword
3147  ,(const char*)cneway);
3148  fCword = cneway;
3149  if (fCword == "SAVE ") goto L1500;
3150  goto L700;
3151 //
3152 }
3153 
3154 ////////////////////////////////////////////////////////////////////////////////
3155 /// Transforms the external parameter values U to internal values
3156 ///
3157 /// Transforms the external parameter values U to internal
3158 /// values in the dense array PINT.
3159 
3161 {
3162  Double_t pinti;
3163  Int_t iint, iext;
3164 
3165  fLimset = kFALSE;
3166  for (iint = 1; iint <= fNpar; ++iint) {
3167  iext = fNexofi[iint-1];
3168  mnpint(fU[iext-1], iext-1, pinti);
3169  pint[iint-1] = pinti;
3170  }
3171 }
3172 
3173 ////////////////////////////////////////////////////////////////////////////////
3174 /// Removes parameter IINT from the internal parameter list
3175 ///
3176 /// and arranges the rest of the list to fill the hole.
3177 
3178 void TMinuit::mnfixp(Int_t iint1, Int_t &ierr)
3179 {
3180  /* Local variables */
3181  Double_t yyover;
3182  Int_t kold, nold, ndex, knew, iext, i, j, m, n, lc, ik;
3183 
3184 // first see if it can be done
3185  ierr = 0;
3186  Int_t iint = iint1+1;
3187  if (iint > fNpar || iint <= 0) {
3188  ierr = 1;
3189  Printf(" MINUIT ERROR. ARGUMENT TO MNFIXP=%4d",iint);
3190  return;
3191  }
3192  iext = fNexofi[iint-1];
3193  if (fNpfix >= fMaxpar) {
3194  ierr = 1;
3195  Printf(" MINUIT CANNOT FIX PARAMETER %4d MAXIMUM NUMBER THAT CAN BE FIXED IS %d",iext,fMaxpar);
3196  return;
3197  }
3198 // reduce number of variable parameters by one
3199 
3200  fNiofex[iext-1] = 0;
3201  nold = fNpar;
3202  --fNpar;
3203 // save values in case parameter is later restored
3204 
3205  ++fNpfix;
3206  fIpfix[fNpfix-1] = iext;
3207  lc = iint;
3208  fXs[fNpfix-1] = fX[lc-1];
3209  fXts[fNpfix-1] = fXt[lc-1];
3210  fDirins[fNpfix-1] = fWerr[lc-1];
3211  fGrds[fNpfix-1] = fGrd[lc-1];
3212  fG2s[fNpfix-1] = fG2[lc-1];
3213  fGsteps[fNpfix-1] = fGstep[lc-1];
3214 // shift values for other parameters to fill hole
3215  for (ik = iext + 1; ik <= fNu; ++ik) {
3216  if (fNiofex[ik-1] > 0) {
3217  lc = fNiofex[ik-1] - 1;
3218  fNiofex[ik-1] = lc;
3219  fNexofi[lc-1] = ik;
3220  fX[lc-1] = fX[lc];
3221  fXt[lc-1] = fXt[lc];
3222  fDirin[lc-1] = fDirin[lc];
3223  fWerr[lc-1] = fWerr[lc];
3224  fGrd[lc-1] = fGrd[lc];
3225  fG2[lc-1] = fG2[lc];
3226  fGstep[lc-1] = fGstep[lc];
3227  }
3228  }
3229  if (fISW[1] <= 0) return;
3230 // remove one row and one column from variance matrix
3231  if (fNpar <= 0) return;
3232  for (i = 1; i <= nold; ++i) {
3233  m = TMath::Max(i,iint);
3234  n = TMath::Min(i,iint);
3235  ndex = m*(m-1) / 2 + n;
3236  fFIXPyy[i-1] = fVhmat[ndex-1];
3237  }
3238  yyover = 1 / fFIXPyy[iint-1];
3239  knew = 0;
3240  kold = 0;
3241  for (i = 1; i <= nold; ++i) {
3242  for (j = 1; j <= i; ++j) {
3243  ++kold;
3244  if (j == iint || i == iint) continue;
3245  ++knew;
3246  fVhmat[knew-1] = fVhmat[kold-1] - fFIXPyy[j-1]*fFIXPyy[i-1]*yyover;
3247  }
3248  }
3249 }
3250 
3251 ////////////////////////////////////////////////////////////////////////////////
3252 /// Restores one or more fixed parameter(s) to variable status
3253 ///
3254 /// Restores one or more fixed parameter(s) to variable status
3255 /// by inserting it into the internal parameter list at the
3256 /// appropriate place.
3257 ///
3258 /// - K = 0 means restore all parameters
3259 /// - K = 1 means restore the last parameter fixed
3260 /// - K = -I means restore external parameter I (if possible)
3261 /// - IQ = fix-location where internal parameters were stored
3262 /// - IR = external number of parameter being restored
3263 /// - IS = internal number of parameter being restored
3264 
3266 {
3267  /* Local variables */
3268  Double_t grdv, xv, dirinv, g2v, gstepv, xtv;
3269  Int_t i, ipsav, ka, lc, ik, iq, ir, is;
3270 
3271  if (k > 1) {
3272  Printf(" CALL TO MNFREE IGNORED. ARGUMENT GREATER THAN ONE");
3273  }
3274  if (fNpfix < 1) {
3275  Printf(" CALL TO MNFREE IGNORED. THERE ARE NO FIXED PARAMETERS");
3276  }
3277  if (k == 1 || k == 0) goto L40;
3278 
3279 // release parameter with specified external number
3280  ka = abs(k);
3281  if (fNiofex[ka-1] == 0) goto L15;
3282  Printf(" IGNORED. PARAMETER SPECIFIED IS ALREADY VARIABLE.");
3283  return;
3284 L15:
3285  if (fNpfix < 1) goto L21;
3286  for (ik = 1; ik <= fNpfix; ++ik) { if (fIpfix[ik-1] == ka) goto L24; }
3287 L21:
3288  Printf(" PARAMETER %4d NOT FIXED. CANNOT BE RELEASED.",ka);
3289  return;
3290 L24:
3291  if (ik == fNpfix) goto L40;
3292 
3293 // move specified parameter to end of list
3294  ipsav = ka;
3295  xv = fXs[ik-1];
3296  xtv = fXts[ik-1];
3297  dirinv = fDirins[ik-1];
3298  grdv = fGrds[ik-1];
3299  g2v = fG2s[ik-1];
3300  gstepv = fGsteps[ik-1];
3301  for (i = ik + 1; i <= fNpfix; ++i) {
3302  fIpfix[i-2] = fIpfix[i-1];
3303  fXs[i-2] = fXs[i-1];
3304  fXts[i-2] = fXts[i-1];
3305  fDirins[i-2] = fDirins[i-1];
3306  fGrds[i-2] = fGrds[i-1];
3307  fG2s[i-2] = fG2s[i-1];
3308  fGsteps[i-2] = fGsteps[i-1];
3309  }
3310  fIpfix[fNpfix-1] = ipsav;
3311  fXs[fNpfix-1] = xv;
3312  fXts[fNpfix-1] = xtv;
3313  fDirins[fNpfix-1] = dirinv;
3314  fGrds[fNpfix-1] = grdv;
3315  fG2s[fNpfix-1] = g2v;
3316  fGsteps[fNpfix-1] = gstepv;
3317 // restore last parameter in fixed list -- IPFIX(NPFIX)
3318 L40:
3319  if (fNpfix < 1) goto L300;
3320  ir = fIpfix[fNpfix-1];
3321  is = 0;
3322  for (ik = fNu; ik >= ir; --ik) {
3323  if (fNiofex[ik-1] > 0) {
3324  lc = fNiofex[ik-1] + 1;
3325  is = lc - 1;
3326  fNiofex[ik-1] = lc;
3327  fNexofi[lc-1] = ik;
3328  fX[lc-1] = fX[lc-2];
3329  fXt[lc-1] = fXt[lc-2];
3330  fDirin[lc-1] = fDirin[lc-2];
3331  fWerr[lc-1] = fWerr[lc-2];
3332  fGrd[lc-1] = fGrd[lc-2];
3333  fG2[lc-1] = fG2[lc-2];
3334  fGstep[lc-1] = fGstep[lc-2];
3335  }
3336  }
3337  ++fNpar;
3338  if (is == 0) is = fNpar;
3339  fNiofex[ir-1] = is;
3340  fNexofi[is-1] = ir;
3341  iq = fNpfix;
3342  fX[is-1] = fXs[iq-1];
3343  fXt[is-1] = fXts[iq-1];
3344  fDirin[is-1] = fDirins[iq-1];
3345  fWerr[is-1] = fDirins[iq-1];
3346  fGrd[is-1] = fGrds[iq-1];
3347  fG2[is-1] = fG2s[iq-1];
3348  fGstep[is-1] = fGsteps[iq-1];
3349  --fNpfix;
3350  fISW[1] = 0;
3351  fDcovar = 1;
3352  if (fISW[4] - fItaur >= 1) {
3353  Printf(" PARAMETER %4d %s RESTORED TO VARIABLE.",ir,
3354  (const char*)fCpnam[ir-1]);
3355  }
3356  if (k == 0) goto L40;
3357 L300:
3358 // if different from internal, external values are taken
3359  mnexin(fX);
3360 }
3361 
3362 ////////////////////////////////////////////////////////////////////////////////
3363 /// Interprets the SET GRAD command
3364 ///
3365 /// - Called from MNSET
3366 /// - Interprets the SET GRAD command, which informs MINUIT whether
3367 /// - the first derivatives of FCN will be calculated by the user
3368 /// - inside FCN. It can check the user derivative calculation
3369 /// - by comparing it with a finite difference approximation.
3370 
3372 {
3373  /* Local variables */
3374  Double_t fzero, err;
3375  Int_t i, nparx, lc, istsav;
3376  Bool_t lnone;
3377 
3378  fISW[2] = 1;
3379  nparx = fNpar;
3380  if (fWord7[0] > 0) goto L2000;
3381 
3382 // get user-calculated first derivatives from FCN
3383  for (i = 1; i <= fNu; ++i) { fGin[i-1] = fUndefi; }
3384  mninex(fX);
3385  Eval(nparx, fGin, fzero, fU, 2); ++fNfcn;
3386  mnderi();
3387  for (i = 1; i <= fNpar; ++i) { fGRADgf[i-1] = fGrd[i-1]; }
3388 // get MINUIT-calculated first derivatives
3389  fISW[2] = 0;
3390  istsav = fIstrat;
3391  fIstrat = 2;
3392  mnhes1();
3393  fIstrat = istsav;
3394  Printf(" CHECK OF GRADIENT CALCULATION IN FCN");
3395  Printf(" PARAMETER G(IN FCN) G(MINUIT) DG(MINUIT) AGREEMENT");
3396  fISW[2] = 1;
3397  lnone = kFALSE;
3398  for (lc = 1; lc <= fNpar; ++lc) {
3399  i = fNexofi[lc-1];
3400  const char *cwd = "GOOD";
3401  err = fDgrd[lc-1];
3402  if (TMath::Abs(fGRADgf[lc-1] - fGrd[lc-1]) > err) {
3403  cwd = " BAD";
3404  fISW[2] = 0;
3405  }
3406  if (fGin[i-1] == fUndefi) {
3407  cwd = "NONE";
3408  lnone = kTRUE;
3409  fGRADgf[lc-1] = 0;
3410  fISW[2] = 0;
3411  }
3412  Printf(" %5d %10s%12.4e%12.4e%12.4e %s",i
3413  ,(const char*)fCpnam[i-1]
3414  ,fGRADgf[lc-1],fGrd[lc-1],err,cwd);
3415  }
3416  if (lnone) {
3417  Printf(" AGREEMENT=NONE MEANS FCN DID NOT CALCULATE THE DERIVATIVE");
3418  }
3419  if (fISW[2] == 0) {
3420  Printf(" MINUIT DOES NOT ACCEPT DERIVATIVE CALCULATIONS BY FCN");
3421  Printf(" TO FORCE ACCEPTANCE, ENTER *SET GRAD 1*");
3422  }
3423 
3424 L2000:
3425  return;
3426 }
3427 
3428 ////////////////////////////////////////////////////////////////////////////////
3429 /// interface to Minuit help
3430 
3431 void TMinuit::mnhelp(const char *command)
3432 {
3433  TString comd = command;
3434  mnhelp(comd);
3435 }
3436 
3437 ////////////////////////////////////////////////////////////////////////////////
3438 /// HELP routine for MINUIT interactive commands
3439 ///
3440 /// - COMD ='*' or "" prints a global help for all commands
3441 /// - COMD =Command_name: print detailed help for one command.
3442 /// Note that at least 3 characters must be given for the command
3443 /// name.
3444 ///
3445 /// Author: Rene Brun
3446 /// comments extracted from the MINUIT documentation file.
3447 
3449 {
3450 //______________________________________________________________________________
3451 //
3452 // Global HELP: Summary of all commands
3453 //
3454  comd.ToUpper();
3455  if( comd.Length() == 0 || comd[0] == '*' || comd[0] == '?' || comd[0] == 0 || comd=="HELP" ) {
3456  Printf(" ==>List of MINUIT Interactive commands:");
3457  Printf(" CLEar Reset all parameter names and values undefined");
3458  Printf(" CONtour Make contour map of the user function");
3459  Printf(" EXIT Exit from Interactive Minuit");
3460  Printf(" FIX Cause parameter(s) to remain constant");
3461  Printf(" HESse Calculate the Hessian or error matrix.");
3462  Printf(" IMPROVE Search for a new minimum around current minimum");
3463  Printf(" MIGrad Minimize by the method of Migrad");
3464  Printf(" MINImize MIGRAD + SIMPLEX method if Migrad fails");
3465  Printf(" MINOs Exact (non-linear) parameter error analysis");
3466  Printf(" MNContour Calculate one MINOS function contour");
3467  Printf(" PARameter Define or redefine new parameters and values");
3468  Printf(" RELease Make previously FIXed parameters variable again");
3469  Printf(" REStore Release last parameter fixed");
3470  Printf(" SAVe Save current parameter values on a file");
3471  Printf(" SCAn Scan the user function by varying parameters");
3472  Printf(" SEEk Minimize by the method of Monte Carlo");
3473  Printf(" SET Set various MINUIT constants or conditions");
3474  Printf(" SHOw Show values of current constants or conditions");
3475  Printf(" SIMplex Minimize by the method of Simplex");
3476  goto L99;
3477  }
3478 
3479 //______________________________________________________________________________
3480 //
3481 // Command CLEAR
3482 //
3483  if( !strncmp(comd.Data(),"CLE",3) ) {
3484  Printf(" ***>CLEAR");
3485  Printf(" Resets all parameter names and values to undefined.");
3486  Printf(" Must normally be followed by a PARameters command or ");
3487  Printf(" equivalent, in order to define parameter values.");
3488  goto L99;
3489  }
3490 //______________________________________________________________________________
3491 //
3492 // Command CONTOUR
3493 //
3494  if( !strncmp(comd.Data(),"CON",3) ) {
3495  Printf(" ***>CONTOUR <par1> <par2> [devs] [ngrid]");
3496  Printf(" Instructs Minuit to trace contour lines of the user function");
3497  Printf(" with respect to the two parameters whose external numbers");
3498  Printf(" are <par1> and <par2>.");
3499  Printf(" Other variable parameters of the function, if any, will have");
3500  Printf(" their values fixed at the current values during the contour");
3501  Printf(" tracing. The optional parameter [devs] (default value 2.)");
3502  Printf(" gives the number of standard deviations in each parameter");
3503  Printf(" which should lie entirely within the plotting area.");
3504  Printf(" Optional parameter [ngrid] (default value 25 unless page");
3505  Printf(" size is too small) determines the resolution of the plot,");
3506  Printf(" i.e. the number of rows and columns of the grid at which the");
3507  Printf(" function will be evaluated. [See also MNContour.]");
3508  goto L99;
3509  }
3510 //______________________________________________________________________________
3511 //
3512 // Command END
3513 //
3514  if( !strncmp(comd.Data(),"END",3) ) {
3515  Printf(" ***>END");
3516  Printf(" Signals the end of a data block (i.e., the end of a fit),");
3517  Printf(" and implies that execution should continue, because another");
3518  Printf(" Data Block follows. A Data Block is a set of Minuit data");
3519  Printf(" consisting of");
3520  Printf(" (1) A Title,");
3521  Printf(" (2) One or more Parameter Definitions,");
3522  Printf(" (3) A blank line, and");
3523  Printf(" (4) A set of Minuit Commands.");
3524  Printf(" The END command is used when more than one Data Block is to");
3525  Printf(" be used with the same FCN function. It first causes Minuit");
3526  Printf(" to issue a CALL FCN with IFLAG=3, in order to allow FCN to");
3527  Printf(" perform any calculations associated with the final fitted");
3528  Printf(" parameter values, unless a CALL FCN 3 command has already");
3529  Printf(" been executed at the current FCN value.");
3530  goto L99;
3531  }
3532 //______________________________________________________________________________
3533 //
3534 // Command EXIT
3535 //
3536  if( !strncmp(comd.Data(),"EXI",3) ) {
3537  Printf(" ***>EXIT");
3538  Printf(" Signals the end of execution.");
3539  Printf(" The EXIT command first causes Minuit to issue a CALL FCN");
3540  Printf(" with IFLAG=3, to allow FCN to perform any calculations");
3541  Printf(" associated with the final fitted parameter values, unless a");
3542  Printf(" CALL FCN 3 command has already been executed.");
3543  goto L99;
3544  }
3545 //______________________________________________________________________________
3546 //
3547 // Command FIX
3548 //
3549  if( !strncmp(comd.Data(),"FIX",3) ) {
3550  Printf(" ***>FIX} <parno> [parno] ... [parno]");
3551  Printf(" Causes parameter(s) <parno> to be removed from the list of");
3552  Printf(" variable parameters, and their value(s) will remain constant");
3553  Printf(" during subsequent minimizations, etc., until another command");
3554  Printf(" changes their value(s) or status.");
3555  goto L99;
3556  }
3557 //______________________________________________________________________________
3558 //
3559 // Command HESSE
3560 //
3561  if( !strncmp(comd.Data(),"HES",3) ) {
3562  Printf(" ***>HESse [maxcalls]");
3563  Printf(" Calculate, by finite differences, the Hessian or error matrix.");
3564  Printf(" That is, it calculates the full matrix of second derivatives");
3565  Printf(" of the function with respect to the currently variable");
3566  Printf(" parameters, and inverts it, printing out the resulting error");
3567  Printf(" matrix. The optional argument [maxcalls] specifies the");
3568  Printf(" (approximate) maximum number of function calls after which");
3569  Printf(" the calculation will be stopped.");
3570  goto L99;
3571  }
3572 //______________________________________________________________________________
3573 //
3574 // Command IMPROVE
3575 //
3576  if( !strncmp(comd.Data(),"IMP",3) ) {
3577  Printf(" ***>IMPROVE [maxcalls]");
3578  Printf(" If a previous minimization has converged, and the current");
3579  Printf(" values of the parameters therefore correspond to a local");
3580  Printf(" minimum of the function, this command requests a search for");
3581  Printf(" additional distinct local minima.");
3582  Printf(" The optional argument [maxcalls] specifies the (approximate");
3583  Printf(" maximum number of function calls after which the calculation");
3584  Printf(" will be stopped.");
3585  goto L99;
3586  }
3587 //______________________________________________________________________________
3588 //
3589 // Command MIGRAD
3590 //
3591  if( !strncmp(comd.Data(),"MIG",3) ) {
3592  Printf(" ***>MIGrad [maxcalls] [tolerance]");
3593  Printf(" Causes minimization of the function by the method of Migrad,");
3594  Printf(" the most efficient and complete single method, recommended");
3595  Printf(" for general functions (see also MINImize).");
3596  Printf(" The minimization produces as a by-product the error matrix");
3597  Printf(" of the parameters, which is usually reliable unless warning");
3598  Printf(" messages are produced.");
3599  Printf(" The optional argument [maxcalls] specifies the (approximate)");
3600  Printf(" maximum number of function calls after which the calculation");
3601  Printf(" will be stopped even if it has not yet converged.");
3602  Printf(" The optional argument [tolerance] specifies required tolerance");
3603  Printf(" on the function value at the minimum.");
3604  Printf(" The default tolerance is 0.1, and the minimization will stop");
3605  Printf(" when the estimated vertical distance to the minimum (EDM) is");
3606  Printf(" less than 0.001*[tolerance]*UP (see [SET ERRordef]).");
3607  goto L99;
3608  }
3609 //______________________________________________________________________________
3610 //
3611 // Command MINIMIZE
3612 //
3613  if( !strncmp(comd.Data(),"MINI",4) ) {
3614  Printf(" ***>MINImize [maxcalls] [tolerance]");
3615  Printf(" Causes minimization of the function by the method of Migrad,");
3616  Printf(" as does the MIGrad command, but switches to the SIMplex method");
3617  Printf(" if Migrad fails to converge. Arguments are as for MIGrad.");
3618  Printf(" Note that command requires four characters to be unambiguous.");
3619  goto L99;
3620  }
3621 //______________________________________________________________________________
3622 //
3623 // Command MINOS
3624 //
3625  if( !strncmp(comd.Data(),"MIN0",4) ) {
3626  Printf(" ***>MINOs [maxcalls] [parno] [parno] ...");
3627  Printf(" Causes a Minos error analysis to be performed on the parameters");
3628  Printf(" whose numbers [parno] are specified. If none are specified,");
3629  Printf(" Minos errors are calculated for all variable parameters.");
3630  Printf(" Minos errors may be expensive to calculate, but are very");
3631  Printf(" reliable since they take account of non-linearities in the");
3632  Printf(" problem as well as parameter correlations, and are in general");
3633  Printf(" asymmetric.");
3634  Printf(" The optional argument [maxcalls] specifies the (approximate)");
3635  Printf(" maximum number of function calls per parameter requested,");
3636  Printf(" after which the calculation will stop for that parameter.");
3637  goto L99;
3638  }
3639 //______________________________________________________________________________
3640 //
3641 // Command MNCONTOUR
3642 //
3643  if( !strncmp(comd.Data(),"MNC",3) ) {
3644  Printf(" ***>MNContour <par1> <par2> [npts]");
3645  Printf(" Calculates one function contour of FCN with respect to");
3646  Printf(" parameters par1 and par2, with FCN minimized always with");
3647  Printf(" respect to all other NPAR-2 variable parameters (if any).");
3648  Printf(" Minuit will try to find npts points on the contour (default 20)");
3649  Printf(" If only two parameters are variable at the time, it is not");
3650  Printf(" necessary to specify their numbers. To calculate more than");
3651  Printf(" one contour, it is necessary to SET ERRordef to the appropriate");
3652  Printf(" value and issue the MNContour command for each contour.");
3653  goto L99;
3654  }
3655 //______________________________________________________________________________
3656 //
3657 // Command PARAMETER
3658 //
3659  if( !strncmp(comd.Data(),"PAR",3) ) {
3660  Printf(" ***>PARameters");
3661  Printf(" followed by one or more parameter definitions.");
3662  Printf(" Parameter definitions are of the form:");
3663  Printf(" <number> ''name'' <value> <step> [lolim] [uplim] ");
3664  Printf(" for example:");
3665  Printf(" 3 ''K width'' 1.2 0.1");
3666  Printf(" the last definition is followed by a blank line or a zero.");
3667  goto L99;
3668  }
3669 //______________________________________________________________________________
3670 //
3671 // Command RELEASE
3672 //
3673  if( !strncmp(comd.Data(),"REL",3) ) {
3674  Printf(" ***>RELease <parno> [parno] ... [parno]");
3675  Printf(" If <parno> is the number of a previously variable parameter");
3676  Printf(" which has been fixed by a command: FIX <parno>, then that");
3677  Printf(" parameter will return to variable status. Otherwise a warning");
3678  Printf(" message is printed and the command is ignored.");
3679  Printf(" Note that this command operates only on parameters which were");
3680  Printf(" at one time variable and have been FIXed. It cannot make");
3681  Printf(" constant parameters variable; that must be done by redefining");
3682  Printf(" the parameter with a PARameters command.");
3683  goto L99;
3684  }
3685 //______________________________________________________________________________
3686 //
3687 // Command RESTORE
3688 //
3689  if( !strncmp(comd.Data(),"RES",3) ) {
3690  Printf(" ***>REStore [code]");
3691  Printf(" If no [code] is specified, this command restores all previously");
3692  Printf(" FIXed parameters to variable status. If [code]=1, then only");
3693  Printf(" the last parameter FIXed is restored to variable status.");
3694  Printf(" If code is neither zero nor one, the command is ignored.");
3695  goto L99;
3696  }
3697 //______________________________________________________________________________
3698 //
3699 // Command RETURN
3700 //
3701  if( !strncmp(comd.Data(),"RET",3) ) {
3702  Printf(" ***>RETURN");
3703  Printf(" Signals the end of a data block, and instructs Minuit to return");
3704  Printf(" to the program which called it. The RETurn command first");
3705  Printf(" causes Minuit to CALL FCN with IFLAG=3, in order to allow FCN");
3706  Printf(" to perform any calculations associated with the final fitted");
3707  Printf(" parameter values, unless a CALL FCN 3 command has already been");
3708  Printf(" executed at the current FCN value.");
3709  goto L99;
3710  }
3711 //______________________________________________________________________________
3712 //
3713 // Command SAVE
3714 //
3715  if( !strncmp(comd.Data(),"SAV",3) ) {
3716  Printf(" ***>SAVe");
3717  Printf(" Causes the current parameter values to be saved on a file in");
3718  Printf(" such a format that they can be read in again as Minuit");
3719  Printf(" parameter definitions. If the covariance matrix exists, it is");
3720  Printf(" also output in such a format. The unit number is by default 7,");
3721  Printf(" or that specified by the user in their call to MINTIO or");
3722  Printf(" MNINIT. The user is responsible for opening the file previous");
3723  Printf(" to issuing the [SAVe] command (except where this can be done");
3724  Printf(" interactively).");
3725  goto L99;
3726  }
3727 //______________________________________________________________________________
3728 //
3729 // Command SCAN
3730 //
3731  if( !strncmp(comd.Data(),"SCA",3) ) {
3732  Printf(" ***>SCAn [parno] [numpts] [from] [to]");
3733  Printf(" Scans the value of the user function by varying parameter");
3734  Printf(" number [parno], leaving all other parameters fixed at the");
3735  Printf(" current value. If [parno] is not specified, all variable");
3736  Printf(" parameters are scanned in sequence.");
3737  Printf(" The number of points [numpts] in the scan is 40 by default,");
3738  Printf(" and cannot exceed 100. The range of the scan is by default");
3739  Printf(" 2 standard deviations on each side of the current best value,");
3740  Printf(" but can be specified as from [from] to [to].");
3741  Printf(" After each scan, if a new minimum is found, the best parameter");
3742  Printf(" values are retained as start values for future scans or");
3743  Printf(" minimizations. The curve resulting from each scan is plotted");
3744  Printf(" on the output unit in order to show the approximate behaviour");
3745  Printf(" of the function.");
3746  Printf(" This command is not intended for minimization, but is sometimes");
3747  Printf(" useful for debugging the user function or finding a");
3748  Printf(" reasonable starting point.");
3749  goto L99;
3750  }
3751 //______________________________________________________________________________
3752 //
3753 // Command SEEK
3754 //
3755  if( !strncmp(comd.Data(),"SEE",3) ) {
3756  Printf(" ***>SEEk [maxcalls] [devs]");
3757  Printf(" Causes a Monte Carlo minimization of the function, by choosing");
3758  Printf(" random values of the variable parameters, chosen uniformly");
3759  Printf(" over a hypercube centered at the current best value.");
3760  Printf(" The region size is by default 3 standard deviations on each");
3761  Printf(" side, but can be changed by specifying the value of [devs].");
3762  goto L99;
3763  }
3764 //______________________________________________________________________________
3765 //
3766 // Command SET
3767 //
3768  if( !strncmp(comd.Data(),"SET",3) ) {
3769  Printf(" ***>SET <option_name>");
3770  Printf(" SET BATch");
3771  Printf(" Informs Minuit that it is running in batch mode.");
3772 
3773  Printf(" ");
3774  Printf(" SET EPSmachine <accuracy>");
3775  Printf(" Informs Minuit that the relative floating point arithmetic");
3776  Printf(" precision is <accuracy>. Minuit determines the nominal");
3777  Printf(" precision itself, but the SET EPSmachine command can be");
3778  Printf(" used to override Minuit own determination, when the user");
3779  Printf(" knows that the FCN function value is not calculated to");
3780  Printf(" the nominal machine accuracy. Typical values of <accuracy>");
3781  Printf(" are between 10**-5 and 10**-14.");
3782 
3783  Printf(" ");
3784  Printf(" SET ERRordef <up>");
3785  Printf(" Sets the value of UP (default value= 1.), defining parameter");
3786  Printf(" errors. Minuit defines parameter errors as the change");
3787  Printf(" in parameter value required to change the function value");
3788  Printf(" by UP. Normally, for chisquared fits UP=1, and for negative");
3789  Printf(" log likelihood, UP=0.5.");
3790 
3791  Printf(" ");
3792  Printf(" SET GRAdient [force]");
3793  Printf(" Informs Minuit that the user function is prepared to");
3794  Printf(" calculate its own first derivatives and return their values");
3795  Printf(" in the array GRAD when IFLAG=2 (see specs of FCN).");
3796  Printf(" If [force] is not specified, Minuit will calculate");
3797  Printf(" the FCN derivatives by finite differences at the current");
3798  Printf(" point and compare with the user calculation at that point,");
3799  Printf(" accepting the user values only if they agree.");
3800  Printf(" If [force]=1, Minuit does not do its own derivative");
3801  Printf(" calculation, and uses the derivatives calculated in FCN.");
3802 
3803  Printf(" ");
3804  Printf(" SET INPut [unitno] [filename]");
3805  Printf(" Causes Minuit, in data-driven mode only, to read subsequent");
3806  Printf(" commands (or parameter definitions) from a different input");
3807  Printf(" file. If no [unitno] is specified, reading reverts to the");
3808  Printf(" previous input file, assuming that there was one.");
3809  Printf(" If [unitno] is specified, and that unit has not been opened,");
3810  Printf(" then Minuit attempts to open the file [filename]} if a");
3811  Printf(" name is specified. If running in interactive mode and");
3812  Printf(" [filename] is not specified and [unitno] is not opened,");
3813  Printf(" Minuit prompts the user to enter a file name.");
3814  Printf(" If the word REWIND is added to the command (note:no blanks");
3815  Printf(" between INPUT and REWIND), the file is rewound before");
3816  Printf(" reading. Note that this command is implemented in standard");
3817  Printf(" Fortran 77 and the results may depend on the system;");
3818  Printf(" for example, if a filename is given under VM/CMS, it must");
3819  Printf(" be preceded by a slash.");
3820 
3821  Printf(" ");
3822  Printf(" SET INTeractive");
3823  Printf(" Informs Minuit that it is running interactively.");
3824 
3825  Printf(" ");
3826  Printf(" SET LIMits [parno] [lolim] [uplim]");
3827  Printf(" Allows the user to change the limits on one or all");
3828  Printf(" parameters. If no arguments are specified, all limits are");
3829  Printf(" removed from all parameters. If [parno] alone is specified,");
3830  Printf(" limits are removed from parameter [parno].");
3831  Printf(" If all arguments are specified, then parameter [parno] will");
3832  Printf(" be bounded between [lolim] and [uplim].");
3833  Printf(" Limits can be specified in either order, Minuit will take");
3834  Printf(" the smaller as [lolim] and the larger as [uplim].");
3835  Printf(" However, if [lolim] is equal to [uplim], an error condition");
3836  Printf(" results.");
3837 
3838  Printf(" ");
3839  Printf(" SET LINesperpage");
3840  Printf(" Sets the number of lines for one page of output.");
3841  Printf(" Default value is 24 for interactive mode");
3842 
3843  Printf(" ");
3844  Printf(" SET NOGradient");
3845  Printf(" The inverse of SET GRAdient, instructs Minuit not to");
3846  Printf(" use the first derivatives calculated by the user in FCN.");
3847 
3848  Printf(" ");
3849  Printf(" SET NOWarnings");
3850  Printf(" Supresses Minuit warning messages.");
3851 
3852  Printf(" ");
3853  Printf(" SET OUTputfile <unitno>");
3854  Printf(" Instructs Minuit to write further output to unit <unitno>.");
3855 
3856  Printf(" ");
3857  Printf(" SET PAGethrow <integer>");
3858  Printf(" Sets the carriage control character for ``new page'' to");
3859  Printf(" <integer>. Thus the value 1 produces a new page, and 0");
3860  Printf(" produces a blank line, on some devices (see TOPofpage)");
3861 
3862 
3863  Printf(" ");
3864  Printf(" SET PARameter <parno> <value>");
3865  Printf(" Sets the value of parameter <parno> to <value>.");
3866  Printf(" The parameter in question may be variable, fixed, or");
3867  Printf(" constant, but must be defined.");
3868 
3869  Printf(" ");
3870  Printf(" SET PRIntout <level>");
3871  Printf(" Sets the print level, determining how much output will be");
3872  Printf(" produced. Allowed values and their meanings are displayed");
3873  Printf(" after a SHOw PRInt command, and are currently <level>=:");
3874  Printf(" [-1] no output except from SHOW commands");
3875  Printf(" [0] minimum output");
3876  Printf(" [1] default value, normal output");
3877  Printf(" [2] additional output giving intermediate results.");
3878  Printf(" [3] maximum output, showing progress of minimizations.");
3879  Printf(" Note: See also the SET WARnings command.");
3880 
3881  Printf(" ");
3882  Printf(" SET RANdomgenerator <seed>");
3883  Printf(" Sets the seed of the random number generator used in SEEk.");
3884  Printf(" This can be any integer between 10000 and 900000000, for");
3885  Printf(" example one which was output from a SHOw RANdom command of");
3886  Printf(" a previous run.");
3887 
3888  Printf(" ");
3889  Printf(" SET STRategy <level>");
3890  Printf(" Sets the strategy to be used in calculating first and second");
3891  Printf(" derivatives and in certain minimization methods.");
3892  Printf(" In general, low values of <level> mean fewer function calls");
3893  Printf(" and high values mean more reliable minimization.");
3894  Printf(" Currently allowed values are 0, 1 (default), and 2.");
3895 
3896  Printf(" ");
3897  Printf(" SET TITle");
3898  Printf(" Informs Minuit that the next input line is to be considered");
3899  Printf(" the (new) title for this task or sub-task. This is for");
3900  Printf(" the convenience of the user in reading their output.");
3901 
3902  Printf(" ");
3903  Printf(" SET WARnings");
3904  Printf(" Instructs Minuit to output warning messages when suspicious");
3905  Printf(" conditions arise which may indicate unreliable results.");
3906  Printf(" This is the default.");
3907 
3908  Printf(" ");
3909  Printf(" SET WIDthpage");
3910  Printf(" Informs Minuit of the output page width.");
3911  Printf(" Default values are 80 for interactive jobs");
3912  goto L99;
3913  }
3914 //______________________________________________________________________________
3915 //
3916 // Command SHOW
3917 //
3918  if( !strncmp(comd.Data(),"SHO",3) ) {
3919  Printf(" ***>SHOw <option_name>");
3920  Printf(" All SET XXXX commands have a corresponding SHOw XXXX command.");
3921  Printf(" In addition, the SHOw commands listed starting here have no");
3922  Printf(" corresponding SET command for obvious reasons.");
3923 
3924  Printf(" ");
3925  Printf(" SHOw CORrelations");
3926  Printf(" Calculates and prints the parameter correlations from the");
3927  Printf(" error matrix.");
3928 
3929  Printf(" ");
3930  Printf(" SHOw COVariance");
3931  Printf(" Prints the (external) covariance (error) matrix.");
3932 
3933  Printf(" ");
3934  Printf(" SHOw EIGenvalues");
3935  Printf(" Calculates and prints the eigenvalues of the covariance");
3936  Printf(" matrix.");
3937 
3938  Printf(" ");
3939  Printf(" SHOw FCNvalue");
3940  Printf(" Prints the current value of FCN.");
3941  goto L99;
3942  }
3943 //______________________________________________________________________________
3944 //
3945 // Command SIMPLEX
3946 //
3947  if( !strncmp(comd.Data(),"SIM",3) ) {
3948  Printf(" ***>SIMplex [maxcalls] [tolerance]");
3949  Printf(" Performs a function minimization using the simplex method of");
3950  Printf(" Nelder and Mead. Minimization terminates either when the");
3951  Printf(" function has been called (approximately) [maxcalls] times,");
3952  Printf(" or when the estimated vertical distance to minimum (EDM) is");
3953  Printf(" less than [tolerance].");
3954  Printf(" The default value of [tolerance] is 0.1*UP(see SET ERRordef).");
3955  goto L99;
3956  }
3957 //______________________________________________________________________________
3958 //
3959 // Command STANDARD
3960 //
3961  if( !strncmp(comd.Data(),"STA",3) ) {
3962  Printf(" ***>STAndard");
3963  goto L99;
3964  }
3965 //______________________________________________________________________________
3966 //
3967 // Command STOP
3968 //
3969  if( !strncmp(comd.Data(),"STO",3) ) {
3970  Printf(" ***>STOP");
3971  Printf(" Same as EXIT.");
3972  goto L99;
3973  }
3974 //______________________________________________________________________________
3975 //
3976 // Command TOPOFPAGE
3977 //
3978  if( !strncmp(comd.Data(),"TOP",3) ) {
3979  Printf(" ***>TOPofpage");
3980  Printf(" Causes Minuit to write the character specified in a");
3981  Printf(" SET PAGethrow command (default = 1) to column 1 of the output");
3982  Printf(" file, which may or may not position your output medium to");
3983  Printf(" the top of a page depending on the device and system.");
3984  goto L99;
3985  }
3986 //______________________________________________________________________________
3987  Printf(" Unknown MINUIT command. Type HELP for list of commands.");
3988 
3989 L99:
3990  return;
3991 }
3992 
3993 ////////////////////////////////////////////////////////////////////////////////
3994 /// Calculates the full second-derivative matrix of FCN
3995 ///
3996 /// by taking finite differences. When calculating diagonal
3997 /// elements, it may iterate so that step size is nearly that
3998 /// which gives function change= UP/10. The first derivatives
3999 /// of course come as a free side effect, but with a smaller
4000 /// step size in order to obtain a known accuracy.
4001 
4003 {
4004  /* Local variables */
4005  Double_t dmin_, dxdi, elem, wint, tlrg2, d, dlast, ztemp, g2bfor;
4006  Double_t df, aimsag, fs1, tlrstp, fs2, stpinm, g2i, sag=0, xtf, xti, xtj;
4007  Int_t icyc, ncyc, ndex, idrv, iext, npar2, i, j, ifail, npard, nparx, id, multpy;
4008  Bool_t ldebug;
4009 
4010  ldebug = fIdbg[3] >= 1;
4011  if (fAmin == fUndefi) {
4012  mnamin();
4013  }
4014  if (fIstrat <= 0) {
4015  ncyc = 3;
4016  tlrstp = .5;
4017  tlrg2 = .1;
4018  } else if (fIstrat == 1) {
4019  ncyc = 5;
4020  tlrstp = .3;
4021  tlrg2 = .05;
4022  } else {
4023  ncyc = 7;
4024  tlrstp = .1;
4025  tlrg2 = .02;
4026  }
4027  if (fISW[4] >= 2 || ldebug) {
4028  Printf(" START COVARIANCE MATRIX CALCULATION.");
4029  }
4030  fCfrom = "HESSE ";
4031  fNfcnfr = fNfcn;
4032  fCstatu = "OK ";
4033  npard = fNpar;
4034 // make sure starting at the right place
4035  mninex(fX);
4036  nparx = fNpar;
4037  Eval(nparx, fGin, fs1, fU, 4); ++fNfcn;
4038  if (fs1 != fAmin) {
4039  df = fAmin - fs1;
4040  mnwarn("D", "MNHESS", TString::Format("function value differs from AMIN by %g",df));
4041  }
4042  fAmin = fs1;
4043  if (ldebug) {
4044  Printf(" PAR D GSTEP D G2 GRD SAG ");
4045  }
4046 // diagonal elements .
4047 
4048 // fISW[1] = 1 if approx, 2 if not posdef, 3 if ok
4049 // AIMSAG is the sagitta we are aiming for in second deriv calc.
4050 
4051  aimsag = TMath::Sqrt(fEpsma2)*(TMath::Abs(fAmin) + fUp);
4052 // Zero the second derivative matrix
4053  npar2 = fNpar*(fNpar + 1) / 2;
4054  for (i = 1; i <= npar2; ++i) { fVhmat[i-1] = 0; }
4055 
4056 // Loop over variable parameters for second derivatives
4057  idrv = 2;
4058  for (id = 1; id <= npard; ++id) {
4059  i = id + fNpar - npard;
4060  iext = fNexofi[i-1];
4061  if (fG2[i-1] == 0) {
4062  mnwarn("W", "HESSE", Form("Second derivative enters zero, param %d",iext));
4063  wint = fWerr[i-1];
4064  if (fNvarl[iext-1] > 1) {
4065  mndxdi(fX[i-1], i-1, dxdi);
4066  if (TMath::Abs(dxdi) < .001) wint = .01;
4067  else wint /= TMath::Abs(dxdi);
4068  }
4069  fG2[i-1] = fUp / (wint*wint);
4070  }
4071  xtf = fX[i-1];
4072  dmin_ = fEpsma2*8*TMath::Abs(xtf);
4073 
4074 // find step which gives sagitta = AIMSAG
4075  d = TMath::Abs(fGstep[i-1]);
4076  int skip50 = 0;
4077  for (icyc = 1; icyc <= ncyc; ++icyc) {
4078 // loop here only if SAG=0
4079  for (multpy = 1; multpy <= 5; ++multpy) {
4080 // take two steps
4081  fX[i-1] = xtf + d;
4082  mninex(fX);
4083  nparx = fNpar;
4084  Eval(nparx, fGin, fs1, fU, 4); ++fNfcn;
4085  fX[i-1] = xtf - d;
4086  mninex(fX);
4087  Eval(nparx, fGin, fs2, fU, 4); ++fNfcn;
4088  fX[i-1] = xtf;
4089  sag = (fs1 + fs2 - fAmin*2)*.5;
4090  if (sag != 0) goto L30;
4091  if (fGstep[i-1] < 0) {
4092  if (d >= .5) goto L26;
4093  d *= 10;
4094  if (d > .5) d = .51;
4095  continue;
4096  }
4097  d *= 10;
4098  }
4099 L26:
4100  mnwarn("W", "HESSE", TString::Format("Second derivative zero for parameter%d",iext));
4101  goto L390;
4102 // SAG is not zero
4103 L30:
4104  g2bfor = fG2[i-1];
4105  fG2[i-1] = sag*2 / (d*d);
4106  fGrd[i-1] = (fs1 - fs2) / (d*2);
4107  if (ldebug) {
4108  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);
4109  }
4110  if (fGstep[i-1] > 0) fGstep[i-1] = TMath::Abs(d);
4111  else fGstep[i-1] = -TMath::Abs(d);
4112  fDirin[i-1] = d;
4113  fHESSyy[i-1]= fs1;
4114  dlast = d;
4115  d = TMath::Sqrt(aimsag*2 / TMath::Abs(fG2[i-1]));
4116 // if parameter has limits, max int step size = 0.5
4117  stpinm = .5;
4118  if (fGstep[i-1] < 0) d = TMath::Min(d,stpinm);
4119  if (d < dmin_) d = dmin_;
4120 // see if converged
4121  if (TMath::Abs((d - dlast) / d) < tlrstp ||
4122  TMath::Abs((fG2[i-1] - g2bfor) / fG2[i-1]) < tlrg2) {
4123  skip50 = 1;
4124  break;
4125  }
4126  d = TMath::Min(d,dlast*102);
4127  d = TMath::Max(d,dlast*.1);
4128  }
4129 // end of step size loop
4130  if (!skip50)
4131  mnwarn("D", "MNHESS", TString::Format("Second Deriv. SAG,AIM= %d%g%g",iext,sag,aimsag));
4132 
4133  ndex = i*(i + 1) / 2;
4134  fVhmat[ndex-1] = fG2[i-1];
4135  }
4136 // end of diagonal second derivative loop
4137  mninex(fX);
4138 // refine the first derivatives
4139  if (fIstrat > 0) mnhes1();
4140  fISW[1] = 3;
4141  fDcovar = 0;
4142 // off-diagonal elements
4143 
4144  if (fNpar == 1) goto L214;
4145  for (i = 1; i <= fNpar; ++i) {
4146  for (j = 1; j <= i-1; ++j) {
4147  xti = fX[i-1];
4148  xtj = fX[j-1];
4149  fX[i-1] = xti + fDirin[i-1];
4150  fX[j-1] = xtj + fDirin[j-1];
4151  mninex(fX);
4152  Eval(nparx, fGin, fs1, fU, 4); ++fNfcn;
4153  fX[i-1] = xti;
4154  fX[j-1] = xtj;
4155  elem = (fs1 + fAmin - fHESSyy[i-1] - fHESSyy[j-1]) / (
4156  fDirin[i-1]*fDirin[j-1]);
4157  ndex = i*(i-1) / 2 + j;
4158  fVhmat[ndex-1] = elem;
4159  }
4160  }
4161 L214:
4162  mninex(fX);
4163 // verify matrix positive-definite
4164  mnpsdf();
4165  for (i = 1; i <= fNpar; ++i) {
4166  for (j = 1; j <= i; ++j) {
4167  ndex = i*(i-1) / 2 + j;
4168  fP[i + j*fMaxpar - fMaxpar-1] = fVhmat[ndex-1];
4169  fP[j + i*fMaxpar - fMaxpar-1] = fP[i + j*fMaxpar - fMaxpar-1];
4170  }
4171  }
4172  mnvert(fP, fMaxint, fMaxint, fNpar, ifail);
4173  if (ifail > 0) {
4174  mnwarn("W", "HESSE", "Matrix inversion fails.");
4175  goto L390;
4176  }
4177 // calculate e d m
4178  fEDM = 0;
4179 
4180  for (i = 1; i <= fNpar; ++i) {
4181 // off-diagonal elements
4182  ndex = i*(i-1) / 2;
4183  for (j = 1; j <= i-1; ++j) {
4184  ++ndex;
4185  ztemp = fP[i + j*fMaxpar - fMaxpar-1]*2;
4186  fEDM += fGrd[i-1]*ztemp*fGrd[j-1];
4187  fVhmat[ndex-1] = ztemp;
4188  }
4189 // diagonal elements
4190  ++ndex;
4191  fVhmat[ndex-1] = fP[i + i*fMaxpar - fMaxpar-1]*2;
4192  fEDM += fP[i + i*fMaxpar - fMaxpar-1]*(fGrd[i-1]*fGrd[i-1]);
4193  }
4194  if (fISW[4] >= 1 && fISW[1] == 3 && fItaur == 0) {
4195  Printf(" COVARIANCE MATRIX CALCULATED SUCCESSFULLY");
4196  }
4197  goto L900;
4198 // failure to invert 2nd deriv matrix
4199 L390:
4200  fISW[1] = 1;
4201  fDcovar = 1;
4202  fCstatu = "FAILED ";
4203  if (fISW[4] >= 0) {
4204  Printf(" MNHESS FAILS AND WILL RETURN DIAGONAL MATRIX. ");
4205  }
4206  for (i = 1; i <= fNpar; ++i) {
4207  ndex = i*(i-1) / 2;
4208  for (j = 1; j <= i-1; ++j) {
4209  ++ndex;
4210  fVhmat[ndex-1] = 0;
4211  }
4212  ++ndex;
4213  g2i = fG2[i-1];
4214  if (g2i <= 0) g2i = 1;
4215  fVhmat[ndex-1] = 2 / g2i;
4216  }
4217 L900:
4218  return;
4219 }
4220 
4221 ////////////////////////////////////////////////////////////////////////////////
4222 /// Calculate first derivatives (GRD) and uncertainties (DGRD)
4223 ///
4224 /// and appropriate step sizes GSTEP
4225 /// Called from MNHESS and MNGRAD
4226 
4228 {
4229  /* Local variables */
4230  Double_t dmin_, d, dfmin, dgmin=0, change, chgold, grdold=0, epspri;
4231  Double_t fs1, optstp, fs2, grdnew=0, sag, xtf;
4232  Int_t icyc, ncyc=0, idrv, i, nparx;
4233  Bool_t ldebug;
4234 
4235  ldebug = fIdbg[5] >= 1;
4236  if (fIstrat <= 0) ncyc = 1;
4237  if (fIstrat == 1) ncyc = 2;
4238  if (fIstrat > 1) ncyc = 6;
4239  idrv = 1;
4240  nparx = fNpar;
4241  dfmin = fEpsma2*4*(TMath::Abs(fAmin) + fUp);
4242 // main loop over parameters
4243  for (i = 1; i <= fNpar; ++i) {
4244  xtf = fX[i-1];
4245  dmin_ = fEpsma2*4*TMath::Abs(xtf);
4246  epspri = fEpsma2 + TMath::Abs(fGrd[i-1]*fEpsma2);
4247  optstp = TMath::Sqrt(dfmin / (TMath::Abs(fG2[i-1]) + epspri));
4248  d = TMath::Abs(fGstep[i-1])*.2;
4249  if (d > optstp) d = optstp;
4250  if (d < dmin_) d = dmin_;
4251  chgold = 1e4;
4252 // iterate reducing step size
4253  for (icyc = 1; icyc <= ncyc; ++icyc) {
4254  fX[i-1] = xtf + d;
4255  mninex(fX);
4256  Eval(nparx, fGin, fs1, fU, 4); ++fNfcn;
4257  fX[i-1] = xtf - d;
4258  mninex(fX);
4259  Eval(nparx, fGin, fs2, fU, 4); ++fNfcn;
4260  fX[i-1] = xtf;
4261 // check if step sizes appropriate
4262  sag = (fs1 + fs2 - fAmin*2)*.5;
4263  grdold = fGrd[i-1];
4264  grdnew = (fs1 - fs2) / (d*2);
4265  dgmin = fEpsmac*(TMath::Abs(fs1) + TMath::Abs(fs2)) / d;
4266  if (ldebug) {
4267  Printf("%4d%2d%12.5g%12.5g%12.5g%12.5g%12.5g",i,idrv,fGstep[i-1],d,fG2[i-1],grdnew,sag);
4268  }
4269  if (grdnew == 0) goto L60;
4270  change = TMath::Abs((grdold - grdnew) / grdnew);
4271  if (change > chgold && icyc > 1) goto L60;
4272  chgold = change;
4273  fGrd[i-1] = grdnew;
4274  if (fGstep[i-1] > 0) fGstep[i-1] = TMath::Abs(d);
4275  else fGstep[i-1] = -TMath::Abs(d);
4276 // decrease step until first derivative changes by <5%
4277  if (change < .05) goto L60;
4278  if (TMath::Abs(grdold - grdnew) < dgmin) goto L60;
4279  if (d < dmin_) {
4280  mnwarn("D", "MNHES1", "Step size too small for 1st drv.");
4281  goto L60;
4282  }
4283  d *= .2;
4284  }
4285 // loop satisfied = too many iter
4286  mnwarn("D", "MNHES1", TString::Format("Too many iterations on D1.%g%g",grdold,grdnew));
4287 L60:
4288  fDgrd[i-1] = TMath::Max(dgmin,TMath::Abs(grdold - grdnew));
4289  }
4290 // end of first deriv. loop
4291  mninex(fX);
4292 }
4293 
4294 ////////////////////////////////////////////////////////////////////////////////
4295 /// Attempts to improve on a good local minimum
4296 ///
4297 /// Attempts to improve on a good local minimum by finding a
4298 /// better one. The quadratic part of FCN is removed by MNCALF
4299 /// and this transformed function is minimised using the simplex
4300 /// method from several random starting points.
4301 ///
4302 /// ref. -- Goldstein and Price, Math.Comp. 25, 569 (1971)
4303 
4305 {
4306  /* Initialized data */
4307 
4308  Double_t rnum = 0;
4309 
4310  /* Local variables */
4311  Double_t amax, ycalf, ystar, ystst;
4312  Double_t pb, ep, wg, xi, sigsav, reg, sig2;
4313  Int_t npfn, ndex, loop=0, i, j, ifail, iseed=0;
4314  Int_t jhold, nloop, nparx, nparp1, jh, jl, iswtr;
4315 
4316  if (fNpar <= 0) return;
4317  if (fAmin == fUndefi) mnamin();
4318  fCstatu = "UNCHANGED ";
4319  fItaur = 1;
4320  fEpsi = fUp*.1;
4321  npfn = fNfcn;
4322  nloop = Int_t(fWord7[1]);
4323  if (nloop <= 0) nloop = fNpar + 4;
4324  nparx = fNpar;
4325  nparp1 = fNpar + 1;
4326  wg = 1 / Double_t(fNpar);
4327  sigsav = fEDM;
4328  fApsi = fAmin;
4329  iswtr = fISW[4] - 2*fItaur;
4330  for (i = 1; i <= fNpar; ++i) {
4331  fXt[i-1] = fX[i-1];
4332  fIMPRdsav[i-1] = fWerr[i-1];
4333  for (j = 1; j <= i; ++j) {
4334  ndex = i*(i-1) / 2 + j;
4335  fP[i + j*fMaxpar - fMaxpar-1] = fVhmat[ndex-1];
4336  fP[j + i*fMaxpar - fMaxpar-1] = fP[i + j*fMaxpar - fMaxpar-1];
4337  }
4338  }
4339  mnvert(fP, fMaxint, fMaxint, fNpar, ifail);
4340  if (ifail >= 1) goto L280;
4341 // Save inverted matrix in VT
4342  for (i = 1; i <= fNpar; ++i) {
4343  ndex = i*(i-1) / 2;
4344  for (j = 1; j <= i; ++j) {
4345  ++ndex;
4346  fVthmat[ndex-1] = fP[i + j*fMaxpar - fMaxpar-1];
4347  }
4348  }
4349  loop = 0;
4350 
4351 L20:
4352  for (i = 1; i <= fNpar; ++i) {
4353  fDirin[i-1] = fIMPRdsav[i-1]*2;
4354  mnrn15(rnum, iseed);
4355  fX[i-1] = fXt[i-1] + fDirin[i-1]*2*(rnum - .5);
4356  }
4357  ++loop;
4358  reg = 2;
4359  if (fISW[4] >= 0) {
4360  Printf("START ATTEMPT NO.%2d TO FIND NEW MINIMUM",loop);
4361  }
4362 L30:
4363  mncalf(fX, ycalf);
4364  fAmin = ycalf;
4365 // set up random simplex
4366  jl = nparp1;
4367  jh = nparp1;
4368  fIMPRy[nparp1-1] = fAmin;
4369  amax = fAmin;
4370  for (i = 1; i <= fNpar; ++i) {
4371  xi = fX[i-1];
4372  mnrn15(rnum, iseed);
4373  fX[i-1] = xi - fDirin[i-1]*(rnum - .5);
4374  mncalf(fX, ycalf);
4375  fIMPRy[i-1] = ycalf;
4376  if (fIMPRy[i-1] < fAmin) {
4377  fAmin = fIMPRy[i-1];
4378  jl = i;
4379  } else if (fIMPRy[i-1] > amax) {
4380  amax = fIMPRy[i-1];
4381  jh = i;
4382  }
4383  for (j = 1; j <= fNpar; ++j) { fP[j + i*fMaxpar - fMaxpar-1] = fX[j-1]; }
4384  fP[i + nparp1*fMaxpar - fMaxpar-1] = xi;
4385  fX[i-1] = xi;
4386  }
4387 
4388  fEDM = fAmin;
4389  sig2 = fEDM;
4390 // start main loop
4391 L50:
4392  if (fAmin < 0) goto L95;
4393  if (fISW[1] <= 2) goto L280;
4394  ep = fAmin*.1;
4395  if (sig2 < ep && fEDM < ep) goto L100;
4396  sig2 = fEDM;
4397  if (fNfcn - npfn > fNfcnmx) goto L300;
4398 // calculate new point * by reflection
4399  for (i = 1; i <= fNpar; ++i) {
4400  pb = 0;
4401  for (j = 1; j <= nparp1; ++j) { pb += wg*fP[i + j*fMaxpar - fMaxpar-1]; }
4402  fPbar[i-1] = pb - wg*fP[i + jh*fMaxpar - fMaxpar-1];
4403  fPstar[i-1] = fPbar[i-1]*2 - fP[i + jh*fMaxpar - fMaxpar-1]*1;
4404  }
4405  mncalf(fPstar, ycalf);
4406  ystar = ycalf;
4407  if (ystar >= fAmin) goto L70;
4408 // point * better than jl, calculate new point **
4409  for (i = 1; i <= fNpar; ++i) {
4410  fPstst[i-1] = fPstar[i-1]*2 + fPbar[i- 1]*-1;
4411  }
4412  mncalf(fPstst, ycalf);
4413  ystst = ycalf;
4414  if (ystst < fIMPRy[jl-1]) goto L67;
4415  mnrazz(ystar, fPstar, fIMPRy, jh, jl);
4416  goto L50;
4417 L67:
4418  mnrazz(ystst, fPstst, fIMPRy, jh, jl);
4419  goto L50;
4420 // point * is not as good as jl
4421 L70:
4422  if (ystar >= fIMPRy[jh-1]) goto L73;
4423  jhold = jh;
4424  mnrazz(ystar, fPstar, fIMPRy, jh, jl);
4425  if (jhold != jh) goto L50;
4426 // calculate new point **
4427 L73:
4428  for (i = 1; i <= fNpar; ++i) {
4429  fPstst[i-1] = fP[i + jh*fMaxpar - fMaxpar-1]*.5 + fPbar[i-1]*.5;
4430  }
4431  mncalf(fPstst, ycalf);
4432  ystst = ycalf;
4433  if (ystst > fIMPRy[jh-1]) goto L30;
4434 // point ** is better than jh
4435  if (ystst < fAmin) goto L67;
4436  mnrazz(ystst, fPstst, fIMPRy, jh, jl);
4437  goto L50;
4438 // end main loop
4439 L95:
4440  if (fISW[4] >= 0) {
4441  Printf(" AN IMPROVEMENT ON THE PREVIOUS MINIMUM HAS BEEN FOUND");
4442  }
4443  reg = .1;
4444 // ask if point is new
4445 L100:
4446  mninex(fX);
4447  Eval(nparx, fGin, fAmin, fU, 4); ++fNfcn;
4448  for (i = 1; i <= fNpar; ++i) {
4449  fDirin[i-1] = reg*fIMPRdsav[i-1];
4450  if (TMath::Abs(fX[i-1] - fXt[i-1]) > fDirin[i-1]) goto L150;
4451  }
4452  goto L230;
4453 L150:
4454  fNfcnmx = fNfcnmx + npfn - fNfcn;
4455  npfn = fNfcn;
4456  mnsimp();
4457  if (fAmin >= fApsi) goto L325;
4458  for (i = 1; i <= fNpar; ++i) {
4459  fDirin[i-1] = fIMPRdsav[i-1]*.1;
4460  if (TMath::Abs(fX[i-1] - fXt[i-1]) > fDirin[i-1]) goto L250;
4461  }
4462 L230:
4463  if (fAmin < fApsi) goto L350;
4464  goto L325;
4465 /* truly new minimum */
4466 L250:
4467  fLnewmn = kTRUE;
4468  if (fISW[1] >= 1) {
4469  fISW[1] = 1;
4470  fDcovar = TMath::Max(fDcovar,.5);
4471  } else fDcovar = 1;
4472  fItaur = 0;
4473  fNfcnmx = fNfcnmx + npfn - fNfcn;
4474  fCstatu = "NEW MINIMU";
4475  if (fISW[4] >= 0) {
4476  Printf(" IMPROVE HAS FOUND A TRULY NEW MINIMUM");
4477  Printf(" *************************************");
4478  }
4479  return;
4480 // return to previous region
4481 L280:
4482  if (fISW[4] > 0) {
4483  Printf(" COVARIANCE MATRIX WAS NOT POSITIVE-DEFINITE");
4484  }
4485  goto L325;
4486 L300:
4487  fISW[0] = 1;
4488 L325:
4489  for (i = 1; i <= fNpar; ++i) {
4490  fDirin[i-1] = fIMPRdsav[i-1]*.01;
4491  fX[i-1] = fXt[i-1];
4492  }
4493  fAmin = fApsi;
4494  fEDM = sigsav;
4495 L350:
4496  mninex(fX);
4497  if (fISW[4] > 0) {
4498  Printf(" IMPROVE HAS RETURNED TO REGION OF ORIGINAL MINIMUM");
4499  }
4500  fCstatu = "UNCHANGED ";
4501  mnrset(0);
4502  if (fISW[1] < 2) goto L380;
4503  if (loop < nloop && fISW[0] < 1) goto L20;
4504 L380:
4505  if (iswtr >= 0) mnprin(5, fAmin);
4506  fItaur = 0;
4507 }
4508 
4509 ////////////////////////////////////////////////////////////////////////////////
4510 /// Transforms from internal coordinates (PINT) to external (U)
4511 ///
4512 /// The minimising routines which work in
4513 /// internal coordinates call this routine before calling FCN.
4514 
4516 {
4517  Int_t i, j;
4518 
4519  for (j = 0; j < fNpar; ++j) {
4520  i = fNexofi[j]-1;
4521  if (fNvarl[i] == 1) {
4522  fU[i] = pint[j];
4523  } else {
4524  fU[i] = fAlim[i] + (TMath::Sin(pint[j]) + 1)*.5*(fBlim[i] - fAlim[i]);
4525  }
4526  }
4527 }
4528 
4529 ////////////////////////////////////////////////////////////////////////////////
4530 /// Main initialization member function for MINUIT
4531 ///
4532 /// It initializes some constants
4533 /// (including the logical I/O unit nos.),
4534 
4536 {
4537  /* Local variables */
4538  volatile Double_t epsp1;
4539  Double_t piby2, epstry, epsbak, distnn;
4540  Int_t i, idb;
4541 
4542 // I/O unit numbers
4543  fIsysrd = i1;
4544  fIsyswr = i2;
4545  fIstkwr[0] = fIsyswr;
4546  fNstkwr = 1;
4547  fIsyssa = i3;
4548  fNstkrd = 0;
4549 // version identifier
4550  fCvrsn = "95.03++ ";
4551 // some CONSTANT
4552  fMaxint = fMaxpar;
4553  fMaxext = 2*fMaxpar;
4554  fUndefi = -54321;
4555  fBigedm = 123456;
4556  fCundef = ")UNDEFINED";
4557  fCovmes[0] = "NO ERROR MATRIX ";
4558  fCovmes[1] = "ERR MATRIX APPROXIMATE";
4559  fCovmes[2] = "ERR MATRIX NOT POS-DEF";
4560  fCovmes[3] = "ERROR MATRIX ACCURATE ";
4561 // some starting values
4562  fNblock = 0;
4563  fIcomnd = 0;
4564  fCtitl = fCundef;
4565  fCfrom = "INPUT ";
4566  fNfcn = 0;
4567  fNfcnfr = fNfcn;
4568  fCstatu = "INITIALIZE";
4569  fISW[2] = 0;
4570  fISW[3] = 0;
4571  fISW[4] = 1;
4572 // fISW[5]=0 for batch jobs, =1 for interactive jobs
4573 // =-1 for originally interactive temporarily batch
4574 
4575  fISW[5] = 0;
4576 // if (intrac(&dummy)) fISW[5] = 1;
4577 // DEBUG options set to default values
4578  for (idb = 0; idb <= 10; ++idb) { fIdbg[idb] = 0; }
4579  fLrepor = kFALSE;
4580  fLwarn = kTRUE;
4581  fLimset = kFALSE;
4582  fLnewmn = kFALSE;
4583  fIstrat = 1;
4584  fItaur = 0;
4585 // default page dimensions and 'new page' carriage control integer
4586  fNpagwd = 120;
4587  fNpagln = 56;
4588  fNewpag = 1;
4589  if (fISW[5] > 0) {
4590  fNpagwd = 80;
4591  fNpagln = 30;
4592  fNewpag = 0;
4593  }
4594  fUp = 1;
4595  fUpdflt = fUp;
4596 // determine machine accuracy epsmac
4597  epstry = .5;
4598  for (i = 1; i <= 100; ++i) {
4599  epstry *= .5;
4600  epsp1 = epstry + 1;
4601  mntiny(epsp1, epsbak);
4602  if (epsbak < epstry) goto L35;
4603  }
4604  epstry = 1e-7;
4605  fEpsmac = epstry*4;
4606  Printf(" MNINIT UNABLE TO DETERMINE ARITHMETIC PRECISION. WILL ASSUME:%g",fEpsmac);
4607 L35:
4608  fEpsmac = epstry*8;
4610 // the vlims are a non-negligible distance from pi/2
4611 // used by MNPINT to set variables "near" the physical limits
4612  piby2 = TMath::ATan(1)*2;
4613  distnn = TMath::Sqrt(fEpsma2)*8;
4614  fVlimhi = piby2 - distnn;
4615  fVlimlo = -piby2 + distnn;
4616  mncler();
4617 // Printf(" MINUIT RELEASE %s INITIALIZED. DIMENSIONS 100/50 EPSMAC=%g",(const char*)fCvrsn,fEpsmac);
4618 }
4619 
4620 ////////////////////////////////////////////////////////////////////////////////
4621 /// Interprets the SET LIM command, to reset the parameter limits
4622 ///
4623 /// Called from MNSET
4624 
4626 {
4627  /* Local variables */
4628  Double_t dxdi, snew;
4629  Int_t kint, i2, newcod, ifx=0, inu;
4630 
4631  fCfrom = "SET LIM ";
4632  fNfcnfr = fNfcn;
4633  fCstatu = "NO CHANGE ";
4634  i2 = Int_t(fWord7[0]);
4635  if (i2 > fMaxext || i2 < 0) goto L900;
4636  if (i2 > 0) goto L30;
4637 // set limits on all parameters
4638  newcod = 4;
4639  if (fWord7[1] == fWord7[2]) newcod = 1;
4640  for (inu = 1; inu <= fNu; ++inu) {
4641  if (fNvarl[inu-1] <= 0) continue;
4642  if (fNvarl[inu-1] == 1 && newcod == 1) continue;
4643  kint = fNiofex[inu-1];
4644 // see if parameter has been fixed
4645  if (kint <= 0) {
4646  if (fISW[4] >= 0) {
4647  Printf(" LIMITS NOT CHANGED FOR FIXED PARAMETER:%4d",inu);
4648  }
4649  continue;
4650  }
4651  if (newcod == 1) {
4652 // remove limits from parameter
4653  if (fISW[4] > 0) {
4654  Printf(" LIMITS REMOVED FROM PARAMETER :%3d",inu);
4655  }
4656  fCstatu = "NEW LIMITS";
4657  mndxdi(fX[kint-1], kint-1, dxdi);
4658  snew = fGstep[kint-1]*dxdi;
4659  fGstep[kint-1] = TMath::Abs(snew);
4660  fNvarl[inu-1] = 1;
4661  } else {
4662 // put limits on parameter
4663  fAlim[inu-1] = TMath::Min(fWord7[1],fWord7[2]);
4664  fBlim[inu-1] = TMath::Max(fWord7[1],fWord7[2]);
4665  if (fISW[4] > 0) {
4666  Printf(" PARAMETER %3d LIMITS SET TO %15.5g%15.5g",inu,fAlim[inu-1],fBlim[inu-1]);
4667  }
4668  fNvarl[inu-1] = 4;
4669  fCstatu = "NEW LIMITS";
4670  fGstep[kint-1] = -.1;
4671  }
4672  }
4673  goto L900;
4674 // set limits on one parameter
4675 L30:
4676  if (fNvarl[i2-1] <= 0) {
4677  Printf(" PARAMETER %3d IS NOT VARIABLE.", i2);
4678  goto L900;
4679  }
4680  kint = fNiofex[i2-1];
4681 // see if parameter was fixed
4682  if (kint == 0) {
4683  Printf(" REQUEST TO CHANGE LIMITS ON FIXED PARAMETER:%3d",i2);
4684  for (ifx = 1; ifx <= fNpfix; ++ifx) {
4685  if (i2 == fIpfix[ifx-1]) goto L92;
4686  }
4687  Printf(" MINUIT BUG IN MNLIMS. SEE F. JAMES");
4688 L92:
4689  ;
4690  }
4691  if (fWord7[1] != fWord7[2]) goto L235;
4692 // remove limits
4693  if (fNvarl[i2-1] != 1) {
4694  if (fISW[4] > 0) {
4695  Printf(" LIMITS REMOVED FROM PARAMETER %2d",i2);
4696  }
4697  fCstatu = "NEW LIMITS";
4698  if (kint <= 0) {
4699  fGsteps[ifx-1] = TMath::Abs(fGsteps[ifx-1]);
4700  } else {
4701  mndxdi(fX[kint-1], kint-1, dxdi);
4702  if (TMath::Abs(dxdi) < .01) dxdi = .01;
4703  fGstep[kint-1] = TMath::Abs(fGstep[kint-1]*dxdi);
4704  fGrd[kint-1] *= dxdi;
4705  }
4706  fNvarl[i2-1] = 1;
4707  } else {
4708  Printf(" NO LIMITS SPECIFIED. PARAMETER %3d IS ALREADY UNLIMITED. NO CHANGE.",i2);
4709  }
4710  goto L900;
4711 // put on limits
4712 L235:
4713  fAlim[i2-1] = TMath::Min(fWord7[1],fWord7[2]);
4714  fBlim[i2-1] = TMath::Max(fWord7[1],fWord7[2]);
4715  fNvarl[i2-1] = 4;
4716  if (fISW[4] > 0) {
4717  Printf(" PARAMETER %3d LIMITS SET TO %15.5g%15.5g",i2,fAlim[i2-1],fBlim[i2-1]);
4718  }
4719  fCstatu = "NEW LIMITS";
4720  if (kint <= 0) fGsteps[ifx-1] = -.1;
4721  else fGstep[kint-1] = -.1;
4722 
4723 L900:
4724  if (fCstatu != "NO CHANGE ") {
4725  mnexin(fX);
4726  mnrset(1);
4727  }
4728 }
4729 
4730 ////////////////////////////////////////////////////////////////////////////////
4731 /// Perform a line search from position START
4732 ///
4733 /// along direction STEP, where the length of vector STEP
4734 /// gives the expected position of minimum.
4735 /// - FSTART is value of function at START
4736 /// - SLOPE (if non-zero) is df/dx along STEP at START
4737 /// - TOLER is initial tolerance of minimum in direction STEP
4738 ///
4739 /// SLAMBG and ALPHA control the maximum individual steps allowed.
4740 /// The first step is always =1. The max length of second step is SLAMBG.
4741 /// The max size of subsequent steps is the maximum previous successful
4742 /// step multiplied by ALPHA + the size of most recent successful step,
4743 /// but cannot be smaller than SLAMBG.
4744 
4745 void TMinuit::mnline(Double_t *start, Double_t fstart, Double_t *step, Double_t slope, Double_t toler)
4746 {
4747  /* Local variables */
4748  Double_t xpq[12], ypq[12], slam, sdev, coeff[3], denom, flast;
4749  Double_t fvals[3], xvals[3], f1, fvmin, xvmin, ratio, f2, f3 = 0., fvmax;
4750  Double_t toler8, toler9, overal, undral, slamin, slamax, slopem;
4751  Int_t i, nparx=0, nvmax=0, nxypt, kk, ipt;
4752  Bool_t ldebug;
4753  TString cmess;
4754  char chpq[13];
4755  int l65, l70, l80;
4756 
4757  /* Function Body */
4758  l65 = 0; l70 = 0; l80 = 0;
4759  ldebug = fIdbg[1] >= 1;
4760 // starting values for overall limits on total step SLAM
4761  overal = 1e3;
4762  undral = -100;
4763 // debug check if start is ok
4764  if (ldebug) {
4765  mninex(&start[0]);
4766  Eval(nparx, fGin, f1, fU, 4); ++fNfcn;
4767  if (f1 != fstart) {
4768  Printf(" MNLINE start point not consistent, F values, parameters=");
4769  for (kk = 1; kk <= fNpar; ++kk) {
4770  Printf(" %14.5e",fX[kk-1]);
4771  }
4772  }
4773  }
4774 // set up linear search along STEP
4775  fvmin = fstart;
4776  xvmin = 0;
4777  nxypt = 1;
4778  chpq[0] = charal[0];
4779  xpq[0] = 0;
4780  ypq[0] = fstart;
4781 // SLAMIN = smallest possible value of ABS(SLAM)
4782  slamin = 0;
4783  for (i = 1; i <= fNpar; ++i) {
4784  if (step[i-1] != 0) {
4785  ratio = TMath::Abs(start[i-1] / step[i-1]);
4786  if (slamin == 0) slamin = ratio;
4787  if (ratio < slamin) slamin = ratio;
4788  }
4789  fX[i-1] = start[i-1] + step[i-1];
4790  }
4791  if (slamin == 0) slamin = fEpsmac;
4792  slamin *= fEpsma2;
4793  nparx = fNpar;
4794 
4795  mninex(fX);
4796  Eval(nparx, fGin, f1, fU, 4); ++fNfcn;
4797  ++nxypt;
4798  chpq[nxypt-1] = charal[nxypt-1];
4799  xpq[nxypt-1] = 1;
4800  ypq[nxypt-1] = f1;
4801  if (f1 < fstart) {
4802  fvmin = f1;
4803  xvmin = 1;
4804  }
4805 // quadr interp using slope GDEL and two points
4806  slam = 1;
4807  toler8 = toler;
4808  slamax = 5;
4809  flast = f1;
4810 // can iterate on two-points (cut) if no imprvmnt
4811 
4812  do {
4813  denom = (flast - fstart - slope*slam)*2 / (slam*slam);
4814  slam = 1;
4815  if (denom != 0) slam = -slope / denom;
4816  if (slam < 0) slam = slamax;
4817  if (slam > slamax) slam = slamax;
4818  if (slam < toler8) slam = toler8;
4819  if (slam < slamin) {
4820  l80 = 1;
4821  break;
4822  }
4823  if (TMath::Abs(slam - 1) < toler8 && f1 < fstart) {
4824  l70 = 1;
4825  break;
4826  }
4827  if (TMath::Abs(slam - 1) < toler8) slam = toler8 + 1;
4828  if (nxypt >= 12) {
4829  l65 = 1;
4830  break;
4831  }
4832  for (i = 1; i <= fNpar; ++i) { fX[i-1] = start[i-1] + slam*step[i-1]; }
4833  mninex(fX);
4834  nparx = fNpar;
4835  Eval(nparx, fGin, f2, fU, 4); ++fNfcn;
4836  ++nxypt;
4837  chpq[nxypt-1] = charal[nxypt-1];
4838  xpq[nxypt-1] = slam;
4839  ypq[nxypt-1] = f2;
4840  if (f2 < fvmin) {
4841  fvmin = f2;
4842  xvmin = slam;
4843  }
4844  if (fstart == fvmin) {
4845  flast = f2;
4846  toler8 = toler*slam;
4847  overal = slam - toler8;
4848  slamax = overal;
4849  }
4850  } while (fstart == fvmin);
4851 
4852  if (!l65 && !l70 && !l80) {
4853 // quadr interp using 3 points
4854  xvals[0] = xpq[0];
4855  fvals[0] = ypq[0];
4856  xvals[1] = xpq[nxypt-2];
4857  fvals[1] = ypq[nxypt-2];
4858  xvals[2] = xpq[nxypt-1];
4859  fvals[2] = ypq[nxypt-1];
4860 // begin iteration, calculate desired step
4861  do {
4862  slamax = TMath::Max(slamax,TMath::Abs(xvmin)*2);
4863  mnpfit(xvals, fvals, 3, coeff, sdev);
4864  if (coeff[2] <= 0) {
4865  slopem = coeff[2]*2*xvmin + coeff[1];
4866  if (slopem <= 0) slam = xvmin + slamax;
4867  else slam = xvmin - slamax;
4868  } else {
4869  slam = -coeff[1] / (coeff[2]*2);
4870  if (slam > xvmin + slamax) slam = xvmin + slamax;
4871  if (slam < xvmin - slamax) slam = xvmin - slamax;
4872  }
4873  if (slam > 0) {
4874  if (slam > overal)
4875  slam = overal;
4876  else if (slam < undral)
4877  slam = undral;
4878  }
4879 
4880 // come here if step was cut below
4881  do {
4882  toler9 = TMath::Max(toler8,TMath::Abs(toler8*slam));
4883  for (ipt = 1; ipt <= 3; ++ipt) {
4884  if (TMath::Abs(slam - xvals[ipt-1]) < toler9) {
4885  l70 = 1;
4886  break;
4887  }
4888  }
4889  if (l70) break;
4890 // take the step
4891  if (nxypt >= 12) {
4892  l65 = 1;
4893  break;
4894  }
4895  for (i = 1; i <= fNpar; ++i) { fX[i-1] = start[i-1] + slam*step[i-1]; }
4896  mninex(fX);
4897  Eval(nparx, fGin, f3, fU, 4); ++fNfcn;
4898  ++nxypt;
4899  chpq[nxypt-1] = charal[nxypt-1];
4900  xpq[nxypt-1] = slam;
4901  ypq[nxypt-1] = f3;
4902 // find worst previous point out of three
4903  fvmax = fvals[0];
4904  nvmax = 1;
4905  if (fvals[1] > fvmax) {
4906  fvmax = fvals[1];
4907  nvmax = 2;
4908  }
4909  if (fvals[2] > fvmax) {
4910  fvmax = fvals[2];
4911  nvmax = 3;
4912  }
4913 // if latest point worse than all three previous, cut step
4914  if (f3 >= fvmax) {
4915  if (nxypt >= 12) {
4916  l65 = 1;
4917  break;
4918  }
4919  if (slam > xvmin) overal = TMath::Min(overal,slam - toler8);
4920  if (slam < xvmin) undral = TMath::Max(undral,slam + toler8);
4921  slam = (slam + xvmin)*.5;
4922  }
4923  } while (f3 >= fvmax);
4924 
4925 // prepare another iteration, replace worst previous point
4926  if (l65 || l70) break;
4927 
4928  xvals[nvmax-1] = slam;
4929  fvals[nvmax-1] = f3;
4930  if (f3 < fvmin) {
4931  fvmin = f3;
4932  xvmin = slam;
4933  } else {
4934  if (slam > xvmin) overal = TMath::Min(overal,slam - toler8);
4935  if (slam < xvmin) undral = TMath::Max(undral,slam + toler8);
4936  }
4937  } while (nxypt < 12);
4938  }
4939 
4940 // end of iteration
4941 // stop because too many iterations
4942  if (!l70 && !l80) {
4943  cmess = " LINE SEARCH HAS EXHAUSTED THE LIMIT OF FUNCTION CALLS ";
4944  if (ldebug) {
4945  Printf(" MNLINE DEBUG: steps=");
4946  for (kk = 1; kk <= fNpar; ++kk) {
4947  Printf(" %12.4g",step[kk-1]);
4948  }
4949  }
4950  }
4951 // stop because within tolerance
4952  if (l70) cmess = " LINE SEARCH HAS ATTAINED TOLERANCE ";
4953  if (l80) cmess = " STEP SIZE AT ARITHMETICALLY ALLOWED MINIMUM";
4954 
4955  fAmin = fvmin;
4956  for (i = 1; i <= fNpar; ++i) {
4957  fDirin[i-1] = step[i-1]*xvmin;
4958  fX[i-1] = start[i-1] + fDirin[i-1];
4959  }
4960  mninex(fX);
4961  if (xvmin < 0) {
4962  mnwarn("D", "MNLINE", " LINE MINIMUM IN BACKWARDS DIRECTION");
4963  }
4964  if (fvmin == fstart) {
4965  mnwarn("D", "MNLINE", " LINE SEARCH FINDS NO IMPROVEMENT ");
4966  }
4967  if (ldebug) {
4968  Printf(" AFTER %3d POINTS,%s",nxypt,(const char*)cmess);
4969  mnplot(xpq, ypq, chpq, nxypt, fNpagwd, fNpagln);
4970  }
4971 }
4972 
4973 ////////////////////////////////////////////////////////////////////////////////
4974 /// Prints the covariance matrix v when KODE=1
4975 ///
4976 /// always prints the global correlations, and
4977 /// calculates and prints the individual correlation coefficients
4978 
4980 {
4981  /* Local variables */
4982  Int_t ndex, i, j, m, n, ncoef, nparm, id, it, ix;
4983  Int_t nsofar, ndi, ndj, iso, isw2, isw5;
4984  TString ctemp;
4985 
4986  isw2 = fISW[1];
4987  if (isw2 < 1) {
4988  Printf("%s",(const char*)fCovmes[isw2]);
4989  return;
4990  }
4991  if (fNpar == 0) {
4992  Printf(" MNMATU: NPAR=0");
4993  return;
4994  }
4995 // external error matrix
4996  if (kode == 1) {
4997  isw5 = fISW[4];
4998  fISW[4] = 2;
4999  mnemat(fP, fMaxint);
5000  if (isw2 < 3) {
5001  Printf("%s",(const char*)fCovmes[isw2]);
5002  }
5003  fISW[4] = isw5;
5004  }
5005 // correlation coeffs
5006  if (fNpar <= 1) return;
5007  mnwerr();
5008 // NCOEF is number of coeff. that fit on one line, not to exceed 20
5009  ncoef = (fNpagwd - 19) / 6;
5010  ncoef = TMath::Min(ncoef,20);
5011  nparm = TMath::Min(fNpar,ncoef);
5012  Printf(" PARAMETER CORRELATION COEFFICIENTS ");
5013  ctemp = " NO. GLOBAL";
5014  for (id = 1; id <= nparm; ++id) {
5015  ctemp += TString::Format(" %6d",fNexofi[id-1]);
5016  }
5017  Printf("%s",(const char*)ctemp);
5018  for (i = 1; i <= fNpar; ++i) {
5019  ix = fNexofi[i-1];
5020  ndi = i*(i + 1) / 2;
5021  for (j = 1; j <= fNpar; ++j) {
5022  m = TMath::Max(i,j);
5023  n = TMath::Min(i,j);
5024  ndex = m*(m-1) / 2 + n;
5025  ndj = j*(j + 1) / 2;
5026  fMATUvline[j-1] = fVhmat[ndex-1] / TMath::Sqrt(TMath::Abs(fVhmat[ndi-1]*fVhmat[ndj-1]));
5027  }
5028  nparm = TMath::Min(fNpar,ncoef);
5029  ctemp.Form(" %3d %7.5f ",ix,fGlobcc[i-1]);
5030  for (it = 1; it <= nparm; ++it) {
5031  ctemp += TString::Format(" %6.3f",fMATUvline[it-1]);
5032  }
5033  Printf("%s",(const char*)ctemp);
5034  if (i <= nparm) continue;
5035  ctemp = " ";
5036  for (iso = 1; iso <= 10; ++iso) {
5037  nsofar = nparm;
5038  nparm = TMath::Min(fNpar,nsofar + ncoef);
5039  for (it = nsofar + 1; it <= nparm; ++it) {
5040  ctemp = ctemp + TString::Format(" %6.3f",fMATUvline[it-1]);
5041  }
5042  Printf("%s",(const char*)ctemp);
5043  if (i <= nparm) break;
5044  }
5045  }
5046  if (isw2 < 3) {
5047  Printf(" %s",(const char*)fCovmes[isw2]);
5048  }
5049 }
5050 
5051 ////////////////////////////////////////////////////////////////////////////////
5052 /// Performs a local function minimization
5053 ///
5054 /// Performs a local function minimization using basically the
5055 /// method of Davidon-Fletcher-Powell as modified by Fletcher
5056 ///
5057 /// ref. -- Fletcher, Comp.J. 13,317 (1970) "switching method"
5058 
5060 {
5061  /* Local variables */
5062  Double_t gdel, gami, vlen, dsum, gssq, vsum, d;
5063  Double_t fzero, fs, ri, delgam, rhotol;
5064  Double_t gdgssq, gvg, vgi;
5065  Int_t npfn, ndex, iext, i, j, m, n, npsdf, nparx;
5066  Int_t iswtr, lined2, kk, nfcnmg, nrstrt,iter;
5067  Bool_t ldebug;
5068  Double_t toler = 0.05;
5069 
5070  if (fNpar <= 0) return;
5071  if (fAmin == fUndefi) mnamin();
5072  ldebug = kFALSE; if ( fIdbg[4] >= 1) ldebug = kTRUE;
5073  fCfrom = "MIGRAD ";
5074  fNfcnfr = fNfcn;
5075  nfcnmg = fNfcn;
5076  fCstatu = "INITIATE ";
5077  iswtr = fISW[4] - 2*fItaur;
5078  npfn = fNfcn;
5079  nparx = fNpar;
5080  vlen = (Double_t) (fNpar*(fNpar + 1) / 2);
5081  nrstrt = 0;
5082  npsdf = 0;
5083  lined2 = 0;
5084  fISW[3] = -1;
5085  rhotol = fApsi*.001;
5086  if (iswtr >= 1) {
5087  Printf(" START MIGRAD MINIMIZATION. STRATEGY %2d. CONVERGENCE WHEN EDM .LT.%9.2e",fIstrat,rhotol);
5088  }
5089 // initialization strategy
5090  if (fIstrat < 2 || fISW[1] >= 3) goto L2;
5091 // come (back) here to restart completely
5092 L1:
5093  if (nrstrt > fIstrat) {
5094  fCstatu = "FAILED ";
5095  fISW[3] = -1;
5096  goto L230;
5097  }
5098 // get full covariance and gradient
5099  mnhess();
5100  mnwerr();
5101  npsdf = 0;
5102  if (fISW[1] >= 1) goto L10;
5103 // get gradient at start point
5104 L2:
5105  mninex(fX);
5106  if (fISW[2] == 1) {
5107  Eval(nparx, fGin, fzero, fU, 2); ++fNfcn;
5108  }
5109  mnderi();
5110  if (fISW[1] >= 1) goto L10;
5111 // sometimes start with diagonal matrix
5112  for (i = 1; i <= fNpar; ++i) {
5113  fMIGRxxs[i-1] = fX[i-1];
5114  fMIGRstep[i-1] = 0;
5115  }
5116 // do line search if second derivative negative
5117  ++lined2;
5118  if (lined2 < (fIstrat + 1)*fNpar) {
5119  for (i = 1; i <= fNpar; ++i) {
5120  if (fG2[i-1] > 0) continue;
5121  if (fGrd[i-1] > 0) fMIGRstep[i-1] = -TMath::Abs(fGstep[i-1]);
5122  else fMIGRstep[i-1] = TMath::Abs(fGstep[i-1]);
5123  gdel = fMIGRstep[i-1]*fGrd[i-1];
5124  fs = fAmin;
5125  mnline(fMIGRxxs, fs, fMIGRstep, gdel, toler);
5126  mnwarn("D", "MNMIGR", "Negative G2 line search");
5127  iext = fNexofi[i-1];
5128  if (ldebug) {
5129  Printf(" Negative G2 line search, param %3d %13.3g%13.3g",iext,fs,fAmin);
5130  }
5131  goto L2;
5132  }
5133  }
5134 // make diagonal error matrix
5135  for (i = 1; i <= fNpar; ++i) {
5136  ndex = i*(i-1) / 2;
5137  for (j = 1; j <= i-1; ++j) {
5138  ++ndex;
5139  fVhmat[ndex-1] = 0;
5140  }
5141  ++ndex;
5142  if (fG2[i-1] <= 0) fG2[i-1] = 1;
5143  fVhmat[ndex-1] = 2 / fG2[i-1];
5144  }
5145  fDcovar = 1;
5146  if (ldebug) {
5147  Printf(" DEBUG MNMIGR, STARTING MATRIX DIAGONAL, VHMAT=");
5148  for (kk = 1; kk <= Int_t(vlen); ++kk) {
5149  Printf(" %10.2g",fVhmat[kk-1]);
5150  }
5151  }
5152 // ready to start first iteration
5153 L10:
5154  ++nrstrt;
5155  if (nrstrt > fIstrat + 1) {
5156  fCstatu = "FAILED ";
5157  goto L230;
5158  }
5159  fs = fAmin;
5160 // get EDM and set up loop
5161  fEDM = 0;
5162  for (i = 1; i <= fNpar; ++i) {
5163  fMIGRgs[i-1] = fGrd[i-1];
5164  fMIGRxxs[i-1] = fX[i-1];
5165  ndex = i*(i-1) / 2;
5166  for (j = 1; j <= i-1; ++j) {
5167  ++ndex;
5168  fEDM += fMIGRgs[i-1]*fVhmat[ndex-1]*fMIGRgs[j-1];
5169  }
5170  ++ndex;
5171  fEDM += fMIGRgs[i-1]*fMIGRgs[i-1]*.5*fVhmat[ndex-1];
5172  }
5173  fEDM = fEDM*.5*(fDcovar*3 + 1);
5174  if (fEDM < 0) {
5175  mnwarn("W", "MIGRAD", "STARTING MATRIX NOT POS-DEFINITE.");
5176  fISW[1] = 0;
5177  fDcovar = 1;
5178  goto L2;
5179  }
5180  if (fISW[1] == 0) fEDM = fBigedm;
5181  iter = 0;
5182  mninex(fX);
5183  mnwerr();
5184  if (iswtr >= 1) mnprin(3, fAmin);
5185  if (iswtr >= 2) mnmatu(0);
5186 // start main loop
5187 L24:
5188  if (fNfcn - npfn >= fNfcnmx) goto L190;
5189  gdel = 0;
5190  gssq = 0;
5191  for (i = 1; i <= fNpar; ++i) {
5192  ri = 0;
5193  gssq += fMIGRgs[i-1]*fMIGRgs[i-1];
5194  for (j = 1; j <= fNpar; ++j) {
5195  m = TMath::Max(i,j);
5196  n = TMath::Min(i,j);
5197  ndex = m*(m-1) / 2 + n;
5198  ri += fVhmat[ndex-1]*fMIGRgs[j-1];
5199  }
5200  fMIGRstep[i-1] = ri*-.5;
5201  gdel += fMIGRstep[i-1]*fMIGRgs[i-1];
5202  }
5203  if (gssq == 0) {
5204  mnwarn("D", "MIGRAD", " FIRST DERIVATIVES OF FCN ARE ALL ZERO");
5205  goto L300;
5206  }
5207 // if gdel positive, V not posdef
5208  if (gdel >= 0) {
5209  mnwarn("D", "MIGRAD", " NEWTON STEP NOT DESCENT.");
5210  if (npsdf == 1) goto L1;
5211  mnpsdf();
5212  npsdf = 1;
5213  goto L24;
5214  }
5215 // do line search
5216  mnline(fMIGRxxs, fs, fMIGRstep, gdel, toler);
5217  if (fAmin == fs) goto L200;
5218  fCfrom = "MIGRAD ";
5219  fNfcnfr = nfcnmg;
5220  fCstatu = "PROGRESS ";
5221 // get gradient at new point
5222  mninex(fX);
5223  if (fISW[2] == 1) {
5224  Eval(nparx, fGin, fzero, fU, 2); ++fNfcn;
5225  }
5226  mnderi();
5227 // calculate new EDM
5228  npsdf = 0;
5229 L81:
5230  fEDM = 0;
5231  gvg = 0;
5232  delgam = 0;
5233  gdgssq = 0;
5234  for (i = 1; i <= fNpar; ++i) {
5235  ri = 0;
5236  vgi = 0;
5237  for (j = 1; j <= fNpar; ++j) {
5238  m = TMath::Max(i,j);
5239  n = TMath::Min(i,j);
5240  ndex = m*(m-1) / 2 + n;
5241  vgi += fVhmat[ndex-1]*(fGrd[j-1] - fMIGRgs[j-1]);
5242  ri += fVhmat[ndex-1]*fGrd[j-1];
5243  }
5244  fMIGRvg[i-1] = vgi*.5;
5245  gami = fGrd[i-1] - fMIGRgs[i-1];
5246  gdgssq += gami*gami;
5247  gvg += gami*fMIGRvg[i-1];
5248  delgam += fDirin[i-1]*gami;
5249  fEDM += fGrd[i-1]*ri*.5;
5250  }
5251  fEDM = fEDM*.5*(fDcovar*3 + 1);
5252 // if EDM negative, not positive-definite
5253  if (fEDM < 0 || gvg <= 0) {
5254  mnwarn("D", "MIGRAD", "NOT POS-DEF. EDM OR GVG NEGATIVE.");
5255  fCstatu = "NOT POSDEF";
5256  if (npsdf == 1) goto L230;
5257  mnpsdf();
5258  npsdf = 1;
5259  goto L81;
5260  }
5261 // print information about this iteration
5262  ++iter;
5263  if (iswtr >= 3 || (iswtr == 2 && iter % 10 == 1)) {
5264  mnwerr();
5265  mnprin(3, fAmin);
5266  }
5267  if (gdgssq == 0) {
5268  mnwarn("D", "MIGRAD", "NO CHANGE IN FIRST DERIVATIVES OVER LAST STEP");
5269  }
5270  if (delgam < 0) {
5271  mnwarn("D", "MIGRAD", "FIRST DERIVATIVES INCREASING ALONG SEARCH LINE");
5272  }
5273 // update covariance matrix
5274  fCstatu = "IMPROVEMNT";
5275  if (ldebug) {
5276  Printf(" VHMAT 1 =");
5277  for (kk = 1; kk <= 10; ++kk) {
5278  Printf(" %10.2g",fVhmat[kk-1]);
5279  }
5280  }
5281  dsum = 0;
5282  vsum = 0;
5283  for (i = 1; i <= fNpar; ++i) {
5284  for (j = 1; j <= i; ++j) {
5285  if(delgam == 0 || gvg == 0) d = 0;
5286  else d = fDirin[i-1]*fDirin[j-1] / delgam - fMIGRvg[i-1]*fMIGRvg[j-1] / gvg;
5287  dsum += TMath::Abs(d);
5288  ndex = i*(i-1) / 2 + j;
5289  fVhmat[ndex-1] += d*2;
5290  vsum += TMath::Abs(fVhmat[ndex-1]);
5291  }
5292  }
5293 // smooth local fluctuations by averaging DCOVAR
5294  fDcovar = (fDcovar + dsum / vsum)*.5;
5295  if (iswtr >= 3 || ldebug) {
5296  Printf(" RELATIVE CHANGE IN COV. MATRIX=%5.1f per cent",fDcovar*100);
5297  }
5298  if (ldebug) {
5299  Printf(" VHMAT 2 =");
5300  for (kk = 1; kk <= 10; ++kk) {
5301  Printf(" %10.3g",fVhmat[kk-1]);
5302  }
5303  }
5304  if (delgam <= gvg) goto L135;
5305  for (i = 1; i <= fNpar; ++i) {
5306  fMIGRflnu[i-1] = fDirin[i-1] / delgam - fMIGRvg[i-1] / gvg;
5307  }
5308  for (i = 1; i <= fNpar; ++i) {
5309  for (j = 1; j <= i; ++j) {
5310  ndex = i*(i-1) / 2 + j;
5311  fVhmat[ndex-1] += gvg*2*fMIGRflnu[i-1]*fMIGRflnu[j-1];
5312  }
5313  }
5314 L135:
5315 // and see if converged
5316  if (fEDM < rhotol*.1) goto L300;
5317 // if not, prepare next iteration
5318  for (i = 1; i <= fNpar; ++i) {
5319  fMIGRxxs[i-1] = fX[i-1];
5320  fMIGRgs[i-1] = fGrd[i-1];
5321  }
5322  fs = fAmin;
5323  if (fISW[1] == 0 && fDcovar < .5) fISW[1] = 1;
5324  if (fISW[1] == 3 && fDcovar > .1) fISW[1] = 1;
5325  if (fISW[1] == 1 && fDcovar < .05) fISW[1] = 3;
5326  goto L24;
5327 // end main loop
5328 // call limit in MNMIGR
5329 L190:
5330  fISW[0] = 1;
5331  if (fISW[4] >= 0) {
5332  Printf(" CALL LIMIT EXCEEDED IN MIGRAD.");
5333  }
5334  fCstatu = "CALL LIMIT";
5335  goto L230;
5336 // fails to improve
5337 L200:
5338  if (iswtr >= 1) {
5339  Printf(" MIGRAD FAILS TO FIND IMPROVEMENT");
5340  }
5341  for (i = 1; i <= fNpar; ++i) { fX[i-1] = fMIGRxxs[i-1]; }
5342  if (fEDM < rhotol) goto L300;
5343  if (fEDM < TMath::Abs(fEpsma2*fAmin)) {
5344  if (iswtr >= 0) {
5345  Printf(" MACHINE ACCURACY LIMITS FURTHER IMPROVEMENT.");
5346  }
5347  goto L300;
5348  }
5349  if (fIstrat < 1) {
5350  if (fISW[4] >= 0) {
5351  Printf(" MIGRAD FAILS WITH STRATEGY=0. WILL TRY WITH STRATEGY=1.");
5352  }
5353  fIstrat = 1;
5354  }
5355  goto L1;
5356 // fails to converge
5357 L230:
5358  if (iswtr >= 0) {
5359  Printf(" MIGRAD TERMINATED WITHOUT CONVERGENCE.");
5360  }
5361  if (fISW[1] == 3) fISW[1] = 1;
5362  fISW[3] = -1;
5363  goto L400;
5364 // apparent convergence
5365 L300:
5366  if (iswtr >= 0) {
5367  Printf(" MIGRAD MINIMIZATION HAS CONVERGED.");
5368  }
5369  if (fItaur == 0) {
5370  if (fIstrat >= 2 || (fIstrat == 1 && fISW[1] < 3)) {
5371  if (fISW[4] >= 0) {
5372  Printf(" MIGRAD WILL VERIFY CONVERGENCE AND ERROR MATRIX.");
5373  }
5374  mnhess();
5375  mnwerr();
5376  npsdf = 0;
5377  if (fEDM > rhotol) goto L10;
5378  }
5379  }
5380  fCstatu = "CONVERGED ";
5381  fISW[3] = 1;
5382 // come here in any case
5383 L400:
5384  fCfrom = "MIGRAD ";
5385  fNfcnfr = nfcnmg;
5386  mninex(fX);
5387  mnwerr();
5388  if (iswtr >= 0) mnprin(3, fAmin);
5389  if (iswtr >= 1) mnmatu(1);
5390 }
5391 
5392 ////////////////////////////////////////////////////////////////////////////////
5393 /// Performs a MINOS error analysis
5394 ///
5395 /// Performs a MINOS error analysis on those parameters for
5396 /// which it is requested on the MINOS command by calling
5397 /// MNMNOT for each parameter requested.
5398 
5400 {
5401  /* Local variables */
5402  Double_t val2mi, val2pl;
5403  Int_t nbad, ilax, ilax2, ngood, nfcnmi, iin, knt;
5404 
5405  if (fNpar <= 0) goto L700;
5406  ngood = 0;
5407  nbad = 0;
5408  nfcnmi = fNfcn;
5409 // loop over parameters requested
5410  for (knt = 1; knt <= fNpar; ++knt) {
5411  if (Int_t(fWord7[1]) == 0) {
5412  ilax = fNexofi[knt-1];
5413  } else {
5414  if (knt >= 7) break;
5415  ilax = Int_t(fWord7[knt]);
5416  if (ilax == 0) break;
5417  if (ilax > 0 && ilax <= fNu) {
5418  if (fNiofex[ilax-1] > 0) goto L565;
5419  }
5420  Printf(" PARAMETER NUMBER %3d NOT A VARIABLE. IGNORED.",ilax);
5421  continue;
5422  }
5423 L565:
5424 // calculate one pair of M E s
5425  ilax2 = 0;
5426  mnmnot(ilax, ilax2, val2pl, val2mi);
5427  if (fLnewmn) goto L650;
5428 // update NGOOD and NBAD
5429  iin = fNiofex[ilax-1];
5430  if (fErp[iin-1] > 0) ++ngood;
5431  else ++nbad;
5432  if (fErn[iin-1] < 0) ++ngood;
5433  else ++nbad;
5434  }
5435 // end of loop
5436 // printout final values
5437  fCfrom = "MINOS ";
5438  fNfcnfr = nfcnmi;
5439  fCstatu = "UNCHANGED ";
5440  if (ngood == 0 && nbad == 0) goto L700;
5441  if (ngood > 0 && nbad == 0) fCstatu = "SUCCESSFUL";
5442  if (ngood == 0 && nbad > 0) fCstatu = "FAILURE ";
5443  if (ngood > 0 && nbad > 0) fCstatu = "PROBLEMS ";
5444  if (fISW[4] >= 0) mnprin(4, fAmin);
5445  if (fISW[4] >= 2) mnmatu(0);
5446  return;
5447 // new minimum found
5448 L650:
5449  fCfrom = "MINOS ";
5450  fNfcnfr = nfcnmi;
5451  fCstatu = "NEW MINIMU";
5452  if (fISW[4] >= 0) mnprin(4, fAmin);
5453  Printf(" NEW MINIMUM FOUND. GO BACK TO MINIMIZATION STEP.");
5454  Printf(" =================================================");
5455  Printf(" V");
5456  Printf(" V");
5457  Printf(" V");
5458  Printf(" VVVVVVV");
5459  Printf(" VVVVV");
5460  Printf(" VVV");
5461  Printf(" V\n");
5462  return;
5463 L700:
5464  Printf(" THERE ARE NO MINOS ERRORS TO CALCULATE.");
5465 }
5466 
5467 ////////////////////////////////////////////////////////////////////////////////
5468 /// Performs a MINOS error analysis on one parameter
5469 ///
5470 /// The parameter ILAX is varied, and the minimum of the
5471 /// function with respect to the other parameters is followed
5472 /// until it crosses the value FMIN+UP.
5473 
5474 void TMinuit::mnmnot(Int_t ilax, Int_t ilax2, Double_t &val2pl, Double_t &val2mi)
5475 {
5476  /* System generated locals */
5477  Int_t i__1;
5478 
5479  /* Local variables */
5480  Double_t delu, aopt, eros;
5481  Double_t abest, xunit, dc, ut, sigsav, du1;
5482  Double_t fac, sig, sav;
5483  Int_t marc, isig, mpar, ndex, imax, indx, ierr, i, j;
5484  Int_t iercr, it, istrav, nfmxin, nlimit, isw2, isw4;
5485  TString csig;
5486 
5487 // save and prepare start vals
5488  isw2 = fISW[1];
5489  isw4 = fISW[3];
5490  sigsav = fEDM;
5491  istrav = fIstrat;
5492  dc = fDcovar;
5493  fLnewmn = kFALSE;
5494  fApsi = fEpsi*.5;
5495  abest = fAmin;
5496  mpar = fNpar;
5497  nfmxin = fNfcnmx;
5498  for (i = 1; i <= mpar; ++i) { fXt[i-1] = fX[i-1]; }
5499  i__1 = mpar*(mpar + 1) / 2;
5500  for (j = 1; j <= i__1; ++j) { fVthmat[j-1] = fVhmat[j-1]; }
5501  for (i = 1; i <= mpar; ++i) {
5502  fMNOTgcc[i-1] = fGlobcc[i-1];
5503  fMNOTw[i-1] = fWerr[i-1];
5504  }
5505  it = fNiofex[ilax-1];
5506  fErp[it-1] = 0;
5507  fErn[it-1] = 0;
5508  mninex(fXt);
5509  ut = fU[ilax-1];
5510  if (fNvarl[ilax-1] == 1) {
5511  fAlim[ilax-1] = ut - fMNOTw[it-1]*100;
5512  fBlim[ilax-1] = ut + fMNOTw[it-1]*100;
5513  }
5514  ndex = it*(it + 1) / 2;
5515  xunit = TMath::Sqrt(fUp / fVthmat[ndex-1]);
5516  marc = 0;
5517  for (i = 1; i <= mpar; ++i) {
5518  if (i == it) continue;
5519  ++marc;
5520  imax = TMath::Max(it,i);
5521  indx = imax*(imax-1) / 2 + TMath::Min(it,i);
5522  fMNOTxdev[marc-1] = xunit*fVthmat[indx-1];
5523  }
5524 // fix the parameter in question
5525  mnfixp(it-1, ierr);
5526  if (ierr > 0) {
5527  Printf(" MINUIT ERROR. CANNOT FIX PARAMETER %4d INTERNAL %3d",ilax,it);
5528  goto L700;
5529  }
5530 // Nota Bene: from here on, NPAR=MPAR-1
5531 // Remember: MNFIXP squeezes IT out of X, XT, WERR, and VHMAT,
5532 // not W, VTHMAT
5533  for (isig = 1; isig <= 2; ++isig) {
5534  if (isig == 1) {
5535  sig = 1;
5536  csig = "POSI";
5537  } else {
5538  sig = -1;
5539  csig = "NEGA";
5540  }
5541 // sig=sign of error being calcd
5542  if (fISW[4] > 1) {
5543  Printf(" DETERMINATION OF %sTIVE MINOS ERROR FOR PARAMETER %d %s"
5544  ,(const char*)csig,ilax
5545  ,(const char*)fCpnam[ilax-1]);
5546  }
5547  if (fISW[1] <= 0) {
5548  mnwarn("D", "MINOS", "NO COVARIANCE MATRIX.");
5549  }
5550  nlimit = fNfcn + nfmxin;
5551  fIstrat = TMath::Max(istrav-1,0);
5552  du1 = fMNOTw[it-1];
5553  fU[ilax-1] = ut + sig*du1;
5554  fU[ilax-1] = TMath::Min(fU[ilax-1],fBlim[ilax-1]);
5555  fU[ilax-1] = TMath::Max(fU[ilax-1],fAlim[ilax-1]);
5556  delu = fU[ilax-1] - ut;
5557 // stop if already at limit with negligible step size
5558  if (TMath::Abs(delu) / (TMath::Abs(ut) + TMath::Abs(fU[ilax-1])) < fEpsmac) goto L440;
5559  fac = delu / fMNOTw[it-1];
5560  for (i = 1; i <= fNpar; ++i) {
5561  fX[i-1] = fXt[i-1] + fac*fMNOTxdev[i-1];
5562  }
5563  if (fISW[4] > 1) {
5564  Printf(" PARAMETER %4d SET TO%11.3e + %10.3e = %12.3e",ilax,ut,delu,fU[ilax-1]);
5565  }
5566 // loop to hit AMIN+UP
5567  fKe1cr = ilax;
5568  fKe2cr = 0;
5569  fXmidcr = fU[ilax-1];
5570  fXdircr = delu;
5571 
5572  fAmin = abest;
5573  fNfcnmx = nlimit - fNfcn;
5574  mncros(aopt, iercr);
5575  if (abest - fAmin > fUp*.01) goto L650;
5576  if (iercr == 1) goto L440;
5577  if (iercr == 2) goto L450;
5578  if (iercr == 3) goto L460;
5579 // error successfully calculated
5580  eros = fXmidcr - ut + aopt*fXdircr;
5581  if (fISW[4] > 1) {
5582  Printf(" THE %4sTIVE MINOS ERROR OF PARAMETER %3d %10s, IS %12.4e"
5583  ,(const char*)csig,ilax
5584  ,(const char*)fCpnam[ilax-1],eros);
5585  }
5586  goto L480;
5587 // failure returns
5588 L440:
5589  if (fISW[4] >= 1) {
5590  Printf(" THE %4sTIVE MINOS ERROR OF PARAMETER %3d, %s EXCEEDS ITS LIMIT."
5591  ,(const char*)csig,ilax
5592  ,(const char*)fCpnam[ilax-1]);
5593  }
5594  eros = fUndefi;
5595  goto L480;
5596 L450:
5597  if (fISW[4] >= 1) {
5598  Printf(" THE %4sTIVE MINOS ERROR %4d REQUIRES MORE THAN %5d FUNCTION CALLS."
5599  ,(const char*)csig,ilax,nfmxin);
5600  }
5601  eros = 0;
5602  goto L480;
5603 L460:
5604  if (fISW[4] >= 1) {
5605  Printf(" %4sTIVE MINOS ERROR NOT CALCULATED FOR PARAMETER %d"
5606  ,(const char*)csig,ilax);
5607  }
5608  eros = 0;
5609 
5610 L480:
5611  if (fISW[4] > 1) {
5612  Printf(" **************************************************************************");
5613  }
5614  if (sig < 0) {
5615  fErn[it-1] = eros;
5616  if (ilax2 > 0 && ilax2 <= fNu) val2mi = fU[ilax2-1];
5617  } else {
5618  fErp[it-1] = eros;
5619  if (ilax2 > 0 && ilax2 <= fNu) val2pl = fU[ilax2-1];
5620  }
5621  }
5622 // parameter finished. reset v
5623 // normal termination */
5624  fItaur = 1;
5625  mnfree(1);
5626  i__1 = mpar*(mpar + 1) / 2;
5627  for (j = 1; j <= i__1; ++j) { fVhmat[j-1] = fVthmat[j-1]; }
5628  for (i = 1; i <= mpar; ++i) {
5629  fWerr[i-1] = fMNOTw[i-1];
5630  fGlobcc[i-1] = fMNOTgcc[i-1];
5631  fX[i-1] = fXt[i-1];
5632  }
5633  mninex(fX);
5634  fEDM = sigsav;
5635  fAmin = abest;
5636  fISW[1] = isw2;
5637  fISW[3] = isw4;
5638  fDcovar = dc;
5639  goto L700;
5640 // new minimum
5641 L650:
5642  fLnewmn = kTRUE;
5643  fISW[1] = 0;
5644  fDcovar = 1;
5645  fISW[3] = 0;
5646  sav = fU[ilax-1];
5647  fItaur = 1;
5648  mnfree(1);
5649  fU[ilax-1] = sav;
5650  mnexin(fX);
5651  fEDM = fBigedm;
5652 // in any case
5653 L700:
5654  fItaur = 0;
5655  fNfcnmx = nfmxin;
5656  fIstrat = istrav;
5657 }
5658 
5659 ////////////////////////////////////////////////////////////////////////////////
5660 /// Implements one parameter definition
5661 ///
5662 /// Called from MNPARS and user-callable
5663 /// Implements one parameter definition, that is:
5664 /// - K (external) parameter number
5665 /// - CNAMK parameter name
5666 /// - UK starting value
5667 /// - WK starting step size or uncertainty
5668 /// - A, B lower and upper physical parameter limits
5669 /// and sets up (updates) the parameter lists.
5670 /// Output:
5671 /// - IERFLG=0 if no problems
5672 /// - >0 if MNPARM unable to implement definition
5673 
5675 {
5676  /* Local variables */
5677  Double_t vplu, a_small, gsmin, pinti, vminu, danger, sav, sav2;
5678  Int_t ierr, kint, in, ix, ktofix, lastin, kinfix, nvl;
5679  TString cnamk, chbufi;
5680 
5681  Int_t k = k1+1;
5682  cnamk = cnamj;
5683  kint = fNpar;
5684  if (k < 1 || k > fMaxext) {
5685 // parameter number exceeds allowed maximum value
5686  Printf(" MINUIT USER ERROR. PARAMETER NUMBER IS %3d ALLOWED RANGE IS ONE TO %4d",k,fMaxext);
5687  goto L800;
5688  }
5689 // normal parameter request
5690  ktofix = 0;
5691  if (fNvarl[k-1] < 0) goto L50;
5692 // previously defined parameter is being redefined
5693 // find if parameter was fixed
5694  for (ix = 1; ix <= fNpfix; ++ix) {
5695  if (fIpfix[ix-1] == k) ktofix = k;
5696  }
5697  if (ktofix > 0) {
5698  mnwarn("W", "PARAM DEF", "REDEFINING A FIXED PARAMETER.");
5699  if (kint >= fMaxint) {
5700  Printf(" CANNOT RELEASE. MAX NPAR EXCEEDED.");
5701  goto L800;
5702  }
5703  mnfree(-k);
5704  }
5705 // if redefining previously variable parameter
5706  if (fNiofex[k-1] > 0) kint = fNpar - 1;
5707 L50:
5708 
5709 // print heading
5710  if (fLphead && fISW[4] >= 0) {
5711  Printf(" PARAMETER DEFINITIONS:");
5712  Printf(" NO. NAME VALUE STEP SIZE LIMITS");
5713  fLphead = kFALSE;
5714  }
5715  if (wk > 0) goto L122;
5716 // constant parameter
5717  if (fISW[4] >= 0) {
5718  Printf(" %5d %-10s %13.5e constant",k,(const char*)cnamk,uk);
5719  }
5720  nvl = 0;
5721  goto L200;
5722 L122:
5723  if (a == 0 && b == 0) {
5724 // variable parameter without limits
5725  nvl = 1;
5726  if (fISW[4] >= 0) {
5727  Printf(" %5d %-10s %13.5e%13.5e no limits",k,(const char*)cnamk,uk,wk);
5728  }
5729  } else {
5730 // variable parameter with limits
5731  nvl = 4;
5732  fLnolim = kFALSE;
5733  if (fISW[4] >= 0) {
5734  Printf(" %5d %-10s %13.5e%13.5e %13.5e%13.5e",k,(const char*)cnamk,uk,wk,a,b);
5735  }
5736  }
5737 // request for another variable parameter
5738  ++kint;
5739  if (kint > fMaxint) {
5740  Printf(" MINUIT USER ERROR. TOO MANY VARIABLE PARAMETERS.");
5741  goto L800;
5742  }
5743  if (nvl == 1) goto L200;
5744  if (a == b) {
5745  Printf(" USER ERROR IN MINUIT PARAMETER");
5746  Printf(" DEFINITION");
5747  Printf(" UPPER AND LOWER LIMITS EQUAL.");
5748  goto L800;
5749  }
5750  if (b < a) {
5751  sav = b;
5752  b = a;
5753  a = sav;
5754  mnwarn("W", "PARAM DEF", "PARAMETER LIMITS WERE REVERSED.");
5755  if (fLwarn) fLphead = kTRUE;
5756  }
5757  if (b - a > 1e7) {
5758  mnwarn("W", "PARAM DEF", TString::Format("LIMITS ON PARAM%d TOO FAR APART.",k));
5759  if (fLwarn) fLphead = kTRUE;
5760  }
5761  danger = (b - uk)*(uk - a);
5762  if (danger < 0) {
5763  mnwarn("W", "PARAM DEF", "STARTING VALUE OUTSIDE LIMITS.");
5764  }
5765  if (danger == 0) {
5766  mnwarn("W", "PARAM DEF", "STARTING VALUE IS AT LIMIT.");
5767  }
5768 L200:
5769 // input OK, set values, arrange lists,
5770 // calculate step sizes GSTEP, DIRIN
5771  fCfrom = "PARAMETR";
5772  fNfcnfr = fNfcn;
5773  fCstatu = "NEW VALUES";
5774  fNu = TMath::Max(fNu,k);
5775  fCpnam[k-1] = cnamk;
5776  fU[k-1] = uk;
5777  fAlim[k-1] = a;
5778  fBlim[k-1] = b;
5779  fNvarl[k-1] = nvl;
5780  mnrset(1);
5781 // K is external number of new parameter
5782 // LASTIN is the number of var. params with ext. param. no.< K
5783  lastin = 0;
5784  for (ix = 1; ix <= k-1; ++ix) { if (fNiofex[ix-1] > 0) ++lastin; }
5785 // KINT is new number of variable params, NPAR is old
5786  if (kint == fNpar) goto L280;
5787  if (kint > fNpar) {
5788 // insert new variable parameter in list
5789  for (in = fNpar; in >= lastin + 1; --in) {
5790  ix = fNexofi[in-1];
5791  fNiofex[ix-1] = in + 1;
5792  fNexofi[in] = ix;
5793  fX[in] = fX[in-1];
5794  fXt[in] = fXt[in-1];
5795  fDirin[in] = fDirin[in-1];
5796  fG2[in] = fG2[in-1];
5797  fGstep[in] = fGstep[in-1];
5798  fWerr[in] = fWerr[in-1];
5799  fGrd[in] = fGrd[in-1];
5800  }
5801  } else {
5802 // remove variable parameter from list
5803  for (in = lastin + 1; in <= kint; ++in) {
5804  ix = fNexofi[in];
5805  fNiofex[ix-1] = in;
5806  fNexofi[in-1] = ix;
5807  fX[in-1] = fX[in];
5808  fXt[in-1] = fXt[in];
5809  fDirin[in-1] = fDirin[in];
5810  fG2[in-1] = fG2[in];
5811  fGstep[in-1] = fGstep[in];
5812  fWerr[in-1] = fWerr[in];
5813  fGrd[in-1] = fGrd[in];
5814  }
5815  }
5816 L280:
5817  ix = k;
5818  fNiofex[ix-1] = 0;
5819  fNpar = kint;
5820 // lists are now arranged
5821  if (nvl > 0) {
5822  in = lastin + 1;
5823  fNexofi[in-1] = ix;
5824  fNiofex[ix-1] = in;
5825  sav = fU[ix-1];
5826  mnpint(sav, ix-1, pinti);
5827  fX[in-1] = pinti;
5828  fXt[in-1] = fX[in-1];
5829  fWerr[in-1] = wk;
5830  sav2 = sav + wk;
5831  mnpint(sav2, ix-1, pinti);
5832  vplu = pinti - fX[in-1];
5833  sav2 = sav - wk;
5834  mnpint(sav2, ix-1, pinti);
5835  vminu = pinti - fX[in-1];
5836  fDirin[in-1] = (TMath::Abs(vplu) + TMath::Abs(vminu))*.5;
5837  fG2[in-1] = fUp*2 / (fDirin[in-1]*fDirin[in-1]);
5838  gsmin = fEpsma2*8*TMath::Abs(fX[in-1]);
5839  fGstep[in-1] = TMath::Max(gsmin,fDirin[in-1]*.1);
5840  if (fAmin != fUndefi) {
5841  a_small = TMath::Sqrt(fEpsma2*(fAmin + fUp) / fUp);
5842  fGstep[in-1] = TMath::Max(gsmin,a_small*fDirin[in-1]);
5843  }
5844  fGrd[in-1] = fG2[in-1]*fDirin[in-1];
5845 // if parameter has limits
5846  if (fNvarl[k-1] > 1) {
5847  if (fGstep[in-1] > .5) fGstep[in-1] = .5;
5848  fGstep[in-1] = -fGstep[in-1];
5849  }
5850  }
5851  if (ktofix > 0) {
5852  ierr = 0;
5853  kinfix = fNiofex[ktofix-1];
5854  if (kinfix > 0) mnfixp(kinfix-1, ierr);
5855  if (ierr > 0) goto L800;
5856  }
5857  ierflg = 0;
5858  return;
5859 // error on input, unable to implement request
5860 L800:
5861  ierflg = 1;
5862 }
5863 
5864 ////////////////////////////////////////////////////////////////////////////////
5865 /// Implements one parameter definition
5866 ///
5867 /// Called from MNREAD and user-callable
5868 /// Implements one parameter definition, that is:
5869 /// parses the string CRDBUF and calls MNPARM
5870 ///
5871 /// output conditions:
5872 /// - ICONDN = 0 all OK
5873 /// - ICONDN = 1 error, attempt to define parameter is ignored
5874 /// - ICONDN = 2 end of parameter definitions
5875 
5876 void TMinuit::mnpars(TString &crdbuf, Int_t &icondn)
5877 {
5878  /* Local variables */
5879  Double_t a=0, b=0, fk=0, uk=0, wk=0, xk=0;
5880  Int_t ierr, kapo1, kapo2;
5881  Int_t k, llist, ibegin, lenbuf, istart, lnc, icy;
5882  TString cnamk, comand, celmnt, ctemp;
5883  char stmp[128];
5884 
5885  lenbuf = strlen((const char*)crdbuf);
5886 // find out whether fixed or free-field format
5887  kapo1 = strspn((const char*)crdbuf, "'");
5888  if (kapo1 == 0) goto L150;
5889  kapo2 = strspn((const char*)crdbuf + kapo1, "'");
5890  if (kapo2 == 0) goto L150;
5891 // new (free-field) format
5892  kapo2 += kapo1;
5893 // skip leading blanks if any
5894  for (istart = 1; istart <= kapo1-1; ++istart) {
5895  if (crdbuf(istart-1,1) != ' ') goto L120;
5896  }
5897  goto L210;
5898 L120:
5899 // parameter number integer
5900  celmnt = crdbuf(istart-1, kapo1-istart);
5901  if (scanf((const char*)celmnt,&fk)) {;}
5902  k = Int_t(fk);
5903  if (k <= 0) goto L210;
5904  cnamk = "PARAM " + celmnt;
5905  if (kapo2 - kapo1 > 1) {
5906  cnamk = crdbuf(kapo1, kapo2-1-kapo1);
5907  }
5908 // special handling if comma or blanks and a comma follow 'name'
5909  for (icy = kapo2 + 1; icy <= lenbuf; ++icy) {
5910  if (crdbuf(icy-1,1) == ',') goto L139;
5911  if (crdbuf(icy-1,1) != ' ') goto L140;
5912  }
5913  uk = 0;
5914  wk = 0;
5915  a = 0;
5916  b = 0;
5917  goto L170;
5918 L139:
5919  ++icy;
5920 L140:
5921  ibegin = icy;
5922  ctemp = crdbuf(ibegin-1,lenbuf-ibegin);
5923  mncrck(ctemp, 20, comand, lnc, fMaxpar, fPARSplist, llist, ierr, fIsyswr);
5924  if (ierr > 0) goto L180;
5925  uk = fPARSplist[0];
5926  wk = 0;
5927  if (llist >= 2) wk = fPARSplist[1];
5928  a = 0;
5929  if (llist >= 3) a = fPARSplist[2];
5930  b = 0;
5931  if (llist >= 4) b = fPARSplist[3];
5932  goto L170;
5933 // old (fixed-field) format
5934 L150:
5935  if (scanf((const char*)crdbuf,&xk,stmp,&uk,&wk,&a,&b)) {;}
5936  cnamk = stmp;
5937  k = Int_t(xk);
5938  if (k == 0) goto L210;
5939 // parameter format cracked, implement parameter definition
5940 L170:
5941  mnparm(k-1, cnamk, uk, wk, a, b, ierr);
5942  icondn = ierr;
5943  return;
5944 // format or other error
5945 L180:
5946  icondn = 1;
5947  return;
5948 // end of data
5949 L210:
5950  icondn = 2;
5951 }
5952 
5953 ////////////////////////////////////////////////////////////////////////////////
5954 /// To fit a parabola to npar2p points
5955 ///
5956 /// - npar2p no. of points
5957 /// - parx2p(i) x value of point i
5958 /// - pary2p(i) y value of point i
5959 ///
5960 /// - coef2p(1...3) coefficients of the fitted parabola
5961 /// - y=coef2p(1) + coef2p(2)*x + coef2p(3)*x**2
5962 /// - sdev2p= variance
5963 /// - method : chi**2 = min equation solved explicitly
5964 
5965 void TMinuit::mnpfit(Double_t *parx2p, Double_t *pary2p, Int_t npar2p, Double_t *coef2p, Double_t &sdev2p)
5966 {
5967  /* Local variables */
5968  Double_t a, f, s, t, y, s2, x2, x3, x4, y2, cz[3], xm, xy, x2y;
5969  x2 = x3 = 0;
5970  Int_t i;
5971 
5972  /* Parameter adjustments */
5973  --coef2p;
5974  --pary2p;
5975  --parx2p;
5976 
5977  /* Function Body */
5978  for (i = 1; i <= 3; ++i) { cz[i-1] = 0; }
5979  sdev2p = 0;
5980  if (npar2p < 3) goto L10;
5981  f = (Double_t) (npar2p);
5982 // center x values for reasons of machine precision
5983  xm = 0;
5984  for (i = 1; i <= npar2p; ++i) { xm += parx2p[i]; }
5985  xm /= f;
5986  x2 = 0;
5987  x3 = 0;
5988  x4 = 0;
5989  y = 0;
5990  y2 = 0;
5991  xy = 0;
5992  x2y = 0;
5993  for (i = 1; i <= npar2p; ++i) {
5994  s = parx2p[i] - xm;
5995  t = pary2p[i];
5996  s2 = s*s;
5997  x2 += s2;
5998  x3 += s*s2;
5999  x4 += s2*s2;
6000  y += t;
6001  y2 += t*t;
6002  xy += s*t;
6003  x2y += s2*t;
6004  }
6005  a = (f*x4 - x2*x2)*x2 - f*(x3*x3);
6006  if (a == 0) goto L10;
6007  cz[2] = (x2*(f*x2y - x2*y) - f*x3*xy) / a;
6008  cz[1] = (xy - x3*cz[2]) / x2;
6009  cz[0] = (y - x2*cz[2]) / f;
6010  if (npar2p == 3) goto L6;
6011  sdev2p = y2 - (cz[0]*y + cz[1]*xy + cz[2]*x2y);
6012  if (sdev2p < 0) sdev2p = 0;
6013  sdev2p /= f - 3;
6014 L6:
6015  cz[0] += xm*(xm*cz[2] - cz[1]);
6016  cz[1] -= xm*2*cz[2];
6017 L10:
6018  for (i = 1; i <= 3; ++i) { coef2p[i] = cz[i-1]; }
6019 }
6020 
6021 ////////////////////////////////////////////////////////////////////////////////
6022 /// Calculates the internal parameter value PINTI
6023 ///
6024 /// corresponding to the external value PEXTI for parameter I.
6025 
6026 void TMinuit::mnpint(Double_t &pexti, Int_t i1, Double_t &pinti)
6027 {
6028  /* Local variables */
6029  Double_t a, alimi, blimi, yy, yy2;
6030  Int_t igo;
6031  TString chbuf2, chbufi;
6032 
6033  Int_t i = i1+1;
6034  pinti = pexti;
6035  igo = fNvarl[i-1];
6036  if (igo == 4) {
6037 // there are two limits
6038  alimi = fAlim[i-1];
6039  blimi = fBlim[i-1];
6040  yy = (pexti - alimi)*2 / (blimi - alimi) - 1;
6041  yy2 = yy*yy;
6042  if (yy2 >= 1 - fEpsma2) {
6043  if (yy < 0) {
6044  a = fVlimlo;
6045  chbuf2 = " IS AT ITS LOWER ALLOWED LIMIT.";
6046  } else {
6047  a = fVlimhi;
6048  chbuf2 = " IS AT ITS UPPER ALLOWED LIMIT.";
6049  }
6050  pinti = a;
6051  pexti = alimi + (blimi - alimi)*.5*(TMath::Sin(a) + 1);
6052  fLimset = kTRUE;
6053  if (yy2 > 1) chbuf2 = " BROUGHT BACK INSIDE LIMITS.";
6054  mnwarn("W", fCfrom, TString::Format("VARIABLE%d%s",i,chbuf2.Data()));
6055  } else {
6056  pinti = TMath::ASin(yy);
6057  }
6058  }
6059 }
6060 
6061 ////////////////////////////////////////////////////////////////////////////////
6062 /// Plots points in array xypt onto one page with labelled axes
6063 ///
6064 /// - NXYPT is the number of points to be plotted
6065 /// - XPT(I) = x-coord. of ith point
6066 /// - YPT(I) = y-coord. of ith point
6067 /// - CHPT(I) = character to be plotted at this position
6068 /// the input point arrays XPT, YPT, CHPT are destroyed.
6069 ///
6070 /// If fGraphicsmode is true (default), a TGraph object is produced
6071 /// via the Plug-in handler. To get the plot, you can do:
6072 /// ~~~ {.cpp}
6073 /// TGraph *gr = (TGraph*)gMinuit->GetPlot();
6074 /// gr->Draw("al");
6075 /// ~~~
6076 
6077 void TMinuit::mnplot(Double_t *xpt, Double_t *ypt, char *chpt, Int_t nxypt, Int_t npagwd, Int_t npagln)
6078 {
6079 
6080  if (fGraphicsMode) {
6081  TPluginHandler *h;
6082  if ((h = gROOT->GetPluginManager()->FindHandler("TMinuitGraph"))) {
6083  //remove the first two points
6084  if (h->LoadPlugin() != -1)
6085  fPlot = (TObject*)h->ExecPlugin(3,nxypt-2,&xpt[2],&ypt[2]);
6086  }
6087  return;
6088  }
6089 
6090  /* Local variables */
6091  Double_t xmin, ymin, xmax, ymax, savx, savy, yprt;
6092  Double_t bwidx, bwidy, xbest, ybest, ax, ay, bx, by;
6093  Double_t xvalus[12], any, dxx, dyy;
6094  Int_t iten, i, j, k, maxnx, maxny, iquit, ni, linodd;
6095  Int_t nxbest, nybest, km1, ibk, isp1, nx, ny, ks, ix;
6096  TString chmess, ctemp;
6097  Bool_t overpr;
6098  char cline[144];
6099  char chsav, chbest;
6100 
6101  /* Function Body */
6102  // Computing MIN
6103  maxnx = TMath::Min(npagwd-20,100);
6104  if (maxnx < 10) maxnx = 10;
6105  maxny = npagln;
6106  if (maxny < 10) maxny = 10;
6107  if (nxypt <= 1) return;
6108  xbest = xpt[0];
6109  ybest = ypt[0];
6110  chbest = chpt[0];
6111  // order the points by decreasing y
6112  km1 = nxypt - 1;
6113  for (i = 1; i <= km1; ++i) {
6114  iquit = 0;
6115  ni = nxypt - i;
6116  for (j = 1; j <= ni; ++j) {
6117  if (ypt[j-1] > ypt[j]) continue;
6118  savx = xpt[j-1];
6119  xpt[j-1] = xpt[j];
6120  xpt[j] = savx;
6121  savy = ypt[j-1];
6122  ypt[j-1] = ypt[j];
6123  ypt[j] = savy;
6124  chsav = chpt[j-1];
6125  chpt[j-1]= chpt[j];
6126  chpt[j] = chsav;
6127  iquit = 1;
6128  }
6129  if (iquit == 0) break;
6130  }
6131  // find extreme values
6132  xmax = xpt[0];
6133  xmin = xmax;
6134  for (i = 1; i <= nxypt; ++i) {
6135  if (xpt[i-1] > xmax) xmax = xpt[i-1];
6136  if (xpt[i-1] < xmin) xmin = xpt[i-1];
6137  }
6138  dxx = (xmax - xmin)*.001;
6139  xmax += dxx;
6140  xmin -= dxx;
6141  mnbins(xmin, xmax, maxnx, xmin, xmax, nx, bwidx);
6142  ymax = ypt[0];
6143  ymin = ypt[nxypt-1];
6144  if (ymax == ymin) ymax = ymin + 1;
6145  dyy = (ymax - ymin)*.001;
6146  ymax += dyy;
6147  ymin -= dyy;
6148  mnbins(ymin, ymax, maxny, ymin, ymax, ny, bwidy);
6149  any = (Double_t) ny;
6150  // if first point is blank, it is an 'origin'
6151  if (chbest == ' ') goto L50;
6152  xbest = (xmax + xmin)*.5;
6153  ybest = (ymax + ymin)*.5;
6154 L50:
6155  // find scale constants
6156  ax = 1 / bwidx;
6157  ay = 1 / bwidy;
6158  bx = -ax*xmin + 2;
6159  by = -ay*ymin - 2;
6160  // convert points to grid positions
6161  for (i = 1; i <= nxypt; ++i) {
6162  xpt[i-1] = ax*xpt[i-1] + bx;
6163  ypt[i-1] = any - ay*ypt[i-1] - by;
6164  }
6165  nxbest = Int_t((ax*xbest + bx));
6166  nybest = Int_t((any - ay*ybest - by));
6167  // print the points
6168  ny += 2;
6169  nx += 2;
6170  isp1 = 1;
6171  linodd = 1;
6172  overpr = kFALSE;
6173  for (i = 1; i <= ny; ++i) {
6174  for (ibk = 1; ibk <= nx; ++ibk) { cline[ibk-1] = ' '; }
6175  cline[nx] = '\0';
6176  cline[nx+1] = '\0';
6177  cline[0] = '.';
6178  // not needed - but to avoid a wrongly reported compiler warning (see ROOT-6496)
6179  if (nx>0) cline[nx-1] = '.';
6180  cline[nxbest-1] = '.';
6181  if (i != 1 && i != nybest && i != ny) goto L320;
6182  for (j = 1; j <= nx; ++j) { cline[j-1] = '.'; }
6183 L320:
6184  yprt = ymax - Double_t(i-1)*bwidy;
6185  if (isp1 > nxypt) goto L350;
6186  // find the points to be plotted on this line
6187  for (k = isp1; k <= nxypt; ++k) {
6188  ks = Int_t(ypt[k-1]);
6189  if (ks > i) goto L345;
6190  ix = Int_t(xpt[k-1]);
6191  if (cline[ix-1] == '.') goto L340;
6192  if (cline[ix-1] == ' ') goto L340;
6193  if (cline[ix-1] == chpt[k-1]) continue;
6194  overpr = kTRUE;
6195  // OVERPR is true if one or more positions contains more than
6196  // one point
6197  cline[ix-1] = '&';
6198  continue;
6199 L340:
6200  cline[ix-1] = chpt[k-1];
6201  }
6202  isp1 = nxypt + 1;
6203  goto L350;
6204 L345:
6205  isp1 = k;
6206 L350:
6207  if (linodd == 1 || i == ny) goto L380;
6208  linodd = 1;
6209  ctemp = cline;
6210  Printf(" %s",(const char*)ctemp);
6211  goto L400;
6212 L380:
6213  ctemp = cline;
6214  Printf(" %14.7g ..%s",yprt,(const char*)ctemp);
6215  linodd = 0;
6216 L400:
6217  ;
6218  }
6219  // print labels on x-axis every ten columns
6220  for (ibk = 1; ibk <= nx; ++ibk) {
6221  cline[ibk-1] = ' ';
6222  if (ibk % 10 == 1) cline[ibk-1] = '/';
6223  }
6224  Printf(" %s",cline);
6225 
6226  for (ibk = 1; ibk <= 12; ++ibk) {
6227  xvalus[ibk-1] = xmin + Double_t(ibk-1)*10*bwidx;
6228  }
6229  iten = (nx + 9) / 10;
6230  Printf(" ");
6231  for (ibk = 1; ibk <= iten; ++ibk)
6232  Printf("%# 8.3g ", xvalus[ibk-1]);
6233  Printf("\n");
6234  chmess = " ";
6235  if (overpr) chmess = " Overprint character is &";
6236  Printf(" ONE COLUMN=%13.7g%s",bwidx,(const char*)chmess);
6237 }
6238 
6239 ////////////////////////////////////////////////////////////////////////////////
6240 /// Provides the user with information concerning the current status
6241 ///
6242 /// of parameter number IUEXT. Namely, it returns:
6243 /// - CHNAM: the name of the parameter
6244 /// - VAL: the current (external) value of the parameter
6245 /// - ERR: the current estimate of the parameter uncertainty
6246 /// - XLOLIM: the lower bound (or zero if no limits)
6247 /// - XUPLIM: the upper bound (or zero if no limits)
6248 /// - IUINT: the internal parameter number (or zero if not variable,
6249 /// or negative if undefined).
6250 ///
6251 /// Note also: If IUEXT is negative, then it is -internal parameter
6252 /// number, and IUINT is returned as the EXTERNAL number.
6253 /// Except for IUINT, this is exactly the inverse of MNPARM
6254 /// User-called
6255 
6256 void TMinuit::mnpout(Int_t iuext1, TString &chnam, Double_t &val, Double_t &err, Double_t &xlolim, Double_t &xuplim, Int_t &iuint) const
6257 {
6258  /* Local variables */
6259  Int_t iint, iext, nvl;
6260 
6261  Int_t iuext = iuext1 + 1;
6262  xlolim = 0;
6263  xuplim = 0;
6264  err = 0;
6265  if (iuext == 0) goto L100;
6266  if (iuext < 0) {
6267 // internal parameter number specified
6268  iint = -(iuext);
6269  if (iint > fNpar) goto L100;
6270  iext = fNexofi[iint-1];
6271  iuint = iext;
6272  } else {
6273 // external parameter number specified
6274  iext = iuext;
6275  if (iext > fNu) goto L100;
6276  iint = fNiofex[iext-1];
6277  iuint = iint;
6278  }
6279 // in both cases
6280  nvl = fNvarl[iext-1];
6281  if (nvl < 0) goto L100;
6282  chnam = fCpnam[iext-1];
6283  val = fU[iext-1];
6284  if (iint > 0) err = fWerr[iint-1];
6285  if (nvl == 4) {
6286  xlolim = fAlim[iext-1];
6287  xuplim = fBlim[iext-1];
6288  }
6289  return;
6290 // parameter is undefined
6291 L100:
6292  iuint = -1;
6293  chnam = "undefined";
6294  val = 0;
6295 }
6296 
6297 ////////////////////////////////////////////////////////////////////////////////
6298 /// Prints the values of the parameters at the time of the call
6299 ///
6300 /// also prints other relevant information such as function value,
6301 /// estimated distance to minimum, parameter errors, step sizes.
6302 ///
6303 /// According to the value of IKODE, the printout is:
6304 /// IKODE=INKODE=
6305 /// - 0 only info about function value
6306 /// - 1 parameter values, errors, limits
6307 /// - 2 values, errors, step sizes, internal values
6308 /// - 3 values, errors, step sizes, first derivs.
6309 /// - 4 values, parabolic errors, MINOS errors
6310 ///
6311 /// when INKODE=5, MNPRIN chooses IKODE=1,2, or 3, according to fISW[1]
6312 
6313 void TMinuit::mnprin(Int_t inkode, Double_t fval)
6314 {
6315  /* Initialized data */
6316 
6317  static const TString cblank = " ";
6318  TString cnambf = " ";
6319 
6320  /* Local variables */
6321  Double_t dcmax, x1, x2, x3, dc;
6322  x2 = x3 = 0;
6323  Int_t nadd, i, k, l, m, ikode, ic, nc, ntrail, lbl;
6324  TString chedm;
6325  TString colhdl[6], colhdu[6], cx2, cx3, cheval;
6326 
6327  if (fNu == 0) {
6328  Printf(" THERE ARE CURRENTLY NO PARAMETERS DEFINED");
6329  return;
6330  }
6331 // get value of IKODE based in INKODE, fISW[1]
6332  ikode = inkode;
6333  if (inkode == 5) {
6334  ikode = fISW[1] + 1;
6335  if (ikode > 3) ikode = 3;
6336  }
6337 // set 'default' column headings
6338  for (k = 1; k <= 6; ++k) {
6339  colhdu[k-1] = "UNDEFINED";
6340  colhdl[k-1] = "COLUMN HEAD";
6341  }
6342 // print title if Minos errors, and title exists.
6343  if (ikode == 4 && fCtitl != fCundef) {
6344  Printf(" MINUIT TASK: %s",(const char*)fCtitl);
6345  }
6346 // report function value and status
6347  if (fval == fUndefi) cheval = " unknown ";
6348  else cheval.Form("%g",fval);
6349 
6350  if (fEDM == fBigedm) chedm = " unknown ";
6351  else chedm.Form("%g",fEDM);
6352 
6353  nc = fNfcn - fNfcnfr;
6354  Printf(" FCN=%s FROM %8s STATUS=%10s %6d CALLS %9d TOTAL"
6355  ,(const char*)cheval
6356  ,(const char*)fCfrom
6357  ,(const char*)fCstatu,nc,fNfcn);
6358  m = fISW[1];
6359  if (m == 0 || m == 2 || fDcovar == 0) {
6360  Printf(" EDM=%s STRATEGY=%2d %s"
6361  ,(const char*)chedm,fIstrat
6362  ,(const char*)fCovmes[m]);
6363  } else {
6364  dcmax = 1;
6365  dc = TMath::Min(fDcovar,dcmax)*100;
6366  Printf(" EDM=%s STRATEGY=%2d ERROR MATRIX UNCERTAINTY %5.1f per cent"
6367  ,(const char*)chedm,fIstrat,dc);
6368  }
6369 
6370  if (ikode == 0) return;
6371 // find longest name (for Rene!)
6372  ntrail = 10;
6373  for (i = 1; i <= fNu; ++i) {
6374  if (fNvarl[i-1] < 0) continue;
6375  for (ic = 10; ic >= 1; --ic) {
6376  if (fCpnam[i-1](ic-1,1) != " ") goto L16;
6377  }
6378  ic = 1;
6379 L16:
6380  lbl = 10 - ic;
6381  if (lbl < ntrail) ntrail = lbl;
6382  }
6383  nadd = ntrail / 2 + 1;
6384  if (ikode == 1) {
6385  colhdu[0] = " ";
6386  colhdl[0] = " ERROR ";
6387  colhdu[1] = " PHYSICAL";
6388  colhdu[2] = " LIMITS ";
6389  colhdl[1] = " NEGATIVE ";
6390  colhdl[2] = " POSITIVE ";
6391  }
6392  if (ikode == 2) {
6393  colhdu[0] = " ";
6394  colhdl[0] = " ERROR ";
6395  colhdu[1] = " INTERNAL ";
6396  colhdl[1] = " STEP SIZE ";
6397  colhdu[2] = " INTERNAL ";
6398  colhdl[2] = " VALUE ";
6399  }
6400  if (ikode == 3) {
6401  colhdu[0] = " ";
6402  colhdl[0] = " ERROR ";
6403  colhdu[1] = " STEP ";
6404  colhdl[1] = " SIZE ";
6405  colhdu[2] = " FIRST ";
6406  colhdl[2] = " DERIVATIVE ";
6407  }
6408  if (ikode == 4) {
6409  colhdu[0] = " PARABOLIC ";
6410  colhdl[0] = " ERROR ";
6411  colhdu[1] = " MINOS ";
6412  colhdu[2] = "ERRORS ";
6413  colhdl[1] = " NEGATIVE ";
6414  colhdl[2] = " POSITIVE ";
6415  }
6416 
6417  if (ikode != 4) {
6418  if (fISW[1] < 3) colhdu[0] = " APPROXIMATE ";
6419  if (fISW[1] < 1) colhdu[0] = " CURRENT GUESS";
6420  }
6421  Printf(" EXT PARAMETER %-14s%-14s%-14s",(const char*)colhdu[0]
6422  ,(const char*)colhdu[1]
6423  ,(const char*)colhdu[2]);
6424  Printf(" NO. NAME VALUE %-14s%-14s%-14s",(const char*)colhdl[0]
6425  ,(const char*)colhdl[1]
6426  ,(const char*)colhdl[2]);
6427 // loop over parameters
6428  for (i = 1; i <= fNu; ++i) {
6429  if (fNvarl[i-1] < 0) continue;
6430  l = fNiofex[i-1];
6431  cnambf = cblank(0,nadd) + fCpnam[i-1];
6432  if (l == 0) goto L55;
6433 // variable parameter.
6434  x1 = fWerr[l-1];
6435  cx2 = "PLEASE GET X..";
6436  cx3 = "PLEASE GET X..";
6437  if (ikode == 1) {
6438  if (fNvarl[i-1] <= 1) {
6439  Printf("%4d %-11s%14.5e%14.5e",i,(const char*)cnambf,fU[i-1],x1);
6440  continue;
6441  } else {
6442  x2 = fAlim[i-1];
6443  x3 = fBlim[i-1];
6444  }
6445  }
6446  if (ikode == 2) {
6447  x2 = fDirin[l-1];
6448  x3 = fX[l-1];
6449  }
6450  if (ikode == 3) {
6451  x2 = fDirin[l-1];
6452  x3 = fGrd[l-1];
6453  if (fNvarl[i-1] > 1 && TMath::Abs(TMath::Cos(fX[l-1])) < .001) {
6454  cx3 = "** at limit **";
6455  }
6456  }
6457  if (ikode == 4) {
6458  x2 = fErn[l-1];
6459  if (x2 == 0) cx2 = " ";
6460  if (x2 == fUndefi) cx2 = " at limit ";
6461  x3 = fErp[l-1];
6462  if (x3 == 0) cx3 = " ";
6463  if (x3 == fUndefi) cx3 = " at limit ";
6464  }
6465  if (cx2 == "PLEASE GET X..") cx2.Form("%14.5e",x2);
6466  if (cx3 == "PLEASE GET X..") cx3.Form("%14.5e",x3);
6467  Printf("%4d %-11s%14.5e%14.5e%-14s%-14s",i
6468  ,(const char*)cnambf,fU[i-1],x1
6469  ,(const char*)cx2,(const char*)cx3);
6470 
6471 // check if parameter is at limit
6472  if (fNvarl[i-1] <= 1 || ikode == 3) continue;
6473  if (TMath::Abs(TMath::Cos(fX[l-1])) < .001) {
6474  Printf(" WARNING - - ABOVE PARAMETER IS AT LIMIT.");
6475  }
6476  continue;
6477 
6478 // print constant or fixed parameter.
6479 L55:
6480  colhdu[0] = " constant ";
6481  if (fNvarl[i-1] > 0) colhdu[0] = " fixed ";
6482  if (fNvarl[i-1] == 4 && ikode == 1) {
6483  Printf("%4d %-11s%14.5e%-14s%14.5e%14.5e",i
6484  ,(const char*)cnambf,fU[i-1]
6485  ,(const char*)colhdu[0],fAlim[i-1],fBlim[i-1]);
6486  } else {
6487  Printf("%4d %-11s%14.5e%s",i
6488  ,(const char*)cnambf,fU[i-1],(const char*)colhdu[0]);
6489  }
6490  }
6491 
6492  if (fUp != fUpdflt) {
6493  Printf(" ERR DEF= %g",fUp);
6494  }
6495  return;
6496 }
6497 
6498 ////////////////////////////////////////////////////////////////////////////////
6499 /// Calculates the eigenvalues of v to see if positive-def
6500 ///
6501 /// if not, adds constant along diagonal to make positive.
6502 
6504 {
6505  /* Local variables */
6506  Double_t dgmin, padd, pmin, pmax, dg, epspdf, epsmin;
6507  Int_t ndex, i, j, ndexd, ip, ifault;
6508  TString chbuff, ctemp;
6509 
6510  epsmin = 1e-6;
6511  epspdf = TMath::Max(epsmin,fEpsma2);
6512  dgmin = fVhmat[0];
6513 // Check if negative or zero on diagonal
6514  for (i = 1; i <= fNpar; ++i) {
6515  ndex = i*(i + 1) / 2;
6516  if (fVhmat[ndex-1] <= 0) {
6517  mnwarn("W", fCfrom, TString::Format("Negative diagonal element %d in Error Matrix",i));
6518  }
6519  if (fVhmat[ndex-1] < dgmin) dgmin = fVhmat[ndex-1];
6520  }
6521  if (dgmin <= 0) {
6522  dg = epspdf + 1 - dgmin;
6523  mnwarn("W", fCfrom, TString::Format("%g added to diagonal of error matrix",dg));
6524  } else {
6525  dg = 0;
6526  }
6527 // Store VHMAT in P, make sure diagonal pos.
6528  for (i = 1; i <= fNpar; ++i) {
6529  ndex = i*(i-1) / 2;
6530  ndexd = ndex + i;
6531  fVhmat[ndexd-1] += dg;
6532  if (fVhmat[ndexd-1]==0) {
6533  fPSDFs[i-1] = 1 / 1e-19; // a totally arbitrary silly small value
6534  } else {
6535  fPSDFs[i-1] = 1 / TMath::Sqrt(fVhmat[ndexd-1]);
6536  }
6537  for (j = 1; j <= i; ++j) {
6538  ++ndex;
6539  fP[i + j*fMaxpar - fMaxpar-1] = fVhmat[ndex-1]*fPSDFs[i-1]*fPSDFs[j-1];
6540  }
6541  }
6542 // call eigen (p,p,maxint,npar,pstar,-npar)
6543  mneig(fP, fMaxint, fNpar, fMaxint, fPstar, epspdf, ifault);
6544  pmin = fPstar[0];
6545  pmax = fPstar[0];
6546  for (ip = 2; ip <= fNpar; ++ip) {
6547  if (fPstar[ip-1] < pmin) pmin = fPstar[ip-1];
6548  if (fPstar[ip-1] > pmax) pmax = fPstar[ip-1];
6549  }
6550  pmax = TMath::Max(TMath::Abs(pmax),Double_t(1));
6551  if ((pmin <= 0 && fLwarn) || fISW[4] >= 2) {
6552  Printf(" EIGENVALUES OF SECOND-DERIVATIVE MATRIX:");
6553  ctemp = " ";
6554  for (ip = 1; ip <= fNpar; ++ip) {
6555  ctemp += TString::Format(" %11.4e",fPstar[ip-1]);
6556  }
6557  Printf("%s", ctemp.Data());
6558  }
6559  if (pmin > epspdf*pmax) return;
6560  if (fISW[1] == 3) fISW[1] = 2;
6561  padd = pmax*.001 - pmin;
6562  for (ip = 1; ip <= fNpar; ++ip) {
6563  ndex = ip*(ip + 1) / 2;
6564  fVhmat[ndex-1] *= padd + 1;
6565  }
6566  fCstatu = "NOT POSDEF";
6567  mnwarn("W", fCfrom, Form("MATRIX FORCED POS-DEF BY ADDING %f TO DIAGONAL.",padd));
6568 
6569 }
6570 
6571 ////////////////////////////////////////////////////////////////////////////////
6572 /// Called only by MNSIMP (and MNIMPR) to add a new point
6573 ///
6574 /// and remove an old one from the current simplex, and get the
6575 /// estimated distance to minimum.
6576 
6577 void TMinuit::mnrazz(Double_t ynew, Double_t *pnew, Double_t *y, Int_t &jh, Int_t &jl)
6578 {
6579  /* Local variables */
6580  Double_t pbig, plit;
6581  Int_t i, j, nparp1;
6582 
6583  /* Function Body */
6584  for (i = 1; i <= fNpar; ++i) { fP[i + jh*fMaxpar - fMaxpar-1] = pnew[i-1]; }
6585  y[jh-1] = ynew;
6586  if (ynew < fAmin) {
6587  for (i = 1; i <= fNpar; ++i) { fX[i-1] = pnew[i-1]; }
6588  mninex(fX);
6589  fAmin = ynew;
6590  fCstatu = "PROGRESS ";
6591  jl = jh;
6592  }
6593  jh = 1;
6594  nparp1 = fNpar + 1;
6595  for (j = 2; j <= nparp1; ++j) { if (y[j-1] > y[jh-1]) jh = j; }
6596  fEDM = y[jh-1] - y[jl-1];
6597  if (fEDM <= 0) goto L45;
6598  for (i = 1; i <= fNpar; ++i) {
6599  pbig = fP[i-1];
6600  plit = pbig;
6601  for (j = 2; j <= nparp1; ++j) {
6602  if (fP[i + j*fMaxpar - fMaxpar-1] > pbig) pbig = fP[i + j*fMaxpar - fMaxpar-1];
6603  if (fP[i + j*fMaxpar - fMaxpar-1] < plit) plit = fP[i + j*fMaxpar - fMaxpar-1];
6604  }
6605  fDirin[i-1] = pbig - plit;
6606  }
6607 L40:
6608  return;
6609 L45:
6610  Printf(" FUNCTION VALUE DOES NOT SEEM TO DEPEND ON ANY OF THE %d VARIABLE PARAMETERS.",fNpar);
6611  Printf(" VERIFY THAT STEP SIZES ARE BIG ENOUGH AND CHECK FCN LOGIC.");
6612  Printf(" *******************************************************************************");
6613  Printf(" *******************************************************************************");
6614  goto L40;
6615 }
6616 
6617 ////////////////////////////////////////////////////////////////////////////////
6618 /// This is a super-portable random number generator
6619 ///
6620 /// It should not overflow on any 32-bit machine.
6621 /// The cycle is only ~10**9, so use with care!
6622 /// Note especially that VAL must not be undefined on input.
6623 ///
6624 /// Set Default Starting Seed
6625 
6626 void TMinuit::mnrn15(Double_t &val, Int_t &inseed)
6627 {
6628  /* Initialized data */
6629 
6630  static std::atomic<Int_t> g_iseed( 12345 );
6631 
6632  Int_t k;
6633 
6634  if (val == 3) {
6635  // "entry" to set seed, flag is VAL=3
6636  g_iseed.store(inseed, std::memory_order_release);
6637  } else {
6638  // Grab the local value. Two threads might comes here at the same
6639  // time and will end up with the same results.
6640  int starting_seed = g_iseed.load( std::memory_order_acquire );
6641  int next_seed;
6642 
6643  do {
6644  next_seed = inseed = starting_seed;
6645 
6646  // Determine the next seed.
6647  k = next_seed / 53668;
6648  next_seed = (next_seed - k*53668)*40014 - k*12211;
6649  if (next_seed < 0) next_seed += 2147483563;
6650 
6651  val = Double_t(next_seed*4.656613e-10);
6652 
6653  // If more than one thread gets here, one will manage the update
6654  // of g_iseed the other we go for at least one more round.
6655  // This is not reproduceable
6656  } while (! g_iseed.compare_exchange_strong(starting_seed, next_seed) );
6657  }
6658 }
6659 
6660 ////////////////////////////////////////////////////////////////////////////////
6661 /// Resets function value and errors to UNDEFINED
6662 ///
6663 /// - If IOPT=1,
6664 /// - If IOPT=0, sets only MINOS errors to undefined
6665 /// Called from MNCLER and whenever problem changes, for example
6666 /// after SET LIMITS, SET PARAM, CALL FCN 6
6667 
6669 {
6670  Int_t iext, i;
6671 
6672  fCstatu = "RESET ";
6673  if (iopt >= 1) {
6674  fAmin = fUndefi;
6675  fFval3 = TMath::Abs(fAmin)*2 + 1;
6676  fEDM = fBigedm;
6677  fISW[3] = 0;
6678  fISW[1] = 0;
6679  fDcovar = 1;
6680  fISW[0] = 0;
6681  }
6682  fLnolim = kTRUE;
6683  for (i = 1; i <= fNpar; ++i) {
6684  iext = fNexofi[i-1];
6685  if (fNvarl[iext-1] >= 4) fLnolim = kFALSE;
6686  fErp[i-1] = 0;
6687  fErn[i-1] = 0;
6688  fGlobcc[i-1] = 0;
6689  }
6690  if (fISW[1] >= 1) {
6691  fISW[1] = 1;
6692  fDcovar = TMath::Max(fDcovar,.5);
6693  }
6694 }
6695 
6696 ////////////////////////////////////////////////////////////////////////////////
6697 /// Writes current parameter values and step sizes onto file ISYSSA
6698 ///
6699 /// in format which can be reread by Minuit for restarting.
6700 /// The covariance matrix is also output if it exists.
6701 
6703 {
6704  Printf("mnsave is dummy in TMinuit");
6705 
6706 }
6707 
6708 ////////////////////////////////////////////////////////////////////////////////
6709 /// Scans the values of FCN as a function of one parameter
6710 ///
6711 /// and plots the resulting values as a curve using MNPLOT.
6712 /// It may be called to scan one parameter or all parameters.
6713 /// retains the best function and parameter values found.
6714 
6716 {
6717  /* Local variables */
6718  Double_t step, uhigh, xhreq, xlreq, ubest, fnext, unext, xh, xl;
6719  Int_t ipar, iint, icall, ncall, nbins, nparx;
6720  Int_t nxypt, nccall, iparwd;
6721 
6722  xlreq = TMath::Min(fWord7[2],fWord7[3]);
6723  xhreq = TMath::Max(fWord7[2],fWord7[3]);
6724  ncall = Int_t((fWord7[1] + .01));
6725  if (ncall <= 1) ncall = 41;
6726  if (ncall > 98) ncall = 98;
6727  nccall = ncall;
6728  if (fAmin == fUndefi) mnamin();
6729  iparwd = Int_t((fWord7[0] + .1));
6730  ipar = TMath::Max(iparwd,0);
6731  fCstatu = "NO CHANGE";
6732  if (iparwd > 0) goto L200;
6733 
6734 // equivalent to a loop over parameters requested
6735 L100:
6736  ++ipar;
6737  if (ipar > fNu) goto L900;
6738  iint = fNiofex[ipar-1];
6739  if (iint <= 0) goto L100;
6740 // set up range for parameter IPAR
6741 L200:
6742  iint = fNiofex[ipar-1];
6743  ubest = fU[ipar-1];
6744  fXpt[0] = ubest;
6745  fYpt[0] = fAmin;
6746  fChpt[0] = ' ';
6747  fXpt[1] = ubest;
6748  fYpt[1] = fAmin;
6749  fChpt[1] = 'X';
6750  nxypt = 2;
6751  if (fNvarl[ipar-1] > 1) goto L300;
6752 
6753 // no limits on parameter
6754  if (xlreq == xhreq) goto L250;
6755  unext = xlreq;
6756  step = (xhreq - xlreq) / Double_t(ncall-1);
6757  goto L500;
6758 L250:
6759  xl = ubest - fWerr[iint-1];
6760  xh = ubest + fWerr[iint-1];
6761  mnbins(xl, xh, ncall, unext, uhigh, nbins, step);
6762  nccall = nbins + 1;
6763  goto L500;
6764 // limits on parameter
6765 L300:
6766  if (xlreq == xhreq) goto L350;
6767 // Computing MAX
6768  xl = TMath::Max(xlreq,fAlim[ipar-1]);
6769 // Computing MIN
6770  xh = TMath::Min(xhreq,fBlim[ipar-1]);
6771  if (xl >= xh) goto L700;
6772  unext = xl;
6773  step = (xh - xl) / Double_t(ncall-1);
6774  goto L500;
6775 L350:
6776  unext = fAlim[ipar-1];
6777  step = (fBlim[ipar-1] - fAlim[ipar-1]) / Double_t(ncall-1);
6778 // main scanning loop over parameter IPAR
6779 L500:
6780  for (icall = 1; icall <= nccall; ++icall) {
6781  fU[ipar-1] = unext;
6782  nparx = fNpar;
6783  Eval(nparx, fGin, fnext, fU, 4); ++fNfcn;
6784  ++nxypt;
6785  fXpt[nxypt-1] = unext;
6786  fYpt[nxypt-1] = fnext;
6787  fChpt[nxypt-1] = '*';
6788  if (fnext < fAmin) {
6789  fAmin = fnext;
6790  ubest = unext;
6791  fCstatu = "IMPROVED ";
6792  }
6793  unext += step;
6794  }
6795  fChpt[nccall] = 0;
6796 
6797 // finished with scan of parameter IPAR
6798  fU[ipar-1] = ubest;
6799  mnexin(fX);
6800  if (fISW[4] >= 1)
6801  Printf("%dSCAN OF PARAMETER NO. %d, %s"
6802  ,fNewpag,ipar,(const char*)fCpnam[ipar-1]);
6803  mnplot(fXpt, fYpt, fChpt, nxypt, fNpagwd, fNpagln);
6804  goto L800;
6805 L700:
6806  Printf(" REQUESTED RANGE OUTSIDE LIMITS FOR PARAMETER %d",ipar);
6807 L800:
6808  if (iparwd <= 0) goto L100;
6809 // finished with all parameters
6810 L900:
6811  if (fISW[4] >= 0) mnprin(5, fAmin);
6812 }
6813 
6814 ////////////////////////////////////////////////////////////////////////////////
6815 /// Performs a rough (but global) minimization by monte carlo search
6816 ///
6817 /// Each time a new minimum is found, the search area is shifted
6818 /// to be centered at the best value. Random points are chosen
6819 /// uniformly over a hypercube determined by current step sizes.
6820 /// The Metropolis algorithm accepts a worse point with probability
6821 /// exp(-d/UP), where d is the degradation. Improved points
6822 /// are of course always accepted. Actual steps are random
6823 /// multiples of the nominal steps (DIRIN).
6824 
6826 {
6827  /* Local variables */
6828  Double_t dxdi, rnum, ftry, rnum1, rnum2, alpha;
6829  Double_t flast, bar;
6830  Int_t ipar, iext, j, ifail, iseed=0, nparx, istep, ib, mxfail, mxstep;
6831 
6832  mxfail = Int_t(fWord7[0]);
6833  if (mxfail <= 0) mxfail = fNpar*20 + 100;
6834  mxstep = mxfail*10;
6835  if (fAmin == fUndefi) mnamin();
6836  alpha = fWord7[1];
6837  if (alpha <= 0) alpha = 3;
6838  if (fISW[4] >= 1) {
6839  Printf(" MNSEEK: MONTE CARLO MINIMIZATION USING METROPOLIS ALGORITHM");
6840  Printf(" TO STOP AFTER %6d SUCCESSIVE FAILURES, OR %7d STEPS",mxfail,mxstep);
6841  Printf(" MAXIMUM STEP SIZE IS %9.3f ERROR BARS.",alpha);
6842  }
6843  fCstatu = "INITIAL ";
6844  if (fISW[4] >= 2) mnprin(2, fAmin);
6845  fCstatu = "UNCHANGED ";
6846  ifail = 0;
6847  rnum = 0;
6848  rnum1 = 0;
6849  rnum2 = 0;
6850  nparx = fNpar;
6851  flast = fAmin;
6852 // set up step sizes, starting values
6853  for (ipar = 1; ipar <= fNpar; ++ipar) {
6854  iext = fNexofi[ipar-1];
6855  fDirin[ipar-1] = alpha*2*fWerr[ipar-1];
6856  if (fNvarl[iext-1] > 1) {
6857 // parameter with limits
6858  mndxdi(fX[ipar-1], ipar-1, dxdi);
6859  if (dxdi == 0) dxdi = 1;
6860  fDirin[ipar-1] = alpha*2*fWerr[ipar-1] / dxdi;
6861  if (TMath::Abs(fDirin[ipar-1]) > 6.2831859999999997) {
6862  fDirin[ipar-1] = 6.2831859999999997;
6863  }
6864  }
6865  fSEEKxmid[ipar-1] = fX[ipar-1];
6866  fSEEKxbest[ipar-1] = fX[ipar-1];
6867  }
6868 // search loop
6869  for (istep = 1; istep <= mxstep; ++istep) {
6870  if (ifail >= mxfail) break;
6871  for (ipar = 1; ipar <= fNpar; ++ipar) {
6872  mnrn15(rnum1, iseed);
6873  mnrn15(rnum2, iseed);
6874  fX[ipar-1] = fSEEKxmid[ipar-1] + (rnum1 + rnum2 - 1)*.5*fDirin[ipar-1];
6875  }
6876  mninex(fX);
6877  Eval(nparx, fGin, ftry, fU, 4); ++fNfcn;
6878  if (ftry < flast) {
6879  if (ftry < fAmin) {
6880  fCstatu = "IMPROVEMNT";
6881  fAmin = ftry;
6882  for (ib = 1; ib <= fNpar; ++ib) { fSEEKxbest[ib-1] = fX[ib-1]; }
6883  ifail = 0;
6884  if (fISW[4] >= 2) mnprin(2, fAmin);
6885  }
6886  goto L300;
6887  } else {
6888  ++ifail;
6889 // Metropolis algorithm
6890  bar = (fAmin - ftry) / fUp;
6891  mnrn15(rnum, iseed);
6892  if (bar < TMath::Log(rnum)) continue;
6893  }
6894 // Accept new point, move there
6895 L300:
6896  for (j = 1; j <= fNpar; ++j) { fSEEKxmid[j-1] = fX[j-1]; }
6897  flast = ftry;
6898  }
6899 // end search loop
6900  if (fISW[4] > 1) {
6901  Printf(" MNSEEK: %5d SUCCESSIVE UNSUCCESSFUL TRIALS.",ifail);
6902  }
6903  for (ib = 1; ib <= fNpar; ++ib) { fX[ib-1] = fSEEKxbest[ib-1]; }
6904  mninex(fX);
6905  if (fISW[4] >= 1) mnprin(2, fAmin);
6906  if (fISW[4] == 0) mnprin(0, fAmin);
6907 }
6908 
6909 ////////////////////////////////////////////////////////////////////////////////
6910 /// Interprets the commands that start with SET and SHOW
6911 ///
6912 /// Called from MNEXCM
6913 /// file characteristics for SET INPUT
6914 /// 'SET ' or 'SHOW', 'ON ' or 'OFF', 'SUPPRESSED' or 'REPORTED '
6915 /// explanation of print level numbers -1:3 and strategies 0:2
6916 /// identification of debug options
6917 /// things that can be set or shown
6918 /// options not intended for normal users
6919 
6921 {
6922  /* Initialized data */
6923 
6924  static const char *const cname[30] = {
6925  "FCN value ",
6926  "PARameters",
6927  "LIMits ",
6928  "COVariance",
6929  "CORrelatio",
6930  "PRInt levl",
6931  "NOGradient",
6932  "GRAdient ",
6933  "ERRor def ",
6934  "INPut file",
6935  "WIDth page",
6936  "LINes page",
6937  "NOWarnings",
6938  "WARnings ",
6939  "RANdom gen",
6940  "TITle ",
6941  "STRategy ",
6942  "EIGenvalue",
6943  "PAGe throw",
6944  "MINos errs",
6945  "EPSmachine",
6946  "OUTputfile",
6947  "BATch ",
6948  "INTeractiv",
6949  "VERsion ",
6950  "reserve ",
6951  "NODebug ",
6952  "DEBug ",
6953  "SHOw ",
6954  "SET "};
6955 
6956  static constexpr Int_t nname = 25; // Must less than sizeof(cname)/sizeof(char*)
6957  static constexpr Int_t nntot = sizeof(cname)/sizeof(char*);
6958  static const TString cprlev[5] = {
6959  "-1: NO OUTPUT EXCEPT FROM SHOW ",
6960  " 0: REDUCED OUTPUT ",
6961  " 1: NORMAL OUTPUT ",
6962  " 2: EXTRA OUTPUT FOR PROBLEM CASES",
6963  " 3: MAXIMUM OUTPUT "};
6964 
6965  static const TString cstrat[3] = {
6966  " 0: MINIMIZE THE NUMBER OF CALLS TO FUNCTION",
6967  " 1: TRY TO BALANCE SPEED AGAINST RELIABILITY",
6968  " 2: MAKE SURE MINIMUM TRUE, ERRORS CORRECT "};
6969 
6970  static const TString cdbopt[7] = {
6971  "REPORT ALL EXCEPTIONAL CONDITIONS ",
6972  "MNLINE: LINE SEARCH MINIMIZATION ",
6973  "MNDERI: FIRST DERIVATIVE CALCULATIONS ",
6974  "MNHESS: SECOND DERIVATIVE CALCULATIONS ",
6975  "MNMIGR: COVARIANCE MATRIX UPDATES ",
6976  "MNHES1: FIRST DERIVATIVE UNCERTAINTIES ",
6977  "MNCONT: MNCONTOUR PLOT (MNCROS SEARCH) "};
6978 
6979  /* System generated locals */
6980  //Int_t f_inqu();
6981 
6982  /* Local variables */
6983  Double_t val;
6984  Int_t iset, iprm, i, jseed, kname, iseed, iunit, id, ii, kk;
6985  Int_t ikseed, idbopt, igrain=0, iswsav, isw2;
6986  TString cfname, cmode, ckind, cwarn, copt, ctemp, ctemp2;
6987  Bool_t lname=kFALSE;
6988 
6989  for (i = 1; i <= nntot; ++i) {
6990  ctemp = cname[i-1];
6991  ckind = ctemp(0,3);
6992  ctemp2 = fCword(4,6);
6993  if (strstr(ctemp2.Data(),ckind.Data())) goto L5;
6994  }
6995  i = 0;
6996 L5:
6997  kname = i;
6998 
6999 // Command could be SET xxx, SHOW xxx, HELP SET or HELP SHOW
7000  ctemp2 = fCword(0,3);
7001  if ( ctemp2.Contains("HEL")) goto L2000;
7002  if ( ctemp2.Contains("SHO")) goto L1000;
7003  if (!ctemp2.Contains("SET")) goto L1900;
7004 // ---
7005  ckind = "SET ";
7006 // set unknown
7007  if (kname <= 0) goto L1900;
7008 // set known
7009  switch ((int)kname) {
7010  case 1: goto L3000;
7011  case 2: goto L20;
7012  case 3: goto L30;
7013  case 4: goto L40;
7014  case 5: goto L3000;
7015  case 6: goto L60;
7016  case 7: goto L70;
7017  case 8: goto L80;
7018  case 9: goto L90;
7019  case 10: goto L100;
7020  case 11: goto L110;
7021  case 12: goto L120;
7022  case 13: goto L130;
7023  case 14: goto L140;
7024  case 15: goto L150;
7025  case 16: goto L160;
7026  case 17: goto L170;
7027  case 18: goto L3000;
7028  case 19: goto L190;
7029  case 20: goto L3000;
7030  case 21: goto L210;
7031  case 22: goto L220;
7032  case 23: goto L230;
7033  case 24: goto L240;
7034  case 25: goto L3000;
7035  case 26: goto L1900;
7036  case 27: goto L270;
7037  case 28: goto L280;
7038  case 29: goto L290;
7039  case 30: goto L300;
7040  }
7041 
7042 // set param
7043 L20:
7044  iprm = Int_t(fWord7[0]);
7045  if (iprm > fNu) goto L25;
7046  if (iprm <= 0) goto L25;
7047  if (fNvarl[iprm-1] < 0) goto L25;
7048  fU[iprm-1] = fWord7[1];
7049  mnexin(fX);
7050  isw2 = fISW[1];
7051  mnrset(1);
7052 // Keep approximate covariance matrix, even if new param value
7053  fISW[1] = TMath::Min(isw2,1);
7054  fCfrom = "SET PARM";
7055  fNfcnfr = fNfcn;
7056  fCstatu = "NEW VALUES";
7057  return;
7058 L25:
7059  Printf(" UNDEFINED PARAMETER NUMBER. IGNORED.");
7060  return;
7061 // set limits
7062 L30:
7063  mnlims();
7064  return;
7065 // set covar
7066 L40:
7067 // this command must be handled by MNREAD, and is not Fortran-callable
7068  goto L3000;
7069 // set print
7070 L60:
7071  fISW[4] = Int_t(fWord7[0]);
7072  return;
7073 // set nograd
7074 L70:
7075  fISW[2] = 0;
7076  return;
7077 // set grad
7078 L80:
7079  mngrad();
7080  return;
7081 // set errdef
7082 L90:
7083  if (fWord7[0] == fUp) return;
7084  if (fWord7[0] <= 0) {
7085  if (fUp == fUpdflt) return;
7086  fUp = fUpdflt;
7087  } else {
7088  fUp = fWord7[0];
7089  }
7090  for (i = 1; i <= fNpar; ++i) {
7091  fErn[i-1] = 0;
7092  fErp[i-1] = 0;
7093  }
7094  mnwerr();
7095  return;
7096 // set input
7097 // This command must be handled by MNREAD. If it gets this far,
7098 // it is illegal.
7099 L100:
7100  goto L3000;
7101 // set width
7102 L110:
7103  fNpagwd = Int_t(fWord7[0]);
7104  fNpagwd = TMath::Max(fNpagwd,50);
7105  return;
7106 
7107 L120:
7108  fNpagln = Int_t(fWord7[0]);
7109  return;
7110 // set nowarn
7111 
7112 L130:
7113  fLwarn = kFALSE;
7114  return;
7115 // set warn
7116 L140:
7117  fLwarn = kTRUE;
7118  mnwarn("W", "SHO", "SHO");
7119  return;
7120 // set random
7121 L150:
7122  jseed = Int_t(fWord7[0]);
7123  val = 3;
7124  mnrn15(val, jseed);
7125  if (fISW[4] > 0) {
7126  Printf(" MINUIT RANDOM NUMBER SEED SET TO %d",jseed);
7127  }
7128  return;
7129 // set title
7130 L160:
7131 // this command must be handled by MNREAD, and is not Fortran-callable
7132  goto L3000;
7133 // set strategy
7134 L170:
7135  fIstrat = Int_t(fWord7[0]);
7136  fIstrat = TMath::Max(fIstrat,0);
7137  fIstrat = TMath::Min(fIstrat,2);
7138  if (fISW[4] > 0) goto L1172;
7139  return;
7140 // set page throw
7141 L190:
7142  fNewpag = Int_t(fWord7[0]);
7143  goto L1190;
7144 // set epsmac
7145 L210:
7146  if (fWord7[0] > 0 && fWord7[0] < .1) {
7147  fEpsmac = fWord7[0];
7148  }
7150  goto L1210;
7151 // set outputfile
7152 L220:
7153  iunit = Int_t(fWord7[0]);
7154  fIsyswr = iunit;
7155  fIstkwr[0] = iunit;
7156  if (fISW[4] >= 0) goto L1220;
7157  return;
7158 // set batch
7159 L230:
7160  fISW[5] = 0;
7161  if (fISW[4] >= 0) goto L1100;
7162  return;
7163 // set interactive
7164 L240:
7165  fISW[5] = 1;
7166  if (fISW[4] >= 0) goto L1100;
7167  return;
7168 // set nodebug
7169 L270:
7170  iset = 0;
7171  goto L281;
7172 // set debug
7173 L280:
7174  iset = 1;
7175 L281:
7176  idbopt = Int_t(fWord7[0]);
7177  if (idbopt > 6) goto L288;
7178  if (idbopt >= 0) {
7179  fIdbg[idbopt] = iset;
7180  if (iset == 1) fIdbg[0] = 1;
7181  } else {
7182 // SET DEBUG -1 sets all debug options
7183  for (id = 0; id <= 6; ++id) { fIdbg[id] = iset; }
7184  }
7185  fLrepor = fIdbg[0] >= 1;
7186  mnwarn("D", "SHO", "SHO");
7187  return;
7188 L288:
7189  Printf(" UNKNOWN DEBUG OPTION %d REQUESTED. IGNORED",idbopt);
7190  return;
7191 // set show
7192 L290:
7193 // set set
7194 L300:
7195  goto L3000;
7196 // -----------------------------------------------------
7197 L1000:
7198 // at this point, CWORD must be 'SHOW'
7199  ckind = "SHOW";
7200  if (kname <= 0) goto L1900;
7201 
7202  switch ((int)kname) {
7203  case 1: goto L1010;
7204  case 2: goto L1020;
7205  case 3: goto L1030;
7206  case 4: goto L1040;
7207  case 5: goto L1050;
7208  case 6: goto L1060;
7209  case 7: goto L1070;
7210  case 8: goto L1070;
7211  case 9: goto L1090;
7212  case 10: goto L1100;
7213  case 11: goto L1110;
7214  case 12: goto L1120;
7215  case 13: goto L1130;
7216  case 14: goto L1130;
7217  case 15: goto L1150;
7218  case 16: goto L1160;
7219  case 17: goto L1170;
7220  case 18: goto L1180;
7221  case 19: goto L1190;
7222  case 20: goto L1200;
7223  case 21: goto L1210;
7224  case 22: goto L1220;
7225  case 23: goto L1100;
7226  case 24: goto L1100;
7227  case 25: goto L1250;
7228  case 26: goto L1900;
7229  case 27: goto L1270;
7230  case 28: goto L1270;
7231  case 29: goto L1290;
7232  case 30: goto L1300;
7233  }
7234 
7235 // show fcn
7236 L1010:
7237  if (fAmin == fUndefi) mnamin();
7238  mnprin(0, fAmin);
7239  return;
7240 // show param
7241 L1020:
7242  if (fAmin == fUndefi) mnamin();
7243  mnprin(5, fAmin);
7244  return;
7245 // show limits
7246 L1030:
7247  if (fAmin == fUndefi) mnamin();
7248  mnprin(1, fAmin);
7249  return;
7250 // show covar
7251 L1040:
7252  mnmatu(1);
7253  return;
7254 // show corre
7255 L1050:
7256  mnmatu(0);
7257  return;
7258 // show print
7259 L1060:
7260  if (fISW[4] < -1) fISW[4] = -1;
7261  if (fISW[4] > 3) fISW[4] = 3;
7262  Printf(" ALLOWED PRINT LEVELS ARE:");
7263  Printf(" %s",cprlev[0].Data());
7264  Printf(" %s",cprlev[1].Data());
7265  Printf(" %s",cprlev[2].Data());
7266  Printf(" %s",cprlev[3].Data());
7267  Printf(" %s",cprlev[4].Data());
7268  Printf(" CURRENT PRINTOUT LEVEL IS %s",cprlev[fISW[4]+1].Data());
7269  return;
7270 // show nograd, grad
7271 L1070:
7272  if (fISW[2] <= 0) {
7273  Printf(" NOGRAD IS SET. DERIVATIVES NOT COMPUTED IN FCN.");
7274  } else {
7275  Printf(" GRAD IS SET. USER COMPUTES DERIVATIVES IN FCN.");
7276  }
7277  return;
7278 // show errdef
7279 L1090:
7280  Printf(" ERRORS CORRESPOND TO FUNCTION CHANGE OF %g",fUp);
7281  return;
7282 // show input,
7283 // batch, or interactive
7284 L1100:
7285 // ioin__1.inerr = 0;
7286 // ioin__1.inunit = fIsysrd;
7287 // ioin__1.infile = 0;
7288 // ioin__1.inex = 0;
7289 // ioin__1.inopen = 0;
7290 // ioin__1.innum = 0;
7291 // ioin__1.innamed = &lname;
7292 // ioin__1.innamlen = 64;
7293 // ioin__1.inname = cfname;
7294 // ioin__1.inacc = 0;
7295 // ioin__1.inseq = 0;
7296 // ioin__1.indir = 0;
7297 // ioin__1.infmt = 0;
7298 // ioin__1.inform = 0;
7299 // ioin__1.inunf = 0;
7300 // ioin__1.inrecl = 0;
7301 // ioin__1.innrec = 0;
7302 // ioin__1.inblank = 0;
7303 // f_inqu(&ioin__1);
7304  cmode = "BATCH MODE ";
7305  if (fISW[5] == 1) cmode = "INTERACTIVE MODE";
7306  if (! lname) cfname = "unknown";
7307  Printf(" INPUT NOW BEING READ IN %s FROM UNIT NO. %d FILENAME: %s"
7308  ,(const char*)cmode,fIsysrd,(const char*)cfname);
7309  return;
7310 // show width
7311 L1110:
7312  Printf(" PAGE WIDTH IS SET TO %d COLUMNS",fNpagwd);
7313  return;
7314 // show lines
7315 L1120:
7316  Printf(" PAGE LENGTH IS SET TO %d LINES",fNpagln);
7317  return;
7318 // show nowarn, warn
7319 L1130:
7320  cwarn = "SUPPRESSED";
7321  if (fLwarn) cwarn = "REPORTED ";
7322  Printf("%s",(const char*)cwarn);
7323  if (! fLwarn) mnwarn("W", "SHO", "SHO");
7324  return;
7325 // show random
7326 L1150:
7327  val = 0;
7328  mnrn15(val, igrain);
7329  ikseed = igrain;
7330  Printf(" MINUIT RNDM SEED IS CURRENTLY=%d",ikseed);
7331  val = 3;
7332  iseed = ikseed;
7333  mnrn15(val, iseed);
7334  return;
7335 // show title
7336 L1160:
7337  Printf(" TITLE OF CURRENT TASK IS:%s",(const char*)fCtitl);
7338  return;
7339 // show strategy
7340 L1170:
7341  Printf(" ALLOWED STRATEGIES ARE:");
7342  Printf(" %s",cstrat[0].Data());
7343  Printf(" %s",cstrat[1].Data());
7344  Printf(" %s",cstrat[2].Data());
7345 L1172:
7346  Printf(" NOW USING STRATEGY %s",(const char*)cstrat[fIstrat]);
7347  return;
7348 // show eigenvalues
7349 L1180:
7350  iswsav = fISW[4];
7351  fISW[4] = 3;
7352  if (fISW[1] < 1) {
7353  Printf("%s",(const char*)fCovmes[0]);
7354  } else {
7355  mnpsdf();
7356  }
7357  fISW[4] = iswsav;
7358  return;
7359 // show page throw
7360 L1190:
7361  Printf(" PAGE THROW CARRIAGE CONTROL = %d",fNewpag);
7362  if (fNewpag == 0) {
7363  Printf(" NO PAGE THROWS IN MINUIT OUTPUT");
7364  }
7365  return;
7366 // show minos errors
7367 L1200:
7368  for (ii = 1; ii <= fNpar; ++ii) {
7369  if (fErp[ii-1] > 0 || fErn[ii-1] < 0) goto L1204;
7370  }
7371  Printf(" THERE ARE NO MINOS ERRORS CURRENTLY VALID.");
7372  return;
7373 L1204:
7374  mnprin(4, fAmin);
7375  return;
7376 // show epsmac
7377 L1210:
7378  Printf(" FLOATING-POINT NUMBERS ASSUMED ACCURATE TO %g",fEpsmac);
7379  return;
7380 // show outputfiles
7381 L1220:
7382  Printf(" MINUIT PRIMARY OUTPUT TO UNIT %d",fIsyswr);
7383  return;
7384 // show version
7385 L1250:
7386  Printf(" THIS IS MINUIT VERSION:%s",(const char*)fCvrsn);
7387  return;
7388 // show nodebug, debug
7389 L1270:
7390  for (id = 0; id <= 6; ++id) {
7391  copt = "OFF";
7392  if (fIdbg[id] >= 1) copt = "ON ";
7393  Printf(" DEBUG OPTION %3d IS %3s :%s"
7394  ,id,(const char*)copt,(const char*)cdbopt[id]);
7395  }
7396  if (! fLrepor) mnwarn("D", "SHO", "SHO");
7397  return;
7398 // show show
7399 L1290:
7400  ckind = "SHOW";
7401  goto L2100;
7402 // show set
7403 L1300:
7404  ckind = "SET ";
7405  goto L2100;
7406 // -----------------------------------------------------
7407 // UNKNOWN COMMAND
7408 L1900:
7409  Printf(" THE COMMAND:%10s IS UNKNOWN.",(const char*)fCword);
7410  goto L2100;
7411 // -----------------------------------------------------
7412 // HELP SHOW, HELP SET, SHOW SET, or SHOW SHOW
7413 L2000:
7414  ckind = "SET ";
7415  ctemp2 = fCword(3,7);
7416  if (strcmp(ctemp2.Data(), "SHO")) ckind = "SHOW";
7417 L2100:
7418  Printf(" THE FORMAT OF THE %4s COMMAND IS:",(const char*)ckind);
7419  Printf(" %s xxx [numerical arguments if any]",(const char*)ckind);
7420  Printf(" WHERE xxx MAY BE ONE OF THE FOLLOWING:");
7421  for (kk = 1; kk <= nname; ++kk) {
7422  Printf(" %s",cname[kk-1]);
7423  }
7424  return;
7425 // -----------------------------------------------------
7426 // ILLEGAL COMMAND
7427 L3000:
7428  Printf(" ABOVE COMMAND IS ILLEGAL. IGNORED");
7429 
7430 }
7431 
7432 ////////////////////////////////////////////////////////////////////////////////
7433 /// Minimization using the simplex method of Nelder and Mead
7434 ///
7435 /// Performs a minimization using the simplex method of Nelder
7436 /// and Mead (ref. -- Comp. J. 7,308 (1965)).
7437 
7439 {
7440  /* Initialized data */
7441 
7442  static constexpr Double_t alpha = 1;
7443  static constexpr Double_t beta = .5;
7444  static constexpr Double_t gamma = 2;
7445  static constexpr Double_t rhomin = 4;
7446  static constexpr Double_t rhomax = 8;
7447 
7448  /* Local variables */
7449  Double_t dmin_, dxdi, yrho, f, ynpp1, aming, ypbar;
7450  Double_t bestx, ystar, y1, y2, ystst, pb, wg;
7451  Double_t absmin, rho, sig2, rho1, rho2;
7452  Int_t npfn, i, j, k, jhold, ncycl, nparx;
7453  Int_t nparp1, kg, jh, nf, jl, ns;
7454 
7455  if (fNpar <= 0) return;
7456  if (fAmin == fUndefi) mnamin();
7457  fCfrom = "SIMPLEX ";
7458  fNfcnfr = fNfcn;
7459  fCstatu = "UNCHANGED ";
7460  npfn = fNfcn;
7461  nparp1 = fNpar + 1;
7462  nparx = fNpar;
7463  rho1 = alpha + 1;
7464  rho2 = rho1 + alpha*gamma;
7465  wg = 1 / Double_t(fNpar);
7466  if (fISW[4] >= 0) {
7467  Printf(" START SIMPLEX MINIMIZATION. CONVERGENCE WHEN EDM .LT. %g",fEpsi);
7468  }
7469  for (i = 1; i <= fNpar; ++i) {
7470  fDirin[i-1] = fWerr[i-1];
7471  mndxdi(fX[i-1], i-1, dxdi);
7472  if (dxdi != 0) fDirin[i-1] = fWerr[i-1] / dxdi;
7473  dmin_ = fEpsma2*TMath::Abs(fX[i-1]);
7474  if (fDirin[i-1] < dmin_) fDirin[i-1] = dmin_;
7475  }
7476 // choose the initial simplex using single-parameter searches
7477 L1:
7478  ynpp1 = fAmin;
7479  jl = nparp1;
7480  fSIMPy[nparp1-1] = fAmin;
7481  absmin = fAmin;
7482  for (i = 1; i <= fNpar; ++i) {
7483  aming = fAmin;
7484  fPbar[i-1] = fX[i-1];
7485  bestx = fX[i-1];
7486  kg = 0;
7487  ns = 0;
7488  nf = 0;
7489 L4:
7490  fX[i-1] = bestx + fDirin[i-1];
7491  mninex(fX);
7492  Eval(nparx, fGin, f, fU, 4); ++fNfcn;
7493  if (f <= aming) goto L6;
7494 // failure
7495  if (kg == 1) goto L8;
7496  kg = -1;
7497  ++nf;
7498  fDirin[i-1] *= -.4;
7499  if (nf < 3) goto L4;
7500  ns = 6;
7501 // success
7502 L6:
7503  bestx = fX[i-1];
7504  fDirin[i-1] *= 3;
7505  aming = f;
7506  fCstatu = "PROGRESS ";
7507  kg = 1;
7508  ++ns;
7509  if (ns < 6) goto L4;
7510 // local minimum found in ith direction
7511 L8:
7512  fSIMPy[i-1] = aming;
7513  if (aming < absmin) jl = i;
7514  if (aming < absmin) absmin = aming;
7515  fX[i-1] = bestx;
7516  for (k = 1; k <= fNpar; ++k) { fP[k + i*fMaxpar - fMaxpar-1] = fX[k-1]; }
7517  }
7518  jh = nparp1;
7519  fAmin = fSIMPy[jl-1];
7520  mnrazz(ynpp1, fPbar, fSIMPy, jh, jl);
7521  for (i = 1; i <= fNpar; ++i) { fX[i-1] = fP[i + jl*fMaxpar - fMaxpar-1]; }
7522  mninex(fX);
7523  fCstatu = "PROGRESS ";
7524  if (fISW[4] >= 1) mnprin(5, fAmin);
7525  fEDM = fBigedm;
7526  sig2 = fEDM;
7527  ncycl = 0;
7528 // start main loop
7529 L50:
7530  if (sig2 < fEpsi && fEDM < fEpsi) goto L76;
7531  sig2 = fEDM;
7532  if (fNfcn - npfn > fNfcnmx) goto L78;
7533 // calculate new point * by reflection
7534  for (i = 1; i <= fNpar; ++i) {
7535  pb = 0;
7536  for (j = 1; j <= nparp1; ++j) { pb += wg*fP[i + j*fMaxpar - fMaxpar-1]; }
7537  fPbar[i-1] = pb - wg*fP[i + jh*fMaxpar - fMaxpar-1];
7538  fPstar[i-1] = (alpha + 1)*fPbar[i-1] - alpha*fP[i + jh*fMaxpar - fMaxpar-1];
7539  }
7540  mninex(fPstar);
7541  Eval(nparx, fGin, ystar, fU, 4); ++fNfcn;
7542  if (ystar >= fAmin) goto L70;
7543 // point * better than jl, calculate new point **
7544  for (i = 1; i <= fNpar; ++i) {
7545  fPstst[i-1] = gamma*fPstar[i-1] + (1 - gamma)*fPbar[i-1];
7546  }
7547  mninex(fPstst);
7548  Eval(nparx, fGin, ystst, fU, 4); ++fNfcn;
7549 // try a parabola through ph, pstar, pstst. min = prho
7550  y1 = (ystar - fSIMPy[jh-1])*rho2;
7551  y2 = (ystst - fSIMPy[jh-1])*rho1;
7552  rho = (rho2*y1 - rho1*y2)*.5 / (y1 - y2);
7553  if (rho < rhomin) goto L66;
7554  if (rho > rhomax) rho = rhomax;
7555  for (i = 1; i <= fNpar; ++i) {
7556  fPrho[i-1] = rho*fPbar[i-1] + (1 - rho)*fP[i + jh*fMaxpar - fMaxpar-1];
7557  }
7558  mninex(fPrho);
7559  Eval(nparx, fGin, yrho, fU, 4); ++fNfcn;
7560  if (yrho < fSIMPy[jl-1] && yrho < ystst) goto L65;
7561  if (ystst < fSIMPy[jl-1]) goto L67;
7562  if (yrho > fSIMPy[jl-1]) goto L66;
7563 // accept minimum point of parabola, PRHO
7564 L65:
7565  mnrazz(yrho, fPrho, fSIMPy, jh, jl);
7566  goto L68;
7567 L66:
7568  if (ystst < fSIMPy[jl-1]) goto L67;
7569  mnrazz(ystar, fPstar, fSIMPy, jh, jl);
7570  goto L68;
7571 L67:
7572  mnrazz(ystst, fPstst, fSIMPy, jh, jl);
7573 L68:
7574  ++ncycl;
7575  if (fISW[4] < 2) goto L50;
7576  if (fISW[4] >= 3 || ncycl % 10 == 0) {
7577  mnprin(5, fAmin);
7578  }
7579  goto L50;
7580 // point * is not as good as jl
7581 L70:
7582  if (ystar >= fSIMPy[jh-1]) goto L73;
7583  jhold = jh;
7584  mnrazz(ystar, fPstar, fSIMPy, jh, jl);
7585  if (jhold != jh) goto L50;
7586 // calculate new point **
7587 L73:
7588  for (i = 1; i <= fNpar; ++i) {
7589  fPstst[i-1] = beta*fP[i + jh*fMaxpar - fMaxpar-1] + (1 - beta)*fPbar[i-1];
7590  }
7591  mninex(fPstst);
7592  Eval(nparx, fGin, ystst, fU, 4); ++fNfcn;
7593  if (ystst > fSIMPy[jh-1]) goto L1;
7594 // point ** is better than jh
7595  if (ystst < fAmin) goto L67;
7596  mnrazz(ystst, fPstst, fSIMPy, jh, jl);
7597  goto L50;
7598 // end main loop
7599 L76:
7600  if (fISW[4] >= 0) {
7601  Printf(" SIMPLEX MINIMIZATION HAS CONVERGED.");
7602  }
7603  fISW[3] = 1;
7604  goto L80;
7605 L78:
7606  if (fISW[4] >= 0) {
7607  Printf(" SIMPLEX TERMINATES WITHOUT CONVERGENCE.");
7608  }
7609  fCstatu = "CALL LIMIT";
7610  fISW[3] = -1;
7611  fISW[0] = 1;
7612 L80:
7613  for (i = 1; i <= fNpar; ++i) {
7614  pb = 0;
7615  for (j = 1; j <= nparp1; ++j) { pb += wg*fP[i + j*fMaxpar - fMaxpar-1]; }
7616  fPbar[i-1] = pb - wg*fP[i + jh*fMaxpar - fMaxpar-1];
7617  }
7618  mninex(fPbar);
7619  Eval(nparx, fGin, ypbar, fU, 4); ++fNfcn;
7620  if (ypbar < fAmin) mnrazz(ypbar, fPbar, fSIMPy, jh, jl);
7621  mninex(fX);
7622  if (fNfcnmx + npfn - fNfcn < fNpar*3) goto L90;
7623  if (fEDM > fEpsi*2) goto L1;
7624 L90:
7625  if (fISW[4] >= 0) mnprin(5, fAmin);
7626 }
7627 
7628 ////////////////////////////////////////////////////////////////////////////////
7629 /// Returns concerning the current status of the minimization
7630 ///
7631 /// User-called
7632 /// Namely, it returns:
7633 /// - FMIN: the best function value found so far
7634 /// - FEDM: the estimated vertical distance remaining to minimum
7635 /// - ERRDEF: the value of UP defining parameter uncertainties
7636 /// - NPARI: the number of currently variable parameters
7637 /// - NPARX: the highest (external) parameter number defined by user
7638 /// - ISTAT: a status integer indicating how good is the covariance
7639 /// matrix:
7640 /// - 0= not calculated at all
7641 /// - 1= approximation only, not accurate
7642 /// - 2= full matrix, but forced positive-definite
7643 /// - 3= full accurate covariance matrix
7644 
7645 void TMinuit::mnstat(Double_t &fmin, Double_t &fedm, Double_t &errdef, Int_t &npari, Int_t &nparx, Int_t &istat)
7646 {
7647  fmin = fAmin;
7648  fedm = fEDM;
7649  errdef = fUp;
7650  npari = fNpar;
7651  nparx = fNu;
7652  istat = fISW[1];
7653  if (fEDM == fBigedm) fedm = fUp;
7654  if (fAmin == fUndefi) {
7655  fmin = 0;
7656  fedm = fUp;
7657  istat = 0;
7658  }
7659 }
7660 
7661 ////////////////////////////////////////////////////////////////////////////////
7662 /// To find the machine precision
7663 ///
7664 /// Compares its argument with the value 1.0, and returns
7665 /// the value .TRUE. if they are equal. To find EPSMAC
7666 /// safely by foiling the Fortran optimiser
7667 
7668 void TMinuit::mntiny(volatile Double_t epsp1, Double_t &epsbak)
7669 {
7670  epsbak = epsp1 - 1;
7671 }
7672 
7673 ////////////////////////////////////////////////////////////////////////////////
7674 /// Returns .TRUE. if CFNAME contains unprintable characters
7675 ///
7676 
7678 {
7679  Int_t i, l, ic;
7680  Bool_t ret_val;
7681  static const TString cpt = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./;:[]$%*_!@#&+()";
7682 
7683  ret_val = kFALSE;
7684  l = strlen((const char*)cfname);
7685  for (i = 1; i <= l; ++i) {
7686  for (ic = 1; ic <= 80; ++ic) {
7687  if (cfname[i-1] == cpt[ic-1]) goto L100;
7688  }
7689  return kTRUE;
7690 L100:
7691  ;
7692  }
7693  return ret_val;
7694 }
7695 
7696 ////////////////////////////////////////////////////////////////////////////////
7697 /// Inverts a symmetric matrix
7698 ///
7699 /// inverts a symmetric matrix. matrix is first scaled to
7700 /// have all ones on the diagonal (equivalent to change of units)
7701 /// but no pivoting is done since matrix is positive-definite.
7702 
7704 {
7705  /* System generated locals */
7706  Int_t a_offset;
7707 
7708  /* Local variables */
7709  Double_t si;
7710  Int_t i, j, k, kp1, km1;
7711 
7712  /* Parameter adjustments */
7713  a_offset = l + 1;
7714  a -= a_offset;
7715 
7716  /* Function Body */
7717  ifail = 0;
7718  if (n < 1) goto L100;
7719  if (n > fMaxint) goto L100;
7720 // scale matrix by sqrt of diag elements
7721  for (i = 1; i <= n; ++i) {
7722  si = a[i + i*l];
7723  if (si <= 0) goto L100;
7724  fVERTs[i-1] = 1 / TMath::Sqrt(si);
7725  }
7726  for (i = 1; i <= n; ++i) {
7727  for (j = 1; j <= n; ++j) {
7728  a[i + j*l] = a[i + j*l]*fVERTs[i-1]*fVERTs[j-1];
7729  }
7730  }
7731 // start main loop
7732  for (i = 1; i <= n; ++i) {
7733  k = i;
7734 // preparation for elimination step1
7735  if (a[k + k*l] != 0) fVERTq[k-1] = 1 / a[k + k*l];
7736  else goto L100;
7737  fVERTpp[k-1] = 1;
7738  a[k + k*l] = 0;
7739  kp1 = k + 1;
7740  km1 = k - 1;
7741  if (km1 < 0) goto L100;
7742  else if (km1 == 0) goto L50;
7743  else goto L40;
7744 L40:
7745  for (j = 1; j <= km1; ++j) {
7746  fVERTpp[j-1] = a[j + k*l];
7747  fVERTq[j-1] = a[j + k*l]*fVERTq[k-1];
7748  a[j + k*l] = 0;
7749  }
7750 L50:
7751  if (k - n < 0) goto L51;
7752  else if (k - n == 0) goto L60;
7753  else goto L100;
7754 L51:
7755  for (j = kp1; j <= n; ++j) {
7756  fVERTpp[j-1] = a[k + j*l];
7757  fVERTq[j-1] = -a[k + j*l]*fVERTq[k-1];
7758  a[k + j*l] = 0;
7759  }
7760 // elimination proper
7761 L60:
7762  for (j = 1; j <= n; ++j) {
7763  for (k = j; k <= n; ++k) { a[j + k*l] += fVERTpp[j-1]*fVERTq[k-1]; }
7764  }
7765  }
7766 // elements of left diagonal and unscaling
7767  for (j = 1; j <= n; ++j) {
7768  for (k = 1; k <= j; ++k) {
7769  a[k + j*l] = a[k + j*l]*fVERTs[k-1]*fVERTs[j-1];
7770  a[j + k*l] = a[k + j*l];
7771  }
7772  }
7773  return;
7774 // failure return
7775 L100:
7776  ifail = 1;
7777 }
7778 
7779 ////////////////////////////////////////////////////////////////////////////////
7780 /// Prints Warning messages
7781 ///
7782 /// - If COPT='W', CMES is a WARning message from CORG.
7783 /// - If COPT='D', CMES is a DEBug message from CORG.
7784 /// - If SET WARnings is in effect (the default), this routine
7785 /// prints the warning message CMES coming from CORG.
7786 /// - If SET NOWarnings is in effect, the warning message is
7787 /// stored in a circular buffer of length kMAXMES.
7788 /// - If called with CORG=CMES='SHO', it prints the messages in
7789 /// the circular buffer, FIFO, and empties the buffer.
7790 
7791 void TMinuit::mnwarn(const char *copt1, const char *corg1, const char *cmes1)
7792 {
7793  TString copt = copt1;
7794  TString corg = corg1;
7795  TString cmes = cmes1;
7796 
7797  const Int_t kMAXMES = 10;
7798  Int_t ityp, i, ic, nm;
7799  TString englsh, ctyp;
7800 
7801  if (corg(0,3) != "SHO" || cmes(0,3) != "SHO") {
7802 
7803 // Either print warning or put in buffer
7804  if (copt == "W") {
7805  ityp = 1;
7806  if (fLwarn) {
7807  Printf(" MINUIT WARNING IN %s",(const char*)corg);
7808  Printf(" ============== %s",(const char*)cmes);
7809  return;
7810  }
7811  } else {
7812  ityp = 2;
7813  if (fLrepor) {
7814  Printf(" MINUIT DEBUG FOR %s",(const char*)corg);
7815  Printf(" =============== %s ",(const char*)cmes);
7816  return;
7817  }
7818  }
7819 // if appropriate flag is off, fill circular buffer
7820  if (fNwrmes[ityp-1] == 0) fIcirc[ityp-1] = 0;
7821  ++fNwrmes[ityp-1];
7822  ++fIcirc[ityp-1];
7823  if (fIcirc[ityp-1] > 10) fIcirc[ityp-1] = 1;
7824  ic = fIcirc[ityp-1];
7825  fOrigin[ic] = corg;
7826  fWarmes[ic] = cmes;
7827  fNfcwar[ic] = fNfcn;
7828  return;
7829  }
7830 
7831 // 'SHO WARnings', ask if any suppressed mess in buffer
7832  if (copt == "W") {
7833  ityp = 1;
7834  ctyp = "WARNING";
7835  } else {
7836  ityp = 2;
7837  ctyp = "*DEBUG*";
7838  }
7839  if (fNwrmes[ityp-1] > 0) {
7840  englsh = " WAS SUPPRESSED. ";
7841  if (fNwrmes[ityp-1] > 1) englsh = "S WERE SUPPRESSED.";
7842  Printf(" %5d MINUIT %s MESSAGE%s",fNwrmes[ityp-1]
7843  ,(const char*)ctyp,(const char*)englsh);
7844  nm = fNwrmes[ityp-1];
7845  ic = 0;
7846  if (nm > kMAXMES) {
7847  Printf(" ONLY THE MOST RECENT 10 WILL BE LISTED BELOW.");
7848  nm = kMAXMES;
7849  ic = fIcirc[ityp-1];
7850  }
7851  Printf(" CALLS ORIGIN MESSAGE");
7852  for (i = 1; i <= nm; ++i) {
7853  ++ic;
7854  if (ic > kMAXMES) ic = 1;
7855  Printf(" %6d %s %s", fNfcwar[ic],fOrigin[ic].Data(),fWarmes[ic].Data());
7856  }
7857  fNwrmes[ityp-1] = 0;
7858  Printf(" ");
7859  }
7860 }
7861 
7862 ////////////////////////////////////////////////////////////////////////////////
7863 /// Calculates the WERR, external parameter errors
7864 ///
7865 /// and the global correlation coefficients, to be called
7866 /// whenever a new covariance matrix is available.
7867 
7869 {
7870  Double_t denom, ba, al, dx, du1, du2;
7871  Int_t ndex, ierr, i, j, k, l, ndiag, k1, iin;
7872 
7873 // calculate external error if v exists
7874  if (fISW[1] >= 1) {
7875  for (l = 1; l <= fNpar; ++l) {
7876  ndex = l*(l + 1) / 2;
7877  dx = TMath::Sqrt(TMath::Abs(fVhmat[ndex-1]*fUp));
7878  i = fNexofi[l-1];
7879  if (fNvarl[i-1] > 1) {
7880  al = fAlim[i-1];
7881  ba = fBlim[i-1] - al;
7882  du1 = al + 0.5*(TMath::Sin(fX[l-1] + dx) + 1)*ba - fU[i-1];
7883  du2 = al + 0.5*(TMath::Sin(fX[l-1] - dx) + 1)*ba - fU[i-1];
7884  if (dx > 1) du1 = ba;
7885  dx = 0.5*(TMath::Abs(du1) + TMath::Abs(du2));
7886  }
7887  fWerr[l-1] = dx;
7888  }
7889  }
7890 // global correlation coefficients
7891  if (fISW[1] >= 1) {
7892  for (i = 1; i <= fNpar; ++i) {
7893  fGlobcc[i-1] = 0;
7894  k1 = i*(i-1) / 2;
7895  for (j = 1; j <= i; ++j) {
7896  k = k1 + j;
7897  fP[i + j*fMaxpar - fMaxpar-1] = fVhmat[k-1];
7898  fP[j + i*fMaxpar - fMaxpar-1] = fP[i + j*fMaxpar - fMaxpar-1];
7899  }
7900  }
7901  mnvert(fP, fMaxint, fMaxint, fNpar, ierr);
7902  if (ierr == 0) {
7903  for (iin = 1; iin <= fNpar; ++iin) {
7904  ndiag = iin*(iin + 1) / 2;
7905  denom = fP[iin + iin*fMaxpar - fMaxpar-1]*fVhmat[ndiag-1];
7906  if (denom <= 1 && denom >= 0) fGlobcc[iin-1] = 0;
7907  else fGlobcc[iin-1] = TMath::Sqrt(1 - 1 / denom);
7908  }
7909  }
7910  }
7911 }
Double_t * fMNOTw
Definition: TMinuit.h:114
virtual void mnmnos()
Performs a MINOS error analysis.
Definition: TMinuit.cxx:5399
virtual void mnsimp()
Minimization using the simplex method of Nelder and Mead.
Definition: TMinuit.cxx:7438
TMinuit()
Minuit normal constructor.
Definition: TMinuit.cxx:356
Double_t * fBlim
Definition: TMinuit.h:70
Double_t * fXpt
Definition: TMinuit.h:97
TString fCword
Definition: TMinuit.h:169
Int_t fMaxext
Definition: TMinuit.h:42
virtual void mnstat(Double_t &fmin, Double_t &fedm, Double_t &errdef, Int_t &npari, Int_t &nparx, Int_t &istat)
Returns concerning the current status of the minimization.
Definition: TMinuit.cxx:7645
Double_t fDcovar
Definition: TMinuit.h:55
double dist(Rotation3D const &r1, Rotation3D const &r2)
Definition: 3DDistances.cxx:48
virtual void mneval(Double_t anext, Double_t &fnext, Int_t &ierev)
Evaluates the function being analysed by MNCROS.
Definition: TMinuit.cxx:2629
Int_t fIstrat
Definition: TMinuit.h:150
Int_t * fIpfix
Definition: TMinuit.h:129
virtual void mnprin(Int_t inkode, Double_t fval)
Prints the values of the parameters at the time of the call.
Definition: TMinuit.cxx:6313
virtual Int_t GetNumFixedPars() const
returns the number of currently fixed parameters
Definition: TMinuit.cxx:864
Double_t * fGlobcc
Definition: TMinuit.h:74
virtual Int_t SetPrintLevel(Int_t printLevel=0)
set Minuit print level.
Definition: TMinuit.cxx:961
float xmin
Definition: THbookFile.cxx:93
Double_t * fP
Definition: TMinuit.h:91
virtual void mnexin(Double_t *pint)
Transforms the external parameter values U to internal values.
Definition: TMinuit.cxx:3160
Double_t * fPrho
Definition: TMinuit.h:95
TString fCstatu
Definition: TMinuit.h:167
virtual void mnhes1()
Calculate first derivatives (GRD) and uncertainties (DGRD)
Definition: TMinuit.cxx:4227
virtual void mnvert(Double_t *a, Int_t l, Int_t m, Int_t n, Int_t &ifail)
Inverts a symmetric matrix.
Definition: TMinuit.cxx:7703
auto * m
Definition: textangle.C:8
Implementation in C++ of the Minuit package written by Fred James.
Definition: TMinuit.h:27
Double_t * fCOMDplist
Definition: TMinuit.h:123
Double_t Log(Double_t x)
Definition: TMath.h:759
int idb
Definition: THbookFile.cxx:91
Int_t fKe2cr
Definition: TMinuit.h:156
Double_t * fWord7
Definition: TMinuit.h:96
TLine * line
virtual void mnemat(Double_t *emat, Int_t ndim)
Calculates the external error matrix from the internal matrix.
Definition: TMinuit.cxx:2510
Double_t * fXs
Definition: TMinuit.h:78
void(* fFCN)(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag)
Definition: TMinuit.h:178
Double_t * fGrds
Definition: TMinuit.h:86
Bool_t fLnewmn
Definition: TMinuit.h:161
virtual void mnwarn(const char *copt, const char *corg, const char *cmes)
Prints Warning messages.
Definition: TMinuit.cxx:7791
float ymin
Definition: THbookFile.cxx:93
Int_t fIdbg[11]
Definition: TMinuit.h:142
Int_t fIsyswr
Definition: TMinuit.h:132
Int_t fItaur
Definition: TMinuit.h:149
virtual void mnline(Double_t *start, Double_t fstart, Double_t *step, Double_t slope, Double_t toler)
Perform a line search from position START.
Definition: TMinuit.cxx:4745
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1113
Double_t * fVhmat
Definition: TMinuit.h:89
virtual void mnseek()
Performs a rough (but global) minimization by monte carlo search.
Definition: TMinuit.cxx:6825
#define gROOT
Definition: TROOT.h:410
static constexpr double bar
Int_t LoadPlugin()
Load the plugin library for this handler.
Int_t fNpagwd
Definition: TMinuit.h:134
Basic string class.
Definition: TString.h:131
Double_t * fMATUvline
Definition: TMinuit.h:107
#define f(i)
Definition: RSha256.hxx:104
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:168
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
Double_t * fGRADgf
Definition: TMinuit.h:103
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:57
virtual void mnderi()
Calculates the first derivatives of FCN (GRD)
Definition: TMinuit.cxx:2187
virtual void mncros(Double_t &aopt, Int_t &iercr)
Find point where MNEVAL=AMIN+UP.
Definition: TMinuit.cxx:1807
virtual void mngrad()
Interprets the SET GRAD command.
Definition: TMinuit.cxx:3371
Double_t * fMNOTxdev
Definition: TMinuit.h:113
virtual void mnbins(Double_t a1, Double_t a2, Int_t naa, Double_t &bl, Double_t &bh, Int_t &nb, Double_t &bwid)
Compute reasonable histogram intervals.
Definition: TMinuit.cxx:1006
Double_t * fX
Definition: TMinuit.h:75
virtual void mnrset(Int_t iopt)
Resets function value and errors to UNDEFINED.
Definition: TMinuit.cxx:6668
TObject * fPlot
Definition: TMinuit.h:176
virtual void mntiny(volatile Double_t epsp1, Double_t &epsbak)
To find the machine precision.
Definition: TMinuit.cxx:7668
virtual Int_t GetParameter(Int_t parNo, Double_t &currentValue, Double_t &currentError) const
return parameter value and error
Definition: TMinuit.cxx:850
Int_t fNfcnlc
Definition: TMinuit.h:147
Short_t Abs(Short_t d)
Definition: TMathBase.h:108
Int_t fNblock
Definition: TMinuit.h:143
TString fCtitl
Definition: TMinuit.h:168
Int_t fNstkwr
Definition: TMinuit.h:140
Int_t fIcirc[2]
Definition: TMinuit.h:153
Double_t * fXts
Definition: TMinuit.h:79
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Definition: TMath.h:734
Double_t * fDirin
Definition: TMinuit.h:77
double beta(double x, double y)
Calculates the beta function.
TString fOrigin[kMAXWARN]
Definition: TMinuit.h:173
virtual Int_t FixParameter(Int_t parNo)
fix a parameter
Definition: TMinuit.cxx:836
Double_t * fErn
Definition: TMinuit.h:72
virtual Int_t Eval(Int_t npar, Double_t *grad, Double_t &fval, Double_t *par, Int_t flag)
Evaluate the minimisation function Input parameters:
Definition: TMinuit.cxx:809
virtual void mneig(Double_t *a, Int_t ndima, Int_t n, Int_t mits, Double_t *work, Double_t precis, Int_t &ifault)
Compute matrix eigen values.
Definition: TMinuit.cxx:2314
void SetParamPtrs(void *paramArr, Int_t nparam=-1)
ParamArr is an array containing the function argument values.
virtual void mnmigr()
Performs a local function minimization.
Definition: TMinuit.cxx:5059
virtual void mnfree(Int_t k)
Restores one or more fixed parameter(s) to variable status.
Definition: TMinuit.cxx:3265
Double_t * fYpt
Definition: TMinuit.h:98
static constexpr double kg
static const double x2[5]
Double_t fEpsmac
Definition: TMinuit.h:56
Int_t * fNexofi
Definition: TMinuit.h:128
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2286
Int_t fMaxint
Definition: TMinuit.h:40
void Class()
Definition: Class.C:29
Int_t fNpar
Definition: TMinuit.h:41
Double_t * fPstar
Definition: TMinuit.h:92
Int_t fKe1cr
Definition: TMinuit.h:155
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
Double_t * fVERTq
Definition: TMinuit.h:120
Double_t fUndefi
Definition: TMinuit.h:60
virtual void mncrck(TString crdbuf, Int_t maxcwd, TString &comand, Int_t &lnc, Int_t mxp, Double_t *plist, Int_t &llist, Int_t &ierr, Int_t isyswr)
Cracks the free-format input.
Definition: TMinuit.cxx:1686
Double_t fBigedm
Definition: TMinuit.h:61
Int_t fIstkwr[10]
Definition: TMinuit.h:139
virtual void mnrn15(Double_t &val, Int_t &inseed)
This is a super-portable random number generator.
Definition: TMinuit.cxx:6626
Double_t * fSIMPy
Definition: TMinuit.h:119
static constexpr double eplus
virtual TObject * Contour(Int_t npoints=10, Int_t pa1=0, Int_t pa2=1)
Creates a TGraph object describing the n-sigma contour of a TMinuit fit.
Definition: TMinuit.cxx:662
Double_t Log10(Double_t x)
Definition: TMath.h:763
virtual Int_t GetNumFreePars() const
returns the number of currently free parameters
Definition: TMinuit.cxx:872
virtual ~TMinuit()
Minuit default destructor.
Definition: TMinuit.cxx:506
static const double x4[22]
Int_t fMaxpar5
Definition: TMinuit.h:44
virtual void DeleteArrays()
Delete internal Minuit arrays.
Definition: TMinuit.cxx:717
virtual void mncuve()
Makes sure that the current point is a local minimum.
Definition: TMinuit.cxx:2139
Double_t fAmin
Definition: TMinuit.h:49
Double_t * fGrd
Definition: TMinuit.h:81
Int_t fNfcnfr
Definition: TMinuit.h:148
Double_t * fAlim
Definition: TMinuit.h:69
XFontStruct * id
Definition: TGX11.cxx:108
virtual void BuildArrays(Int_t maxpar=15)
Create internal Minuit arrays for the maxpar parameters.
Definition: TMinuit.cxx:521
Method or function calling interface.
Definition: TMethodCall.h:37
Double_t * fPARSplist
Definition: TMinuit.h:124
Double_t fYdircr
Definition: TMinuit.h:66
TObject * fObjectFit
Definition: TMinuit.h:175
Double_t * fGsteps
Definition: TMinuit.h:88
Int_t * fNvarl
Definition: TMinuit.h:126
virtual void mnmnot(Int_t ilax, Int_t ilax2, Double_t &val2pl, Double_t &val2mi)
Performs a MINOS error analysis on one parameter.
Definition: TMinuit.cxx:5474
Int_t fNstkrd
Definition: TMinuit.h:138
Int_t fMaxpar1
Definition: TMinuit.h:47
Double_t * fPbar
Definition: TMinuit.h:94
virtual void mnpout(Int_t iuext, TString &chnam, Double_t &val, Double_t &err, Double_t &xlolim, Double_t &xuplim, Int_t &iuint) const
Provides the user with information concerning the current status.
Definition: TMinuit.cxx:6256
Double_t fYmidcr
Definition: TMinuit.h:64
Double_t * fSEEKxmid
Definition: TMinuit.h:117
TString fCfrom
Definition: TMinuit.h:166
Int_t fNewpag
Definition: TMinuit.h:136
virtual Int_t DefineParameter(Int_t parNo, const char *name, Double_t initVal, Double_t initErr, Double_t lowerLimit, Double_t upperLimit)
Define a parameter.
Definition: TMinuit.cxx:704
double gamma(double x)
virtual void mncont(Int_t ke1, Int_t ke2, Int_t nptu, Double_t *xptu, Double_t *yptu, Int_t &ierrf)
Find points along a contour where FCN is minimum.
Definition: TMinuit.cxx:1404
float ymax
Definition: THbookFile.cxx:93
Int_t fNfcnmx
Definition: TMinuit.h:146
Double_t * fVERTpp
Definition: TMinuit.h:122
TString fCundef
Definition: TMinuit.h:170
TPaveText * pt
Int_t fNpfix
Definition: TMinuit.h:37
ROOT::R::TRInterface & r
Definition: Object.C:4
TString * fCpnam
Character to be plotted at the X,Y contour positions.
Definition: TMinuit.h:165
Double_t * fG2
Definition: TMinuit.h:82
Double_t fEpsi
Definition: TMinuit.h:53
XPoint xy[kMAXMK]
Definition: TGX11.cxx:122
Double_t * fSEEKxbest
Definition: TMinuit.h:118
Int_t fMaxpar2
Definition: TMinuit.h:46
virtual void mncler()
Resets the parameter list to UNDEFINED.
Definition: TMinuit.cxx:1112
virtual void mnparm(Int_t k, TString cnamj, Double_t uk, Double_t wk, Double_t a, Double_t b, Int_t &ierflg)
Implements one parameter definition.
Definition: TMinuit.cxx:5674
auto * a
Definition: textangle.C:12
virtual void mnfixp(Int_t iint, Int_t &ierr)
Removes parameter IINT from the internal parameter list.
Definition: TMinuit.cxx:3178
Double_t fXmidcr
Definition: TMinuit.h:63
Long_t ExecPlugin(int nargs, const T &... params)
Int_t fStatus
Definition: TMinuit.h:154
virtual void mncalf(Double_t *pvec, Double_t &ycalf)
Transform FCN to find further minima.
Definition: TMinuit.cxx:1079
Double_t * fWerr
Definition: TMinuit.h:73
Double_t * fMIGRgs
Definition: TMinuit.h:110
char * fChpt
Definition: TMinuit.h:164
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2264
Bool_t fLnolim
Definition: TMinuit.h:160
Double_t * fDirins
Definition: TMinuit.h:80
Double_t * fIMPRdsav
Definition: TMinuit.h:105
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
char * Form(const char *fmt,...)
Double_t * fPstst
Definition: TMinuit.h:93
virtual Int_t SetErrorDef(Double_t up)
To get the n-sigma contour the error def parameter "up" has to set to n^2.
Definition: TMinuit.cxx:917
Ssiz_t Length() const
Definition: TString.h:405
Bool_t fLrepor
Definition: TMinuit.h:158
Double_t * fIMPRy
Definition: TMinuit.h:106
Double_t fApsi
Definition: TMinuit.h:54
#define s1(x)
Definition: RSha256.hxx:91
Double_t * fXt
Definition: TMinuit.h:76
float xmax
Definition: THbookFile.cxx:93
TMethodCall * fMethodCall
Definition: TMinuit.h:177
Double_t fUpdflt
Definition: TMinuit.h:62
Double_t * fVERTs
Definition: TMinuit.h:121
virtual void mnerrs(Int_t number, Double_t &eplus, Double_t &eminus, Double_t &eparab, Double_t &gcc)
Utility routine to get MINOS errors.
Definition: TMinuit.cxx:2587
virtual void mnhess()
Calculates the full second-derivative matrix of FCN.
Definition: TMinuit.cxx:4002
static constexpr double nm
Double_t fFval3
Definition: TMinuit.h:52
Double_t * fGstep
Definition: TMinuit.h:83
Int_t fIsyssa
Definition: TMinuit.h:133
Double_t * fMIGRflnu
Definition: TMinuit.h:108
TGraphErrors * gr
Definition: legend1.C:25
#define h(i)
Definition: RSha256.hxx:106
Bool_t fGraphicsMode
Definition: TMinuit.h:163
#define Printf
Definition: TGeoToOCC.h:18
Bool_t fLwarn
Definition: TMinuit.h:157
Double_t * fErp
Definition: TMinuit.h:71
Double_t Cos(Double_t)
Definition: TMath.h:640
Int_t * fNiofex
Definition: TMinuit.h:127
const Bool_t kFALSE
Definition: RtypesCore.h:88
virtual void mnpsdf()
Calculates the eigenvalues of v to see if positive-def.
Definition: TMinuit.cxx:6503
virtual void mndxdi(Double_t pint, Int_t ipar, Double_t &dxdi)
Calculates the transformation factor between ext/internal values.
Definition: TMinuit.cxx:2302
long Long_t
Definition: RtypesCore.h:50
Int_t fNpagln
Definition: TMinuit.h:135
Double_t * fMIGRxxs
Definition: TMinuit.h:112
#define d(i)
Definition: RSha256.hxx:102
Double_t fEDM
Definition: TMinuit.h:51
Double_t * fCONTgcc
Definition: TMinuit.h:100
Double_t * fFIXPyy
Definition: TMinuit.h:102
virtual void mnamin()
Initialize AMIN.
Definition: TMinuit.cxx:981
Int_t fNfcn
Definition: TMinuit.h:145
static const double x1[5]
#define ClassImp(name)
Definition: Rtypes.h:359
Double_t * fMNOTgcc
Definition: TMinuit.h:115
Double_t * fCONTw
Definition: TMinuit.h:101
virtual void mnscan()
Scans the values of FCN as a function of one parameter.
Definition: TMinuit.cxx:6715
TString fWarmes[kMAXWARN]
Definition: TMinuit.h:174
double Double_t
Definition: RtypesCore.h:55
virtual void mnhelp(TString comd)
HELP routine for MINUIT interactive commands.
Definition: TMinuit.cxx:3448
void InteractiveFCNm(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag)
Static function called when SetFCN is called in interactive mode.
Definition: TMinuit.cxx:937
virtual Int_t Release(Int_t parNo)
release a parameter
Definition: TMinuit.cxx:903
Int_t fNfcwar[20]
Definition: TMinuit.h:152
Double_t * fG2s
Definition: TMinuit.h:87
Double_t y[n]
Definition: legend1.C:17
Bool_t fLimset
Definition: TMinuit.h:159
TMethodCall * GetMethodCall() const
Definition: TMinuit.h:193
virtual void mnpfit(Double_t *parx2p, Double_t *pary2p, Int_t npar2p, Double_t *coef2p, Double_t &sdev2p)
To fit a parabola to npar2p points.
Definition: TMinuit.cxx:5965
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
Double_t * fU
Definition: TMinuit.h:68
static constexpr double s
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
virtual void mnlims()
Interprets the SET LIM command, to reset the parameter limits.
Definition: TMinuit.cxx:4625
virtual void mnexcm(const char *comand, Double_t *plist, Int_t llist, Int_t &ierflg)
Interprets a command and takes appropriate action.
Definition: TMinuit.cxx:2673
#define R__LOCKGUARD(mutex)
virtual void mncntr(Int_t ke1, Int_t ke2, Int_t &ierrf)
Print function contours in two variables, on line printer.
Definition: TMinuit.cxx:1141
Int_t fMaxcpt
Definition: TMinuit.h:45
virtual void SetMaxIterations(Int_t maxiter=500)
Definition: TMinuit.h:264
virtual void mncomd(const char *crdbin, Int_t &icondn)
Reads a command string and executes.
Definition: TMinuit.cxx:1319
Double_t * fGin
Definition: TMinuit.h:84
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TNamed.cxx:74
virtual Int_t Command(const char *command)
Execute a Minuit command.
Definition: TMinuit.cxx:635
virtual void mninit(Int_t i1, Int_t i2, Int_t i3)
Main initialization member function for MINUIT.
Definition: TMinuit.cxx:4535
Mother of all ROOT objects.
Definition: TObject.h:37
Double_t * fMIGRstep
Definition: TMinuit.h:109
virtual Int_t Migrad()
invokes the MIGRAD minimizer
Definition: TMinuit.cxx:889
Int_t fIcomnd
Definition: TMinuit.h:144
virtual void mnpars(TString &crdbuf, Int_t &icondn)
Implements one parameter definition.
Definition: TMinuit.cxx:5876
Double_t * fVthmat
Definition: TMinuit.h:90
virtual void mnplot(Double_t *xpt, Double_t *ypt, char *chpt, Int_t nxypt, Int_t npagwd, Int_t npagln)
Plots points in array xypt onto one page with labelled axes.
Definition: TMinuit.cxx:6077
virtual void mnpint(Double_t &pexti, Int_t i, Double_t &pinti)
Calculates the internal parameter value PINTI.
Definition: TMinuit.cxx:6026
virtual void mnsave()
Writes current parameter values and step sizes onto file ISYSSA.
Definition: TMinuit.cxx:6702
virtual void mninex(Double_t *pint)
Transforms from internal coordinates (PINT) to external (U)
Definition: TMinuit.cxx:4515
Double_t * fPSDFs
Definition: TMinuit.h:116
auto * l
Definition: textangle.C:4
static const char charal[29]
Definition: TMinuit.cxx:348
void Execute(const char *, const char *, int *=0)
Execute method on this object with the given parameter string, e.g.
Definition: TMethodCall.h:64
Double_t * fMIGRvg
Definition: TMinuit.h:111
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:200
Double_t fVlimlo
Definition: TMinuit.h:58
Double_t Sin(Double_t)
Definition: TMath.h:636
TF1 * f1
Definition: legend1.C:11
Double_t fEpsma2
Definition: TMinuit.h:57
TMinuit * gMinuit
Definition: TMinuit.cxx:346
virtual void mnmatu(Int_t kode)
Prints the covariance matrix v when KODE=1.
Definition: TMinuit.cxx:4979
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
virtual void mnset()
Interprets the commands that start with SET and SHOW.
Definition: TMinuit.cxx:6920
Double_t ASin(Double_t)
Definition: TMath.h:660
Double_t fUp
Definition: TMinuit.h:50
Int_t fEmpty
Definition: TMinuit.h:38
Double_t fXdircr
Definition: TMinuit.h:65
#define c(i)
Definition: RSha256.hxx:101
int * iq
Definition: THbookFile.cxx:86
Bool_t mnunpt(TString &cfname)
Returns .TRUE.
Definition: TMinuit.cxx:7677
Int_t fMaxpar
Definition: TMinuit.h:39
virtual void mnrazz(Double_t ynew, Double_t *pnew, Double_t *y, Int_t &jh, Int_t &jl)
Called only by MNSIMP (and MNIMPR) to add a new point.
Definition: TMinuit.cxx:6577
virtual void SetFCN(void(*fcn)(Int_t &, Double_t *, Double_t &f, Double_t *, Int_t))
To set the address of the minimization function.
Definition: TMinuit.cxx:929
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TMinuit.cxx:605
Double_t Sqrt(Double_t x)
Definition: TMath.h:690
virtual Int_t GetNumPars() const
returns the total number of parameters that have been defined as fixed or free.
Definition: TMinuit.cxx:881
Double_t * fDgrd
Definition: TMinuit.h:85
Bool_t fLphead
Definition: TMinuit.h:162
TString fCvrsn
Definition: TMinuit.h:171
const Bool_t kTRUE
Definition: RtypesCore.h:87
Int_t fIsysrd
Definition: TMinuit.h:131
Int_t fNu
Definition: TMinuit.h:130
Double_t * fHESSyy
Definition: TMinuit.h:104
static constexpr double ns
const Int_t n
Definition: legend1.C:16
Int_t fNwrmes[2]
Definition: TMinuit.h:151
Double_t fVlimhi
Definition: TMinuit.h:59
char name[80]
Definition: TGX11.cxx:109
TString fCovmes[4]
Definition: TMinuit.h:172
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
virtual void mnimpr()
Attempts to improve on a good local minimum.
Definition: TMinuit.cxx:4304
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
Definition: TString.cxx:1070
Int_t fISW[7]
Definition: TMinuit.h:141
static const double x3[11]
const char * Data() const
Definition: TString.h:364
Double_t ATan(Double_t)
Definition: TMath.h:674
virtual void mnwerr()
Calculates the WERR, external parameter errors.
Definition: TMinuit.cxx:7868