Minor simplifications for std::to_chars implementation
authorJonathan Wakely <jwakely@redhat.com>
Mon, 2 Sep 2019 11:31:25 +0000 (12:31 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Mon, 2 Sep 2019 11:31:25 +0000 (12:31 +0100)
* 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

libstdc++-v3/ChangeLog
libstdc++-v3/include/std/charconv

index 20cec73afb9994e1d5b03a7a6ae7e0a4221ac079..876e7ff49f6a810811e8d2bb5c39cbd940f27510 100644 (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>
 
        * config/abi/post/i386-solaris/baseline_symbols.txt: Regenerate.
index 4e94c39656de27073b0b0b2d88d90c3b243bf6f4..ceefa3b6778124768abe082dce18328a7f678945 100644 (file)
@@ -35,8 +35,9 @@
 
 #include <type_traits>
 #include <limits>
-#include <cctype>
-#include <bits/charconv.h> // for __to_chars_len, __to_chars_10_impl
+#include <bit>                 // for __log2p1
+#include <cctype>              // for isdigit
+#include <bits/charconv.h>     // for __to_chars_len, __to_chars_10_impl
 #include <bits/error_constants.h> // for std::errc
 
 // Define when floating point is supported: #define __cpp_lib_to_chars 201611L
@@ -96,43 +97,7 @@ namespace __detail
   template<typename _Tp>
     constexpr unsigned
     __to_chars_len_2(_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);
-
-      // 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;
-    }
+    { return std::__log2p1(__value); }
 
   // Generic implementation for arbitrary bases.
   template<typename _Tp>
@@ -255,8 +220,19 @@ namespace __detail
       static_assert(is_unsigned<_Tp>::value, "implementation bug");
 
       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))
        {
@@ -397,7 +373,7 @@ namespace __detail
          __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.