1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the class library                   */
4    	/*       SoPlex --- the Sequential object-oriented simPlex.                  */
5    	/*                                                                           */
6    	/*  Copyright (c) 1996-2023 Zuse Institute Berlin (ZIB)                      */
7    	/*                                                                           */
8    	/*  Licensed under the Apache License, Version 2.0 (the "License");          */
9    	/*  you may not use this file except in compliance with the License.         */
10   	/*  You may obtain a copy of the License at                                  */
11   	/*                                                                           */
12   	/*      http://www.apache.org/licenses/LICENSE-2.0                           */
13   	/*                                                                           */
14   	/*  Unless required by applicable law or agreed to in writing, software      */
15   	/*  distributed under the License is distributed on an "AS IS" BASIS,        */
16   	/*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17   	/*  See the License for the specific language governing permissions and      */
18   	/*  limitations under the License.                                           */
19   	/*                                                                           */
20   	/*  You should have received a copy of the Apache-2.0 license                */
21   	/*  along with SoPlex; see the file LICENSE. If not email to soplex@zib.de.  */
22   	/*                                                                           */
23   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24   	
25   	/**@file  spxout.h
26   	 * @brief Wrapper for different output streams and verbosity levels.
27   	 */
28   	#ifndef _SPXOUT_H_
29   	#define _SPXOUT_H_
30   	
31   	#include <iostream>
32   	#include <iomanip>
33   	#include <assert.h>
34   	#include "soplex/fmt.hpp"
35   	
36   	#include "soplex/spxdefines.h"
37   	
38   	// ----------------------------------------------------------------------
39   	//    class SPxOut
40   	// ----------------------------------------------------------------------
41   	
42   	namespace soplex
43   	{
44   	
45   	struct EnableDebugOutput
46   	{
47   	};
48   	
49   	/**@class SPxOut
50   	   @ingroup Elementary
51   	
52   	   @brief Wrapper for several output streams.
53   	   A verbosity level is used to decide which stream to use and whether to
54   	   really print a given message. Regardless of whether the verbosity level
55   	   is set via a manipulator or via the member function, it is persistent
56   	   until a new value is set.
57   	
58   	   Most ostream member functions are not provided here; use the corresponding
59   	   stream manipulators (e.g., @c setprecision()) instead. These are passed on
60   	   to the <em>current</em> ostream, which is chosen according to the verbosity
61   	   level. In particular, this means that the first element in an output stream
62   	   should always be the verbosity. For instance, use
63   	   @code
64   	      spxout << verb( SPxOut::WARNING ) << std::setw( 15 ) << 42 << std::endl;
65   	   @endcode
66   	   or
67   	   @code
68   	      spxout.setVerbosity( SPxOut::WARNING );
69   	      spxout << std::setw( 15 ) << 42 << std::endl;
70   	   @endcode
71   	   instead of
72   	   @code
73   	      spxout << std::setw( 15 ) << verb( SPxOut::WARNING ) << 42 << std::endl;
74   	   @endcode
75   	   in order to make sure that @c std::setw( 15 ) is applied to the warning stream.
76   	*/
77   	class SPxOut
78   	{
79   	public:
80   	
81   	
82   	   //-----------------------------------
83   	   /**@name Output control types */
84   	   ///@{
85   	   /// Verbosity level
86   	   typedef enum
87   	   {
88   	      // Note: the implementation uses the fact that ERROR == 0
89   	      // and that the verbosity levels are subsequent numbers.
90   	      // If you change this, change the implementation as well.
91   	      ERROR    = 0,
92   	      WARNING  = 1,
93   	      DEBUG    = 2,
94   	      INFO1    = 3,
95   	      INFO2    = 4,
96   	      INFO3    = 5
97   	   } Verbosity;
98   	
99   	   /// helper struct for the output operator
100  	   struct struct_Verbosity
101  	   {
102  	      /// verbosity level
103  	      Verbosity v_;
104  	   };
105  	   ///@}
106  	
107  	   //-----------------------------------
108  	   /**@name Construction / destruction */
109  	   ///@{
110  	   /// constructor
111  	   SPxOut();
112  	   /// destructor
113  	   virtual ~SPxOut();
114  	   /// copy constructor
115  	   SPxOut(const SPxOut&);
116  	   /// assignment operator
117  	   SPxOut& operator=(const SPxOut&);
118  	   ///@}
119  	
120  	   //-----------------------------------
121  	   /**@name Verbosity */
122  	   ///@{
123  	   ///
124  	   virtual void
125  	   setVerbosity(const Verbosity& v)
126  	   {
127  	      m_verbosity = v;
128  	   }
129  	   ///
130  	   inline Verbosity
131  	   getVerbosity()
132  	   const
133  	   {
134  	      return m_verbosity;
135  	   }
136  	
137  	   ///@}
138  	
139  	   //----------------------------------------
140  	   /**@name Wrappers for the current stream */
141  	   ///@{
142  	   ///
143  	   inline bool good() const
144  	   {
145  	      return getCurrentStream().good();
146  	   }
147  	   ///
148  	   inline bool operator !() const
149  	   {
150  	      return ! getCurrentStream();
151  	   }
152  	   ///
153  	   inline std::streamsize precision() const
154  	   {
155  	      return getCurrentStream().precision();
156  	   }
157  	   ///@}
158  	
159  	   //-----------------------------------
160  	   /**@name Getting / setting streams */
161  	   ///@{
162  	   /// Sets the stream for the specified verbosity level.
163  	   virtual void
164  	   setStream(const Verbosity& verbosity,
165  	             std::ostream&   stream)
166  	   {
167  	      m_streams[ verbosity ] = &stream;
168  	   }
169  	   /// Returns the stream for the specified verbosity level.
170  	   inline std::ostream&
171  	   getStream(const Verbosity& verbosity)
172  	   const
173  	   {
174  	      return *(m_streams[ verbosity ]);
175  	   }
176  	   /// Returns the stream for the current verbosity.
177  	   inline std::ostream&
178  	   getCurrentStream()
179  	   const
180  	   {
181  	      return getStream(getVerbosity());
182  	   }
183  	
184  	   /// Sets the precision of the stream to 16 and the floatfield to scientifix.
185  	   static inline void setScientific(std::ostream& stream, int precision = 8)
186  	   {
187  	      stream << std::setprecision(precision) << std::scientific;
188  	   }
189  	
190  	   /// Sets the precision of the stream to 8 and the floatfield to fixed.
191  	   static inline void setFixed(std::ostream& stream, int precision = 8)
192  	   {
193  	      stream << std::setprecision(precision) << std::fixed;
194  	   }
195  	
196  	   // select with SFINAE to print debug output or depending on whether the class
197  	   // type of the pointer inherits from the marker struct EnableDebugOutput
198  	
199  	   template < typename T, typename... Args,
200  	              typename std::enable_if <
201  	                 !std::is_base_of<EnableDebugOutput, T>::value, int >::type = 0 >
202  	   static void
203  	   debug(const T*, Args && ... args)
204  	   {
205  	   }
206  	
207  	   template <typename T, typename... Args,
208  	             typename std::enable_if<
209  	                std::is_base_of<EnableDebugOutput, T>::value, int>::type = 0>
210  	   static void
211  	   debug(const T*, Args && ... args)
212  	   {
213  	      fmt::print(std::forward<Args>(args)...);
214  	   }
215  	   ///@}
216  	
217  	private:
218  	
219  	   //-----------------------------------
220  	   /**@name Private data */
221  	   ///@{
222  	   /// verbosity level
223  	   Verbosity               m_verbosity;
224  	   /// array of pointers to internal streams, indexed by verbosity level
225  	   std::ostream**          m_streams;
226  	   ///@}
227  	};
228  	
229  	// ---------------------------------------------------------
230  	//    Manipulators
231  	// ---------------------------------------------------------
232  	
233  	
234  	//-------------------------------------------
235  	/**@name Verbosity manipulator
236  	    Manipulators are implemented in a similar way as done for @c setw(),
237  	    @c setprecision(), etc. in the standard library file iomanip. For
238  	    instance, the non-member function \ref verb() "verb(v)" returns a
239  	    struct struct_Severity which contains only the verbosity level.
240  	    Calling
241  	    @code
242  	         SPxOut spxout;
243  	         spxout << verb( SPxOut::ERROR ) << "This is an error!" << std::endl;
244  	    @endcode
245  	    passes such a struct to the output operator defined below, which
246  	    extracts the verbosity level from the struct and passes it to the
247  	    member function SPxOut::setVerbosity().
248  	*/
249  	//@{
250  	/// manipulator to be used in an output statement
251  	inline SPxOut::struct_Verbosity
252  	verb(const SPxOut::Verbosity&  v)
253  	{
254  	   SPxOut::struct_Verbosity verbosity;
255  	   verbosity.v_ = v;
256  	   return verbosity;
257  	}
258  	
259  	/// output operator with verbosity level struct
260  	inline SPxOut&
261  	operator<< (SPxOut& stream,
262  	            const SPxOut::struct_Verbosity&  verbosity)
263  	{
264  	   stream.setVerbosity(verbosity.v_);
265  	   return stream;
266  	}
267  	///@}
268  	
269  	//--------------------------------------------------------
270  	/**@name Output of standard manipulators and other types
271  	 *
272  	 * We have to define an output operator for many kinds of numeric
273  	 * types here because they can all be more or less casted into each
274  	 * other. When using only a template type, it is not clear what the
275  	 * compiler makes out of it (according to lint).
276  	 */
277  	//@{
278  	///
279  	/// Passes instances of type \p Type to the current stream.
280  	inline SPxOut& operator<< (SPxOut& _spxout, long t)
281  	{
282  	   _spxout.getCurrentStream() << t;
283  	   return _spxout;
284  	}
285  	
286  	inline SPxOut& operator<< (SPxOut& _spxout, unsigned long t)
287  	{
288  	   _spxout.getCurrentStream() << t;
289  	   return _spxout;
290  	}
291  	
292  	inline SPxOut& operator<< (SPxOut& _spxout, bool t)
293  	{
294  	   _spxout.getCurrentStream() << t;
295  	   return _spxout;
296  	}
297  	
298  	inline SPxOut& operator<< (SPxOut& _spxout, short t)
299  	{
300  	   _spxout.getCurrentStream() << t;
301  	   return _spxout;
302  	}
303  	
304  	inline SPxOut& operator<< (SPxOut& _spxout, unsigned short t)
305  	{
306  	   _spxout.getCurrentStream() << t;
307  	   return _spxout;
308  	}
309  	
310  	inline SPxOut& operator<< (SPxOut& _spxout, int t)
311  	{
312  	   _spxout.getCurrentStream() << t;
313  	   return _spxout;
314  	}
315  	
316  	inline SPxOut& operator<< (SPxOut& _spxout, unsigned int t)
317  	{
318  	   _spxout.getCurrentStream() << t;
319  	   return _spxout;
320  	}
321  	
322  	inline SPxOut& operator<< (SPxOut& _spxout, double t)
323  	{
324  	   _spxout.getCurrentStream() << t;
325  	   return _spxout;
326  	}
327  	
328  	inline SPxOut& operator<< (SPxOut& _spxout, float t)
329  	{
330  	   _spxout.getCurrentStream() << t;
331  	   return _spxout;
332  	}
333  	
334  	inline SPxOut& operator<< (SPxOut& _spxout, long double t)
335  	{
336  	   _spxout.getCurrentStream() << t;
337  	   return _spxout;
338  	}
339  	
340  	inline SPxOut& operator<< (SPxOut& _spxout, const void* t)
341  	{
342  	   _spxout.getCurrentStream() << t;
343  	   return _spxout;
344  	}
345  	
346  	/// Passes standard manipulators without arguments, like @c std::endl
347  	/// or @c std::ios::right to the current stream.
348  	inline SPxOut&
349  	operator<< (SPxOut&       _spxout,
350  	            std::ostream & (*manip)(std::ostream&))
351  	{
352  	   _spxout.getCurrentStream() << manip;
353  	   return _spxout;
354  	}
355  	
356  	//lint -e{818} (pointer could be made const; this is ok.)
357  	/// Passes everything else to the current stream. In particular,
358  	/// this includes structs corresponding to manipulators with arguments,
359  	/// such as the struct @c _Setw for the @c setw() manipulator.
360  	template <typename T>
361  	inline SPxOut& operator<< (SPxOut& _spxout, T  t)
362  	{
363  	   _spxout.getCurrentStream() << t;
364  	   return _spxout;
365  	}
366  	
367  	//@}
368  	
369  	}  // namespace soplex
370  	
371  	#endif // _SPXOUT_H_
372