lemon/assert.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 936 ddd3c0d3d9bf
parent 290 f6899946c1ac
child 1072 0e30f63d45d0
permissions -rw-r--r--
Implement the scaling Price Refinement heuristic in CostScaling (#417)
instead of Early Termination.

These two heuristics are similar, but the newer one is faster
and not only makes it possible to skip some epsilon phases, but
it can improve the performance of the other phases, as well.
     1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library.
     4  *
     5  * Copyright (C) 2003-2009
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 #ifndef LEMON_ASSERT_H
    20 #define LEMON_ASSERT_H
    21 
    22 /// \ingroup exceptions
    23 /// \file
    24 /// \brief Extended assertion handling
    25 
    26 #include <lemon/error.h>
    27 
    28 namespace lemon {
    29 
    30   inline void assert_fail_abort(const char *file, int line,
    31                                 const char *function, const char* message,
    32                                 const char *assertion)
    33   {
    34     std::cerr << file << ":" << line << ": ";
    35     if (function)
    36       std::cerr << function << ": ";
    37     std::cerr << message;
    38     if (assertion)
    39       std::cerr << " (assertion '" << assertion << "' failed)";
    40     std::cerr << std::endl;
    41     std::abort();
    42   }
    43 
    44   namespace _assert_bits {
    45 
    46 
    47     inline const char* cstringify(const std::string& str) {
    48       return str.c_str();
    49     }
    50 
    51     inline const char* cstringify(const char* str) {
    52       return str;
    53     }
    54   }
    55 }
    56 
    57 #endif // LEMON_ASSERT_H
    58 
    59 #undef LEMON_ASSERT
    60 #undef LEMON_DEBUG
    61 
    62 #if (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +               \
    63   (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
    64 #error "LEMON assertion system is not set properly"
    65 #endif
    66 
    67 #if ((defined(LEMON_ASSERT_ABORT) ? 1 : 0) +            \
    68      (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 ||     \
    69      defined(LEMON_ENABLE_ASSERTS)) &&                  \
    70   (defined(LEMON_DISABLE_ASSERTS) ||                    \
    71    defined(NDEBUG))
    72 #error "LEMON assertion system is not set properly"
    73 #endif
    74 
    75 
    76 #if defined LEMON_ASSERT_ABORT
    77 #  undef LEMON_ASSERT_HANDLER
    78 #  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
    79 #elif defined LEMON_ASSERT_CUSTOM
    80 #  undef LEMON_ASSERT_HANDLER
    81 #  ifndef LEMON_CUSTOM_ASSERT_HANDLER
    82 #    error "LEMON_CUSTOM_ASSERT_HANDLER is not set"
    83 #  endif
    84 #  define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER
    85 #elif defined LEMON_DISABLE_ASSERTS
    86 #  undef LEMON_ASSERT_HANDLER
    87 #elif defined NDEBUG
    88 #  undef LEMON_ASSERT_HANDLER
    89 #else
    90 #  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
    91 #endif
    92 
    93 #ifndef LEMON_FUNCTION_NAME
    94 #  if defined __GNUC__
    95 #    define LEMON_FUNCTION_NAME (__PRETTY_FUNCTION__)
    96 #  elif defined _MSC_VER
    97 #    define LEMON_FUNCTION_NAME (__FUNCSIG__)
    98 #  elif __STDC_VERSION__ >= 199901L
    99 #    define LEMON_FUNCTION_NAME (__func__)
   100 #  else
   101 #    define LEMON_FUNCTION_NAME ("<unknown>")
   102 #  endif
   103 #endif
   104 
   105 #ifdef DOXYGEN
   106 
   107 /// \ingroup exceptions
   108 ///
   109 /// \brief Macro for assertion with customizable message
   110 ///
   111 /// Macro for assertion with customizable message.
   112 /// \param exp An expression that must be convertible to \c bool.  If it is \c
   113 /// false, then an assertion is raised. The concrete behaviour depends on the
   114 /// settings of the assertion system.
   115 /// \param msg A <tt>const char*</tt> parameter, which can be used to provide
   116 /// information about the circumstances of the failed assertion.
   117 ///
   118 /// The assertions are enabled in the default behaviour.
   119 /// You can disable them with the following code:
   120 /// \code
   121 /// #define LEMON_DISABLE_ASSERTS
   122 /// \endcode
   123 /// or with compilation parameters:
   124 /// \code
   125 /// g++ -DLEMON_DISABLE_ASSERTS
   126 /// make CXXFLAGS='-DLEMON_DISABLE_ASSERTS'
   127 /// \endcode
   128 /// The checking is also disabled when the standard macro \c NDEBUG is defined.
   129 ///
   130 /// As a default behaviour the failed assertion prints a short log message to
   131 /// the standard error and aborts the execution.
   132 ///
   133 /// However, the following modes can be used in the assertion system:
   134 /// - \c LEMON_ASSERT_ABORT The failed assertion prints a short log message to
   135 ///   the standard error and aborts the program. It is the default behaviour.
   136 /// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler
   137 ///   function.
   138 ///   \code
   139 ///     void custom_assert_handler(const char* file, int line,
   140 ///                                const char* function, const char* message,
   141 ///                                const char* assertion);
   142 ///   \endcode
   143 ///   The name of the function should be defined as the \c
   144 ///   LEMON_CUSTOM_ASSERT_HANDLER macro name.
   145 ///   \code
   146 ///     #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
   147 ///   \endcode
   148 ///   Whenever an assertion is occured, the custom assertion
   149 ///   handler is called with appropiate parameters.
   150 ///
   151 /// The assertion mode can also be changed within one compilation unit.
   152 /// If the macros are redefined with other settings and the
   153 /// \ref lemon/assert.h "assert.h" file is reincluded, then the
   154 /// behaviour is changed appropiately to the new settings.
   155 #  define LEMON_ASSERT(exp, msg)                                        \
   156   (static_cast<void> (!!(exp) ? 0 : (                                   \
   157     LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                            \
   158                          LEMON_FUNCTION_NAME,                           \
   159                          ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
   160 
   161 /// \ingroup exceptions
   162 ///
   163 /// \brief Macro for internal assertions
   164 ///
   165 /// Macro for internal assertions, it is used in the library to check
   166 /// the consistency of results of algorithms, several pre- and
   167 /// postconditions and invariants. The checking is disabled by
   168 /// default, but it can be turned on with the macro \c
   169 /// LEMON_ENABLE_DEBUG.
   170 /// \code
   171 /// #define LEMON_ENABLE_DEBUG
   172 /// \endcode
   173 /// or with compilation parameters:
   174 /// \code
   175 /// g++ -DLEMON_ENABLE_DEBUG
   176 /// make CXXFLAGS='-DLEMON_ENABLE_DEBUG'
   177 /// \endcode
   178 ///
   179 /// This macro works like the \c LEMON_ASSERT macro, therefore the
   180 /// current behaviour depends on the settings of \c LEMON_ASSERT
   181 /// macro.
   182 ///
   183 /// \see LEMON_ASSERT
   184 #  define LEMON_DEBUG(exp, msg)                                         \
   185   (static_cast<void> (!!(exp) ? 0 : (                                   \
   186     LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                            \
   187                          LEMON_FUNCTION_NAME,                           \
   188                          ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
   189 
   190 #else
   191 
   192 #  ifndef LEMON_ASSERT_HANDLER
   193 #    define LEMON_ASSERT(exp, msg)  (static_cast<void>(0))
   194 #    define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
   195 #  else
   196 #    define LEMON_ASSERT(exp, msg)                                      \
   197        (static_cast<void> (!!(exp) ? 0 : (                              \
   198         LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                        \
   199                              LEMON_FUNCTION_NAME,                       \
   200                              ::lemon::_assert_bits::cstringify(msg),    \
   201                              #exp), 0)))
   202 #    if LEMON_ENABLE_DEBUG
   203 #      define LEMON_DEBUG(exp, msg)                                     \
   204          (static_cast<void> (!!(exp) ? 0 : (                            \
   205            LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                     \
   206                                 LEMON_FUNCTION_NAME,                    \
   207                                 ::lemon::_assert_bits::cstringify(msg), \
   208                                 #exp), 0)))
   209 #    else
   210 #      define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
   211 #    endif
   212 #  endif
   213 
   214 #endif