45900a7a7e64ad1206e006444d4153dd344fe66e
[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 #define DAI_PV(x) do {std::cerr << #x "= " << x << std::endl;} while(0)
56 #define DAI_DMSG(str) do {std::cerr << str << std::endl;} while(0)
57 #else
58 #define DAI_PV(x) do {} while(0)
59 #define DAI_DMSG(str) do {} while(0)
60 #endif
61
62 #define DAI_ACCMUT(x,y) \
63 x y; \
64 const x const y;
65
66 #define DAI_IFVERB(n, stmt) if(props.verbose>=n) { cerr << stmt; }
67
68
69 /// Real number (alias for double, which could be changed to long double if necessary)
70 typedef double Real;
71
72
73 #ifdef WINDOWS
74 /// Returns true if argument is NAN (Not A Number)
75 bool isnan( double x );
76
77 /// Returns inverse hyperbolic tangent of argument
78 double atanh( double x );
79
80 /// Returns log(1+x)
81 double log1p( double x );
82
83 /// Define INFINITY
84 #define INFINITY (std::numeric_limits<double>::infinity())
85 #endif
86
87
88 namespace dai {
89
90
91 #ifdef WINDOWS
92 /// hash_map is an alias for std::map.
93 /** Since there is no TR1 unordered_map implementation available yet, we fall back on std::map.
94 */
95 template <typename T, typename U, typename H = boost::hash<T> >
96 class hash_map : public std::map<T,U> {};
97 #else
98 /// hash_map is an alias for std::tr1::unordered_map.
99 /** We use the (experimental) TR1 unordered_map implementation included in modern GCC distributions.
100 */
101 template <typename T, typename U, typename H = boost::hash<T> >
102 class hash_map : public std::tr1::unordered_map<T,U,H> {};
103 #endif
104
105
106 /// Returns wall clock time in seconds
107 double toc();
108
109
110 /// Sets the random seed
111 void rnd_seed( size_t seed );
112
113 /// Returns a real number, distributed uniformly on [0,1)
114 double rnd_uniform();
115
116 /// Returns a real number from a standard-normal distribution
117 double rnd_stdnormal();
118
119 /// Returns a random integer in interval [min, max]
120 int rnd_int( int min, int max );
121
122
123 /// Writes a std::vector to a std::ostream
124 template<class T>
125 std::ostream& operator << (std::ostream& os, const std::vector<T> & x) {
126 os << "(";
127 for( typename std::vector<T>::const_iterator it = x.begin(); it != x.end(); it++ )
128 os << (it != x.begin() ? ", " : "") << *it;
129 os << ")";
130 return os;
131 }
132
133 /// Writes a std::set to a std::ostream
134 template<class T>
135 std::ostream& operator << (std::ostream& os, const std::set<T> & x) {
136 os << "{";
137 for( typename std::set<T>::const_iterator it = x.begin(); it != x.end(); it++ )
138 os << (it != x.begin() ? ", " : "") << *it;
139 os << "}";
140 return os;
141 }
142
143 /// Writes a std::map to a std::ostream
144 template<class T1, class T2>
145 std::ostream& operator << (std::ostream& os, const std::map<T1,T2> & x) {
146 os << "{";
147 for( typename std::map<T1,T2>::const_iterator it = x.begin(); it != x.end(); it++ )
148 os << (it != x.begin() ? ", " : "") << it->first << "->" << it->second;
149 os << "}";
150 return os;
151 }
152
153 /// Writes a std::pair to a std::ostream
154 template<class T1, class T2>
155 std::ostream& operator << (std::ostream& os, const std::pair<T1,T2> & x) {
156 os << "(" << x.first << ", " << x.second << ")";
157 return os;
158 }
159
160
161 /// Used to keep track of the progress made by iterative algorithms
162 class Diffs : public std::vector<double> {
163 private:
164 size_t _maxsize;
165 double _def;
166 std::vector<double>::iterator _pos;
167 std::vector<double>::iterator _maxpos;
168 public:
169 /// Constructor
170 Diffs(long maxsize, double def) : std::vector<double>(), _maxsize(maxsize), _def(def) {
171 this->reserve(_maxsize);
172 _pos = begin();
173 _maxpos = begin();
174 }
175 /// Returns maximum difference encountered
176 double maxDiff() {
177 if( size() < _maxsize )
178 return _def;
179 else
180 return( *_maxpos );
181 }
182 /// Register new difference x
183 void push(double x) {
184 if( size() < _maxsize ) {
185 push_back(x);
186 _pos = end();
187 if( size() > 1 ) {
188 if( *_maxpos < back() ) {
189 _maxpos = end();
190 _maxpos--;
191 }
192 } else {
193 _maxpos = begin();
194 }
195 }
196 else {
197 if( _pos == end() )
198 _pos = begin();
199 if( _maxpos == _pos ) {
200 *_pos++ = x;
201 _maxpos = max_element(begin(),end());
202 } else {
203 if( x > *_maxpos )
204 _maxpos = _pos;
205 *_pos++ = x;
206 }
207 }
208 }
209 /// Return maximum number of differences stored
210 size_t maxSize() { return _maxsize; }
211 };
212
213
214 } // end of namespace dai
215
216
217 #endif