Fixed division-by-zero issue in pow() which caused problems for GLC+ with sparse...
[libdai.git] / include / dai / util.h
index 96e7887..dba4002 100644 (file)
@@ -1,11 +1,8 @@
 /*  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-2011, The libDAI authors. All rights reserved.
  *
- *  Copyright (C) 2006-2010  Joris Mooij  [joris dot mooij at libdai dot org]
- *  Copyright (C) 2006-2007  Radboud University Nijmegen, The Netherlands
+ *  Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
  */
 
 
 #include <iostream>
 #include <boost/foreach.hpp>
 #include <boost/functional/hash.hpp>
+#include <boost/lexical_cast.hpp>
 #include <algorithm>
 #include <cerrno>
 
+#if defined(WINDOWS)
+#include <cstdint> // only defined in C++11 and higher, but needed for Win64 builds in order to enable conditional code in MPIR library
+#endif
+#include <gmpxx.h>
+
 #include <dai/exceptions.h>
 
 
@@ -41,8 +44,8 @@
 #endif
 
 
-/// An alias to the BOOST_FOREACH macro from the boost::foreach library
-#define foreach BOOST_FOREACH
+/// An alias to the BOOST_FOREACH macro from the boost::bforeach library
+#define bforeach BOOST_FOREACH
 
 #ifdef DAI_DEBUG
 /// \brief "Print variable". Prints the text of an expression, followed by its value (only if DAI_DEBUG is defined)
 #define DAI_IFVERB(n, stmt) if(props.verbose>=n) { std::cerr << stmt; }
 
 
-#ifdef CYGWIN
-    /// Returns true if argument is NAN (Not A Number)
-    bool isnan( double x );
-#endif
-
-
 #ifdef WINDOWS
-    /// Returns true if argument is NAN (Not A Number)
-    bool isnan( double x );
-
     /// Returns inverse hyperbolic tangent of argument
     double atanh( double x );
 
 
     /// Define INFINITY
     #define INFINITY (std::numeric_limits<Real>::infinity())
+
+    /// Define NAN
+    #define NAN (std::numeric_limits<Real>::quiet_NaN())
+
+    #if defined(_MSC_VER)
+      // Disable unsafe warning (use of the function 'strcpy' instead of 
+      // 'strcpy_s' for portability reasons;
+      #pragma warning( disable : 4996 )
+      // Workaround for the char16_t type defined in Matlab and MSVC 2010
+      #if (_MSC_VER >= 1600)
+        #define __STDC_UTF_16__
+      #endif
+    #endif
 #endif
 
 
@@ -90,6 +97,18 @@ namespace dai {
 /// Real number (alias for \c double, which could be changed to <tt>long double</tt> if necessary)
 typedef double Real;
 
+/// Arbitrary precision integer number
+typedef mpz_class BigInt;
+
+/// Safe down-cast of big integer to size_t
+inline size_t BigInt_size_t( const BigInt &N ) {
+    DAI_ASSERT( N <= (BigInt)std::numeric_limits<std::size_t>::max() );
+    return N.get_ui();
+}
+
+/// 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);
@@ -105,9 +124,15 @@ inline Real exp( Real x ) {
     return std::exp(x);
 }
 
-/// Returns \a to the power \a y
+/// Returns \a x to the power \a y
+/** We use the convention that division by zero yields zero;
+ *  for powers, this means that if \a x == 0.0 and \a y < 0.0, we 
+ *  return 0.0 instead of generating an error.
+ */
 inline Real pow( Real x, Real y ) {
     errno = 0;
+    if( x == 0.0 && y < 0.0 )
+        return 0.0;
     Real result = std::pow(x, y);
     DAI_DEBASSERT( errno == 0 );
     return result;
@@ -150,6 +175,20 @@ inline int rnd( int n ) {
 }
 
 
+/// 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) {
@@ -200,7 +239,12 @@ std::vector<T> concat( const std::vector<T>& u, const std::vector<T>& v ) {
 }
 
 /// Split a string into tokens delimited by one of the characters in \a delim
-void tokenizeString( const std::string& s, std::vector<std::string>& outTokens, const std::string& delim="\t\n" );
+/** \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" );
 
 
 /// Enumerates different ways of normalizing a probability measure.