Skip to content

Commit

Permalink
remove fallback for floating point std::to_char
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
CrustyAuklet committed Apr 28, 2024
1 parent cb6e74e commit bb2bf96
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 19 deletions.
7 changes: 7 additions & 0 deletions include/snitch/snitch_config.hpp.config
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@
# define SNITCH_CONSTEXPR_FLOAT_USE_BITCAST 0
#endif

#if (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE <= 11) || \
(defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 14000) || \
(defined(_MSC_VER) && _MSC_VER <= 1924)
# undef SNITCH_APPEND_TO_CHARS
# define SNITCH_APPEND_TO_CHARS 0
#endif

#if SNITCH_SHARED_LIBRARY
# if defined(_MSC_VER)
# if defined(SNITCH_EXPORTS)
Expand Down
19 changes: 4 additions & 15 deletions src/snitch_append.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,19 @@
#include "snitch/snitch_concepts.hpp"
#include "snitch/snitch_string.hpp"

#include <charconv> // for std::to_chars
#include <cstdint> // for std::uintptr_t
#include <cstring> // for std::memmove
#include <system_error> // for std::errc
#if SNITCH_APPEND_TO_CHARS
# include <charconv> // for std::to_chars
# include <system_error> // for std::errc
#endif

namespace snitch::impl {
namespace {
using snitch::small_string_span;
using namespace std::literals;

#if SNITCH_APPEND_TO_CHARS
// libstdc++ version 11 or greater
// libc++ version 14 or greater
// MSVC 19.24 or greater (also known as Visual Studio 2019 16.4)
// Apple clang and others have no support as of April-2024
# if (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE > 11) || \
(defined(_LIBCPP_VERSION) && _LIBCPP_VERSION > 14000) || \
(defined(_MSC_VER) && _MSC_VER > 1924)
template<floating_point T>
bool append_to(small_string_span ss, T value) noexcept {
constexpr auto fmt = std::chars_format::scientific;
Expand All @@ -43,12 +38,6 @@ bool append_to(small_string_span ss, T value) noexcept {
ss.grow(end - ss.end());
return true;
}
# else
template<std::floating_point T>
bool append_to(small_string_span ss, T value) noexcept {
return append_constexpr(ss, value);
}
# endif

template<large_int_t Base = 10, integral T>
bool append_to(small_string_span ss, T value) noexcept {
Expand Down
20 changes: 16 additions & 4 deletions tests/runtime_tests/string_utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,9 @@ TEST_CASE("append ints", "[utility]") {

TEST_CASE("append floats", "[utility]") {
using ae = append_test::append_expected;
#if !SNITCH_CONSTEXPR_FLOAT_USE_BITCAST
#if !SNITCH_CONSTEXPR_FLOAT_USE_BITCAST && SNITCH_APPEND_TO_CHARS
// answers will be different only if no bitcast AND we do have runtime to_char
// otherwise append_constexpr will be used at runtime
using aed = append_test::append_expected_diff;
#endif

Expand All @@ -354,11 +356,16 @@ TEST_CASE("append floats", "[utility]") {

CONSTEXPR_CHECK(a(0.0f) == ae{"0.000000e+00"sv, true});
#if SNITCH_CONSTEXPR_FLOAT_USE_BITCAST
// std::bit_cast is enabled, and will match the output of std::to_char if used at runtime
CONSTEXPR_CHECK(a(-0.0f) == ae{"-0.000000e+00"sv, true});
#else
#elif SNITCH_APPEND_TO_CHARS
// Without std::bit_cast (or C++23), we are unable to tell the difference between -0.0f and
// +0.0f in constexpr expressions. Therefore -0.0f in constexpr gets displayed as +0.0f.
CONSTEXPR_CHECK(a(-0.0f) == aed{{"0.000000e+00"sv, true}, {"-0.000000e+00"sv, true}});
#else
// No std::bit_cast, but also no std::to_char. append_constexpr will be used
// for runtime and match the compile time results
CONSTEXPR_CHECK(a(-0.0f) == ae{"0.000000e+00"sv, true});
#endif
CONSTEXPR_CHECK(a(1.0f) == ae{"1.000000e+00"sv, true});
CONSTEXPR_CHECK(a(1.5f) == ae{"1.500000e+00"sv, true});
Expand Down Expand Up @@ -453,7 +460,7 @@ TEST_CASE("append floats", "[utility]") {

TEST_CASE("append doubles", "[utility]") {
using ae = append_test::append_expected;
#if !SNITCH_CONSTEXPR_FLOAT_USE_BITCAST
#if !SNITCH_CONSTEXPR_FLOAT_USE_BITCAST && SNITCH_APPEND_TO_CHARS
using aed = append_test::append_expected_diff;
#endif

Expand All @@ -464,12 +471,17 @@ TEST_CASE("append doubles", "[utility]") {

CONSTEXPR_CHECK(a(0.0) == ae{"0.000000000000000e+00"sv, true});
#if SNITCH_CONSTEXPR_FLOAT_USE_BITCAST
// std::bit_cast is enabled, and will match the output of std::to_char if used at runtime
CONSTEXPR_CHECK(a(-0.0) == ae{"-0.000000000000000e+00"sv, true});
#else
#elif SNITCH_APPEND_TO_CHARS
// Without std::bit_cast (or C++23), we are unable to tell the difference between -0.0f and
// +0.0f in constexpr expressions. Therefore -0.0f in constexpr gets displayed as +0.0f.
CONSTEXPR_CHECK(
a(-0.0) == aed{{"0.000000000000000e+00"sv, true}, {"-0.000000000000000e+00"sv, true}});
#else
// No std::bit_cast, but also no std::to_char. append_constexpr will be used for
// runtime and match the compile time results
CONSTEXPR_CHECK(a(-0.0) == ae{"0.000000000000000e+00"sv, true});
#endif
CONSTEXPR_CHECK(a(1.0) == ae{"1.000000000000000e+00"sv, true});
CONSTEXPR_CHECK(a(1.5) == ae{"1.500000000000000e+00"sv, true});
Expand Down

0 comments on commit bb2bf96

Please sign in to comment.