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