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