-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
To chars #160
To chars #160
Conversation
Interesting discovery, the std::to_char implementation (at least in GCC) is extremely large! I started working on the tests I am adding to our production pipeline and all of a sudden the tests blew up in size and wouldn't link. I had to erase most tests to get the size down so I could use bloaty and found this:
All the I've been using the charconv functions and been happy so far, but I never really deal with floating point since all our values are in fixed point representations. So maybe this implies that the flag should be over-ridable. So if floating point |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #160 +/- ##
==========================================
+ Coverage 93.87% 93.91% +0.04%
==========================================
Files 27 27
Lines 1664 1660 -4
==========================================
- Hits 1562 1559 -3
+ Misses 102 101 -1
Continue to review full report in Codecov by Sentry.
|
I think falling back to the constexpr functions is simplest and most portable. The issue with the large size of I'll see if I can rerun the benchmarks with that solution, to test the impact. Thanks for looking into this. Otherwise, it seems the Windows CI is broken, I don't think that's related to your PRs. I'll investigate separately. Edit: Yes, it's #140 again, with a newer version of MSVC. We need to disable the offending test with that version. I'll make a separate PR. |
The CI failures weren't related to this PR and have been fixed in Otherwise, I have benchmarked using Debug:
Release:
--> no significant change, so that would be a viable solution. |
I think in the end it is your decision but since there is minimal performance difference I would lean towards using the constexpr version so that those functions get more use and implicit testing. At least until C++23 wide support and you could just use to_char for everything integral if you wanted. to_char for floating point seems like a non-starter for embedded at least. |
I think I'd be happy with either of these two solutions:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments above :)
use std::to_char for formatting, fallback to constexpr formatting if needed and the compiler supports it. std::to_char is available widley except for floating point. Updated tests to expect the same value from runtime and constexpr format tests. std::to_char for floating point is the real edge case since it has poor compiler support. Where it is supported it seems most implementations are using a space-inefficient algorithm that can increase code size by about 1.2kB on ARM thumb architectures. This makes it unusable on embedded platforms.
bb2bf96
to
65fd6c7
Compare
Looking at the performance measurements in #18, I went with option 2. I don't think it's reasonable to give up the 5x performance increase of I moved the standard library detection macro logic to the config header, and disable the setting if a library version is detected that doesn't support I like to restrict macro logic to one location so I re-named the functions in the anonymous namespace to |
The single MacOS failure is a little baffling to me. I think apple clang, in Release mode, is printing out an extra character of precision and therefore the acceptance test regex isn't converting the time to a "*" as expected. Not sure why this wouldn't happen in debug, or normal clang.. it does look like libc++ doesn't define the feature test macro for so format will fall back to the constexpr versions. |
The offending number that fails the regex (1e-6, it seems) is the duration of a test (in seconds), as measured in the CI environment. That number is likely to be highly variable, so it would not be a surprise if the other runs (e.g. in Debug, or with other OS/compilers) ended up with a different value. If the problem is real (i.e. not a compiler bug) and only affects specific values, then it's possible that the other runs were just lucky and didn't trigger the issue. And it seems indeed the issue is real, and I can reproduce it on my local branch. Adding the following line to the CONSTEXPR_CHECK(a(1e-6f) == ae{"1.000000e-06"sv, true}); So that's a bug in |
constexpr append changes to take into account the base of string conversion so that pointers can be printed out in hex format and with padding zeros.
If the compiler doesn't support std::to_char forfloating point, then the compile time option should disable use of std::to_char for all conversions. This avoids mixing and matching implementations. Either append_constexpr is used for all conversion, or std::to_char is used for all conversions. This slightly complicates the testing as there is now a two variable truth table as to the expected results when formatting -0.0.
On the 32-bit platforms in CI (windows and emscripten) large_int_t and large_uint_t seem to alias each other in function definitions. Fix this by using signed/unsigned concepts for the parameter. That way the incorrect function will not be considered. This required small bug fix in snitch::concepts. signed_integral and unsigned_integral concepts need to check for sign and also make sure the type is integral so that floating point or other types are not considered.
Looking good! I'm happy to approve it once the small changes requested above are made. |
Explicit base template parameter on num_digits in set_precision function. Also change all instances of `std::to_char` to the correct spelling `std::to_chars`.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for contributing! If you are interested in joining us as maintainer of the library, please have a look here. This comes with no strings attached.
As discussed in #158 , this is a merge request exploring the best option to eliminate the dependence on snprintf, since the capability of printf family of functions may vary depending on implementation. Specifically in the most common embedded ARM compiler newlib-nano won't print large integers.
This change currently goes with option 2, falling back on snitch
append_constexpr()
function for floating point based on standard library version. standard library detection is using macros for libstdc++, libc++, and MSVC. A "cleaner" solution in CMake could be to set a configuration based on a test compile. Not sure how to do the same in meson.Should this have an option to override the detected capability?