Fix for Win32+ClangCL

This commit is contained in:
Daniel Lemire 2022-11-16 14:35:31 -05:00
parent 95321767ee
commit d225059873
2 changed files with 35 additions and 0 deletions

View File

@ -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<T>::max_exponent_fast_path() && pns.mantissa <=binary_format<T>::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<T>::exact_power_of_ten(pns.exponent);
if (pns.negative) { value = -value; }
return answer;

View File

@ -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;