This is an archive of the discontinued LLVM Phabricator instance.

[libc] add options to printf decimal floats
ClosedPublic

Authored by michaelrj on May 11 2023, 2:18 PM.

Details

Summary

This patch adds three options for printf decimal long doubles, and these
can also apply to doubles.

  1. Use a giant table which is fast and accurate, but takes up ~5MB).
  2. Use dyadic floats for approximations, which only gives ~50 digits of accuracy but is very fast.
  3. Use large integers for approximations, which is accurate but very slow.

Diff Detail

Event Timeline

michaelrj created this revision.May 11 2023, 2:18 PM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptMay 11 2023, 2:18 PM
michaelrj requested review of this revision.May 11 2023, 2:18 PM

Currently ryu_long_double_constants is empty, this is because it's 12 megabytes and arcanist complains when I try to upload it. I can add it for testing purposes, or you can generate it yourself with ryu_tablegen.py. It writes to the console so pipe it to a file. You'll also need to set POW10_ADDITIONAL_BITS_TABLE to 120, IDX_SIZE to 128, and MID_INT_SIZE to 320 in ryu_long_double_constants.h.

This patch isn't quite done yet, I still need to add an interface for the compile flags, but I wanted to get it out so that other people can review the math and overall design.

lntue added inline comments.May 11 2023, 9:51 PM
libc/src/__support/float_to_string.h
220

You could also mention that 50 digits is more than enough for the round trip long double -> decimal string -> long double to be correct, even when long double is quad precision (i.e. float128).

242

You can add a mul_pow_2 method that simply adds the exponent field in-place for a DyadicFloat.

michaelrj updated this revision to Diff 523605.May 18 2023, 4:57 PM
michaelrj marked 2 inline comments as done.

cleanup for all three modes after some testing.

lntue accepted this revision.May 18 2023, 5:29 PM
lntue added inline comments.
libc/src/__support/float_to_string.h
608–613

Are those still relevant?

640–645

Are those still relevant?

668

The definitions of shift_amount are the same in all branches?

717

The definitions of shift_amount are the same in all branches?

This revision is now accepted and ready to land.May 18 2023, 5:29 PM
michaelrj added inline comments.May 19 2023, 3:48 PM
libc/src/__support/float_to_string.h
668

not quite, the table mode shift_amount uses POW10_ADDITIONAL_BITS_TABLE instead of POW10_ADDITIONAL_BITS_CALC. I'm going to rename those variables to avoid this confusion.

michaelrj updated this revision to Diff 525772.May 25 2023, 1:28 PM

updates and cleanup

lntue added inline comments.May 25 2023, 3:07 PM
libc/src/__support/FPUtil/dyadic_float.h
128

Use in-place <<= or add it to UInt if missing.

130

Use in-place >>= or add it to UInt if missing.

libc/src/__support/float_to_string.h
190

I'm just curious, will changing from 1000000000 * 2^(...) to 1953125 * 2^(... + 9) has any affect, like performance or accuracy? Same with other instances below.

393

Use val.div_uint32_times_pow_2(1000000000, 0) to speed up?

michaelrj updated this revision to Diff 525852.May 25 2023, 3:59 PM
michaelrj marked 6 inline comments as done.

address comments, still need to mess with the is_lowest_block and zero_blocks_after_point functions. They aren't strictly necessary, but they do provide significant speed improvements.

libc/src/__support/float_to_string.h
190

This number is constexpr, so there should be no change.

640–645

I need to see if I can fix their calculations to make them work, but they should speed up the int mode.

sivachandra accepted this revision.Jun 7 2023, 12:55 AM

Just minor comments but LGTM.

libc/src/__support/float_to_string.h
21

s/LIBC_COPT_FLOAT_TO_STR_USE_MEGA_TABLE/LIBC_COPT_FLOAT_TO_STR_USE_LARGE_LONG_DOUBLE_TABLE

473

Add commentary about how the options here compare.

libc/utils/mathtools/ryu_tablegen.py
2

Add comments about usage of this script.

utils/bazel/llvm-project-overlay/libc/BUILD.bazel
315

Either remove or add comments about why this is commented out.

michaelrj updated this revision to Diff 529443.Jun 7 2023, 2:49 PM
michaelrj marked 4 inline comments as done.

add comments explaining compile flags in float_to_string.h and the constants in ryu_tablegen.py

libc/src/__support/float_to_string.h
21

I like the name MEGA_TABLE since the table is several megabytes in size. Additionally, when the mega table is enabled it's used for both doubles and long doubles.

473

I've added it to the top of the file.

sivachandra added inline comments.Jun 8 2023, 1:08 AM
libc/src/__support/float_to_string.h
21

You can choose to keep MEGA in there but the name should reflect that it is about long doubles. So, I suggest to make it: ..._USE_MEGA_LONG_DOUBLE_TABLE.

michaelrj updated this revision to Diff 529675.Jun 8 2023, 10:38 AM

rename to LIBC_COPT_FLOAT_TO_STR_USE_MEGA_LONG_DOUBLE_TABLE

sivachandra accepted this revision.Jun 8 2023, 10:46 AM
This revision was landed with ongoing or failed builds.Jun 8 2023, 2:23 PM
This revision was automatically updated to reflect the committed changes.