1 // @(#)root/minuit2:$Id$
2 // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei   2003-2005
3 
4 /**********************************************************************
5  *                                                                    *
6  * Copyright (c) 2005 LCG ROOT Math team,  CERN/PH-SFT                *
7  *                                                                    *
8  **********************************************************************/
9 
10 #ifndef ROOT_Minuit2_MnPrint
11 #define ROOT_Minuit2_MnPrint
12 
13 #include "Minuit2/MnConfig.h"
14 
15 #include <sstream>
16 #include <utility>
17 #include <cassert>
18 #include <string>
19 #include <ios>
20 
21 namespace ROOT {
22 namespace Minuit2 {
23 
24 /**
25     define std::ostream operators for output
26 */
27 
28 class FunctionMinimum;
29 std::ostream &operator<<(std::ostream &, const FunctionMinimum &);
30 
31 class MinimumState;
32 std::ostream &operator<<(std::ostream &, const MinimumState &);
33 
34 class LAVector;
35 std::ostream &operator<<(std::ostream &, const LAVector &);
36 
37 class LASymMatrix;
38 std::ostream &operator<<(std::ostream &, const LASymMatrix &);
39 
40 class MnUserParameters;
41 std::ostream &operator<<(std::ostream &, const MnUserParameters &);
42 
43 class MnUserCovariance;
44 std::ostream &operator<<(std::ostream &, const MnUserCovariance &);
45 
46 class MnGlobalCorrelationCoeff;
47 std::ostream &operator<<(std::ostream &, const MnGlobalCorrelationCoeff &);
48 
49 class MnUserParameterState;
50 std::ostream &operator<<(std::ostream &, const MnUserParameterState &);
51 
52 class MnMachinePrecision;
53 std::ostream &operator<<(std::ostream &, const MnMachinePrecision &);
54 
55 class MinosError;
56 std::ostream &operator<<(std::ostream &, const MinosError &);
57 
58 class ContoursError;
59 std::ostream &operator<<(std::ostream &, const ContoursError &);
60 
61 // std::pair<double, double> is used by MnContour
62 std::ostream &operator<<(std::ostream &os, const std::pair<double, double> &point);
63 
64 /* Design notes: 1) We want to delay the costly conversion from object references to
65    strings to a point after we have decided whether or not to
66    show that string to the user at all. 2) We want to offer a customization point for
67    external libraries that want to replace the MnPrint logging. The actual
68    implementation is in a separate file, MnPrintImpl.cxx file that external libraries
69    can replace with their own implementation.
70 */
71 
72 // logging class for messages of varying severity
73 class MnPrint {
74 public:
75    // want this to be an enum class for strong typing...
76    enum class Verbosity { Error = 0, Warn = 1, Info = 2, Debug = 3 };
77 
78    // ...but also want the values accessible from MnPrint scope for convenience
79    static constexpr auto eError = Verbosity::Error;
80    static constexpr auto eWarn = Verbosity::Warn;
81    static constexpr auto eInfo = Verbosity::Info;
82    static constexpr auto eDebug = Verbosity::Debug;
83 
84    // used for one-line printing of fcn minimum state
85    class Oneline {
86    public:
87       Oneline(double fcn, double edm, int ncalls, int iter = -1);
88       Oneline(const MinimumState &state, int iter = -1);
89       Oneline(const FunctionMinimum &fmin, int iter = -1);
90 
91    private:
92       double fFcn, fEdm;
93       int fNcalls, fIter;
94 
95       friend std::ostream &operator<<(std::ostream &os, const Oneline &x);
96    };
97 
98    MnPrint(const char *prefix, int level = MnPrint::GlobalLevel());
99    ~MnPrint();
100 
101    // set global print level and return the previous one
102    static int SetGlobalLevel(int level);
103 
104    // return current global print level
105    static int GlobalLevel();
106 
107    // Whether to show the full prefix stack or only the end
108    static void ShowPrefixStack(bool yes);
109 
110    static void AddFilter(const char *prefix);
111    static void ClearFilter();
112 
113    // set print level and return the previous one
114    int SetLevel(int level);
115 
116    // return current print level
117    int Level() const;
118 
119    template <class... Ts>
Error(const Ts &...args)120    void Error(const Ts &... args)
121    {
122       Log(eError, args...);
123    }
124 
125    template <class... Ts>
Warn(const Ts &...args)126    void Warn(const Ts &... args)
127    {
128       Log(eWarn, args...);
129    }
130 
131    template <class... Ts>
Info(const Ts &...args)132    void Info(const Ts &... args)
133    {
134       Log(eInfo, args...);
135    }
136 
137    template <class... Ts>
Debug(const Ts &...args)138    void Debug(const Ts &... args)
139    {
140       Log(eDebug, args...);
141    }
142 
143 private:
144    // low level logging
145    template <class... Ts>
Log(Verbosity level,const Ts &...args)146    void Log(Verbosity level, const Ts &... args)
147    {
148       if (Level() < static_cast<int>(level))
149          return;
150       if (Hidden())
151          return;
152 
153       std::ostringstream os;
154       StreamPrefix(os);
155       StreamArgs(os, args...);
156       Impl(level, os.str());
157    }
158 
159    static void StreamPrefix(std::ostringstream &os);
160 
161    // returns true if filters are installed and message is not selected by any filter
162    static bool Hidden();
163 
164    // see MnPrintImpl.cxx
165    static void Impl(Verbosity level, const std::string &s);
166 
167    // TMP to handle lambda argument correctly, exploiting overload resolution rules
168    template <class T>
169    static auto HandleLambda(std::ostream &os, const T &t, int) -> decltype(t(os), void())
170    {
171       t(os);
172    }
173 
174    template <class T>
HandleLambda(std::ostream & os,const T & t,float)175    static void HandleLambda(std::ostream &os, const T &t, float)
176    {
177       os << t;
178    }
179 
StreamArgs(std::ostringstream &)180    static void StreamArgs(std::ostringstream &) {}
181 
182    // end of recursion
183    template <class T>
StreamArgs(std::ostringstream & os,const T & t)184    static void StreamArgs(std::ostringstream &os, const T &t)
185    {
186       os << " ";
187       HandleLambda(os, t, 0);
188    }
189 
190    template <class T, class... Ts>
StreamArgs(std::ostringstream & os,const T & t,const Ts &...ts)191    static void StreamArgs(std::ostringstream &os, const T &t, const Ts &... ts)
192    {
193       os << " " << t;
194       StreamArgs(os, ts...);
195    }
196 
197    int fLevel;
198 };
199 
200 } // namespace Minuit2
201 } // namespace ROOT
202 
203 #endif // ROOT_Minuit2_MnPrint
204