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