lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [5478] Work around strtod("inf") defect in msvcrt (VS)


From: Greg Chicares
Subject: [lmi-commits] [5478] Work around strtod("inf") defect in msvcrt (VS)
Date: Thu, 31 May 2012 15:16:25 +0000

Revision: 5478
          http://svn.sv.gnu.org/viewvc/?view=rev&root=lmi&revision=5478
Author:   chicares
Date:     2012-05-31 15:16:24 +0000 (Thu, 31 May 2012)
Log Message:
-----------
Work around strtod("inf") defect in msvcrt (VS)

Modified Paths:
--------------
    lmi/trunk/ChangeLog
    lmi/trunk/numeric_io_cast.hpp
    lmi/trunk/numeric_io_test.cpp
    lmi/trunk/numeric_io_traits.hpp

Modified: lmi/trunk/ChangeLog
===================================================================
--- lmi/trunk/ChangeLog 2012-05-29 20:59:10 UTC (rev 5477)
+++ lmi/trunk/ChangeLog 2012-05-31 15:16:24 UTC (rev 5478)
@@ -30186,3 +30186,11 @@
 Fix assorted warnings (VS). See:
   http://lists.nongnu.org/archive/html/lmi/2012-05/msg00016.html
 
+20120531T1516Z <address@hidden> [578]
+
+  numeric_io_cast.hpp
+  numeric_io_traits.hpp
+  numeric_io_test.cpp
+Work around strtod("inf") defect in msvcrt (VS). See:
+  http://lists.nongnu.org/archive/html/lmi/2012-05/msg00021.html
+

Modified: lmi/trunk/numeric_io_cast.hpp
===================================================================
--- lmi/trunk/numeric_io_cast.hpp       2012-05-29 20:59:10 UTC (rev 5477)
+++ lmi/trunk/numeric_io_cast.hpp       2012-05-31 15:16:24 UTC (rev 5478)
@@ -29,9 +29,10 @@
 #include "numeric_io_traits.hpp"
 #include "rtti_lmi.hpp"
 
+#include <cstring>                      // std::strcmp()
 #include <sstream>
 #include <stdexcept>
-#include <stdio.h> // snprintf() (C99, not C++98).
+#include <stdio.h>                      // snprintf() (C99, not C++98).
 #include <string>
 #include <typeinfo>
 
@@ -309,6 +310,14 @@
             }
         else
             {
+#if defined LMI_MSC || defined LMI_COMO_WITH_MINGW
+            // COMPILER !! MSVC formats infinity into a string as "1.#INF", not
+            // "inf" as gcc does and C99/C++11 mandates. Translate it manually.
+            if(0 == std::strcmp(buffer, "1.#INF"))
+                {
+                return "inf";
+                }
+#endif // defined LMI_MSC || defined LMI_COMO_WITH_MINGW
             return numeric_conversion_traits<From>::simplify(To(buffer));
             }
         }

Modified: lmi/trunk/numeric_io_test.cpp
===================================================================
--- lmi/trunk/numeric_io_test.cpp       2012-05-29 20:59:10 UTC (rev 5477)
+++ lmi/trunk/numeric_io_test.cpp       2012-05-31 15:16:24 UTC (rev 5478)
@@ -132,7 +132,9 @@
     BOOST_TEST_EQUAL( 3, floating_point_decimals(-1000.0f));
     BOOST_TEST_EQUAL(15, floating_point_decimals(-1000.0L));
 
+#if !defined LMI_MSC && !defined LMI_COMO_WITH_MINGW
     BOOST_TEST_EQUAL( 0, floating_point_decimals(infinity<double>()));
+#endif // !defined LMI_MSC && !defined LMI_COMO_WITH_MINGW
 
     // Consider the number of exact decimal digits in the neighborhood
     // of epsilon's reciprocal for type double, which is approximately

Modified: lmi/trunk/numeric_io_traits.hpp
===================================================================
--- lmi/trunk/numeric_io_traits.hpp     2012-05-29 20:59:10 UTC (rev 5477)
+++ lmi/trunk/numeric_io_traits.hpp     2012-05-31 15:16:24 UTC (rev 5478)
@@ -26,11 +26,12 @@
 
 #include "config.hpp"
 
-#include "ieee754.hpp" // is_infinite<>()
+#include "ieee754.hpp"                  // is_infinite<>()
 
-#include <algorithm>   // std::max()
-#include <cmath>       // C99 functions fabsl(), log10l(), strtold()
-#include <cstdlib>     // std::strto*()
+#include <algorithm>                    // std::max()
+#include <cmath>                        // C99 functions fabsl(), log10l(), 
strtold()
+#include <cstdlib>                      // std::strto*()
+#include <cstring>                      // std::strncmp()
 #include <limits>
 #include <stdexcept>
 #include <string>
@@ -80,6 +81,15 @@
 inline int floating_point_decimals(T t)
 {
     BOOST_STATIC_ASSERT(boost::is_float<T>::value);
+#if defined LMI_MSC || defined LMI_COMO_WITH_MINGW
+    // COMPILER !! Not only does MSVC write infinity as "1.#INF" rather
+    // than "inf", it respects decimals specification, "shortening" it
+    // into "1." if we return 0 here.
+    if(is_infinite(t))
+        {
+        return 4;
+        }
+#endif // defined LMI_MSC || defined LMI_COMO_WITH_MINGW
     // Avoid taking the logarithm of zero or infinity.
     if(0 == t || is_infinite(t))
         {
@@ -331,7 +341,25 @@
     static int digits(T t) {return floating_point_decimals(t);}
     static char const* fmt() {return "%#.*f";}
     static T strtoT(char const* nptr, char** endptr)
-        {return strtof(nptr, endptr);}
+        {
+#if defined LMI_MSC || defined LMI_COMO_WITH_MINGW
+        // COMPILER !! MSVC strtod() doesn't support C99 "inf[inity]" nor
+        // "nan[(...)]" strings nor hexadecimal notation so provide our
+        // work around for at least the first one of them which we actually
+        // need. This workaround is, of course, incomplete as it doesn't
+        // even support "-inf" without mentioning long and non-lower-case
+        // versions or NaN support.
+        if(0 == std::strncmp(nptr, "inf", 3))
+            {
+            if(endptr)
+                {
+                *endptr = const_cast<char *>(nptr) + 3;
+                }
+            return std::numeric_limits<T>::infinity();
+            }
+#endif // defined LMI_MSC || defined LMI_COMO_WITH_MINGW
+        return strtof(nptr, endptr);
+        }
 };
 
 template<> struct numeric_conversion_traits<double>
@@ -341,7 +369,25 @@
     static int digits(T t) {return floating_point_decimals(t);}
     static char const* fmt() {return "%#.*f";}
     static T strtoT(char const* nptr, char** endptr)
-        {return std::strtod(nptr, endptr);}
+        {
+#if defined LMI_MSC || defined LMI_COMO_WITH_MINGW
+        // COMPILER !! MSVC strtod() doesn't support C99 "inf[inity]" nor
+        // "nan[(...)]" strings nor hexadecimal notation so provide our
+        // work around for at least the first one of them which we actually
+        // need. This workaround is, of course, incomplete as it doesn't
+        // even support "-inf" without mentioning long and non-lower-case
+        // versions or NaN support.
+        if(0 == std::strncmp(nptr, "inf", 3))
+            {
+            if(endptr)
+                {
+                *endptr = const_cast<char *>(nptr) + 3;
+                }
+            return std::numeric_limits<T>::infinity();
+            }
+#endif // defined LMI_MSC || defined LMI_COMO_WITH_MINGW
+        return std::strtod(nptr, endptr);
+        }
 };
 
 #if !defined LMI_COMPILER_PROVIDES_STRTOLD




reply via email to

[Prev in Thread] Current Thread [Next in Thread]