Conversation
|
Sorry for the CI failures. That said, I recommend adding to |
|
Thanks for the PR! Could you check how it performs on itoa-benchmark (https://github.com/fmtlib/format-benchmark/tree/master/src/itoa-benchmark)? |
|
I made a pull request fmtlib/format-benchmark#31 that adds |
|
Thanks for adding fmt to itoa-benchmark. Have you checked the results of your change there and could you post them here? |
|
Anyway, I merged it and will take a closer look at the whole numeric formatting later. Thanks! |
|
Sorry, I forget about this. That said, looking at the output of itoa-benchmark: why are |
|
It's been a while since I looked at it but IIRC some of those methods only performed well for fixed number of digits due to excessive branching (which wasn't reflected in that particular benchmark). In any case, I plan to revamp numeric formatting and currently looking into FP (https://github.com/vitaut/zmij) with integer to follow. |
| // the decimal point of i / 100 in base 2, the first 2 bytes | ||
| // after digits2_i(x) is the string representation of i. | ||
| inline auto digits2_i(size_t value) -> const char* { | ||
| alignas(2) static const char data[] = |
There was a problem hiding this comment.
Any reason not to make this array constexpr? I think this might enable certain compiler to do static compile time bounds checks if it's constexpr, especially if the whole function is constexpr.
Actually, I see why this done given the C++14 compatibiltiy requirements? Frustrating though as they could be merged easier across translation units otherwise in C++17 or newer.
There was a problem hiding this comment.
Should probably mark as noexcept though like the following for consistency: 3269c1c#diff-bdc6f79e8e9f5b4331d66fb785636a87d29f55cf729865e13925b4209424c878R1033
There was a problem hiding this comment.
I copy the style of digits2 function where the data array is not constexpr. I don't know what the compatibility requirement is exactly. If this array can be changed to constexpr then similar arrays should be as well.
Edit: hm, maybe the noexcept wasn't in digits2 when I looked.
Minor speedup.
Before (using https://github.com/fmtlib/format-benchmark):
After:
The idea is to avoid the modulo (which gets compiled to a
imuland asub) by looking at the 7 bits after the decimal point ofvalue / 100.This adds 256+1 bytes worth of lookup table (the old lookup table still need to stay there, unfortunately). Although technically the null terminator and the last 2 spaces are unused.
Correctness is shown by exhaustively search through the whole range of 32-bit integers and ensure that for all
i,(i * ((1ull<<39)/100+1)) >> (39 - 7) & ((1<<7) - 1)uniquely determines the value ofi % 100and((i * ((1ull<<39)/100+1)) >> 39) + ((i>=(100u<<25))<<25)is exactly equal toi / 100.The check
sizeof(UInt) == 4implicitly assumesCHAR_BIT == 8(is it worth being spelled out?)Source code of brute force checker
Future work:
write_significand__int128).note:
digits2_iis not constexpr (before C++20)write2digits_iis not constexpr either, so there's no need for thestd::is_constant_evaluatedmemcpyifFMT_OPTIMIZE_SIZEis true, butwrite2digitsdo that.hofman_funwill always be slower.