100 static constexpr uint64_t pow10_64[] =
111 UINT64_C(1000000000),
112 UINT64_C(10000000000),
113 UINT64_C(100000000000),
114 UINT64_C(1000000000000),
115 UINT64_C(10000000000000),
116 UINT64_C(100000000000000),
117 UINT64_C(1000000000000000),
118 UINT64_C(10000000000000000),
119 UINT64_C(100000000000000000),
120 UINT64_C(1000000000000000000),
121 UINT64_C(10000000000000000000),
124 static constexpr uint32_t pow10_32[] =
126 UINT32_C(0), UINT32_C(10), UINT32_C(100),
127 UINT32_C(1000), UINT32_C(10000), UINT32_C(100000),
128 UINT32_C(1000000), UINT32_C(10000000), UINT32_C(100000000),
129 UINT32_C(1000000000),
132 static constexpr
char cDigitsLut[200] = {
133 '0',
'0',
'0',
'1',
'0',
'2',
'0',
'3',
'0',
'4',
'0',
'5',
'0',
'6',
'0',
134 '7',
'0',
'8',
'0',
'9',
'1',
'0',
'1',
'1',
'1',
'2',
'1',
'3',
'1',
'4',
135 '1',
'5',
'1',
'6',
'1',
'7',
'1',
'8',
'1',
'9',
'2',
'0',
'2',
'1',
'2',
136 '2',
'2',
'3',
'2',
'4',
'2',
'5',
'2',
'6',
'2',
'7',
'2',
'8',
'2',
'9',
137 '3',
'0',
'3',
'1',
'3',
'2',
'3',
'3',
'3',
'4',
'3',
'5',
'3',
'6',
'3',
138 '7',
'3',
'8',
'3',
'9',
'4',
'0',
'4',
'1',
'4',
'2',
'4',
'3',
'4',
'4',
139 '4',
'5',
'4',
'6',
'4',
'7',
'4',
'8',
'4',
'9',
'5',
'0',
'5',
'1',
'5',
140 '2',
'5',
'3',
'5',
'4',
'5',
'5',
'5',
'6',
'5',
'7',
'5',
'8',
'5',
'9',
141 '6',
'0',
'6',
'1',
'6',
'2',
'6',
'3',
'6',
'4',
'6',
'5',
'6',
'6',
'6',
142 '7',
'6',
'8',
'6',
'9',
'7',
'0',
'7',
'1',
'7',
'2',
'7',
'3',
'7',
'4',
143 '7',
'5',
'7',
'6',
'7',
'7',
'7',
'8',
'7',
'9',
'8',
'0',
'8',
'1',
'8',
144 '2',
'8',
'3',
'8',
'4',
'8',
'5',
'8',
'6',
'8',
'7',
'8',
'8',
'8',
'9',
145 '9',
'0',
'9',
'1',
'9',
'2',
'9',
'3',
'9',
'4',
'9',
'5',
'9',
'6',
'9',
146 '7',
'9',
'8',
'9',
'9'};
148 template <
typename T>
149 inline char* append1(
char* buffer, T i)
151 *buffer =
'0' +
static_cast<char>(i);
155 template <
typename T>
156 inline char* append2(
char* buffer, T i)
158 memcpy(buffer, &cDigitsLut[(i)*2], 2);
162 template <
typename T>
163 inline char* append3(
char* buffer, T i)
165 return append2(append1(buffer, (i) / 100), (i) % 100);
168 template <
typename T>
169 inline char* append4(
char* buffer, T i)
171 return append2(append2(buffer, (i) / 100), (i) % 100);
174 char* u32toa(uint32_t value,
char* buffer)
181 buffer = append1(buffer, value);
183 buffer = append2(buffer, value);
188 buffer = append3(buffer, value);
190 buffer = append4(buffer, value);
193 else if (value < 100000000)
196 const uint32_t b = value / 10000;
197 const uint32_t c = value % 10000;
202 buffer = append1(buffer, b);
204 buffer = append2(buffer, b);
208 if (value < 10000000)
209 buffer = append3(buffer, b);
211 buffer = append4(buffer, b);
214 buffer = append4(buffer, c);
219 const uint32_t a = value / 100000000;
223 buffer = append1(buffer, a);
225 buffer = append2(buffer, a);
227 buffer = append4(buffer, value / 10000);
228 buffer = append4(buffer, value % 10000);
234 char* u64toa(uint64_t value,
char* buffer)
236 if (value < 100000000)
238 uint32_t v =
static_cast<uint32_t
>(value);
244 buffer = append1(buffer, v);
246 buffer = append2(buffer, v);
251 buffer = append3(buffer, v);
253 buffer = append4(buffer, v);
259 const uint32_t b = v / 10000;
260 const uint32_t c = v % 10000;
265 buffer = append1(buffer, b);
267 buffer = append2(buffer, b);
272 buffer = append3(buffer, b);
274 buffer = append4(buffer, b);
277 buffer = append4(buffer, c);
280 else if (value < 10000000000000000)
282 const uint32_t v0 =
static_cast<uint32_t
>(value / 100000000);
283 const uint32_t v1 =
static_cast<uint32_t
>(value % 100000000);
285 const uint32_t b0 = v0 / 10000;
286 const uint32_t c0 = v0 % 10000;
291 buffer = append1(buffer, b0);
293 buffer = append2(buffer, b0);
298 buffer = append3(buffer, b0);
300 buffer = append4(buffer, b0);
303 buffer = append4(buffer, c0);
304 buffer = append4(buffer, v1 / 10000);
305 buffer = append4(buffer, v1 % 10000);
310 static_cast<uint32_t
>(value / 10000000000000000);
311 value %= 10000000000000000;
316 buffer = append1(buffer, a);
318 buffer = append2(buffer, a);
323 buffer = append3(buffer, a);
325 buffer = append4(buffer, a);
328 const uint32_t v0 =
static_cast<uint32_t
>(value / 100000000);
329 const uint32_t v1 =
static_cast<uint32_t
>(value % 100000000);
330 buffer = append4(buffer, v0 / 10000);
331 buffer = append4(buffer, v0 % 10000);
332 buffer = append4(buffer, v1 / 10000);
333 buffer = append4(buffer, v1 % 10000);
339 template <
typename value_type,
typename =
void>
342 using type = uint64_t;
344 static int width(value_type v)
346 auto t = (64 - __builtin_clzll(v | 1)) * 1233 >> 12;
347 return t - (v < pow10_64[t]) + 1;
350 static char*
convert(value_type v,
char* p)
355 static auto& pow() {
return pow10_64; }
358 template <
typename value_type>
359 struct traits_base<value_type, decltype(void(uint32_t{std::declval<value_type>()}))>
361 using type = uint32_t;
363 static int width(value_type v)
365 auto t = (32 - __builtin_clz(v | 1)) * 1233 >> 12;
366 return t - (v < pow10_32[t]) + 1;
369 static char*
convert(value_type v,
char* p)
374 static auto& pow() {
return pow10_32; }
377 template <
typename value_type>
378 inline bool mul_overflowed(
unsigned char a, value_type b,
unsigned char& r)
382 return c > (std::numeric_limits<unsigned char>::max)();
385 template <
typename value_type>
386 inline bool mul_overflowed(
unsigned short a, value_type b,
unsigned short& r)
390 return c > (std::numeric_limits<unsigned short>::max)();
393 template <
typename value_type>
394 inline bool mul_overflowed(value_type a, value_type b, value_type & r)
396 static_assert(std::is_unsigned<value_type>::value,
"");
397 return __builtin_mul_overflow(a, b, &r);
400 template <
typename value_type,
typename _Up>
401 inline bool mul_overflowed(value_type a, _Up b, value_type & r)
403 return mul_overflowed(a, static_cast<value_type>(b), r);
406 template <
typename value_type>
407 struct traits : traits_base<value_type>
409 static constexpr
int digits = std::numeric_limits<value_type>::digits10 + 1;
410 using traits_base<value_type>::pow;
411 using typename traits_base<value_type>::type;
415 read(
char const* p,
char const* ep, type& a, type& b)
422 if (!(
'0' <= *p && *p <=
'9'))
424 cprod[--i] = *p++ -
'0';
425 }
while (p != ep && i != 0);
427 a = inner_product(cprod + i + 1, cprod + j, pow() + 1,
429 if (mul_overflowed(cprod[j], pow()[j - i], b))
434 template <
typename _It1,
typename _It2,
class _Up>
436 inner_product(_It1 first1, _It1 last1, _It2 first2, _Up init)
438 for (; first1 < last1; ++first1, ++first2)
439 init = init + *first1 * *first2;
444 template <
typename value_type>
448 return value_type(~x + 1);
451 template <
typename value_type>
452 inline auto to_unsigned(value_type x)
454 return static_cast<std::make_unsigned_t<value_type>
>(x);
457 template <
typename value_type>
458 inline std::to_chars_result to_chars_itoa(
char* first,
char* last, value_type value, std::false_type)
460 using tx = traits<value_type>;
461 auto diff = last - first;
463 if (tx::digits <= diff || tx::width(value) <= diff)
464 return {tx::convert(value, first), {}};
466 return {last, std::errc::value_too_large};
469 template <
typename value_type>
470 inline std::to_chars_result to_chars_itoa(
char* first,
char* last, value_type value, std::true_type)
472 auto x = to_unsigned(value);
473 if (value < 0 && first != last)
479 return to_chars_itoa(first, last, x, std::false_type());
482 template <
typename value_type>
483 inline std::to_chars_result to_chars_integral(
char* first,
char* last, value_type value,
int base,
486 auto x = to_unsigned(value);
487 if (value < 0 && first != last)
493 return to_chars_integral(first, last, x, base, std::false_type());
496 template <
typename value_type>
497 inline std::to_chars_result to_chars_integral(
char* first,
char* last, value_type value,
int base,
501 return to_chars_itoa(first, last, value, std::false_type());
506 auto c = value % base;
508 *--p =
"0123456789abcdefghijklmnopqrstuvwxyz"[c];
514 if (value != 0 || !len)
515 return {last, std::errc::value_too_large};
518 memmove(first, p, len);
519 return {first + len, {}};
523 template <
typename _It,
typename value_type,
typename _Fn,
typename... _Ts>
524 inline std::from_chars_result sign_combinator(_It first, _It last, value_type & value, _Fn f, _Ts... args)
526 using tl = std::numeric_limits<value_type>;
527 decltype(to_unsigned(value)) x;
529 bool neg = (first != last && *first ==
'-');
530 auto r = f(neg ? first + 1 : first, last, x, args...);
534 case std::errc::invalid_argument:
535 return {first, r.ec};
536 case std::errc::result_out_of_range:
547 memcpy(&value, &x,
sizeof(x));
553 if (x <= (tl::max)())
560 return {r.ptr, std::errc::result_out_of_range};
563 template <
typename value_type>
564 inline bool in_pattern(value_type c)
566 return '0' <= c && c <=
'9';
569 struct in_pattern_result
574 explicit operator bool()
const {
return ok; }
577 template <
typename value_type>
578 inline in_pattern_result in_pattern(value_type c,
int base)
581 return {
'0' <= c && c <
'0' + base, c -
'0'};
582 else if (in_pattern(c))
583 return {
true, c -
'0'};
584 else if (
'a' <= c && c <
'a' + base - 10)
585 return {
true, c -
'a' + 10};
587 return {
'A' <= c && c <
'A' + base - 10, c -
'A' + 10};
590 template <
typename _It,
typename value_type,
typename _Fn,
typename... _Ts>
591 inline std::from_chars_result subject_seq_combinator(_It first, _It last, value_type & value, _Fn f, _Ts... args)
593 auto find_non_zero = [](_It first, _It last)
595 for (; first != last; ++first)
601 auto p = find_non_zero(first, last);
602 if (p == last || !in_pattern(*p, args...))
605 return {first, std::errc::invalid_argument};
613 auto r = f(p, last, value, args...);
614 if (r.ec == std::errc::result_out_of_range)
616 for (; r.ptr != last; ++r.ptr)
618 if (!in_pattern(*r.ptr, args...))
626 template <typename value_type, std::enable_if_t<std::is_unsigned<value_type>::value,
int> = 0>
628 from_chars_atoi(
char const * first,
char const * last, value_type & value)
630 using tx = traits<value_type>;
631 using output_type =
typename tx::type;
633 return subject_seq_combinator(first, last, value,
637 auto p = tx::read(first, last, a, b);
638 if (p == last || !in_pattern(*p))
640 output_type m = (std::numeric_limits<value_type>::max)();
641 if (m >= a && m - a >= b)
647 return {p, std::errc::result_out_of_range};
651 template <std::SignedIntegral value_type>
654 using t = decltype(to_unsigned(value));
655 return sign_combinator(first, last, value, from_chars_atoi<t>);
658 template <std::Un
signedIntegral value_type>
659 inline std::from_chars_result from_chars_integral(
char const * first,
char const * last, value_type & value,
int base)
662 return from_chars_atoi(first, last, value);
664 return subject_seq_combinator(first, last, value,
667 using tl = std::numeric_limits<value_type>;
668 auto digits = tl::digits / log2f(
float(base));
669 value_type a = in_pattern(*p++, base).val, b = 0;
671 for (
int i = 1; p != last; ++i, ++p)
673 if (
auto c = in_pattern(*p, base))
676 a = a * base + c.val;
679 if (!mul_overflowed(a, base, a))
689 if (p == last || !in_pattern(*p, base))
691 if ((tl::max)() - a >= b)
697 return {p, std::errc::result_out_of_range};
702 template <std::SignedIntegral value_type>
703 inline std::from_chars_result from_chars_integral(
char const * first,
char const * last, value_type & value,
int base)
705 using t = decltype(to_unsigned(value));
706 return sign_combinator(first, last, value, from_chars_integral<t>, base);
711 template <seqan3::
floating_po
int_concept value_type>
725 return {last, std::errc::invalid_argument};
728 ptrdiff_t constexpr buffer_size = 10000;
729 char hex_buffer[buffer_size];
735 bool exponent_is_present{
false};
736 for (
auto it = first; it != last; ++it)
738 if (seqan3::is_char<'e'>(*it) || seqan3::is_char<'E'>(*it))
740 exponent_is_present =
true;
746 !exponent_is_present)
747 return {last, std::errc::invalid_argument};
751 return {last, std::errc::invalid_argument};
765 for (
unsigned i = 0; i < std::min(buffer_size - 2, last - first); ++i)
766 hex_buffer[i+2] = first[i];
768 start = &hex_buffer[0];
769 end = &hex_buffer[0] +
sizeof(hex_buffer);
773 start =
const_cast<char *
>(first);
774 end =
const_cast<char *
>(last);
777 if constexpr (
std::Same<std::remove_reference_t<value_type>,
float>)
779 tmp = strtof(start, &end);
781 if constexpr (
std::Same<std::remove_reference_t<value_type>,
double>)
783 tmp = strtod(start, &end);
785 if constexpr (
std::Same<std::remove_reference_t<value_type>,
long double>)
787 tmp = strtold(start, &end);
792 return {last, std::errc::result_out_of_range};
794 else if (tmp == 0 && end == first)
796 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:89
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:66
constexpr nucleotide_type complement(nucleotide_type const alph) requires requires(nucleotide_type alph)
Implementation of seqan3::nucleotide_concept::complement() that delegates to a member function...
Definition: member_exposure.hpp:220
Fixed number of digits for precision.
Result type of std::from_chars.
Definition: charconv:74
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:82
The concept std::Same<T, U> is satisfied if and only if T and U denote the same type.
Definition: aligned_sequence_concept.hpp:288
Provides C++20 additions to the type_traits header.
Scientific notation, e.g. 3.991E-0003.
Provides parse conditions for tokenization.
The concept std::UnsignedIntegral is satisfied if and only if T is an integral type and std::is_signe...
::ranges::end end
Alias for ranges::end. Returns an iterator to the end of a range.
Definition: ranges:190