1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the class library                   */
4    	/*       SoPlex --- the Sequential object-oriented simPlex.                  */
5    	/*                                                                           */
6    	/*    Copyright (C) 1996-2022 Konrad-Zuse-Zentrum                            */
7    	/*                            fuer Informationstechnik Berlin                */
8    	/*                                                                           */
9    	/*  SoPlex is distributed under the terms of the ZIB Academic Licence.       */
10   	/*                                                                           */
11   	/*  You should have received a copy of the ZIB Academic License              */
12   	/*  along with SoPlex; see the file COPYING. If not email to soplex@zib.de.  */
13   	/*                                                                           */
14   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15   	
16   	/**@file  spxdefines.h
17   	 * @brief Debugging, floating point type and parameter definitions.
18   	 *
19   	 * In optimized code with \c NDEBUG defined, only
20   	 * \ref soplex::SPxOut::INFO1 "INFO1",
21   	 * \ref soplex::SPxOut::INFO2 "INFO2", and
22   	 * \ref soplex::SPxOut::INFO3 "INFO3" are set.
23   	 * If \c NDEBUG is not defined, the code within \#TRACE is used.
24   	 * If \c SOPLEX_DEBUG is defined, the code within
25   	 * \ref soplex::SPxOut::DEBUG "DEBUG" is also used.
26   	 *
27   	 * If \c WITH_LONG_DOUBLE is defined, all Real numbers are of type
28   	 * long double instead of just double.
29   	 */
30   	#ifndef _SPXDEFINES_H_
31   	#define _SPXDEFINES_H_
32   	#include <cmath>
33   	
34   	#ifdef _MSC_VER
35   	#include <float.h>
36   	#endif
37   	
38   	#include <assert.h>
39   	#include <stdarg.h>
40   	#include <stdio.h>
41   	#include <iostream>
42   	
43   	#include <cstdlib>
44   	
45   	/*
46   	 * include build configuration flags
47   	 */
48   	#ifndef SOPLEX_NO_CONFIG_HEADER
49   	#include "soplex/config.h"
50   	#endif
51   	
52   	#ifdef SOPLEX_WITH_BOOST
53   	#include "boost/multiprecision/number.hpp"
54   	#ifdef SOPLEX_WITH_FLOAT128
55   	#include <boost/multiprecision/float128.hpp>
56   	#endif
57   	
58   	#ifdef SOPLEX_WITH_MPFR
59   	// For multiple precision
60   	#include <boost/multiprecision/mpfr.hpp>
61   	#ifndef NDEBUG
62   	#include "boost/multiprecision/debug_adaptor.hpp" // For debuging mpf numbers
63   	#endif // NDEBUG
64   	#endif // SOPLEX_WITH_MPFR
65   	#ifdef SOPLEX_WITH_CPPMPF
66   	#include <boost/multiprecision/cpp_dec_float.hpp>
67   	#endif  // SOPLEX_WITH_CPPMPF
68   	
69   	#ifdef SOPLEX_WITH_GMP
70   	#include <boost/multiprecision/gmp.hpp>
71   	#else
72   	#include <boost/multiprecision/cpp_int.hpp>
73   	using mpq_t = double;
74   	#endif
75   	
76   	#endif
77   	
78   	namespace soplex
79   	{
80   	// Overloaded EQ function
81   	bool EQ(int a, int b);
82   	
83   	#define SOPLEX_VERSION         601
84   	#define SOPLEX_SUBVERSION        0
85   	#define SOPLEX_APIVERSION       13
86   	#define SOPLEX_COPYRIGHT       "Copyright (c) 1996-2022 Konrad-Zuse-Zentrum fuer Informationstechnik Berlin (ZIB)"
87   	
88   	/*-----------------------------------------------------------------------------
89   	 * Assertion Macros etc.
90   	 *-----------------------------------------------------------------------------
91   	 */
92   	
93   	/**
94   	   \brief Macro to turn some assertions into warnings.
95   	
96   	   If both \c NDEBUG and \c WITH_WARNINGS are defined then the failed
97   	   assertion is converted to a warning. In all other cases this macro is
98   	   equivalent to assert().
99   	
100  	   @param  prefix  Short string for grepping in source code.
101  	   @param  expr    Expression that must be satisfied.
102  	*/
103  	#if defined (NDEBUG) && defined (WITH_WARNINGS)
104  	#define ASSERT_WARN( prefix, expr )                        \
105  	   if ( !( expr ) )                                        \
106  	      {                                                    \
107  	         std::cerr                                         \
108  	         << prefix                                         \
109  	         << " failed assertion on line " << __LINE__       \
110  	         << " in file " << __FILE__ << ": "                \
111  	         << #expr                                          \
112  	         << std::endl;                                     \
113  	      }
114  	#else // just a normal assert
115  	#define ASSERT_WARN( prefix, expr ) ( assert( expr ) )
116  	#endif
117  	
118  	
119  	
120  	/*-----------------------------------------------------------------------------
121  	 * Debugging Macros etc.
122  	 *-----------------------------------------------------------------------------
123  	 */
124  	
125  	/**
126  	   Prints/Executes \p stream with verbosity level \p verbosity, resetting
127  	   the old verbosity level afterwards.
128  	   Usually the parameter \p stream prints something out.
129  	   This is an internal define used by MSG_ERROR, MSG_WARNING, etc.
130  	*/
131  	#ifdef DISABLE_VERBOSITY
132  	#define DO_WITH_TMP_VERBOSITY( verbosity, spxout, do_something ) {}
133  	#define DO_WITH_ERR_VERBOSITY( do_something ) {}
134  	#else
135  	#define DO_WITH_TMP_VERBOSITY( verbosity, spxout, do_something ) \
136  	   {                                                             \
137  	     if( &spxout != NULL )                                       \
138  	     {                                                           \
139  	        if( verbosity <= spxout.getVerbosity() )                 \
140  	        {                                                        \
141  	           const SPxOut::Verbosity  old_verbosity = spxout.getVerbosity(); \
142  	           spxout.setVerbosity( verbosity );                     \
143  	           do_something;                                         \
144  	           spxout.setVerbosity( old_verbosity );                 \
145  	        }                                                        \
146  	     }                                                           \
147  	   }
148  	#define DO_WITH_ERR_VERBOSITY( do_something ) { do_something; }
149  	#endif
150  	
151  	/// Prints out message \p x if the verbosity level is at least SPxOut::ERROR.
152  	#define MSG_ERROR(x)            { DO_WITH_ERR_VERBOSITY( x ) }
153  	/// Prints out message \p x if the verbosity level is at least SPxOut::WARNING.
154  	#define MSG_WARNING(spxout, x)  { DO_WITH_TMP_VERBOSITY( SPxOut::WARNING, spxout, x ) }
155  	/// Prints out message \p x if the verbosity level is at least SPxOut::INFO1.
156  	#define MSG_INFO1(spxout, x)    { DO_WITH_TMP_VERBOSITY( SPxOut::INFO1, spxout, x ) }
157  	/// Prints out message \p x if the verbosity level is at least SPxOut::INFO2.
158  	#define MSG_INFO2(spxout, x)    { DO_WITH_TMP_VERBOSITY( SPxOut::INFO2, spxout, x ) }
159  	/// Prints out message \p x if the verbosity level is at least SPxOut::INFO3.
160  	#define MSG_INFO3(spxout, x)    { DO_WITH_TMP_VERBOSITY( SPxOut::INFO3, spxout, x ) }
161  	
162  	extern bool msginconsistent(const char* name, const char* file, int line);
163  	
164  	#define MSGinconsistent(name) msginconsistent(name, __FILE__, __LINE__)
165  	
166  	#if defined(SOPLEX_DEBUG)
167  	// print output in any case, regardless of Param::verbose():
168  	#define MSG_DEBUG(x) { x; }
169  	#else
170  	#define MSG_DEBUG(x) /**/
171  	#endif //!SOPLEX_DEBUG
172  	
173  	
174  	/*-----------------------------------------------------------------------------
175  	 * multi-thread support
176  	 *-----------------------------------------------------------------------------
177  	 */
178  	// enable the user to compile without thread_local by setting USRCXXFLAGS=-DTHREADLOCAL=""
179  	#if !defined(THREADLOCAL)
180  	#if defined(_MSC_VER) && _MSC_VER < 1900
181  	#define THREADLOCAL
182  	#else
183  	#define THREADLOCAL thread_local
184  	#endif
185  	#endif
186  	
187  	/*-----------------------------------------------------------------------------
188  	 * Long double support, Parameters and Epsilons
189  	 *-----------------------------------------------------------------------------
190  	 */
191  	
192  	
193  	#ifdef WITH_LONG_DOUBLE
194  	
195  	
196  	typedef long double Real;
197  	
198  	#ifndef REAL
199  	#define REAL(x)  x##L
200  	#define REAL_FORMAT "Lf"
201  	#endif
202  	/// default allowed bound violation
203  	#ifndef DEFAULT_BND_VIOL
204  	#define DEFAULT_BND_VIOL   1e-12L
205  	#endif
206  	/// default allowed additive zero: 1.0 + EPS_ZERO == 1.0
207  	#ifndef DEFAULT_EPS_ZERO
208  	#define DEFAULT_EPS_ZERO   1e-28L
209  	#endif
210  	/// epsilon for factorization
211  	#ifndef DEFAULT_EPS_FACTOR
212  	#define DEFAULT_EPS_FACTOR 1e-30L
213  	#endif
214  	/// epsilon for factorization update
215  	#ifndef DEFAULT_EPS_UPDATE
216  	#define DEFAULT_EPS_UPDATE 1e-26L
217  	#endif
218  	#ifndef DEFAULT_EPS_PIVOT
219  	#define DEFAULT_EPS_PIVOT 1e-20L
220  	#endif
221  	///
222  	#define DEFAULT_INFINITY   1e100L
223  	
224  	
225  	#else
226  	
227  	#ifdef WITH_FLOAT
228  	
229  	typedef float Real;
230  	
231  	#ifndef REAL
232  	#define REAL(x)  x
233  	#define REAL_FORMAT "f"
234  	#endif
235  	/// default allowed bound violation
236  	#ifndef DEFAULT_BND_VIOL
237  	#define DEFAULT_BND_VIOL   1e-1f
238  	#endif
239  	/// default allowed additive zero: 1.0 + EPS_ZERO == 1.0
240  	#ifndef DEFAULT_EPS_ZERO
241  	#define DEFAULT_EPS_ZERO   1e-7f
242  	#endif
243  	#ifndef DEFAULT_EPS_FACTOR
244  	#define DEFAULT_EPS_FACTOR 1e-7f
245  	#endif
246  	#ifndef DEFAULT_EPS_UPDATE
247  	#define DEFAULT_EPS_UPDATE 1e-6f
248  	#endif
249  	#ifndef DEFAULT_EPS_PIVOT
250  	#define DEFAULT_EPS_PIVOT 1e-6f
251  	#endif
252  	#define DEFAULT_INFINITY   1e35f
253  	
254  	#else
255  	
256  	typedef double Real;
257  	
258  	#ifndef REAL
259  	#define REAL(x)  x
260  	#define REAL_FORMAT "lf"
261  	#endif
262  	/// default allowed bound violation
263  	#ifndef DEFAULT_BND_VIOL
264  	#define DEFAULT_BND_VIOL   1e-6
265  	#endif
266  	/// default allowed additive zero: 1.0 + EPS_ZERO == 1.0
267  	#ifndef DEFAULT_EPS_ZERO
268  	#define DEFAULT_EPS_ZERO   1e-16
269  	#endif
270  	#ifndef DEFAULT_EPS_FACTOR
271  	#define DEFAULT_EPS_FACTOR 1e-20
272  	#endif
273  	#ifndef DEFAULT_EPS_UPDATE
274  	#define DEFAULT_EPS_UPDATE 1e-16
275  	#endif
276  	#ifndef DEFAULT_EPS_PIVOT
277  	#define DEFAULT_EPS_PIVOT 1e-10
278  	#endif
279  	#define DEFAULT_INFINITY   1e100
280  	
281  	#endif // !WITH_FLOAT
282  	#endif // !WITH_LONG_DOUBLE
283  	
284  	#define MAXIMUM(x,y)        ((x)>(y) ? (x) : (y))
285  	#define MINIMUM(x,y)        ((x)<(y) ? (x) : (y))
286  	
287  	#define SPX_MAXSTRLEN       1024 /**< maximum string length in SoPlex */
288  	
289  	THREADLOCAL extern const Real infinity;
290  	
291  	class Param
292  	{
293  	private:
294  	
295  	   //------------------------------------
296  	   /**@name Data */
297  	   ///@{
298  	   /// default allowed additive zero: 1.0 + EPS_ZERO == 1.0
299  	   THREADLOCAL static Real s_epsilon;
300  	   /// epsilon for factorization
301  	   THREADLOCAL static Real s_epsilon_factorization;
302  	   /// epsilon for factorization update
303  	   THREADLOCAL static Real s_epsilon_update;
304  	   /// epsilon for pivot zero tolerance in factorization
305  	   THREADLOCAL static Real s_epsilon_pivot;
306  	   ///@}
307  	
308  	public:
309  	
310  	   //------------------------------------
311  	   /**@name Access / modification */
312  	   ///@{
313  	   ///
314  	   static Real epsilon();
315  	   ///
316  	   static void setEpsilon(Real eps);
317  	   ///
318  	   static Real epsilonFactorization();
319  	   ///
320  	   static void setEpsilonFactorization(Real eps);
321  	   ///
322  	   static Real epsilonUpdate();
323  	   ///
324  	   static void setEpsilonUpdate(Real eps);
325  	   ///
326  	   static Real epsilonPivot();
327  	   ///
328  	   static void setEpsilonPivot(Real eps);
329  	   ///@}
330  	};
331  	
332  	// A generic version of spxAbs. It would be nice if we could replace spxAbs
333  	// with std::abs. Currently there are different versions of spxAbs under
334  	// compile time #if. It's better to make this an overloaded function. Even
335  	// better, replace it by std::abs since types from boost/multiprecision would
336  	// need no extra modification.
337  	template <class R>
338  	R spxAbs(R a)
339  	{
340  	   return abs(a);
341  	}
342  	
343  	// cmath means proper long double function gets called, e.g. for fabs -> fabsl.
344  	// Documentation unclear for nextafterl, so the ifdef remains for that case.
345  	#ifdef WITH_LONG_DOUBLE
346  	// returns the next representable value after x in the direction of y
347  	inline Real spxNextafter(Real x, Real y)
348  	{
349  	   return nextafterl(x, y);
350  	}
351  	#else
352  	// returns the next representable value after x in the direction of y
353  	inline Real spxNextafter(Real x, Real y)
354  	{
355  	#ifndef _MSC_VER
356  	   return nextafter(x, y);
357  	#else
358  	   return _nextafter(x, y);
359  	#endif
360  	}
361  	#endif
362  	
363  	/// returns |a|
364  	template <>
365  	inline Real spxAbs(Real a)
366  	{
367  	   return fabs(a);
368  	}
369  	
370  	/// returns square root
371  	inline Real spxSqrt(Real a)
372  	{
373  	   return std::sqrt(a);
374  	}
375  	
376  	/// returns max(|a|,|b|)
377  	inline Real maxAbs(Real a, Real b)
378  	{
379  	   const Real absa = spxAbs(a);
380  	   const Real absb = spxAbs(b);
381  	
382  	   return absa > absb ? absa : absb;
383  	}
384  	
385  	/// returns (a-b) / max(|a|,|b|,1.0)
386  	inline Real relDiff(Real a, Real b)
387  	{
388  	   return (a - b) / (maxAbs(a, b) > 1.0 ? maxAbs(a, b) : 1.0);
389  	}
390  	
391  	/// safe version of snprintf
392  	inline int spxSnprintf(
393  	   char*                 t,                  /**< target string */
394  	   size_t                len,                /**< length of the string to copy */
395  	   const char*           s,                  /**< source string */
396  	   ...                                       /**< further parameters */
397  	)
398  	{
399  	   va_list ap;
400  	   int n;
401  	
402  	   assert(t != NULL);
403  	   assert(len > 0);
404  	
405  	   va_start(ap, s); /*lint !e826*/
406  	
407  	#if defined(_WIN32) || defined(_WIN64)
408  	   n = _vsnprintf(t, len, s, ap);
409  	#else
410  	   n = vsnprintf(t, len, s, ap); /*lint !e571*/
411  	#endif
412  	   va_end(ap);
413  	
414  	   if(n < 0 || (size_t) n >= len)
415  	   {
416  	#ifndef NDEBUG
417  	
418  	      if(n < 0)
419  	      {
420  	         MSG_ERROR(std::cerr << "vsnprintf returned " << n << " while reading: " << s << std::endl;)
421  	      }
422  	
423  	#endif
424  	      t[len - 1] = '\0';
425  	      n = (int) len - 1;
426  	   }
427  	
428  	   return n;
429  	}
430  	
431  	#ifdef SOPLEX_WITH_BOOST
432  	
433  	using namespace boost::multiprecision;
434  	
435  	#ifdef SOPLEX_WITH_GMP
436  	template<boost::multiprecision::expression_template_option eto>
437  	inline number<gmp_rational, eto> ldexp(number<gmp_rational, eto>, int exp)
438  	{
439  	   assert(false);
440  	   return number<gmp_rational>();
441  	}
442  	
443  	template<boost::multiprecision::expression_template_option eto>
444  	inline number<gmp_rational, eto> frexp(number<gmp_rational, eto>, int* exp)
445  	{
446  	   assert(false);
447  	   return number<gmp_rational>();
448  	}
449  	#else
450  	inline cpp_rational ldexp(cpp_rational r, int exp)
451  	{
452  	   assert(false);
453  	   return cpp_rational();
454  	}
455  	
456  	inline cpp_rational frexp(cpp_rational, int* exp)
457  	{
458  	   assert(false);
459  	   return cpp_rational();
460  	}
461  	#endif
462  	
463  	// wrapped frexp function
464  	template <typename T, boost::multiprecision::expression_template_option eto>
465  	boost::multiprecision::number<T, eto> spxFrexp(boost::multiprecision::number<T, eto> y, int* exp)
466  	{
467  	   return frexp(y, exp);
468  	}
469  	
470  	// Overloaded spxLdexp
471  	template <typename T, boost::multiprecision::expression_template_option eto>
472  	boost::multiprecision::number<T> spxLdexp(boost::multiprecision::number<T, eto> x, int exp)
473  	{
474  	   return ldexp(x, exp);
475  	}
476  	
477  	// Overloaded function to return the square-root
478  	template <typename T, expression_template_option ep>
479  	number<T, ep> spxSqrt(number<T, ep> a)
480  	{
481  	   return sqrt(a);
482  	}
483  	
484  	// the nextafter function
485  	template <typename T, expression_template_option eto>
486  	number<T, eto> spxNextafter(number<T, eto> x,
487  	                            number<T, eto> y)
488  	{
489  	   // Turns out that nextafter is not supported in the mpfr library? The mpfr
490  	   // library does a different function named nextabove. Probably a
491  	   // replacement? I've made an issue about this.
492  	   // return nextafter(x,y);
493  	
494  	   // @todo Temporarily, I'm returning 0
495  	   assert(false);
496  	   return 0;
497  	}
498  	
499  	// Returns the square root
500  	template <typename T>
501  	number<T> spxSqrt(number<T> a)
502  	{
503  	   return sqrt(a);
504  	}
505  	
506  	/// returns max(|a|,|b|)
507  	template <typename T, expression_template_option et>
508  	inline number<T, et> maxAbs(
509  	   number<T, et> a, number<T, et> b)
510  	{
511  	   const auto absa = spxAbs(a);
512  	   const auto absb = spxAbs(b);
513  	
514  	   return absa > absb ? absa : absb;
515  	}
516  	
517  	template <typename T, expression_template_option et>
518  	inline number<T, et> relDiff(number<T, et> a,
519  	                             number<T, et> b)
520  	{
521  	   return (a - b) / (maxAbs(a, b) > 1.0 ? maxAbs(a, b) : 1.0);
522  	}
523  	#endif
524  	using namespace soplex;
525  	
526  	} // namespace soplex
527  	
528  	// For the templated functions
529  	#include "spxdefines.hpp"
530  	
531  	#endif // _SPXDEFINES_H_
532