Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions libc/src/__support/float_to_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -618,16 +618,18 @@ template <> class FloatToString<long double> {
fputil::FPBits<long double> float_bits;
bool is_negative = 0;
int exponent = 0;
FPBits::StorageType mantissa = 0;
fputil::FPBits<long double>::StorageType mantissa = 0;

static constexpr int FRACTION_LEN = fputil::FPBits<long double>::FRACTION_LEN;
static constexpr int EXP_BIAS = fputil::FPBits<long double>::EXP_BIAS;
static constexpr size_t UINT_WORD_SIZE = 64;

static constexpr size_t FLOAT_AS_INT_WIDTH =
internal::div_ceil(fputil::FPBits<long double>::MAX_BIASED_EXPONENT -
FPBits::EXP_BIAS,
UINT_WORD_SIZE) *
internal::div_ceil(
fputil::FPBits<long double>::MAX_BIASED_EXPONENT -
fputil::FPBits<long double>::EXP_BIAS +
FRACTION_LEN, // Add fraction len to provide space for subnormals.
UINT_WORD_SIZE) *
UINT_WORD_SIZE;
static constexpr size_t EXTRA_INT_WIDTH =
internal::div_ceil(sizeof(long double) * CHAR_BIT, UINT_WORD_SIZE) *
Expand Down Expand Up @@ -699,12 +701,11 @@ template <> class FloatToString<long double> {
float_as_fixed = mantissa;

const int SHIFT_AMOUNT = FLOAT_AS_INT_WIDTH + exponent;
// if the shift amount would be negative, then the shift would cause a
// loss of precision.
LIBC_ASSERT(SHIFT_AMOUNT >= 0);
static_assert(EXTRA_INT_WIDTH >= sizeof(long double) * 8);
if (SHIFT_AMOUNT > 0) {
float_as_fixed <<= SHIFT_AMOUNT;
} else {
float_as_fixed >>= -SHIFT_AMOUNT;
}
float_as_fixed <<= SHIFT_AMOUNT;

// If there are still digits above the decimal point, handle those.
if (cpp::countl_zero(float_as_fixed) <
Expand Down
12 changes: 12 additions & 0 deletions libc/test/src/stdio/sprintf_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2484,6 +2484,18 @@ TEST(LlvmLibcSPrintfTest, FloatExponentLongDoubleConv) {

written = LIBC_NAMESPACE::sprintf(buff, "%Le", 1.2345678e4900L);
ASSERT_STREQ_LEN(written, buff, "1.234568e+4900");

#ifndef LIBC_COPT_FLOAT_TO_STR_REDUCED_PRECISION
// Minimum normal + epsilon
written =
LIBC_NAMESPACE::sprintf(buff, "%.20Le", 3.36210314311209350663E-4932L);
ASSERT_STREQ_LEN(written, buff, "3.36210314311209350663e-4932");

// Minimum subnormal
written =
LIBC_NAMESPACE::sprintf(buff, "%.20Le", 3.64519953188247460253E-4951L);
ASSERT_STREQ_LEN(written, buff, "3.64519953188247460253e-4951");
#endif // LIBC_COPT_FLOAT_TO_STR_REDUCED_PRECISION
#endif
}

Expand Down
Loading