Skip to content

Commit 2735cfc

Browse files
cleanup and address comments
1 parent 4e860d7 commit 2735cfc

File tree

3 files changed

+53
-105
lines changed

3 files changed

+53
-105
lines changed

libc/src/__support/UInt.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,15 @@ template <size_t Bits, bool Signed> struct BigInt {
2929

3030
// This being hardcoded as 64 is okay because we're using uint64_t as our
3131
// internal type which will always be 64 bits.
32-
LIBC_INLINE_VAR static constexpr size_t WORD_SIZE = 64;
32+
using word_type = uint64_t;
33+
LIBC_INLINE_VAR static constexpr size_t WORD_SIZE =
34+
sizeof(word_type) * CHAR_BIT;
3335

34-
// TODO: Replace references to 64 with WORD_SIZE.
36+
// TODO: Replace references to 64 with WORD_SIZE, and uint64_t with word_type.
3537
static_assert(Bits > 0 && Bits % 64 == 0,
3638
"Number of bits in BigInt should be a multiple of 64.");
3739
LIBC_INLINE_VAR static constexpr size_t WORDCOUNT = Bits / 64;
38-
cpp::array<uint64_t, WORDCOUNT> val{};
40+
cpp::array<word_type, WORDCOUNT> val{};
3941

4042
LIBC_INLINE_VAR static constexpr uint64_t MASK32 = 0xFFFFFFFFu;
4143

libc/src/__support/float_to_string.h

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include <stdint.h>
1313

14+
#include "src/__support/CPP/limits.h"
1415
#include "src/__support/CPP/type_traits.h"
1516
#include "src/__support/FPUtil/FPBits.h"
1617
#include "src/__support/FPUtil/dyadic_float.h"
@@ -108,6 +109,8 @@ namespace LIBC_NAMESPACE {
108109

109110
using BlockInt = uint32_t;
110111
constexpr uint32_t BLOCK_SIZE = 9;
112+
constexpr uint64_t EXP5_9 = 1953125;
113+
constexpr uint64_t EXP10_9 = 1000000000;
111114

112115
using FPBits = fputil::FPBits<long double>;
113116

@@ -118,7 +121,7 @@ constexpr size_t CALC_SHIFT_CONST = 128;
118121
namespace internal {
119122

120123
// Returns floor(log_10(2^e)); requires 0 <= e <= 42039.
121-
LIBC_INLINE constexpr uint32_t log10_pow2(const uint64_t e) {
124+
LIBC_INLINE constexpr uint32_t log10_pow2(uint64_t e) {
122125
LIBC_ASSERT(e <= 42039 &&
123126
"Incorrect exponent to perform log10_pow2 approximation.");
124127
// This approximation is based on the float value for log_10(2). It first
@@ -144,27 +147,26 @@ LIBC_INLINE constexpr uint32_t log10_pow2(const uint64_t e) {
144147
}
145148

146149
// Same as above, but with different constants.
147-
LIBC_INLINE constexpr uint32_t log2_pow5(const uint64_t e) {
150+
LIBC_INLINE constexpr uint32_t log2_pow5(uint64_t e) {
148151
return static_cast<uint32_t>((e * 0x12934f0979bll) >> 39);
149152
}
150153

151154
// Returns 1 + floor(log_10(2^e). This could technically be off by 1 if any
152155
// power of 2 was also a power of 10, but since that doesn't exist this is
153156
// always accurate. This is used to calculate the maximum number of base-10
154157
// digits a given e-bit number could have.
155-
LIBC_INLINE constexpr uint32_t ceil_log10_pow2(const uint32_t e) {
158+
LIBC_INLINE constexpr uint32_t ceil_log10_pow2(uint32_t e) {
156159
return log10_pow2(e) + 1;
157160
}
158161

159-
LIBC_INLINE constexpr uint32_t div_ceil(const uint32_t num,
160-
const uint32_t denom) {
162+
LIBC_INLINE constexpr uint32_t div_ceil(uint32_t num, uint32_t denom) {
161163
return (num + (denom - 1)) / denom;
162164
}
163165

164166
// Returns the maximum number of 9 digit blocks a number described by the given
165167
// index (which is ceil(exponent/16)) and mantissa width could need.
166-
LIBC_INLINE constexpr uint32_t length_for_num(const uint32_t idx,
167-
const uint32_t mantissa_width) {
168+
LIBC_INLINE constexpr uint32_t length_for_num(uint32_t idx,
169+
uint32_t mantissa_width) {
168170
return div_ceil(ceil_log10_pow2(idx) + ceil_log10_pow2(mantissa_width + 1),
169171
BLOCK_SIZE);
170172
}
@@ -194,24 +196,21 @@ LIBC_INLINE constexpr cpp::UInt<MID_INT_SIZE> get_table_positive(int exponent,
194196
// can get, since it needs to be small enough to fit in the result UInt,
195197
// otherwise we'll get truncation on return.
196198
constexpr cpp::UInt<INT_SIZE> MOD_SIZE =
197-
(cpp::UInt<INT_SIZE>(1000000000)
199+
(cpp::UInt<INT_SIZE>(EXP10_9)
198200
<< (CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0)));
199201

200-
constexpr uint64_t FIVE_EXP_NINE = 1953125;
201-
202202
num = cpp::UInt<INT_SIZE>(1) << (shift_amount);
203203
if (i > 0) {
204-
cpp::UInt<INT_SIZE> fives(FIVE_EXP_NINE);
204+
cpp::UInt<INT_SIZE> fives(EXP5_9);
205205
fives.pow_n(i);
206206
num = num / fives;
207207
}
208208

209209
num = num + 1;
210210
if (num > MOD_SIZE) {
211-
auto rem =
212-
num.div_uint32_times_pow_2(
213-
1000000000, CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0))
214-
.value();
211+
auto rem = num.div_uint32_times_pow_2(
212+
EXP10_9, CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0))
213+
.value();
215214
num = rem;
216215
}
217216
return num;
@@ -235,7 +234,7 @@ LIBC_INLINE cpp::UInt<MID_INT_SIZE> get_table_positive_df(int exponent,
235234
}
236235
fputil::DyadicFloat<INT_SIZE> num(false, 0, 1);
237236
constexpr cpp::UInt<INT_SIZE> MOD_SIZE =
238-
(cpp::UInt<INT_SIZE>(1000000000)
237+
(cpp::UInt<INT_SIZE>(EXP10_9)
239238
<< (CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0)));
240239

241240
constexpr cpp::UInt<INT_SIZE> FIVE_EXP_MINUS_NINE_MANT{
@@ -256,8 +255,8 @@ LIBC_INLINE cpp::UInt<MID_INT_SIZE> get_table_positive_df(int exponent,
256255
if (int_num > MOD_SIZE) {
257256
auto rem =
258257
int_num
259-
.div_uint32_times_pow_2(
260-
1000000000, CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0))
258+
.div_uint32_times_pow_2(EXP10_9, CALC_SHIFT_CONST +
259+
(IDX_SIZE > 1 ? IDX_SIZE : 0))
261260
.value();
262261
int_num = rem;
263262
}
@@ -280,11 +279,9 @@ LIBC_INLINE cpp::UInt<MID_INT_SIZE> get_table_negative(int exponent, size_t i) {
280279
int shift_amount = CALC_SHIFT_CONST - exponent;
281280
cpp::UInt<INT_SIZE> num(1);
282281
constexpr cpp::UInt<INT_SIZE> MOD_SIZE =
283-
(cpp::UInt<INT_SIZE>(1000000000)
282+
(cpp::UInt<INT_SIZE>(EXP10_9)
284283
<< (CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0)));
285284

286-
constexpr uint64_t TEN_EXP_NINE = 1000000000;
287-
constexpr uint64_t FIVE_EXP_NINE = 1953125;
288285
size_t ten_blocks = i;
289286
size_t five_blocks = 0;
290287
if (shift_amount < 0) {
@@ -301,12 +298,12 @@ LIBC_INLINE cpp::UInt<MID_INT_SIZE> get_table_negative(int exponent, size_t i) {
301298
}
302299

303300
if (five_blocks > 0) {
304-
cpp::UInt<INT_SIZE> fives(FIVE_EXP_NINE);
301+
cpp::UInt<INT_SIZE> fives(EXP5_9);
305302
fives.pow_n(five_blocks);
306303
num = fives;
307304
}
308305
if (ten_blocks > 0) {
309-
cpp::UInt<INT_SIZE> tens(TEN_EXP_NINE);
306+
cpp::UInt<INT_SIZE> tens(EXP10_9);
310307
tens.pow_n(ten_blocks);
311308
if (five_blocks <= 0) {
312309
num = tens;
@@ -321,10 +318,9 @@ LIBC_INLINE cpp::UInt<MID_INT_SIZE> get_table_negative(int exponent, size_t i) {
321318
num = num >> (-shift_amount);
322319
}
323320
if (num > MOD_SIZE) {
324-
auto rem =
325-
num.div_uint32_times_pow_2(
326-
1000000000, CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0))
327-
.value();
321+
auto rem = num.div_uint32_times_pow_2(
322+
EXP10_9, CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0))
323+
.value();
328324
num = rem;
329325
}
330326
return num;
@@ -346,10 +342,10 @@ LIBC_INLINE cpp::UInt<MID_INT_SIZE> get_table_negative_df(int exponent,
346342

347343
fputil::DyadicFloat<INT_SIZE> num(false, 0, 1);
348344
constexpr cpp::UInt<INT_SIZE> MOD_SIZE =
349-
(cpp::UInt<INT_SIZE>(1000000000)
345+
(cpp::UInt<INT_SIZE>(EXP10_9)
350346
<< (CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0)));
351347

352-
constexpr cpp::UInt<INT_SIZE> TEN_EXP_NINE_MANT(1000000000);
348+
constexpr cpp::UInt<INT_SIZE> TEN_EXP_NINE_MANT(EXP10_9);
353349

354350
static const fputil::DyadicFloat<INT_SIZE> TEN_EXP_NINE(false, 0,
355351
TEN_EXP_NINE_MANT);
@@ -364,8 +360,8 @@ LIBC_INLINE cpp::UInt<MID_INT_SIZE> get_table_negative_df(int exponent,
364360
if (int_num > MOD_SIZE) {
365361
auto rem =
366362
int_num
367-
.div_uint32_times_pow_2(
368-
1000000000, CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0))
363+
.div_uint32_times_pow_2(EXP10_9, CALC_SHIFT_CONST +
364+
(IDX_SIZE > 1 ? IDX_SIZE : 0))
369365
.value();
370366
int_num = rem;
371367
}
@@ -385,16 +381,15 @@ LIBC_INLINE uint32_t fast_uint_mod_1e9(const cpp::UInt<MID_INT_SIZE> &val) {
385381
const uint64_t result = static_cast<uint64_t>(middle[2]);
386382
const uint64_t shifted = result >> 29;
387383
return static_cast<uint32_t>(static_cast<uint32_t>(val) -
388-
(1000000000 * shifted));
384+
(EXP10_9 * shifted));
389385
}
390386

391387
LIBC_INLINE uint32_t mul_shift_mod_1e9(const FPBits::StorageType mantissa,
392388
const cpp::UInt<MID_INT_SIZE> &large,
393389
const int32_t shift_amount) {
394390
cpp::UInt<MID_INT_SIZE + FPBits::STORAGE_LEN> val(large);
395391
val = (val * mantissa) >> shift_amount;
396-
return static_cast<uint32_t>(
397-
val.div_uint32_times_pow_2(1000000000, 0).value());
392+
return static_cast<uint32_t>(val.div_uint32_times_pow_2(EXP10_9, 0).value());
398393
}
399394

400395
} // namespace internal
@@ -623,6 +618,11 @@ class FloatToString {
623618
!defined(LIBC_COPT_FLOAT_TO_STR_NO_SPECIALIZE_LD)
624619
// --------------------------- LONG DOUBLE FUNCTIONS ---------------------------
625620

621+
// this algorithm will work exactly the same for 80 bit and 128 bit long
622+
// doubles. They have the same max exponent, but even if they didn't the
623+
// constants should be calculated to be correct for any provided floating point
624+
// type.
625+
626626
template <> class FloatToString<long double> {
627627
fputil::FPBits<long double> float_bits;
628628
bool is_negative = 0;
@@ -631,19 +631,23 @@ template <> class FloatToString<long double> {
631631

632632
static constexpr int FRACTION_LEN = fputil::FPBits<long double>::FRACTION_LEN;
633633
static constexpr int EXP_BIAS = fputil::FPBits<long double>::EXP_BIAS;
634+
static constexpr size_t UINT_WORD_SIZE = 64;
634635

635636
static constexpr size_t FLOAT_AS_INT_WIDTH =
636637
internal::div_ceil(fputil::FPBits<long double>::MAX_BIASED_EXPONENT -
637638
FPBits::EXP_BIAS,
638-
64) *
639-
64;
639+
UINT_WORD_SIZE) *
640+
UINT_WORD_SIZE;
640641
static constexpr size_t EXTRA_INT_WIDTH =
641-
internal::div_ceil(sizeof(long double) * 8, 64) * 64;
642+
internal::div_ceil(sizeof(long double) * CHAR_BIT, UINT_WORD_SIZE) *
643+
UINT_WORD_SIZE;
644+
645+
using wide_int = cpp::UInt<FLOAT_AS_INT_WIDTH + EXTRA_INT_WIDTH>;
642646

643647
// float_as_fixed represents the floating point number as a fixed point number
644648
// with the point EXTRA_INT_WIDTH bits from the left of the number. This can
645649
// store any number with a negative exponent.
646-
cpp::UInt<FLOAT_AS_INT_WIDTH + EXTRA_INT_WIDTH> float_as_fixed = 0;
650+
wide_int float_as_fixed = 0;
647651
int int_block_index = 0;
648652

649653
static constexpr size_t BLOCK_BUFFER_LEN =
@@ -653,19 +657,18 @@ template <> class FloatToString<long double> {
653657

654658
template <size_t Bits>
655659
LIBC_INLINE static constexpr BlockInt grab_digits(cpp::UInt<Bits> &int_num) {
656-
auto wide_result = int_num.div_uint32_times_pow_2(1953125, 9);
660+
auto wide_result = int_num.div_uint32_times_pow_2(EXP5_9, 9);
657661
// the optional only comes into effect when dividing by 0, which will
658662
// never happen here. Thus, we just assert that it has value.
659663
LIBC_ASSERT(wide_result.has_value());
660664
return static_cast<BlockInt>(wide_result.value());
661665
}
662666

663-
LIBC_INLINE static constexpr void zero_leading_digits(
664-
cpp::UInt<FLOAT_AS_INT_WIDTH + EXTRA_INT_WIDTH> &int_num) {
667+
LIBC_INLINE static constexpr void zero_leading_digits(wide_int &int_num) {
665668
// WORD_SIZE is the width of the numbers used to internally represent the
666669
// UInt
667-
for (size_t i = 0; i < EXTRA_INT_WIDTH / int_num.WORD_SIZE; ++i)
668-
int_num[i + (FLOAT_AS_INT_WIDTH / int_num.WORD_SIZE)] = 0;
670+
for (size_t i = 0; i < EXTRA_INT_WIDTH / wide_int::WORD_SIZE; ++i)
671+
int_num[i + (FLOAT_AS_INT_WIDTH / wide_int::WORD_SIZE)] = 0;
669672
}
670673

671674
// init_convert initializes float_as_int, cur_block, and block_buffer based on
@@ -684,7 +687,7 @@ template <> class FloatToString<long double> {
684687
// from left to right, so it caches the results so they can be read in
685688
// reverse order.
686689

687-
cpp::UInt<FLOAT_AS_INT_WIDTH + EXTRA_INT_WIDTH> float_as_int = mantissa;
690+
wide_int float_as_int = mantissa;
688691

689692
float_as_int.shift_left(exponent);
690693
int_block_index = 0;
@@ -812,7 +815,7 @@ template <> class FloatToString<long double> {
812815
// requested block. This is likely to only be one step.
813816
while (block_index < int_block_index) {
814817
zero_leading_digits(float_as_fixed);
815-
float_as_fixed.mul(1000000000);
818+
float_as_fixed.mul(EXP10_9);
816819
--int_block_index;
817820
}
818821

libc/test/src/stdio/sprintf_test.cpp

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1803,35 +1803,6 @@ TEST_F(LlvmLibcSPrintfTest, FloatDecimalLongDoubleConv) {
18031803
"422771447006016890777855573925295187921971811871399320142563330377888532"
18041804
"179817332113");
18051805
#endif // LIBC_LONG_DOUBLE_IS_X86_FLOAT80
1806-
1807-
/*
1808-
written = LIBC_NAMESPACE::sprintf(buff, "%La", 0.1L);
1809-
#if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80)
1810-
ASSERT_STREQ_LEN(written, buff, "0xc.ccccccccccccccdp-7");
1811-
#elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64)
1812-
ASSERT_STREQ_LEN(written, buff, "0x1.999999999999ap-4");
1813-
#else // 128 bit long double
1814-
ASSERT_STREQ_LEN(written, buff, "0x1.999999999999999999999999999ap-4");
1815-
#endif
1816-
1817-
written = LIBC_NAMESPACE::sprintf(buff, "%La", 1.0e1000L);
1818-
#if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80)
1819-
ASSERT_STREQ_LEN(written, buff, "0xf.38db1f9dd3dac05p+3318");
1820-
#elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64)
1821-
ASSERT_STREQ_LEN(written, buff, "inf");
1822-
#else // 128 bit long double
1823-
ASSERT_STREQ_LEN(written, buff, "0x1.e71b63f3ba7b580af1a52d2a7379p+3321");
1824-
#endif
1825-
1826-
written = LIBC_NAMESPACE::sprintf(buff, "%La", 1.0e-1000L);
1827-
#if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80)
1828-
ASSERT_STREQ_LEN(written, buff, "0x8.68a9188a89e1467p-3325");
1829-
#elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64)
1830-
ASSERT_STREQ_LEN(written, buff, "0x0p+0");
1831-
#else // 128 bit long double
1832-
ASSERT_STREQ_LEN(written, buff, "0x1.0d152311513c28ce202627c06ec2p-3322");
1833-
#endif
1834-
*/
18351806
}
18361807

18371808
TEST_F(LlvmLibcSPrintfTest, FloatExponentConv) {
@@ -2441,34 +2412,6 @@ TEST_F(LlvmLibcSPrintfTest, FloatExponentLongDoubleConv) {
24412412
"231934194956788626761834746430104077432547436359522462253411168467463134"
24422413
"24896.000000");
24432414
*/
2444-
/*
2445-
written = LIBC_NAMESPACE::sprintf(buff, "%La", 0.1L);
2446-
#if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80)
2447-
ASSERT_STREQ_LEN(written, buff, "0xc.ccccccccccccccdp-7");
2448-
#elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64)
2449-
ASSERT_STREQ_LEN(written, buff, "0x1.999999999999ap-4");
2450-
#else // 128 bit long double
2451-
ASSERT_STREQ_LEN(written, buff, "0x1.999999999999999999999999999ap-4");
2452-
#endif
2453-
2454-
written = LIBC_NAMESPACE::sprintf(buff, "%La", 1.0e1000L);
2455-
#if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80)
2456-
ASSERT_STREQ_LEN(written, buff, "0xf.38db1f9dd3dac05p+3318");
2457-
#elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64)
2458-
ASSERT_STREQ_LEN(written, buff, "inf");
2459-
#else // 128 bit long double
2460-
ASSERT_STREQ_LEN(written, buff, "0x1.e71b63f3ba7b580af1a52d2a7379p+3321");
2461-
#endif
2462-
2463-
written = LIBC_NAMESPACE::sprintf(buff, "%La", 1.0e-1000L);
2464-
#if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80)
2465-
ASSERT_STREQ_LEN(written, buff, "0x8.68a9188a89e1467p-3325");
2466-
#elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64)
2467-
ASSERT_STREQ_LEN(written, buff, "0x0p+0");
2468-
#else // 128 bit long double
2469-
ASSERT_STREQ_LEN(written, buff, "0x1.0d152311513c28ce202627c06ec2p-3322");
2470-
#endif
2471-
*/
24722415
}
24732416

24742417
TEST_F(LlvmLibcSPrintfTest, FloatAutoConv) {

0 commit comments

Comments
 (0)