Minor simplifications for std::to_chars implementation

* include/std/charconv (__detail::__to_chars_2_len): Use std::log2p1.
	(__detail::__to_chars_8_len): Remove.
	(__detail::__to_chars_8): Inline length calculation here.
	(__detail::__from_chars_binary): Use numeric_limits instead of
	CHAR_BIT.

From-SVN: r275313
This commit is contained in:
Jonathan Wakely 2019-09-02 12:31:25 +01:00 committed by Jonathan Wakely
parent 000a5f8d23
commit 6e672b1801
2 changed files with 25 additions and 41 deletions

View File

@ -1,3 +1,11 @@
2019-09-02 Jonathan Wakely <jwakely@redhat.com>
* include/std/charconv (__detail::__to_chars_2_len): Use std::log2p1.
(__detail::__to_chars_8_len): Remove.
(__detail::__to_chars_8): Inline length calculation here.
(__detail::__from_chars_binary): Use numeric_limits instead of
CHAR_BIT.
2019-09-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> 2019-09-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* config/abi/post/i386-solaris/baseline_symbols.txt: Regenerate. * config/abi/post/i386-solaris/baseline_symbols.txt: Regenerate.

View File

@ -35,8 +35,9 @@
#include <type_traits> #include <type_traits>
#include <limits> #include <limits>
#include <cctype> #include <bit> // for __log2p1
#include <bits/charconv.h> // for __to_chars_len, __to_chars_10_impl #include <cctype> // for isdigit
#include <bits/charconv.h> // for __to_chars_len, __to_chars_10_impl
#include <bits/error_constants.h> // for std::errc #include <bits/error_constants.h> // for std::errc
// Define when floating point is supported: #define __cpp_lib_to_chars 201611L // Define when floating point is supported: #define __cpp_lib_to_chars 201611L
@ -96,43 +97,7 @@ namespace __detail
template<typename _Tp> template<typename _Tp>
constexpr unsigned constexpr unsigned
__to_chars_len_2(_Tp __value) noexcept __to_chars_len_2(_Tp __value) noexcept
{ { return std::__log2p1(__value); }
static_assert(is_integral<_Tp>::value, "implementation bug");
static_assert(is_unsigned<_Tp>::value, "implementation bug");
constexpr size_t __nbits = __CHAR_BIT__ * sizeof(_Tp);
// N.B. __builtin_clzll is undefined if __value == 0, but std::to_chars
// handles zero values directly.
// For sizeof(_Tp) > 1 this is an order of magnitude faster than
// the generic __to_chars_len.
return __nbits
- (__builtin_clzll(__value)
- ((__CHAR_BIT__ * sizeof(long long)) - __nbits));
}
template<typename _Tp>
constexpr unsigned
__to_chars_len_8(_Tp __value) noexcept
{
static_assert(is_integral<_Tp>::value, "implementation bug");
static_assert(is_unsigned<_Tp>::value, "implementation bug");
constexpr size_t __nbits = __CHAR_BIT__ * sizeof(_Tp);
if _GLIBCXX17_CONSTEXPR (__nbits <= 16)
{
return __value > 077777u ? 6u
: __value > 07777u ? 5u
: __value > 0777u ? 4u
: __value > 077u ? 3u
: __value > 07u ? 2u
: 1u;
}
else
return (__to_chars_len_2(__value) + 2) / 3;
}
// Generic implementation for arbitrary bases. // Generic implementation for arbitrary bases.
template<typename _Tp> template<typename _Tp>
@ -255,8 +220,19 @@ namespace __detail
static_assert(is_unsigned<_Tp>::value, "implementation bug"); static_assert(is_unsigned<_Tp>::value, "implementation bug");
to_chars_result __res; to_chars_result __res;
unsigned __len;
const unsigned __len = __to_chars_len_8(__val); if _GLIBCXX17_CONSTEXPR (numeric_limits<_Tp>::digits <= 16)
{
__len = __val > 077777u ? 6u
: __val > 07777u ? 5u
: __val > 0777u ? 4u
: __val > 077u ? 3u
: __val > 07u ? 2u
: 1u;
}
else
__len = (__to_chars_len_2(__val) + 2) / 3;
if (__builtin_expect((__last - __first) < __len, 0)) if (__builtin_expect((__last - __first) < __len, 0))
{ {
@ -397,7 +373,7 @@ namespace __detail
__i++; __i++;
} }
__first += __i; __first += __i;
return __i <= (sizeof(_Tp) * __CHAR_BIT__); return __i <= numeric_limits<_Tp>::digits;
} }
/// std::from_chars implementation for integers in bases 3 to 10. /// std::from_chars implementation for integers in bases 3 to 10.