74 static constexpr uint64_t pow10_64[] =
86 UINT64_C(10000000000),
87 UINT64_C(100000000000),
88 UINT64_C(1000000000000),
89 UINT64_C(10000000000000),
90 UINT64_C(100000000000000),
91 UINT64_C(1000000000000000),
92 UINT64_C(10000000000000000),
93 UINT64_C(100000000000000000),
94 UINT64_C(1000000000000000000),
95 UINT64_C(10000000000000000000),
98 static constexpr uint32_t pow10_32[] =
100 UINT32_C(0), UINT32_C(10), UINT32_C(100),
101 UINT32_C(1000), UINT32_C(10000), UINT32_C(100000),
102 UINT32_C(1000000), UINT32_C(10000000), UINT32_C(100000000),
103 UINT32_C(1000000000),
106 static constexpr
char cDigitsLut[200] = {
107 '0',
'0',
'0',
'1',
'0',
'2',
'0',
'3',
'0',
'4',
'0',
'5',
'0',
'6',
'0',
108 '7',
'0',
'8',
'0',
'9',
'1',
'0',
'1',
'1',
'1',
'2',
'1',
'3',
'1',
'4',
109 '1',
'5',
'1',
'6',
'1',
'7',
'1',
'8',
'1',
'9',
'2',
'0',
'2',
'1',
'2',
110 '2',
'2',
'3',
'2',
'4',
'2',
'5',
'2',
'6',
'2',
'7',
'2',
'8',
'2',
'9',
111 '3',
'0',
'3',
'1',
'3',
'2',
'3',
'3',
'3',
'4',
'3',
'5',
'3',
'6',
'3',
112 '7',
'3',
'8',
'3',
'9',
'4',
'0',
'4',
'1',
'4',
'2',
'4',
'3',
'4',
'4',
113 '4',
'5',
'4',
'6',
'4',
'7',
'4',
'8',
'4',
'9',
'5',
'0',
'5',
'1',
'5',
114 '2',
'5',
'3',
'5',
'4',
'5',
'5',
'5',
'6',
'5',
'7',
'5',
'8',
'5',
'9',
115 '6',
'0',
'6',
'1',
'6',
'2',
'6',
'3',
'6',
'4',
'6',
'5',
'6',
'6',
'6',
116 '7',
'6',
'8',
'6',
'9',
'7',
'0',
'7',
'1',
'7',
'2',
'7',
'3',
'7',
'4',
117 '7',
'5',
'7',
'6',
'7',
'7',
'7',
'8',
'7',
'9',
'8',
'0',
'8',
'1',
'8',
118 '2',
'8',
'3',
'8',
'4',
'8',
'5',
'8',
'6',
'8',
'7',
'8',
'8',
'8',
'9',
119 '9',
'0',
'9',
'1',
'9',
'2',
'9',
'3',
'9',
'4',
'9',
'5',
'9',
'6',
'9',
120 '7',
'9',
'8',
'9',
'9'};
122 template <
typename T>
123 inline char* append1(
char* buffer, T i) noexcept
125 *buffer =
'0' +
static_cast<char>(i);
129 template <
typename T>
130 inline char* append2(
char* buffer, T i) noexcept
132 memcpy(buffer, &cDigitsLut[(i)*2], 2);
136 template <
typename T>
137 inline char* append3(
char* buffer, T i) noexcept
139 return append2(append1(buffer, (i) / 100), (i) % 100);
142 template <
typename T>
143 inline char* append4(
char* buffer, T i) noexcept
145 return append2(append2(buffer, (i) / 100), (i) % 100);
148 inline char* u32toa(uint32_t value,
char* buffer) noexcept
155 buffer = append1(buffer, value);
157 buffer = append2(buffer, value);
162 buffer = append3(buffer, value);
164 buffer = append4(buffer, value);
167 else if (value < 100000000)
170 const uint32_t b = value / 10000;
171 const uint32_t c = value % 10000;
176 buffer = append1(buffer, b);
178 buffer = append2(buffer, b);
182 if (value < 10000000)
183 buffer = append3(buffer, b);
185 buffer = append4(buffer, b);
188 buffer = append4(buffer, c);
193 const uint32_t a = value / 100000000;
197 buffer = append1(buffer, a);
199 buffer = append2(buffer, a);
201 buffer = append4(buffer, value / 10000);
202 buffer = append4(buffer, value % 10000);
208 inline char* u64toa(uint64_t value,
char* buffer) noexcept
210 if (value < 100000000)
212 uint32_t v =
static_cast<uint32_t
>(value);
218 buffer = append1(buffer, v);
220 buffer = append2(buffer, v);
225 buffer = append3(buffer, v);
227 buffer = append4(buffer, v);
233 const uint32_t b = v / 10000;
234 const uint32_t c = v % 10000;
239 buffer = append1(buffer, b);
241 buffer = append2(buffer, b);
246 buffer = append3(buffer, b);
248 buffer = append4(buffer, b);
251 buffer = append4(buffer, c);
254 else if (value < 10000000000000000)
256 const uint32_t v0 =
static_cast<uint32_t
>(value / 100000000);
257 const uint32_t v1 =
static_cast<uint32_t
>(value % 100000000);
259 const uint32_t b0 = v0 / 10000;
260 const uint32_t c0 = v0 % 10000;
265 buffer = append1(buffer, b0);
267 buffer = append2(buffer, b0);
272 buffer = append3(buffer, b0);
274 buffer = append4(buffer, b0);
277 buffer = append4(buffer, c0);
278 buffer = append4(buffer, v1 / 10000);
279 buffer = append4(buffer, v1 % 10000);
284 static_cast<uint32_t
>(value / 10000000000000000);
285 value %= 10000000000000000;
290 buffer = append1(buffer, a);
292 buffer = append2(buffer, a);
297 buffer = append3(buffer, a);
299 buffer = append4(buffer, a);
302 const uint32_t v0 =
static_cast<uint32_t
>(value / 100000000);
303 const uint32_t v1 =
static_cast<uint32_t
>(value % 100000000);
304 buffer = append4(buffer, v0 / 10000);
305 buffer = append4(buffer, v0 % 10000);
306 buffer = append4(buffer, v1 / 10000);
307 buffer = append4(buffer, v1 % 10000);
313 template <
typename value_type,
typename =
void>
316 using type = uint64_t;
318 static int width(value_type v) noexcept
320 auto t = (64 - __builtin_clzll(v | 1)) * 1233 >> 12;
321 return t - (v < pow10_64[t]) + 1;
324 static char*
convert(value_type v,
char* p) noexcept
329 static auto&
pow() {
return pow10_64; }
332 template <
typename value_type>
333 struct traits_base<value_type, decltype(void(uint32_t{std::declval<value_type>()}))>
335 using type = uint32_t;
337 static int width(value_type v) noexcept
339 auto t = (32 - __builtin_clz(v | 1)) * 1233 >> 12;
340 return t - (v < pow10_32[t]) + 1;
343 static char*
convert(value_type v,
char* p) noexcept
348 static auto&
pow() noexcept {
return pow10_32; }
351 template <
typename value_type>
352 inline bool mul_overflowed(
unsigned char a, value_type b,
unsigned char& r) noexcept
359 template <
typename value_type>
360 inline bool mul_overflowed(
unsigned short a, value_type b,
unsigned short& r) noexcept
367 template <
typename value_type>
368 inline bool mul_overflowed(value_type a, value_type b, value_type & r) noexcept
371 return __builtin_mul_overflow(a, b, &r);
374 template <
typename value_type,
typename _Up>
375 inline bool mul_overflowed(value_type a, _Up b, value_type & r) noexcept
377 return mul_overflowed(a, static_cast<value_type>(b), r);
380 template <
typename value_type>
381 struct traits : traits_base<value_type>
384 using traits_base<value_type>::pow;
385 using typename traits_base<value_type>::type;
389 read(
char const* p,
char const* ep, type& a, type& b) noexcept
396 if (!(
'0' <= *p && *p <=
'9'))
398 cprod[--i] = *p++ -
'0';
399 }
while (p != ep && i != 0);
403 if (mul_overflowed(cprod[j],
pow()[j - i], b))
408 template <
typename _It1,
typename _It2,
class _Up>
410 inner_product(_It1 first1, _It1 last1, _It2 first2, _Up init) noexcept
412 for (; first1 < last1; ++first1, ++first2)
413 init = init + *first1 * *first2;
418 template <
typename value_type>
419 inline value_type complement_(value_type x) noexcept
422 return value_type(~x + 1);
425 template <
typename value_type>
426 inline auto to_unsigned(value_type x) noexcept
431 template <
typename value_type>
434 using tx = traits<value_type>;
435 auto diff = last - first;
437 if (tx::digits <= diff || tx::width(value) <= diff)
438 return {tx::convert(value, first), {}};
440 return {last, std::errc::value_too_large};
443 template <
typename value_type>
446 auto x = to_unsigned(value);
447 if (value < 0 && first != last)
456 template <
typename value_type>
457 inline std::to_chars_result to_chars_integral(
char* first,
char* last, value_type value,
int base,
460 auto x = to_unsigned(value);
461 if (value < 0 && first != last)
470 template <
typename value_type>
471 inline std::to_chars_result to_chars_integral(
char* first,
char* last, value_type value,
int base,
480 auto c = value % base;
482 *--p =
"0123456789abcdefghijklmnopqrstuvwxyz"[c];
488 if (value != 0 || !len)
489 return {last, std::errc::value_too_large};
493 return {first + len, {}};
497 template <
typename _It,
typename value_type,
typename _Fn,
typename... _Ts>
498 inline std::from_chars_result sign_combinator(_It first, _It last, value_type & value, _Fn f, _Ts... args) noexcept
501 decltype(to_unsigned(value)) x;
503 bool neg = (first != last && *first ==
'-');
504 auto r = f(neg ? first + 1 : first, last, x, args...);
508 case std::errc::invalid_argument:
509 return {first, r.ec};
510 case std::errc::result_out_of_range:
518 if (x <= complement_(to_unsigned(tl::min())))
521 memcpy(&value, &x,
sizeof(x));
527 if (x <= to_unsigned(tl::max()))
534 return {r.ptr, std::errc::result_out_of_range};
537 template <
typename value_type>
538 inline bool in_pattern(value_type c) noexcept
540 return '0' <= c && c <=
'9';
543 struct in_pattern_result
548 explicit operator bool() const noexcept {
return ok; }
551 template <
typename value_type>
552 inline in_pattern_result in_pattern(value_type c,
int base) noexcept
555 return {
'0' <= c && c <
'0' + base, c -
'0'};
556 else if (in_pattern(c))
557 return {
true, c -
'0'};
558 else if (
'a' <= c && c <
'a' + base - 10)
559 return {
true, c -
'a' + 10};
561 return {
'A' <= c && c <
'A' + base - 10, c -
'A' + 10};
564 template <
typename _It,
typename value_type,
typename _Fn,
typename... _Ts>
565 inline std::from_chars_result subject_seq_combinator(_It first, _It last, value_type & value, _Fn f, _Ts... args) noexcept
567 auto find_non_zero = [](_It first, _It last)
569 for (; first != last; ++first)
575 auto p = find_non_zero(first, last);
576 if (p == last || !in_pattern(*p, args...))
579 return {first, std::errc::invalid_argument};
587 auto r = f(p, last, value, args...);
588 if (r.ec == std::errc::result_out_of_range)
590 for (; r.ptr != last; ++r.ptr)
592 if (!in_pattern(*r.ptr, args...))
600 template <typename value_type, std::enable_if_t<std::is_unsigned<value_type>::value,
int> = 0>
602 from_chars_atoi(
char const * first,
char const * last, value_type & value) noexcept
604 using tx = traits<value_type>;
605 using output_type =
typename tx::type;
607 return subject_seq_combinator(first, last, value,
611 auto p = tx::read(first, last, a, b);
612 if (p == last || !in_pattern(*p))
615 if (m >= a && m - a >= b)
621 return {p, std::errc::result_out_of_range};
625 template <std::SignedIntegral value_type>
626 inline std::from_chars_result from_chars_atoi(
char const * first,
char const * last, value_type & value) noexcept
628 using t = decltype(to_unsigned(value));
629 return sign_combinator(first, last, value, from_chars_atoi<t>);
632 template <std::Un
signedIntegral value_type>
633 inline std::from_chars_result from_chars_integral(
char const * first,
char const * last, value_type & value,
int base) noexcept
636 return from_chars_atoi(first, last, value);
638 return subject_seq_combinator(first, last, value,
642 auto digits = tl::digits / log2f(
float(base));
643 value_type a = in_pattern(*p++, base).val, b = 0;
645 for (
int i = 1; p != last; ++i, ++p)
647 if (
auto c = in_pattern(*p, base))
650 a = a * base + c.val;
653 if (!mul_overflowed(a, base, a))
663 if (p == last || !in_pattern(*p, base))
665 if ((tl::max)() - a >= b)
671 return {p, std::errc::result_out_of_range};
676 template <std::SignedIntegral value_type>
677 inline std::from_chars_result from_chars_integral(
char const * first,
char const * last, value_type & value,
int base) noexcept
679 using t = decltype(to_unsigned(value));
680 return sign_combinator(first, last, value, from_chars_integral<t>, base);
685 template <seqan3::FloatingPo
int value_type>
699 return {last, std::errc::invalid_argument};
702 ptrdiff_t constexpr buffer_size = 100;
703 char buffer[buffer_size];
707 bool exponent_is_present{
false};
708 for (
auto it = first; it != last; ++it)
710 if (seqan3::is_char<'e'>(*it) || seqan3::is_char<'E'>(*it))
712 exponent_is_present =
true;
718 !exponent_is_present)
719 return {last, std::errc::invalid_argument};
723 return {last, std::errc::invalid_argument};
752 buffer[std::min<ptrdiff_t>(buffer_size - offset, last - first)] =
'\0';
758 start =
const_cast<char *
>(first);
765 tmp =
strtof(start, &end);
769 tmp =
strtod(start, &end);
776 last = first + (end - start);
780 return {last, std::errc::result_out_of_range};
782 else if (tmp == 0 && end == start)
784 return {last, std::errc::invalid_argument};
auto const convert
A view that converts each element in the input range (implicitly or via static_cast).
Definition: convert.hpp:67
Provides concepts for core language types and relations that don't have concepts in C++20 (yet)...
Result type of std::to_chars.
Definition: charconv:39
Fixed number of digits for precision.
Result type of std::from_chars.
Definition: charconv:47
Hexadecimal notation. Ff specified in from_chars, prefix 0x,0X,x is not allowed.
chars_format
A BitmaskType used to specify floating-point formatting for std::to_chars and std::from_chars.
Definition: charconv:55
The concept std::Same<T, U> is satisfied if and only if T and U denote the same type.
Definition: aligned_sequence_concept.hpp:35
Provides character predicates for tokenisation.
Provides C++20 additions to the type_traits header.
Scientific notation, e.g. 3.991E-0003.
Adaptations of algorithms from the Ranges TS.
The concept std::UnsignedIntegral is satisfied if and only if T is an integral type and std::is_signe...
T inner_product(T... args)
::ranges::end end
Alias for ranges::end. Returns an iterator to the end of a range.
Definition: ranges:179