2 //===----------------------------------------------------------------------===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___CHARCONV_TRAITS
11 #define _LIBCPP___CHARCONV_TRAITS
13 #include <__bit/countl.h>
14 #include <__charconv/tables.h>
15 #include <__charconv/to_chars_base_10.h>
17 #include <__type_traits/enable_if.h>
18 #include <__type_traits/is_unsigned.h>
22 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
23 # pragma GCC system_header
27 #include <__undef_macros>
29 _LIBCPP_BEGIN_NAMESPACE_STD
31 #if _LIBCPP_STD_VER >= 17
35 template <typename _Tp
, typename
= void>
36 struct _LIBCPP_HIDDEN __traits_base
;
38 template <typename _Tp
>
39 struct _LIBCPP_HIDDEN __traits_base
<_Tp
, __enable_if_t
<sizeof(_Tp
) <= sizeof(uint32_t)>> {
40 using type
= uint32_t;
42 /// The width estimation using a log10 algorithm.
44 /// The algorithm is based on
45 /// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
46 /// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that
47 /// function requires its input to have at least one bit set the value of
48 /// zero is set to one. This means the first element of the lookup table is
50 static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
int __width(_Tp __v
) {
51 auto __t
= (32 - std::__libcpp_clz(static_cast<type
>(__v
| 1))) * 1233 >> 12;
52 return __t
- (__v
< __itoa::__pow10_32
[__t
]) + 1;
55 static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
char* __convert(char* __p
, _Tp __v
) {
56 return __itoa::__base_10_u32(__p
, __v
);
59 static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
decltype(__pow10_32
)& __pow() {
60 return __itoa::__pow10_32
;
64 template <typename _Tp
>
65 struct _LIBCPP_HIDDEN __traits_base
<_Tp
, __enable_if_t
<sizeof(_Tp
) == sizeof(uint64_t)>> {
66 using type
= uint64_t;
68 /// The width estimation using a log10 algorithm.
70 /// The algorithm is based on
71 /// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
72 /// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that
73 /// function requires its input to have at least one bit set the value of
74 /// zero is set to one. This means the first element of the lookup table is
76 static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
int __width(_Tp __v
) {
77 auto __t
= (64 - std::__libcpp_clz(static_cast<type
>(__v
| 1))) * 1233 >> 12;
78 return __t
- (__v
< __itoa::__pow10_64
[__t
]) + 1;
81 static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
char* __convert(char* __p
, _Tp __v
) {
82 return __itoa::__base_10_u64(__p
, __v
);
85 static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
decltype(__pow10_64
)& __pow() {
86 return __itoa::__pow10_64
;
90 # ifndef _LIBCPP_HAS_NO_INT128
91 template <typename _Tp
>
92 struct _LIBCPP_HIDDEN __traits_base
<_Tp
, __enable_if_t
<sizeof(_Tp
) == sizeof(__uint128_t
)> > {
93 using type
= __uint128_t
;
95 /// The width estimation using a log10 algorithm.
97 /// The algorithm is based on
98 /// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
99 /// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that
100 /// function requires its input to have at least one bit set the value of
101 /// zero is set to one. This means the first element of the lookup table is
103 static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
int __width(_Tp __v
) {
104 _LIBCPP_ASSERT_UNCATEGORIZED(
105 __v
> numeric_limits
<uint64_t>::max(), "The optimizations for this algorithm fail when this isn't true.");
106 // There's always a bit set in the upper 64-bits.
107 auto __t
= (128 - std::__libcpp_clz(static_cast<uint64_t>(__v
>> 64))) * 1233 >> 12;
108 _LIBCPP_ASSERT_UNCATEGORIZED(__t
>= __itoa::__pow10_128_offset
, "Index out of bounds");
109 // __t is adjusted since the lookup table misses the lower entries.
110 return __t
- (__v
< __itoa::__pow10_128
[__t
- __itoa::__pow10_128_offset
]) + 1;
113 static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
char* __convert(char* __p
, _Tp __v
) {
114 return __itoa::__base_10_u128(__p
, __v
);
117 // TODO FMT This pow function should get an index.
118 // By moving this to its own header it can be reused by the pow function in to_chars_base_10.
119 static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
decltype(__pow10_128
)& __pow() {
120 return __itoa::__pow10_128
;
125 template <typename _Tp
>
126 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
bool
127 __mul_overflowed(unsigned char __a
, _Tp __b
, unsigned char& __r
) {
128 auto __c
= __a
* __b
;
130 return __c
> numeric_limits
<unsigned char>::max();
133 template <typename _Tp
>
134 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
bool
135 __mul_overflowed(unsigned short __a
, _Tp __b
, unsigned short& __r
) {
136 auto __c
= __a
* __b
;
138 return __c
> numeric_limits
<unsigned short>::max();
141 template <typename _Tp
>
142 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
bool __mul_overflowed(_Tp __a
, _Tp __b
, _Tp
& __r
) {
143 static_assert(is_unsigned
<_Tp
>::value
, "");
144 return __builtin_mul_overflow(__a
, __b
, &__r
);
147 template <typename _Tp
, typename _Up
>
148 inline _LIBCPP_HIDE_FROM_ABI
bool _LIBCPP_CONSTEXPR_SINCE_CXX23
__mul_overflowed(_Tp __a
, _Up __b
, _Tp
& __r
) {
149 return __itoa::__mul_overflowed(__a
, static_cast<_Tp
>(__b
), __r
);
152 template <typename _Tp
>
153 struct _LIBCPP_HIDDEN __traits
: __traits_base
<_Tp
> {
154 static constexpr int digits
= numeric_limits
<_Tp
>::digits10
+ 1;
155 using __traits_base
<_Tp
>::__pow
;
156 using typename __traits_base
<_Tp
>::type
;
158 // precondition: at least one non-zero character available
159 static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
char const*
160 __read(char const* __p
, char const* __ep
, type
& __a
, type
& __b
) {
161 type __cprod
[digits
];
162 int __j
= digits
- 1;
165 if (*__p
< '0' || *__p
> '9')
167 __cprod
[--__i
] = *__p
++ - '0';
168 } while (__p
!= __ep
&& __i
!= 0);
170 __a
= __inner_product(__cprod
+ __i
+ 1, __cprod
+ __j
, __pow() + 1, __cprod
[__i
]);
171 if (__itoa::__mul_overflowed(__cprod
[__j
], __pow()[__j
- __i
], __b
))
176 template <typename _It1
, typename _It2
, class _Up
>
177 static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _Up
178 __inner_product(_It1 __first1
, _It1 __last1
, _It2 __first2
, _Up __init
) {
179 for (; __first1
< __last1
; ++__first1
, ++__first2
)
180 __init
= __init
+ *__first1
* *__first2
;
185 } // namespace __itoa
187 template <typename _Tp
>
188 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _Tp
__complement(_Tp __x
) {
189 static_assert(is_unsigned
<_Tp
>::value
, "cast to unsigned first");
190 return _Tp(~__x
+ 1);
193 #endif // _LIBCPP_STD_VER >= 17
195 _LIBCPP_END_NAMESPACE_STD
199 #endif // _LIBCPP___CHARCONV_TRAITS