Introduced DAI_DEBASSERT macro to abbreviate a common pattern
[libdai.git] / include / dai / util.h
1 /* Copyright (C) 2006-2008 Joris Mooij [joris dot mooij at tuebingen dot mpg dot de]
2 Radboud University Nijmegen, The Netherlands /
3 Max Planck Institute for Biological Cybernetics, Germany
4
5 This file is part of libDAI.
6
7 libDAI is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 libDAI is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with libDAI; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22
23 /// \file
24 /// \brief Defines general utility functions and adds an abstraction layer for platform-dependent functionality
25 /// \todo Improve documentation
26
27
28 #ifndef __defined_libdai_util_h
29 #define __defined_libdai_util_h
30
31
32 #include <vector>
33 #include <set>
34 #include <map>
35 #include <iostream>
36 #include <cstdio>
37 #include <boost/foreach.hpp>
38 #include <boost/functional/hash.hpp>
39 #include <algorithm>
40
41
42 #if defined(WINDOWS)
43 #include <map>
44 #elif defined(CYGWIN)
45 #include <boost/tr1/unordered_map.hpp>
46 #else
47 #include <tr1/unordered_map>
48 #endif
49
50
51 /// An alias to the BOOST_FOREACH macro from the boost::foreach library
52 #define foreach BOOST_FOREACH
53
54 #ifdef DAI_DEBUG
55 /// \brief "Print variable". Prints the text of an expression, followed by its value (only if DAI_DEBUG is defined)
56 /**
57 * Useful debugging macro to see what your code is doing.
58 * Example: \code DAI_PV(3+4) \endcode
59 * Output: \code 3+4= 7 \endcode
60 */
61 #define DAI_PV(x) do {std::cerr << #x "= " << (x) << std::endl;} while(0)
62 /// "Debugging message": Prints a message (only if DAI_DEBUG is defined)
63 #define DAI_DMSG(str) do {std::cerr << str << std::endl;} while(0)
64 /// Assertion if DAI_DEBUG is defined
65 #define DAI_DEBASSERT(x) do {assert(x);} while(0)
66 #else
67 #define DAI_PV(x) do {} while(0)
68 #define DAI_DMSG(str) do {} while(0)
69 #define DAI_DEBASSERT(X) do {} while(0)
70 #endif
71
72 /// Produces accessor and mutator methods according to the common pattern.
73 /** Example:
74 * \code DAI_ACCMUT(size_t& maxIter(), { return props.maxiter; }); \endcode
75 * \todo At the moment, only the mutator appears in doxygen documentation.
76 */
77 #define DAI_ACCMUT(x,y) \
78 x y; \
79 const x const y;
80
81 /// Macro to give error message \a stmt if props.verbose>=\a n
82 #define DAI_IFVERB(n, stmt) if(props.verbose>=n) { cerr << stmt; }
83
84
85 /// Real number (alias for double, which could be changed to long double if necessary)
86 typedef double Real;
87
88
89 #ifdef WINDOWS
90 /// Returns true if argument is NAN (Not A Number)
91 bool isnan( double x );
92
93 /// Returns inverse hyperbolic tangent of argument
94 double atanh( double x );
95
96 /// Returns log(1+x)
97 double log1p( double x );
98
99 /// Define INFINITY
100 #define INFINITY (std::numeric_limits<double>::infinity())
101 #endif
102
103
104 namespace dai {
105
106
107 #ifdef WINDOWS
108 /// hash_map is an alias for std::map.
109 /** Since there is no TR1 unordered_map implementation available yet, we fall back on std::map.
110 */
111 template <typename T, typename U, typename H = boost::hash<T> >
112 class hash_map : public std::map<T,U> {};
113 #else
114 /// hash_map is an alias for std::tr1::unordered_map.
115 /** We use the (experimental) TR1 unordered_map implementation included in modern GCC distributions.
116 */
117 template <typename T, typename U, typename H = boost::hash<T> >
118 class hash_map : public std::tr1::unordered_map<T,U,H> {};
119 #endif
120
121
122 /// Returns wall clock time in seconds
123 double toc();
124
125
126 /// Sets the random seed
127 void rnd_seed( size_t seed );
128
129 /// Returns a real number, distributed uniformly on [0,1)
130 double rnd_uniform();
131
132 /// Returns a real number from a standard-normal distribution
133 double rnd_stdnormal();
134
135 /// Returns a random integer in interval [min, max]
136 int rnd_int( int min, int max );
137
138 /// Returns a random integer in the half-open interval \f$[0,n)\f$
139 inline int rnd( int n) {
140 return rnd_int( 0, n-1 );
141 }
142
143
144 /// Writes a std::vector to a std::ostream
145 template<class T>
146 std::ostream& operator << (std::ostream& os, const std::vector<T> & x) {
147 os << "(";
148 for( typename std::vector<T>::const_iterator it = x.begin(); it != x.end(); it++ )
149 os << (it != x.begin() ? ", " : "") << *it;
150 os << ")";
151 return os;
152 }
153
154 /// Writes a std::set to a std::ostream
155 template<class T>
156 std::ostream& operator << (std::ostream& os, const std::set<T> & x) {
157 os << "{";
158 for( typename std::set<T>::const_iterator it = x.begin(); it != x.end(); it++ )
159 os << (it != x.begin() ? ", " : "") << *it;
160 os << "}";
161 return os;
162 }
163
164 /// Writes a std::map to a std::ostream
165 template<class T1, class T2>
166 std::ostream& operator << (std::ostream& os, const std::map<T1,T2> & x) {
167 os << "{";
168 for( typename std::map<T1,T2>::const_iterator it = x.begin(); it != x.end(); it++ )
169 os << (it != x.begin() ? ", " : "") << it->first << "->" << it->second;
170 os << "}";
171 return os;
172 }
173
174 /// Writes a std::pair to a std::ostream
175 template<class T1, class T2>
176 std::ostream& operator << (std::ostream& os, const std::pair<T1,T2> & x) {
177 os << "(" << x.first << ", " << x.second << ")";
178 return os;
179 }
180
181 /// Concatenate two vectors
182 template<class T>
183 std::vector<T> concat( const std::vector<T>& u, const std::vector<T>& v ) {
184 std::vector<T> w;
185 w.reserve( u.size() + v.size() );
186 for( size_t i = 0; i < u.size(); i++ )
187 w.push_back( u[i] );
188 for( size_t i = 0; i < v.size(); i++ )
189 w.push_back( v[i] );
190 return w;
191 }
192
193 /// Used to keep track of the progress made by iterative algorithms
194 class Diffs : public std::vector<double> {
195 private:
196 size_t _maxsize;
197 double _def;
198 std::vector<double>::iterator _pos;
199 std::vector<double>::iterator _maxpos;
200 public:
201 /// Constructor
202 Diffs(long maxsize, double def) : std::vector<double>(), _maxsize(maxsize), _def(def) {
203 this->reserve(_maxsize);
204 _pos = begin();
205 _maxpos = begin();
206 }
207 /// Returns maximum difference encountered
208 double maxDiff() {
209 if( size() < _maxsize )
210 return _def;
211 else
212 return( *_maxpos );
213 }
214 /// Register new difference x
215 void push(double x) {
216 if( size() < _maxsize ) {
217 push_back(x);
218 _pos = end();
219 if( size() > 1 ) {
220 if( *_maxpos < back() ) {
221 _maxpos = end();
222 _maxpos--;
223 }
224 } else {
225 _maxpos = begin();
226 }
227 }
228 else {
229 if( _pos == end() )
230 _pos = begin();
231 if( _maxpos == _pos ) {
232 *_pos++ = x;
233 _maxpos = max_element(begin(),end());
234 } else {
235 if( x > *_maxpos )
236 _maxpos = _pos;
237 *_pos++ = x;
238 }
239 }
240 }
241 /// Return maximum number of differences stored
242 size_t maxSize() { return _maxsize; }
243 };
244
245
246 /// Split a string into tokens
247 void tokenizeString( const std::string& s,
248 std::vector<std::string>& outTokens,
249 const std::string& delim="\t\n" );
250
251
252 } // end of namespace dai
253
254
255 #endif