106c3fb27SDimitry Andric // -*- C++ -*- 206c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 306c3fb27SDimitry Andric // 406c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 506c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 606c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 706c3fb27SDimitry Andric // 806c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 906c3fb27SDimitry Andric 1006c3fb27SDimitry Andric #ifndef _LIBCPP___CHARCONV_TRAITS 1106c3fb27SDimitry Andric #define _LIBCPP___CHARCONV_TRAITS 1206c3fb27SDimitry Andric 13*0fca6ea1SDimitry Andric #include <__assert> 1406c3fb27SDimitry Andric #include <__bit/countl.h> 1506c3fb27SDimitry Andric #include <__charconv/tables.h> 1606c3fb27SDimitry Andric #include <__charconv/to_chars_base_10.h> 1706c3fb27SDimitry Andric #include <__config> 1806c3fb27SDimitry Andric #include <__type_traits/enable_if.h> 1906c3fb27SDimitry Andric #include <__type_traits/is_unsigned.h> 2006c3fb27SDimitry Andric #include <cstdint> 2106c3fb27SDimitry Andric #include <limits> 2206c3fb27SDimitry Andric 2306c3fb27SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 2406c3fb27SDimitry Andric # pragma GCC system_header 2506c3fb27SDimitry Andric #endif 2606c3fb27SDimitry Andric 2706c3fb27SDimitry Andric _LIBCPP_PUSH_MACROS 2806c3fb27SDimitry Andric #include <__undef_macros> 2906c3fb27SDimitry Andric 3006c3fb27SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 3106c3fb27SDimitry Andric 3206c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 17 3306c3fb27SDimitry Andric 3406c3fb27SDimitry Andric namespace __itoa { 3506c3fb27SDimitry Andric 3606c3fb27SDimitry Andric template <typename _Tp, typename = void> 3706c3fb27SDimitry Andric struct _LIBCPP_HIDDEN __traits_base; 3806c3fb27SDimitry Andric 3906c3fb27SDimitry Andric template <typename _Tp> 4006c3fb27SDimitry Andric struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t<sizeof(_Tp) <= sizeof(uint32_t)>> { 4106c3fb27SDimitry Andric using type = uint32_t; 4206c3fb27SDimitry Andric 4306c3fb27SDimitry Andric /// The width estimation using a log10 algorithm. 4406c3fb27SDimitry Andric /// 4506c3fb27SDimitry Andric /// The algorithm is based on 4606c3fb27SDimitry Andric /// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 4706c3fb27SDimitry Andric /// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that 4806c3fb27SDimitry Andric /// function requires its input to have at least one bit set the value of 4906c3fb27SDimitry Andric /// zero is set to one. This means the first element of the lookup table is 5006c3fb27SDimitry Andric /// zero. 5106c3fb27SDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __width(_Tp __v) { 5206c3fb27SDimitry Andric auto __t = (32 - std::__libcpp_clz(static_cast<type>(__v | 1))) * 1233 >> 12; 5306c3fb27SDimitry Andric return __t - (__v < __itoa::__pow10_32[__t]) + 1; 5406c3fb27SDimitry Andric } 5506c3fb27SDimitry Andric 5606c3fb27SDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __convert(char* __p, _Tp __v) { 5706c3fb27SDimitry Andric return __itoa::__base_10_u32(__p, __v); 5806c3fb27SDimitry Andric } 5906c3fb27SDimitry Andric 6006c3fb27SDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI decltype(__pow10_32)& __pow() { 6106c3fb27SDimitry Andric return __itoa::__pow10_32; 6206c3fb27SDimitry Andric } 6306c3fb27SDimitry Andric }; 6406c3fb27SDimitry Andric 6506c3fb27SDimitry Andric template <typename _Tp> 6606c3fb27SDimitry Andric struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t<sizeof(_Tp) == sizeof(uint64_t)>> { 6706c3fb27SDimitry Andric using type = uint64_t; 6806c3fb27SDimitry Andric 6906c3fb27SDimitry Andric /// The width estimation using a log10 algorithm. 7006c3fb27SDimitry Andric /// 7106c3fb27SDimitry Andric /// The algorithm is based on 7206c3fb27SDimitry Andric /// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 7306c3fb27SDimitry Andric /// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that 7406c3fb27SDimitry Andric /// function requires its input to have at least one bit set the value of 7506c3fb27SDimitry Andric /// zero is set to one. This means the first element of the lookup table is 7606c3fb27SDimitry Andric /// zero. 7706c3fb27SDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __width(_Tp __v) { 7806c3fb27SDimitry Andric auto __t = (64 - std::__libcpp_clz(static_cast<type>(__v | 1))) * 1233 >> 12; 7906c3fb27SDimitry Andric return __t - (__v < __itoa::__pow10_64[__t]) + 1; 8006c3fb27SDimitry Andric } 8106c3fb27SDimitry Andric 8206c3fb27SDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __convert(char* __p, _Tp __v) { 8306c3fb27SDimitry Andric return __itoa::__base_10_u64(__p, __v); 8406c3fb27SDimitry Andric } 8506c3fb27SDimitry Andric 8606c3fb27SDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI decltype(__pow10_64)& __pow() { 8706c3fb27SDimitry Andric return __itoa::__pow10_64; 8806c3fb27SDimitry Andric } 8906c3fb27SDimitry Andric }; 9006c3fb27SDimitry Andric 9106c3fb27SDimitry Andric # ifndef _LIBCPP_HAS_NO_INT128 9206c3fb27SDimitry Andric template <typename _Tp> 9306c3fb27SDimitry Andric struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t<sizeof(_Tp) == sizeof(__uint128_t)> > { 9406c3fb27SDimitry Andric using type = __uint128_t; 9506c3fb27SDimitry Andric 9606c3fb27SDimitry Andric /// The width estimation using a log10 algorithm. 9706c3fb27SDimitry Andric /// 9806c3fb27SDimitry Andric /// The algorithm is based on 9906c3fb27SDimitry Andric /// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 10006c3fb27SDimitry Andric /// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that 10106c3fb27SDimitry Andric /// function requires its input to have at least one bit set the value of 10206c3fb27SDimitry Andric /// zero is set to one. This means the first element of the lookup table is 10306c3fb27SDimitry Andric /// zero. 10406c3fb27SDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __width(_Tp __v) { 1051db9f3b2SDimitry Andric _LIBCPP_ASSERT_INTERNAL( 10606c3fb27SDimitry Andric __v > numeric_limits<uint64_t>::max(), "The optimizations for this algorithm fail when this isn't true."); 10706c3fb27SDimitry Andric // There's always a bit set in the upper 64-bits. 10806c3fb27SDimitry Andric auto __t = (128 - std::__libcpp_clz(static_cast<uint64_t>(__v >> 64))) * 1233 >> 12; 1091db9f3b2SDimitry Andric _LIBCPP_ASSERT_INTERNAL(__t >= __itoa::__pow10_128_offset, "Index out of bounds"); 11006c3fb27SDimitry Andric // __t is adjusted since the lookup table misses the lower entries. 11106c3fb27SDimitry Andric return __t - (__v < __itoa::__pow10_128[__t - __itoa::__pow10_128_offset]) + 1; 11206c3fb27SDimitry Andric } 11306c3fb27SDimitry Andric 11406c3fb27SDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __convert(char* __p, _Tp __v) { 11506c3fb27SDimitry Andric return __itoa::__base_10_u128(__p, __v); 11606c3fb27SDimitry Andric } 11706c3fb27SDimitry Andric 11806c3fb27SDimitry Andric // TODO FMT This pow function should get an index. 11906c3fb27SDimitry Andric // By moving this to its own header it can be reused by the pow function in to_chars_base_10. 12006c3fb27SDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI decltype(__pow10_128)& __pow() { 12106c3fb27SDimitry Andric return __itoa::__pow10_128; 12206c3fb27SDimitry Andric } 12306c3fb27SDimitry Andric }; 12406c3fb27SDimitry Andric # endif 12506c3fb27SDimitry Andric 12606c3fb27SDimitry Andric template <typename _Tp> 12706c3fb27SDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool 12806c3fb27SDimitry Andric __mul_overflowed(unsigned char __a, _Tp __b, unsigned char& __r) { 12906c3fb27SDimitry Andric auto __c = __a * __b; 13006c3fb27SDimitry Andric __r = __c; 13106c3fb27SDimitry Andric return __c > numeric_limits<unsigned char>::max(); 13206c3fb27SDimitry Andric } 13306c3fb27SDimitry Andric 13406c3fb27SDimitry Andric template <typename _Tp> 13506c3fb27SDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool 13606c3fb27SDimitry Andric __mul_overflowed(unsigned short __a, _Tp __b, unsigned short& __r) { 13706c3fb27SDimitry Andric auto __c = __a * __b; 13806c3fb27SDimitry Andric __r = __c; 13906c3fb27SDimitry Andric return __c > numeric_limits<unsigned short>::max(); 14006c3fb27SDimitry Andric } 14106c3fb27SDimitry Andric 14206c3fb27SDimitry Andric template <typename _Tp> 14306c3fb27SDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool __mul_overflowed(_Tp __a, _Tp __b, _Tp& __r) { 14406c3fb27SDimitry Andric static_assert(is_unsigned<_Tp>::value, ""); 14506c3fb27SDimitry Andric return __builtin_mul_overflow(__a, __b, &__r); 14606c3fb27SDimitry Andric } 14706c3fb27SDimitry Andric 14806c3fb27SDimitry Andric template <typename _Tp, typename _Up> 14906c3fb27SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool _LIBCPP_CONSTEXPR_SINCE_CXX23 __mul_overflowed(_Tp __a, _Up __b, _Tp& __r) { 15006c3fb27SDimitry Andric return __itoa::__mul_overflowed(__a, static_cast<_Tp>(__b), __r); 15106c3fb27SDimitry Andric } 15206c3fb27SDimitry Andric 15306c3fb27SDimitry Andric template <typename _Tp> 15406c3fb27SDimitry Andric struct _LIBCPP_HIDDEN __traits : __traits_base<_Tp> { 15506c3fb27SDimitry Andric static constexpr int digits = numeric_limits<_Tp>::digits10 + 1; 15606c3fb27SDimitry Andric using __traits_base<_Tp>::__pow; 15706c3fb27SDimitry Andric using typename __traits_base<_Tp>::type; 15806c3fb27SDimitry Andric 15906c3fb27SDimitry Andric // precondition: at least one non-zero character available 16006c3fb27SDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char const* 16106c3fb27SDimitry Andric __read(char const* __p, char const* __ep, type& __a, type& __b) { 16206c3fb27SDimitry Andric type __cprod[digits]; 16306c3fb27SDimitry Andric int __j = digits - 1; 16406c3fb27SDimitry Andric int __i = digits; 16506c3fb27SDimitry Andric do { 16606c3fb27SDimitry Andric if (*__p < '0' || *__p > '9') 16706c3fb27SDimitry Andric break; 16806c3fb27SDimitry Andric __cprod[--__i] = *__p++ - '0'; 16906c3fb27SDimitry Andric } while (__p != __ep && __i != 0); 17006c3fb27SDimitry Andric 17106c3fb27SDimitry Andric __a = __inner_product(__cprod + __i + 1, __cprod + __j, __pow() + 1, __cprod[__i]); 17206c3fb27SDimitry Andric if (__itoa::__mul_overflowed(__cprod[__j], __pow()[__j - __i], __b)) 17306c3fb27SDimitry Andric --__p; 17406c3fb27SDimitry Andric return __p; 17506c3fb27SDimitry Andric } 17606c3fb27SDimitry Andric 17706c3fb27SDimitry Andric template <typename _It1, typename _It2, class _Up> 17806c3fb27SDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _Up 17906c3fb27SDimitry Andric __inner_product(_It1 __first1, _It1 __last1, _It2 __first2, _Up __init) { 18006c3fb27SDimitry Andric for (; __first1 < __last1; ++__first1, ++__first2) 18106c3fb27SDimitry Andric __init = __init + *__first1 * *__first2; 18206c3fb27SDimitry Andric return __init; 18306c3fb27SDimitry Andric } 18406c3fb27SDimitry Andric }; 18506c3fb27SDimitry Andric 18606c3fb27SDimitry Andric } // namespace __itoa 18706c3fb27SDimitry Andric 18806c3fb27SDimitry Andric template <typename _Tp> 18906c3fb27SDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _Tp __complement(_Tp __x) { 19006c3fb27SDimitry Andric static_assert(is_unsigned<_Tp>::value, "cast to unsigned first"); 19106c3fb27SDimitry Andric return _Tp(~__x + 1); 19206c3fb27SDimitry Andric } 19306c3fb27SDimitry Andric 19406c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 17 19506c3fb27SDimitry Andric 19606c3fb27SDimitry Andric _LIBCPP_END_NAMESPACE_STD 19706c3fb27SDimitry Andric 19806c3fb27SDimitry Andric _LIBCPP_POP_MACROS 19906c3fb27SDimitry Andric 20006c3fb27SDimitry Andric #endif // _LIBCPP___CHARCONV_TRAITS 201