diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index 1340a0d..b5f92ce 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -135,7 +135,12 @@ from_chars_result from_chars_advanced(const char *first, const char *last, // We do not have that fegetround() == FE_TONEAREST. // Next is a modified Clinger's fast path, inspired by Jakub JelĂ­nek's proposal if (pns.exponent >= 0 && pns.exponent <= binary_format::max_exponent_fast_path() && pns.mantissa <=binary_format::max_mantissa_fast_path(pns.exponent) && !pns.too_many_digits) { +#if (defined(_WIN32) && defined(__clang__)) + // 32-bit ClangCL maps 0 to -0.0 when fegetround() == FE_DOWNWARD + value = pns.mantissa ? T(pns.mantissa) : 0.0; +#else value = T(pns.mantissa); +#endif value = value * binary_format::exact_power_of_ten(pns.exponent); if (pns.negative) { value = -value; } return answer; diff --git a/tests/basictest.cpp b/tests/basictest.cpp index d79fb82..980ead1 100644 --- a/tests/basictest.cpp +++ b/tests/basictest.cpp @@ -98,6 +98,36 @@ const char * round_name(int d) { } + +TEST_CASE("parse_zero") { + // + // If this function fails, we may be left in a non-standard rounding state. + // + const char * zero = "0"; + double f = 0; + fesetround(FE_UPWARD); + auto r1 = fast_float::from_chars(zero, zero + 1, f); + CHECK(r1.ec == std::errc()); + std::cout << "FE_UPWARD parsed zero as " << iHexAndDec(f) << std::endl; + CHECK(f == 0); + fesetround(FE_TOWARDZERO); + auto r2 = fast_float::from_chars(zero, zero + 1, f); + CHECK(r2.ec == std::errc()); + std::cout << "FE_TOWARDZERO parsed zero as " << iHexAndDec(f) << std::endl; + CHECK(f == 0); + fesetround(FE_DOWNWARD); + auto r3 = fast_float::from_chars(zero, zero + 1, f); + CHECK(r3.ec == std::errc()); + std::cout << "FE_DOWNWARD parsed zero as " << iHexAndDec(f) << std::endl; + CHECK(f == 0); + fesetround(FE_TONEAREST); + auto r4 = fast_float::from_chars(zero, zero + 1, f); + CHECK(r4.ec == std::errc()); + std::cout << "FE_TONEAREST parsed zero as " << iHexAndDec(f) << std::endl; + CHECK(f == 0); +} + + // return true on success bool check_file(std::string file_name) { std::cout << "Checking " << file_name << std::endl;