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