Skip to content

Commit f2307f9

Browse files
authored
Merge pull request #929 from cppalliance/869
Fix `to_chars` for `decimal128` being disproportionally slower
2 parents ca047d2 + c185d89 commit f2307f9

File tree

4 files changed

+336
-50
lines changed

4 files changed

+336
-50
lines changed

include/boost/decimal/charconv.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ BOOST_DECIMAL_CONSTEXPR auto to_chars_scientific_impl(char* first, char* last, c
324324
}
325325

326326
// Offset the value of first by 1 so that we can copy the leading digit and insert a decimal point
327-
auto r = to_chars_integer_impl<uint_type, uint_type>(first + 1, last, significand, 10);
327+
auto r = to_chars_integer_impl<uint_type>(first + 1, last, significand);
328328

329329
// Only real reason we will hit this is a buffer overflow
330330
if (BOOST_DECIMAL_UNLIKELY(!r))
@@ -398,7 +398,7 @@ BOOST_DECIMAL_CONSTEXPR auto to_chars_scientific_impl(char* first, char* last, c
398398
*first++ = '0';
399399
}
400400

401-
r = to_chars_integer_impl<int, unsigned>(first, last, abs_exp, 10);
401+
r = to_chars_integer_impl<int>(first, last, abs_exp);
402402
if (BOOST_DECIMAL_UNLIKELY(!r))
403403
{
404404
return r; // LCOV_EXCL_LINE
@@ -544,7 +544,7 @@ BOOST_DECIMAL_CONSTEXPR auto to_chars_fixed_impl(char* first, char* last, const
544544
std::numeric_limits<std::uint64_t>::digits),
545545
int128::uint128_t, std::uint64_t>;
546546

547-
auto r = to_chars_integer_impl<uint_type, uint_type>(first, last, significand, 10);
547+
auto r = to_chars_integer_impl<uint_type>(first, last, significand);
548548

549549
if (BOOST_DECIMAL_UNLIKELY(!r))
550550
{
@@ -775,7 +775,7 @@ BOOST_DECIMAL_CONSTEXPR auto to_chars_hex_impl(char* first, char* last, const Ta
775775
*first++ = '0';
776776
}
777777

778-
return to_chars_integer_impl<std::uint32_t, std::uint32_t>(first, last, static_cast<std::uint32_t>(abs_exp), 10);
778+
return to_chars_integer_impl<std::uint32_t>(first, last, static_cast<std::uint32_t>(abs_exp));
779779
}
780780

781781
#ifdef _MSC_VER

include/boost/decimal/detail/memcpy.hpp

Lines changed: 54 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,61 @@ namespace boost {
3131
namespace decimal {
3232
namespace detail {
3333

34-
#if !defined(BOOST_DECIMAL_NO_CONSTEVAL_DETECTION)
34+
namespace impl {
3535

3636
#define BOOST_DECIMAL_CONSTEXPR constexpr
3737

38-
BOOST_DECIMAL_CONSTEXPR char* memcpy(char* dest, const char* src, std::size_t count)
38+
constexpr char* memcpy_impl(char* dest, const char* src, std::size_t count)
3939
{
40-
if (BOOST_DECIMAL_IS_CONSTANT_EVALUATED(count))
40+
for (std::size_t i = 0; i < count; ++i)
41+
{
42+
dest[i] = src[i];
43+
}
44+
45+
return dest;
46+
}
47+
48+
constexpr char* memset_impl(char* dest, int ch, std::size_t count)
49+
{
50+
for (std::size_t i = 0; i < count; ++i)
51+
{
52+
dest[i] = static_cast<char>(ch);
53+
}
54+
55+
return dest;
56+
}
57+
58+
constexpr char* memmove_impl(char* dest, const char* src, std::size_t count)
59+
{
60+
if (dest < src || dest >= src + count)
4161
{
62+
// Non-overlapping or safe to copy forward
4263
for (std::size_t i = 0; i < count; ++i)
4364
{
44-
*(dest + i) = *(src + i);
65+
dest[i] = src[i];
4566
}
67+
}
68+
else
69+
{
70+
// Overlapping, copy backward to avoid overwriting source
71+
for (std::size_t i = count; i > 0; --i)
72+
{
73+
dest[i - 1] = src[i - 1];
74+
}
75+
}
4676

47-
return dest;
77+
return dest;
78+
}
79+
80+
}
81+
82+
#if !defined(BOOST_DECIMAL_NO_CONSTEVAL_DETECTION)
83+
84+
BOOST_DECIMAL_CONSTEXPR char* memcpy(char* dest, const char* src, std::size_t count)
85+
{
86+
if (BOOST_DECIMAL_IS_CONSTANT_EVALUATED(count))
87+
{
88+
return static_cast<char*>(impl::memcpy_impl(dest, src, count));
4889
}
4990
else
5091
{
@@ -68,12 +109,7 @@ BOOST_DECIMAL_CONSTEXPR char* memset(char* dest, int ch, std::size_t count)
68109
{
69110
if (BOOST_DECIMAL_IS_CONSTANT_EVALUATED(count))
70111
{
71-
for (std::size_t i = 0; i < count; ++i)
72-
{
73-
*(dest + i) = static_cast<char>(ch);
74-
}
75-
76-
return dest;
112+
return static_cast<char*>(impl::memset_impl(dest, ch, count));
77113
}
78114
else
79115
{
@@ -85,12 +121,7 @@ BOOST_DECIMAL_CONSTEXPR char* memmove(char* dest, const char* src, std::size_t c
85121
{
86122
if (BOOST_DECIMAL_IS_CONSTANT_EVALUATED(count))
87123
{
88-
for (std::size_t i = 0; i < count; ++i)
89-
{
90-
*(dest + i) = *(src + i);
91-
}
92-
93-
return dest;
124+
return static_cast<char*>(impl::memmove_impl(dest, src, count));
94125
}
95126
else
96127
{
@@ -100,21 +131,19 @@ BOOST_DECIMAL_CONSTEXPR char* memmove(char* dest, const char* src, std::size_t c
100131

101132
#else // No consteval detection
102133

103-
#define BOOST_DECIMAL_CONSTEXPR inline
104-
105-
BOOST_DECIMAL_CONSTEXPR void* memcpy(void* dest, const void* src, std::size_t count)
134+
BOOST_DECIMAL_CONSTEXPR char* memcpy(char* dest, const char* src, std::size_t count)
106135
{
107-
return std::memcpy(dest, src, count);
136+
return impl::memcpy_impl(dest, src, count);
108137
}
109138

110-
BOOST_DECIMAL_CONSTEXPR void* memset(void* dest, int ch, std::size_t count)
139+
BOOST_DECIMAL_CONSTEXPR char* memset(char* dest, int ch, std::size_t count)
111140
{
112-
return std::memset(dest, ch, count);
141+
return impl::memset_impl(dest, ch, count);
113142
}
114143

115-
BOOST_DECIMAL_CONSTEXPR void* memmove(void* dest, const void* src, std::size_t count)
144+
BOOST_DECIMAL_CONSTEXPR char* memmove(char* dest, const char* src, std::size_t count)
116145
{
117-
return std::memmove(dest, src, count);
146+
return impl::memmove_impl(dest, src, count);
118147
}
119148

120149
#endif

0 commit comments

Comments
 (0)