Improved tokenizeString
[libdai.git] / include / dai / util.h
index 9356e8c..b1378be 100644 (file)
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
+/*  This file is part of libDAI - http://www.libdai.org/
+ *
+ *  libDAI is licensed under the terms of the GNU General Public License version
+ *  2, or (at your option) any later version. libDAI is distributed without any
+ *  warranty. See the file COPYING for more details.
+ *
+ *  Copyright (C) 2006-2010  Joris Mooij  [joris dot mooij at libdai dot org]
+ *  Copyright (C) 2006-2007  Radboud University Nijmegen, The Netherlands
+ */
 
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
 
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
+/// \file
+/// \brief Defines general utility functions and adds an abstraction layer for platform-dependent functionality
 
 
 #ifndef __defined_libdai_util_h
 #define __defined_libdai_util_h
 
 
-#include <sys/times.h>
-#include <cstdio>
+#include <string>
+#include <vector>
+#include <set>
+#include <map>
+#include <iostream>
+#include <boost/foreach.hpp>
+#include <boost/functional/hash.hpp>
+#include <boost/lexical_cast.hpp>
+#include <algorithm>
+#include <cerrno>
+
+#include <dai/exceptions.h>
+
+
+#if defined(WINDOWS)
+    #include <boost/tr1/unordered_map.hpp> // only present in boost 1.37 and higher
+#elif defined(CYGWIN)
+    #include <boost/tr1/unordered_map.hpp> // only present in boost 1.37 and higher
+#elif defined(MACOSX)
+    #include <boost/tr1/unordered_map.hpp> // only present in boost 1.37 and higher
+#else
+    #include <tr1/unordered_map> // only present in modern GCC distributions
+#endif
+
+
+/// An alias to the BOOST_FOREACH macro from the boost::foreach library
+#define foreach BOOST_FOREACH
+
+#ifdef DAI_DEBUG
+/// \brief "Print variable". Prints the text of an expression, followed by its value (only if DAI_DEBUG is defined)
+/**
+ *  Useful debugging macro to see what your code is doing.
+ *  Example: \code DAI_PV(3+4) \endcode
+ *  Output: \code 3+4= 7 \endcode
+ */
+#define DAI_PV(x) do {std::cerr << #x "= " << (x) << std::endl;} while(0)
+/// "Debugging message": Prints a message (only if DAI_DEBUG is defined)
+#define DAI_DMSG(str) do {std::cerr << str << std::endl;} while(0)
+#else
+#define DAI_PV(x) do {} while(0)
+#define DAI_DMSG(str) do {} while(0)
+#endif
+
+/// Macro to write message \a stmt to \c std::cerr if \a props.verbose >= \a n
+#define DAI_IFVERB(n, stmt) if(props.verbose>=n) { std::cerr << stmt; }
+
+
+#ifdef WINDOWS
+    /// Returns inverse hyperbolic tangent of argument
+    double atanh( double x );
+
+    /// Returns log(1+x)
+    double log1p( double x );
+
+    /// Define INFINITY
+    #define INFINITY (std::numeric_limits<Real>::infinity())
+#endif
 
 
 namespace dai {
 
 
-clock_t toc();
-void rnd_seed( int seed );
-double rnd_uniform();
-double rnd_stdnormal();
+/// Real number (alias for \c double, which could be changed to <tt>long double</tt> if necessary)
+typedef double Real;
+
+/// Returns true if argument is NAN (Not A Number)
+bool isnan( Real x );
+
+/// Returns logarithm of \a x
+inline Real log( Real x ) {
+    return std::log(x);
+}
+
+/// Returns logarithm of \a x, or 0 if \a x == 0
+inline Real log0( Real x ) {
+    return x ? std::log(x) : 0;
+}
+
+/// Returns exponent of \a x
+inline Real exp( Real x ) {
+    return std::exp(x);
+}
+
+/// Returns \a to the power \a y
+inline Real pow( Real x, Real y ) {
+    errno = 0;
+    Real result = std::pow(x, y);
+    DAI_DEBASSERT( errno == 0 );
+    return result;
+}
+
+
+/// hash_map is an alias for \c std::tr1::unordered_map.
+/** We use the (experimental) TR1 unordered_map implementation included in modern GCC distributions or in boost versions 1.37 and higher.
+ */
+template <typename T, typename U, typename H = boost::hash<T> >
+    class hash_map : public std::tr1::unordered_map<T,U,H> {};
+
+
+/// Returns wall clock time in seconds
+double toc();
+
+
+/// Returns absolute value of \a t
+template<class T>
+inline T abs( const T &t ) {
+    return (t < 0) ? (-t) : t;
+}
+
+
+/// Sets the random seed
+void rnd_seed( size_t seed );
+
+/// Returns a real number, distributed uniformly on [0,1)
+Real rnd_uniform();
+
+/// Returns a real number from a standard-normal distribution
+Real rnd_stdnormal();
+
+/// Returns a random integer in interval [\a min, \a max]
+int rnd_int( int min, int max );
+
+/// Returns a random integer in the half-open interval [0, \a n)
+inline int rnd( int n ) {
+    return rnd_int( 0, n-1 );
+}
+
+
+/// Converts a variable of type \a T to a \c std::string by using a \c boost::lexical_cast
+template<class T>
+std::string toString( const T& x ) {
+    return boost::lexical_cast<std::string>(x);
+}
+
+
+/// Converts a variable of type std::string to \a T by using a \c boost::lexical_cast
+template<class T>
+T fromString( const std::string& x ) {
+    return boost::lexical_cast<T>(x);
+}
+
+
+/// Writes a \c std::vector<> to a \c std::ostream
+template<class T>
+std::ostream& operator << (std::ostream& os, const std::vector<T> & x) {
+    os << "(";
+    for( typename std::vector<T>::const_iterator it = x.begin(); it != x.end(); it++ )
+        os << (it != x.begin() ? ", " : "") << *it;
+    os << ")";
+    return os;
+}
+
+/// Writes a \c std::set<> to a \c std::ostream
+template<class T>
+std::ostream& operator << (std::ostream& os, const std::set<T> & x) {
+    os << "{";
+    for( typename std::set<T>::const_iterator it = x.begin(); it != x.end(); it++ )
+        os << (it != x.begin() ? ", " : "") << *it;
+    os << "}";
+    return os;
+}
+
+/// Writes a \c std::map<> to a \c std::ostream
+template<class T1, class T2>
+std::ostream& operator << (std::ostream& os, const std::map<T1,T2> & x) {
+    os << "{";
+    for( typename std::map<T1,T2>::const_iterator it = x.begin(); it != x.end(); it++ )
+        os << (it != x.begin() ? ", " : "") << it->first << "->" << it->second;
+    os << "}";
+    return os;
+}
+
+/// Writes a \c std::pair<> to a \c std::ostream
+template<class T1, class T2>
+std::ostream& operator << (std::ostream& os, const std::pair<T1,T2> & x) {
+    os << "(" << x.first << ", " << x.second << ")";
+    return os;
+}
+
+/// Concatenates two vectors
+template<class T>
+std::vector<T> concat( const std::vector<T>& u, const std::vector<T>& v ) {
+    std::vector<T> w;
+    w.reserve( u.size() + v.size() );
+    for( size_t i = 0; i < u.size(); i++ )
+        w.push_back( u[i] );
+    for( size_t i = 0; i < v.size(); i++ )
+        w.push_back( v[i] );
+    return w;
+}
+
+/// Split a string into tokens delimited by one of the characters in \a delim
+/** \param s the string to be split into tokens
+ *  \param singleDelim if \c true, any single delimiter forms a boundary between two tokens; 
+ *         if \c false, a maximal group of consecutive delimiters forms a boundary between two tokens
+ *  \param delim delimiter characters
+ */
+std::vector<std::string> tokenizeString( const std::string& s, bool singleDelim, const std::string& delim="\t\n" );
+
+
+/// Split a string into tokens delimited by one of the characters in \a delim
+/** \deprecated Please use dai::tokenizeString( const std::string&, bool, const std::string& ) instead
+ */
+void tokenizeString( const std::string& s, std::vector<std::string>& outTokens, const std::string& delim="\t\n" );
+
+
+/// Enumerates different ways of normalizing a probability measure.
+/**
+ *  - NORMPROB means that the sum of all entries should be 1;
+ *  - NORMLINF means that the maximum absolute value of all entries should be 1.
+ */
+typedef enum { NORMPROB, NORMLINF } ProbNormType;
+
+/// Enumerates different distance measures between probability measures.
+/**
+ *  - DISTL1 is the \f$\ell_1\f$ distance (sum of absolute values of pointwise difference);
+ *  - DISTLINF is the \f$\ell_\infty\f$ distance (maximum absolute value of pointwise difference);
+ *  - DISTTV is the total variation distance (half of the \f$\ell_1\f$ distance);
+ *  - DISTKL is the Kullback-Leibler distance (\f$\sum_i p_i (\log p_i - \log q_i)\f$).
+ *  - DISTHEL is the Hellinger distance (\f$\frac{1}{2}\sum_i (\sqrt{p_i}-\sqrt{q_i})^2\f$).
+ */
+typedef enum { DISTL1, DISTLINF, DISTTV, DISTKL, DISTHEL } ProbDistType;
 
 
 } // end of namespace dai