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