diff --git a/src/shogun/io/SerializableXmlReader00.cpp b/src/shogun/io/SerializableXmlReader00.cpp index 9b3a697545c..b27ce022e54 100644 --- a/src/shogun/io/SerializableXmlReader00.cpp +++ b/src/shogun/io/SerializableXmlReader00.cpp @@ -81,16 +81,13 @@ SerializableXmlReader00::read_scalar_wrapped( result = false; break; case PT_FLOAT32: - if (sscanf(buf, "%g", (float32_t*) param) != 1) - result = false; + result = CMath::strtof(buf, (float32_t*) param); break; case PT_FLOAT64: - if (sscanf(buf, "%lg", (float64_t*) param) != 1) - result = false; + result = CMath::strtod(buf, (float64_t*) param); break; case PT_FLOATMAX: - if (sscanf(buf, "%Lg", (floatmax_t*) param) != 1) - result = false; + result = CMath::strtold(buf, (floatmax_t*) param); break; case PT_COMPLEX128: float64_t c_real, c_imag; diff --git a/src/shogun/mathematics/Math.cpp b/src/shogun/mathematics/Math.cpp index 880e0b7442e..ffae4688cf7 100644 --- a/src/shogun/mathematics/Math.cpp +++ b/src/shogun/mathematics/Math.cpp @@ -14,11 +14,18 @@ #include #include #include +#include #include #include #include +#ifndef NAN +#include +#define NAN (strtod("NAN",NULL)) +#endif + + using namespace shogun; #ifdef USE_LOGCACHE @@ -34,7 +41,8 @@ int32_t CMath::LOGACCURACY = 0; // 100000 steps per integer int32_t CMath::LOGRANGE = 0; // range for logtable: log(1+exp(x)) -25 <= x <= 0 -const float64_t CMath::INFTY = -log(0.0); // infinity +const float64_t CMath::NOT_A_NUMBER = NAN; +const float64_t CMath::INFTY = INFINITY; // infinity const float64_t CMath::ALMOST_INFTY = +1e+20; //a large number const float64_t CMath::ALMOST_NEG_INFTY = -1000; const float64_t CMath::PI=M_PI; @@ -244,4 +252,98 @@ int CMath::is_finite(double f) #endif // #ifndef HAVE_STD_ISFINITE return std::isfinite(f); -} \ No newline at end of file +} + +bool CMath::strtof(const char* str, float32_t* result) +{ + ASSERT(str); + ASSERT(result); + + SGVector buf(strlen(str)+1); + + for (index_t i=0; i buf(strlen(str)+1); + + for (index_t i=0; i buf(strlen(str)+1); + + for (index_t i=0; i -#define NAN (strtod("NAN",NULL)) -#endif - /* Size of RNG seed */ #define RNG_SEED_SIZE 256 @@ -507,6 +502,10 @@ class CMath : public CSGObject return area; } + static bool strtof(const char* str, float32_t* result); + static bool strtod(const char* str, float64_t* result); + static bool strtold(const char* str, floatmax_t* result); + static inline int64_t factorial(int32_t n) { int64_t res=1; @@ -1259,7 +1258,7 @@ class CMath : public CSGObject if (!CMath::is_finite(q)) { SG_SWARNING("INVALID second operand to logsum(%f,%f) expect undefined results\n", p, q) - return NAN; + return NOT_A_NUMBER; } diff = p - q; if (diff > 0) @@ -1325,6 +1324,8 @@ class CMath : public CSGObject public: /**@name constants*/ //@{ + /// not a number + static const float64_t NOT_A_NUMBER; /// infinity static const float64_t INFTY; static const float64_t ALMOST_INFTY; diff --git a/tests/unit/mathematics/Math_unittest.cc b/tests/unit/mathematics/Math_unittest.cc index 29b391e157f..8dcc69fedd0 100644 --- a/tests/unit/mathematics/Math_unittest.cc +++ b/tests/unit/mathematics/Math_unittest.cc @@ -164,3 +164,51 @@ TEST(CMath, log_mean_exp) values.range_fill(); EXPECT_NEAR(CMath::log_mean_exp(values), 1.3089936757762706, 1e-15); } + +TEST(CMath, strtofloat) +{ + float32_t float_result = 0; + EXPECT_TRUE(CMath::strtof("nan", &float_result)); + EXPECT_TRUE(CMath::is_nan(float_result)); + + EXPECT_TRUE(CMath::strtof("inf", &float_result)); + EXPECT_TRUE(CMath::is_infinity(float_result)); + + EXPECT_TRUE(CMath::strtof("-inf", &float_result)); + EXPECT_DOUBLE_EQ(-CMath::INFTY, float_result); + + EXPECT_TRUE(CMath::strtof("1.2345", &float_result)); + EXPECT_FLOAT_EQ(1.2345, float_result); +} + +TEST(CMath, strtodouble) +{ + float64_t double_result = 0; + EXPECT_TRUE(CMath::strtod("nan", &double_result)); + EXPECT_TRUE(CMath::is_nan(double_result)); + + EXPECT_TRUE(CMath::strtod("inf", &double_result)); + EXPECT_TRUE(CMath::is_infinity(double_result)); + + EXPECT_TRUE(CMath::strtod("-inf", &double_result)); + EXPECT_DOUBLE_EQ(-CMath::INFTY, double_result); + + EXPECT_TRUE(CMath::strtod("1.234567890123", &double_result)); + EXPECT_DOUBLE_EQ(1.234567890123, double_result); +} + +TEST(CMath, strtolongdouble) +{ + floatmax_t long_double_result = 0; + EXPECT_TRUE(CMath::strtold("nan", &long_double_result)); + EXPECT_TRUE(CMath::is_nan(long_double_result)); + + EXPECT_TRUE(CMath::strtold("inf", &long_double_result)); + EXPECT_TRUE(CMath::is_infinity(long_double_result)); + + EXPECT_TRUE(CMath::strtold("-inf", &long_double_result)); + EXPECT_DOUBLE_EQ(-CMath::INFTY, long_double_result); + + EXPECT_TRUE(CMath::strtold("1.234567890123", &long_double_result)); + EXPECT_EQ(long_double_result, 1.234567890123); +}