mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-07 17:26:51 +08:00
Merge pull request #186 from leni536/negative_zero_clang
Fix parsing -0 on clang in non-nearest rounding modes.
This commit is contained in:
commit
c09c855ea6
@ -191,7 +191,7 @@ from_chars_result from_chars_advanced(const char *first, const char *last,
|
|||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
// Clang may map 0 to -0.0 when fegetround() == FE_DOWNWARD
|
// Clang may map 0 to -0.0 when fegetround() == FE_DOWNWARD
|
||||||
if(pns.mantissa == 0) {
|
if(pns.mantissa == 0) {
|
||||||
value = 0;
|
value = pns.negative ? -0. : 0.;
|
||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -184,6 +184,53 @@ TEST_CASE("parse_zero") {
|
|||||||
CHECK(float64_parsed == 0);
|
CHECK(float64_parsed == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("parse_negative_zero") {
|
||||||
|
//
|
||||||
|
// If this function fails, we may be left in a non-standard rounding state.
|
||||||
|
//
|
||||||
|
const char * negative_zero = "-0";
|
||||||
|
uint64_t float64_parsed;
|
||||||
|
double f = -0.;
|
||||||
|
::memcpy(&float64_parsed, &f, sizeof(f));
|
||||||
|
CHECK(float64_parsed == 0x8000'0000'0000'0000);
|
||||||
|
|
||||||
|
fesetround(FE_UPWARD);
|
||||||
|
auto r1 = fast_float::from_chars(negative_zero, negative_zero + 2, f);
|
||||||
|
CHECK(r1.ec == std::errc());
|
||||||
|
std::cout << "FE_UPWARD parsed negative zero as " << iHexAndDec(f) << std::endl;
|
||||||
|
CHECK(f == 0);
|
||||||
|
::memcpy(&float64_parsed, &f, sizeof(f));
|
||||||
|
std::cout << "double as uint64_t is " << float64_parsed << std::endl;
|
||||||
|
CHECK(float64_parsed == 0x8000'0000'0000'0000);
|
||||||
|
|
||||||
|
fesetround(FE_TOWARDZERO);
|
||||||
|
auto r2 = fast_float::from_chars(negative_zero, negative_zero + 2, f);
|
||||||
|
CHECK(r2.ec == std::errc());
|
||||||
|
std::cout << "FE_TOWARDZERO parsed negative zero as " << iHexAndDec(f) << std::endl;
|
||||||
|
CHECK(f == 0);
|
||||||
|
::memcpy(&float64_parsed, &f, sizeof(f));
|
||||||
|
std::cout << "double as uint64_t is " << float64_parsed << std::endl;
|
||||||
|
CHECK(float64_parsed == 0x8000'0000'0000'0000);
|
||||||
|
|
||||||
|
fesetround(FE_DOWNWARD);
|
||||||
|
auto r3 = fast_float::from_chars(negative_zero, negative_zero + 2, f);
|
||||||
|
CHECK(r3.ec == std::errc());
|
||||||
|
std::cout << "FE_DOWNWARD parsed negative zero as " << iHexAndDec(f) << std::endl;
|
||||||
|
CHECK(f == 0);
|
||||||
|
::memcpy(&float64_parsed, &f, sizeof(f));
|
||||||
|
std::cout << "double as uint64_t is " << float64_parsed << std::endl;
|
||||||
|
CHECK(float64_parsed == 0x8000'0000'0000'0000);
|
||||||
|
|
||||||
|
fesetround(FE_TONEAREST);
|
||||||
|
auto r4 = fast_float::from_chars(negative_zero, negative_zero + 2, f);
|
||||||
|
CHECK(r4.ec == std::errc());
|
||||||
|
std::cout << "FE_TONEAREST parsed negative zero as " << iHexAndDec(f) << std::endl;
|
||||||
|
CHECK(f == 0);
|
||||||
|
::memcpy(&float64_parsed, &f, sizeof(f));
|
||||||
|
std::cout << "double as uint64_t is " << float64_parsed << std::endl;
|
||||||
|
CHECK(float64_parsed == 0x8000'0000'0000'0000);
|
||||||
|
}
|
||||||
|
|
||||||
// C++ 17 because it is otherwise annoying to browse all files in a directory.
|
// C++ 17 because it is otherwise annoying to browse all files in a directory.
|
||||||
// We also only run these tests on little endian systems.
|
// We also only run these tests on little endian systems.
|
||||||
#if (FASTFLOAT_CPLUSPLUS >= 201703L) && (FASTFLOAT_IS_BIG_ENDIAN == 0) && !defined(FASTFLOAT_ODDPLATFORM)
|
#if (FASTFLOAT_CPLUSPLUS >= 201703L) && (FASTFLOAT_IS_BIG_ENDIAN == 0) && !defined(FASTFLOAT_ODDPLATFORM)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user