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