xref: /freebsd-src/contrib/llvm-project/libcxx/include/__charconv/to_chars_base_10.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
181ad6265SDimitry Andric // -*- C++ -*-
281ad6265SDimitry Andric //===----------------------------------------------------------------------===//
381ad6265SDimitry Andric //
481ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
581ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
681ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
781ad6265SDimitry Andric //
881ad6265SDimitry Andric //===----------------------------------------------------------------------===//
981ad6265SDimitry Andric 
1081ad6265SDimitry Andric #ifndef _LIBCPP___CHARCONV_TO_CHARS_BASE_10_H
1181ad6265SDimitry Andric #define _LIBCPP___CHARCONV_TO_CHARS_BASE_10_H
1281ad6265SDimitry Andric 
1381ad6265SDimitry Andric #include <__algorithm/copy_n.h>
14*0fca6ea1SDimitry Andric #include <__assert>
1581ad6265SDimitry Andric #include <__charconv/tables.h>
1681ad6265SDimitry Andric #include <__config>
1781ad6265SDimitry Andric #include <cstdint>
18753f127fSDimitry Andric #include <limits>
1981ad6265SDimitry Andric 
2081ad6265SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2181ad6265SDimitry Andric #  pragma GCC system_header
2281ad6265SDimitry Andric #endif
2381ad6265SDimitry Andric 
24753f127fSDimitry Andric _LIBCPP_PUSH_MACROS
25753f127fSDimitry Andric #include <__undef_macros>
26753f127fSDimitry Andric 
2781ad6265SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
2881ad6265SDimitry Andric 
2906c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 17
3081ad6265SDimitry Andric 
3181ad6265SDimitry Andric namespace __itoa {
3281ad6265SDimitry Andric 
33bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append1(char* __first, uint32_t __value) noexcept {
3481ad6265SDimitry Andric   *__first = '0' + static_cast<char>(__value);
3581ad6265SDimitry Andric   return __first + 1;
3681ad6265SDimitry Andric }
3781ad6265SDimitry Andric 
38bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append2(char* __first, uint32_t __value) noexcept {
39bdd1243dSDimitry Andric   return std::copy_n(&__digits_base_10[__value * 2], 2, __first);
4081ad6265SDimitry Andric }
4181ad6265SDimitry Andric 
42bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append3(char* __first, uint32_t __value) noexcept {
4381ad6265SDimitry Andric   return __itoa::__append2(__itoa::__append1(__first, __value / 100), __value % 100);
4481ad6265SDimitry Andric }
4581ad6265SDimitry Andric 
46bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append4(char* __first, uint32_t __value) noexcept {
4781ad6265SDimitry Andric   return __itoa::__append2(__itoa::__append2(__first, __value / 100), __value % 100);
4881ad6265SDimitry Andric }
4981ad6265SDimitry Andric 
50bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append5(char* __first, uint32_t __value) noexcept {
5181ad6265SDimitry Andric   return __itoa::__append4(__itoa::__append1(__first, __value / 10000), __value % 10000);
5281ad6265SDimitry Andric }
5381ad6265SDimitry Andric 
54bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append6(char* __first, uint32_t __value) noexcept {
5581ad6265SDimitry Andric   return __itoa::__append4(__itoa::__append2(__first, __value / 10000), __value % 10000);
5681ad6265SDimitry Andric }
5781ad6265SDimitry Andric 
58bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append7(char* __first, uint32_t __value) noexcept {
5981ad6265SDimitry Andric   return __itoa::__append6(__itoa::__append1(__first, __value / 1000000), __value % 1000000);
6081ad6265SDimitry Andric }
6181ad6265SDimitry Andric 
62bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append8(char* __first, uint32_t __value) noexcept {
6381ad6265SDimitry Andric   return __itoa::__append6(__itoa::__append2(__first, __value / 1000000), __value % 1000000);
6481ad6265SDimitry Andric }
6581ad6265SDimitry Andric 
66bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append9(char* __first, uint32_t __value) noexcept {
6781ad6265SDimitry Andric   return __itoa::__append8(__itoa::__append1(__first, __value / 100000000), __value % 100000000);
6881ad6265SDimitry Andric }
6981ad6265SDimitry Andric 
7081ad6265SDimitry Andric template <class _Tp>
71bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __append10(char* __first, _Tp __value) noexcept {
7281ad6265SDimitry Andric   return __itoa::__append8(__itoa::__append2(__first, static_cast<uint32_t>(__value / 100000000)),
7381ad6265SDimitry Andric                            static_cast<uint32_t>(__value % 100000000));
7481ad6265SDimitry Andric }
7581ad6265SDimitry Andric 
7606c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char*
7706c3fb27SDimitry Andric __base_10_u32(char* __first, uint32_t __value) noexcept {
7881ad6265SDimitry Andric   if (__value < 1000000) {
7981ad6265SDimitry Andric     if (__value < 10000) {
8081ad6265SDimitry Andric       if (__value < 100) {
8181ad6265SDimitry Andric         // 0 <= __value < 100
8281ad6265SDimitry Andric         if (__value < 10)
8381ad6265SDimitry Andric           return __itoa::__append1(__first, __value);
8481ad6265SDimitry Andric         return __itoa::__append2(__first, __value);
8581ad6265SDimitry Andric       }
8681ad6265SDimitry Andric       // 100 <= __value < 10'000
8781ad6265SDimitry Andric       if (__value < 1000)
8881ad6265SDimitry Andric         return __itoa::__append3(__first, __value);
8981ad6265SDimitry Andric       return __itoa::__append4(__first, __value);
9081ad6265SDimitry Andric     }
9181ad6265SDimitry Andric 
9281ad6265SDimitry Andric     // 10'000 <= __value < 1'000'000
9381ad6265SDimitry Andric     if (__value < 100000)
9481ad6265SDimitry Andric       return __itoa::__append5(__first, __value);
9581ad6265SDimitry Andric     return __itoa::__append6(__first, __value);
9681ad6265SDimitry Andric   }
9781ad6265SDimitry Andric 
9881ad6265SDimitry Andric   // __value => 1'000'000
9981ad6265SDimitry Andric   if (__value < 100000000) {
10081ad6265SDimitry Andric     // 1'000'000 <= __value < 100'000'000
10181ad6265SDimitry Andric     if (__value < 10000000)
10281ad6265SDimitry Andric       return __itoa::__append7(__first, __value);
10381ad6265SDimitry Andric     return __itoa::__append8(__first, __value);
10481ad6265SDimitry Andric   }
10581ad6265SDimitry Andric 
10681ad6265SDimitry Andric   // 100'000'000 <= __value < max
10781ad6265SDimitry Andric   if (__value < 1000000000)
10881ad6265SDimitry Andric     return __itoa::__append9(__first, __value);
10981ad6265SDimitry Andric   return __itoa::__append10(__first, __value);
11081ad6265SDimitry Andric }
11181ad6265SDimitry Andric 
11206c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char*
11306c3fb27SDimitry Andric __base_10_u64(char* __buffer, uint64_t __value) noexcept {
11481ad6265SDimitry Andric   if (__value <= UINT32_MAX)
11581ad6265SDimitry Andric     return __itoa::__base_10_u32(__buffer, static_cast<uint32_t>(__value));
11681ad6265SDimitry Andric 
11781ad6265SDimitry Andric   // Numbers in the range UINT32_MAX <= val < 10'000'000'000 always contain 10
11881ad6265SDimitry Andric   // digits and are outputted after this if statement.
11981ad6265SDimitry Andric   if (__value >= 10000000000) {
12081ad6265SDimitry Andric     // This function properly deterimines the first non-zero leading digit.
12181ad6265SDimitry Andric     __buffer = __itoa::__base_10_u32(__buffer, static_cast<uint32_t>(__value / 10000000000));
12281ad6265SDimitry Andric     __value %= 10000000000;
12381ad6265SDimitry Andric   }
12481ad6265SDimitry Andric   return __itoa::__append10(__buffer, __value);
12581ad6265SDimitry Andric }
12681ad6265SDimitry Andric 
127753f127fSDimitry Andric #  ifndef _LIBCPP_HAS_NO_INT128
128753f127fSDimitry Andric /// \returns 10^\a exp
129753f127fSDimitry Andric ///
130753f127fSDimitry Andric /// \pre \a exp [19, 39]
131753f127fSDimitry Andric ///
132753f127fSDimitry Andric /// \note The lookup table contains a partial set of exponents limiting the
133753f127fSDimitry Andric /// range that can be used. However the range is sufficient for
134753f127fSDimitry Andric /// \ref __base_10_u128.
135bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline __uint128_t __pow_10(int __exp) noexcept {
1361db9f3b2SDimitry Andric   _LIBCPP_ASSERT_INTERNAL(__exp >= __pow10_128_offset, "Index out of bounds");
137bdd1243dSDimitry Andric   return __pow10_128[__exp - __pow10_128_offset];
138753f127fSDimitry Andric }
139753f127fSDimitry Andric 
14006c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char*
14106c3fb27SDimitry Andric __base_10_u128(char* __buffer, __uint128_t __value) noexcept {
1421db9f3b2SDimitry Andric   _LIBCPP_ASSERT_INTERNAL(
1431db9f3b2SDimitry Andric       __value > numeric_limits<uint64_t>::max(), "The optimizations for this algorithm fails when this isn't true.");
144753f127fSDimitry Andric 
145753f127fSDimitry Andric   // Unlike the 64 to 32 bit case the 128 bit case the "upper half" can't be
146753f127fSDimitry Andric   // stored in the "lower half". Instead we first need to handle the top most
147753f127fSDimitry Andric   // digits separately.
148753f127fSDimitry Andric   //
149753f127fSDimitry Andric   // Maximum unsigned values
150753f127fSDimitry Andric   // 64  bit                             18'446'744'073'709'551'615 (20 digits)
151753f127fSDimitry Andric   // 128 bit    340'282'366'920'938'463'463'374'607'431'768'211'455 (39 digits)
152753f127fSDimitry Andric   // step 1     ^                                                   ([0-1] digits)
153753f127fSDimitry Andric   // step 2      ^^^^^^^^^^^^^^^^^^^^^^^^^                          ([0-19] digits)
154753f127fSDimitry Andric   // step 3                               ^^^^^^^^^^^^^^^^^^^^^^^^^ (19 digits)
155753f127fSDimitry Andric   if (__value >= __itoa::__pow_10(38)) {
156753f127fSDimitry Andric     // step 1
157753f127fSDimitry Andric     __buffer = __itoa::__append1(__buffer, static_cast<uint32_t>(__value / __itoa::__pow_10(38)));
158753f127fSDimitry Andric     __value %= __itoa::__pow_10(38);
159753f127fSDimitry Andric 
160753f127fSDimitry Andric     // step 2 always 19 digits.
161753f127fSDimitry Andric     // They are handled here since leading zeros need to be appended to the buffer,
162753f127fSDimitry Andric     __buffer = __itoa::__append9(__buffer, static_cast<uint32_t>(__value / __itoa::__pow_10(29)));
163753f127fSDimitry Andric     __value %= __itoa::__pow_10(29);
164753f127fSDimitry Andric     __buffer = __itoa::__append10(__buffer, static_cast<uint64_t>(__value / __itoa::__pow_10(19)));
165753f127fSDimitry Andric     __value %= __itoa::__pow_10(19);
16606c3fb27SDimitry Andric   } else {
167753f127fSDimitry Andric     // step 2
168753f127fSDimitry Andric     // This version needs to determine the position of the leading non-zero digit.
169753f127fSDimitry Andric     __buffer = __base_10_u64(__buffer, static_cast<uint64_t>(__value / __itoa::__pow_10(19)));
170753f127fSDimitry Andric     __value %= __itoa::__pow_10(19);
171753f127fSDimitry Andric   }
172753f127fSDimitry Andric 
173753f127fSDimitry Andric   // Step 3
174753f127fSDimitry Andric   __buffer = __itoa::__append9(__buffer, static_cast<uint32_t>(__value / 10000000000));
175753f127fSDimitry Andric   __buffer = __itoa::__append10(__buffer, static_cast<uint64_t>(__value % 10000000000));
176753f127fSDimitry Andric 
177753f127fSDimitry Andric   return __buffer;
178753f127fSDimitry Andric }
179753f127fSDimitry Andric #  endif
18081ad6265SDimitry Andric } // namespace __itoa
18181ad6265SDimitry Andric 
18206c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 17
18381ad6265SDimitry Andric 
18481ad6265SDimitry Andric _LIBCPP_END_NAMESPACE_STD
18581ad6265SDimitry Andric 
186753f127fSDimitry Andric _LIBCPP_POP_MACROS
187753f127fSDimitry Andric 
18881ad6265SDimitry Andric #endif // _LIBCPP___CHARCONV_TO_CHARS_BASE_10_H
189