Little additional improvement of documentation of include/dai/util.h
[libdai.git] / include / dai / util.h
1 /* This file is part of libDAI - http://www.libdai.org/
2 *
3 * libDAI is licensed under the terms of the GNU General Public License version
4 * 2, or (at your option) any later version. libDAI is distributed without any
5 * warranty. See the file COPYING for more details.
6 *
7 * Copyright (C) 2006-2009 Joris Mooij [joris dot mooij at libdai dot org]
8 * Copyright (C) 2006-2007 Radboud University Nijmegen, The Netherlands
9 */
10
11
12 /// \file
13 /// \brief Defines general utility functions and adds an abstraction layer for platform-dependent functionality
14
15
16 #ifndef __defined_libdai_util_h
17 #define __defined_libdai_util_h
18
19
20 #include <string>
21 #include <vector>
22 #include <set>
23 #include <map>
24 #include <iostream>
25 #include <boost/foreach.hpp>
26 #include <boost/functional/hash.hpp>
27 #include <algorithm>
28
29
30 #if defined(WINDOWS)
31 #include <map> // an alternative would be to use boost/tr1/unordered_map.hpp
32 #elif defined(CYGWIN)
33 #include <boost/tr1/unordered_map.hpp> // only present in boost 1.37 and higher
34 #else
35 #include <tr1/unordered_map> // only present in modern GCC distributions
36 #endif
37
38
39 /// An alias to the BOOST_FOREACH macro from the boost::foreach library
40 #define foreach BOOST_FOREACH
41
42 #ifdef DAI_DEBUG
43 /// \brief "Print variable". Prints the text of an expression, followed by its value (only if DAI_DEBUG is defined)
44 /**
45 * Useful debugging macro to see what your code is doing.
46 * Example: \code DAI_PV(3+4) \endcode
47 * Output: \code 3+4= 7 \endcode
48 */
49 #define DAI_PV(x) do {std::cerr << #x "= " << (x) << std::endl;} while(0)
50 /// "Debugging message": Prints a message (only if DAI_DEBUG is defined)
51 #define DAI_DMSG(str) do {std::cerr << str << std::endl;} while(0)
52 #else
53 #define DAI_PV(x) do {} while(0)
54 #define DAI_DMSG(str) do {} while(0)
55 #endif
56
57 /// Macro to write message \a stmt to \c std::cerr if \a props.verbose >= \a n
58 #define DAI_IFVERB(n, stmt) if(props.verbose>=n) { std::cerr << stmt; }
59
60
61 #ifdef WINDOWS
62 /// Returns true if argument is NAN (Not A Number)
63 bool isnan( double x );
64
65 /// Returns inverse hyperbolic tangent of argument
66 double atanh( double x );
67
68 /// Returns log(1+x)
69 double log1p( double x );
70
71 /// Define INFINITY
72 #define INFINITY (std::numeric_limits<Real>::infinity())
73 #endif
74
75
76 namespace dai {
77
78
79 /// Real number (alias for \c double, which could be changed to <tt>long double</tt> if necessary)
80 typedef double Real;
81
82 /// Returns logarithm of \a x
83 inline Real log( Real x ) {
84 return std::log(x);
85 }
86
87 /// Returns logarithm of \a x, or 0 if \a x == 0
88 inline Real log0( Real x ) {
89 return x ? std::log(x) : 0;
90 }
91
92 /// Returns exponent of \a x
93 inline Real exp( Real x ) {
94 return std::exp(x);
95 }
96
97
98 #ifdef WINDOWS
99 /// hash_map is an alias for \c std::map.
100 /** Since there is no TR1 unordered_map implementation available yet, we fall back on std::map.
101 */
102 template <typename T, typename U, typename H = boost::hash<T> >
103 class hash_map : public std::map<T,U> {};
104 #else
105 /// hash_map is an alias for \c std::tr1::unordered_map.
106 /** We use the (experimental) TR1 unordered_map implementation included in modern GCC distributions or in boost versions 1.37 and higher.
107 */
108 template <typename T, typename U, typename H = boost::hash<T> >
109 class hash_map : public std::tr1::unordered_map<T,U,H> {};
110 #endif
111
112
113 /// Returns wall clock time in seconds
114 double toc();
115
116
117 /// Returns absolute value of \a t
118 template<class T>
119 inline T abs( const T &t ) {
120 return (t < 0) ? (-t) : t;
121 }
122
123
124 /// Sets the random seed
125 void rnd_seed( size_t seed );
126
127 /// Returns a real number, distributed uniformly on [0,1)
128 Real rnd_uniform();
129
130 /// Returns a real number from a standard-normal distribution
131 Real rnd_stdnormal();
132
133 /// Returns a random integer in interval [\a min, \a max]
134 int rnd_int( int min, int max );
135
136 /// Returns a random integer in the half-open interval [0, \a n)
137 inline int rnd( int n) {
138 return rnd_int( 0, n-1 );
139 }
140
141
142 /// Writes a \c std::vector<> to a \c std::ostream
143 template<class T>
144 std::ostream& operator << (std::ostream& os, const std::vector<T> & x) {
145 os << "(";
146 for( typename std::vector<T>::const_iterator it = x.begin(); it != x.end(); it++ )
147 os << (it != x.begin() ? ", " : "") << *it;
148 os << ")";
149 return os;
150 }
151
152 /// Writes a \c std::set<> to a \c std::ostream
153 template<class T>
154 std::ostream& operator << (std::ostream& os, const std::set<T> & x) {
155 os << "{";
156 for( typename std::set<T>::const_iterator it = x.begin(); it != x.end(); it++ )
157 os << (it != x.begin() ? ", " : "") << *it;
158 os << "}";
159 return os;
160 }
161
162 /// Writes a \c std::map<> to a \c std::ostream
163 template<class T1, class T2>
164 std::ostream& operator << (std::ostream& os, const std::map<T1,T2> & x) {
165 os << "{";
166 for( typename std::map<T1,T2>::const_iterator it = x.begin(); it != x.end(); it++ )
167 os << (it != x.begin() ? ", " : "") << it->first << "->" << it->second;
168 os << "}";
169 return os;
170 }
171
172 /// Writes a \c std::pair<> to a \c std::ostream
173 template<class T1, class T2>
174 std::ostream& operator << (std::ostream& os, const std::pair<T1,T2> & x) {
175 os << "(" << x.first << ", " << x.second << ")";
176 return os;
177 }
178
179 /// Concatenates two vectors
180 template<class T>
181 std::vector<T> concat( const std::vector<T>& u, const std::vector<T>& v ) {
182 std::vector<T> w;
183 w.reserve( u.size() + v.size() );
184 for( size_t i = 0; i < u.size(); i++ )
185 w.push_back( u[i] );
186 for( size_t i = 0; i < v.size(); i++ )
187 w.push_back( v[i] );
188 return w;
189 }
190
191 /// Split a string into tokens delimited by characters in \a delim
192 void tokenizeString( const std::string& s, std::vector<std::string>& outTokens, const std::string& delim="\t\n" );
193
194 /// Used to keep track of the progress made by iterative algorithms.
195 /** A Diffs object stores an array of fixed size, containing the
196 * history of certain values (for example, the \f$\ell_\infty\f$
197 * differences between all the old beliefs and the new beliefs
198 * in one pass of belief propagation updates). A new value can be
199 * registered by calling Diffs::push(); the BP algorithm would use
200 * this to register the difference between the old and a newly
201 * calculated belief. The Diffs object keeps track of the maximum
202 * value encountered in the last Diffs::maxSize() values registered.
203 * The maximum value can then be queried by Diffs::maxDiff(). The
204 * BP algorithm would use this maximum value to compare it with a
205 * given tolerance in order to decide whether the algorithm has converged.
206 */
207 class Diffs : public std::vector<Real> {
208 private:
209 size_t _maxsize;
210 Real _def;
211 std::vector<Real>::iterator _pos;
212 std::vector<Real>::iterator _maxpos;
213 public:
214 /// Constructor
215 /** \param maxsize Maximum number of differences to store
216 * \param def Default value
217 */
218 Diffs(long maxsize, Real def) : std::vector<Real>(), _maxsize(maxsize), _def(def) {
219 this->reserve(_maxsize);
220 _pos = begin();
221 _maxpos = begin();
222 }
223 /// Returns maximum difference encountered so far
224 Real maxDiff() {
225 if( size() < _maxsize )
226 return _def;
227 else
228 return( *_maxpos );
229 }
230 /// Register new difference \a x
231 void push(Real x) {
232 if( size() < _maxsize ) {
233 push_back(x);
234 _pos = end();
235 if( size() > 1 ) {
236 if( *_maxpos < back() ) {
237 _maxpos = end();
238 _maxpos--;
239 }
240 } else {
241 _maxpos = begin();
242 }
243 } else {
244 if( _pos == end() )
245 _pos = begin();
246 if( _maxpos == _pos ) {
247 *_pos++ = x;
248 _maxpos = max_element(begin(),end());
249 } else {
250 if( x > *_maxpos )
251 _maxpos = _pos;
252 *_pos++ = x;
253 }
254 }
255 }
256 /// Return maximum number of differences that can be stored
257 size_t maxSize() { return _maxsize; }
258 };
259
260
261 } // end of namespace dai
262
263
264 #endif