Partially fix printf hex float numbers/%a rounding (#1286)

Hexadecimal printing of floating-point numbers in cosmopolitan (that is,
using the the conversion specifier) is improved to have correct rounding
of results in rounding modes other than the default one (ie. FE_NEAREST)

This commit fixes that, and adds tests for the change (note that there's
still some rounding issues with the a conversion specifier in general in
relatively rare cases (that is without non-default rounding modes) where
I've left commented-out tests for anyone interested in improving it more
This commit is contained in:
Gabriel Ravier 2024-09-11 05:42:52 +02:00 committed by GitHub
parent 51c0f44d1c
commit 4d05060aac
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 61 additions and 8 deletions

View file

@ -216,3 +216,37 @@ TEST(snprintf, testLongDoubleRounding) {
ASSERT_EQ(0, fesetround(previous_rounding));
}
TEST(snprintf, testAConversionSpecifierRounding) {
int previous_rounding = fegetround();
ASSERT_EQ(0, fesetround(FE_DOWNWARD));
char buf[20];
int i = snprintf(buf, sizeof(buf), "%.1a", 0x1.fffffp+4);
ASSERT_EQ(8, i);
ASSERT_STREQ("0x1.fp+4", buf);
ASSERT_EQ(0, fesetround(FE_UPWARD));
i = snprintf(buf, sizeof(buf), "%.1a", 0x1.f8p+4);
ASSERT_EQ(8, i);
ASSERT_STREQ("0x2.0p+4", buf);
ASSERT_EQ(0, fesetround(previous_rounding));
}
// This test currently fails because of rounding issues
// If that ever gets fixed, uncomment this
/*
TEST(snprintf, testAConversionSpecifier) {
char buf[20];
int i = snprintf(buf, sizeof(buf), "%.1a", 0x1.7800000000001p+4);
ASSERT_EQ(8, i);
ASSERT_STREQ("0x1.8p+4", buf);
memset(buf, 0, sizeof(buf));
i = snprintf(buf, sizeof(buf), "%.1a", 0x1.78p+4);
ASSERT_EQ(8, i);
ASSERT_STREQ("0x1.8p+4", buf);
}
*/