Skip to content
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

FP formatting at compile-time #2426

Merged

Conversation

alexezeder
Copy link
Contributor

@alexezeder alexezeder commented Jul 16, 2021

Few points for this PR, I mentioned some of them in #1895 (comment):

  • works only with FMT_HEADER_ONLY
  • works only with fast_floats, even when specs passed, because of the sign check
  • separate compile-fp-test added with HEADER_ONLY argument (tested via G++11 C++20 and MSVC 2019 C++20 configs on CI), the compile-test still uses static(/shared?) library

Copy link
Contributor

@DanielaE DanielaE left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seem to be a few general portability issues that need to be addressed.

include/fmt/core.h Outdated Show resolved Hide resolved
include/fmt/format-inl.h Outdated Show resolved Hide resolved
include/fmt/format.h Show resolved Hide resolved
test/CMakeLists.txt Show resolved Hide resolved
@alexezeder alexezeder force-pushed the feature/FP_formatting_at_compile_time branch from ec4e993 to 5bdc572 Compare July 19, 2021 00:31
@alexezeder alexezeder marked this pull request as draft July 20, 2021 15:37
Copy link
Contributor

@vitaut vitaut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

.github/workflows/linux.yml Outdated Show resolved Hide resolved
include/fmt/core.h Outdated Show resolved Hide resolved
include/fmt/format-inl.h Outdated Show resolved Hide resolved
@alexezeder
Copy link
Contributor Author

JFI, I will get back on this PR about a week later.

@alexezeder alexezeder force-pushed the feature/FP_formatting_at_compile_time branch from 5bdc572 to 30f17cc Compare August 12, 2021 16:22
@alexezeder
Copy link
Contributor Author

JFI, I'm back on this PR.
God, FO4 has too many sidequests...

Copy link
Contributor

@vitaut vitaut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you move bigint constexprification to a separate PR since it's pretty straightforward?

include/fmt/format.h Outdated Show resolved Hide resolved
include/fmt/format.h Outdated Show resolved Hide resolved
include/fmt/format.h Outdated Show resolved Hide resolved
@alexezeder alexezeder force-pushed the feature/FP_formatting_at_compile_time branch 2 times, most recently from 7087b17 to 2f74e6c Compare August 23, 2021 19:26
@vitaut
Copy link
Contributor

vitaut commented Aug 26, 2021

Thanks for the update, I'll take a look shortly. As a general comment, could you move all straightforward additions of constexpr (that don't remove static) such as the ones in fmt/core.h, fp, bigint, etc. to a separate diff? Those can be merged without much discussion and it will simplify reviewing the current diff. CI changes can go there too.

@alexezeder
Copy link
Contributor Author

alexezeder commented Aug 26, 2021

As a general comment, could you move all straightforward additions of constexpr (that don't remove static) such as the ones in fmt/core.h, fp, bigint, etc. to a separate diff?

Done with #2470. I will rebase this PR then, as soon as the new one is merged.

@alexezeder alexezeder force-pushed the feature/FP_formatting_at_compile_time branch 2 times, most recently from f645dc0 to ff0cf70 Compare August 28, 2021 22:50
@alexezeder
Copy link
Contributor Author

Hmm... looks like we have problems with digit_grouping in the write_float() since it's used without is_constant_evaluated() check and probably because it contains std::string, which is not constexpr-friendly (but it should be, right? 🤔). I tried to solve this by using the code from few commits back under is_constant_evaluated() check, since it doesn't use digit_grouping, but this solution only works for MSVC, while GCC still has some problems with this function.

include/fmt/format-inl.h Outdated Show resolved Hide resolved
include/fmt/format-inl.h Outdated Show resolved Hide resolved
include/fmt/format-inl.h Outdated Show resolved Hide resolved
include/fmt/format.h Outdated Show resolved Hide resolved
test/CMakeLists.txt Show resolved Hide resolved
include/fmt/format.h Outdated Show resolved Hide resolved
include/fmt/format.h Outdated Show resolved Hide resolved
@vitaut
Copy link
Contributor

vitaut commented Aug 29, 2021

Hmm... looks like we have problems with digit_grouping in the write_float() since it's used without is_constant_evaluated() check and probably because it contains std::string, which is not constexpr-friendly (but it should be, right? 🤔)

We could probably create a fallback digit_grouping for the consteval case.

@alexezeder alexezeder force-pushed the feature/FP_formatting_at_compile_time branch 2 times, most recently from ae1aeca to 5911f4f Compare August 29, 2021 21:11
@alexezeder
Copy link
Contributor Author

We could probably create a fallback digit_grouping for the consteval case.

Without creating a fallback, but I managed to make it compile on GCC 11.

@alexezeder alexezeder marked this pull request as ready for review August 29, 2021 21:35
@alexezeder alexezeder requested a review from vitaut August 29, 2021 21:36
Copy link
Contributor

@vitaut vitaut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly looks good, a few more comments inline.

include/fmt/format-inl.h Show resolved Hide resolved
include/fmt/format-inl.h Outdated Show resolved Hide resolved
include/fmt/format.h Outdated Show resolved Hide resolved
Comment on lines 1958 to 1949
} else {
FMT_ASSERT(false, "floating point type is not supported");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can if + assert be replaced with a static_assert?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like no because the code under is_constant_evaluated() check is still a part of function code. Without optimization, it's not even omitted, according to Compiler Explorer. So this constant-evaluated code has to be valid, and when it contains static assert, which is false, then the "runtime" version of this function becomes ill-formed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure but at the very least we could drop the else branch because non-IEEE is very uncommon and we would get a reasonable error anyway from signbit below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you dropped it from isinf and isfinite but not here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you dropped it from isinf and isfinite but not here.

Only because you wrote:

we would get a reasonable error anyway from signbit below.

and it's signbit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this line is about the std::signbit() call below, then we won't get a reasonable error from there in some cases when FP numbers are non-IEEE and std::signbit() manages to work with them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we won't get a reasonable error from there in some cases when FP numbers are non-IEEE and std::signbit() manages to work with them

That seems fine to me. We'll either get an error if signbit is not constexpr or it will return the correct result.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed also here.

include/fmt/format.h Outdated Show resolved Hide resolved
include/fmt/format.h Outdated Show resolved Hide resolved
@alexezeder alexezeder force-pushed the feature/FP_formatting_at_compile_time branch from 5911f4f to 9285127 Compare September 2, 2021 19:20
@alexezeder alexezeder requested a review from vitaut September 2, 2021 19:29
@alexezeder alexezeder force-pushed the feature/FP_formatting_at_compile_time branch 3 times, most recently from ecdd2a8 to 0f18453 Compare September 7, 2021 20:12
if (const_check(!is_supported_floating_point(value))) return out;
float_specs fspecs = parse_float_type_spec(specs);
fspecs.sign = specs.sign;
if (std::signbit(value)) { // value < 0 is false for NaN so use signbit.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you keep the comment since it may not be obvious to the reader why we don't use < 0 here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment reverted back.

@@ -1886,22 +1897,95 @@ auto write_float(OutputIt out, const DecimalFP& fp,
});
}

template <typename Char> class fallback_digit_grouping {
public:
explicit constexpr fallback_digit_grouping(locale_ref, bool) {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it needs to be explicit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's just copied from digit_grouping, done.

Copy link
Contributor

@vitaut vitaut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few more nits, otherwise LGTM.

@alexezeder
Copy link
Contributor Author

I will address these nits and resolve merge conflicts tomorrow.

* works only with FMT_HEADER_ONLY
* works only with float and double types (not long double)
@alexezeder alexezeder force-pushed the feature/FP_formatting_at_compile_time branch from 0f18453 to ea86c06 Compare September 17, 2021 14:42
@alexezeder
Copy link
Contributor Author

Unfortunately, my continuous benchmark pages broke at some point (June 10). I will try to fix them soon since I have access to this Raspberry finally 😄.

@vitaut vitaut merged commit b4d9d82 into fmtlib:master Sep 18, 2021
@vitaut
Copy link
Contributor

vitaut commented Sep 18, 2021

Merged, thanks!

@jk-jeon jk-jeon mentioned this pull request Sep 22, 2021
PoetaKodu pushed a commit to pacc-repo/fmt that referenced this pull request Nov 11, 2021
* works only with FMT_HEADER_ONLY
* works only with float and double types (not long double)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants