Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:14

0001 // -*- C++ -*-
0002 //===----------------------------------------------------------------------===//
0003 //
0004 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0005 // See https://llvm.org/LICENSE.txt for license information.
0006 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0007 //
0008 //===----------------------------------------------------------------------===//
0009 
0010 #ifndef _LIBCPP___CHARCONV_FROM_CHARS_INTEGRAL_H
0011 #define _LIBCPP___CHARCONV_FROM_CHARS_INTEGRAL_H
0012 
0013 #include <__algorithm/copy_n.h>
0014 #include <__assert>
0015 #include <__charconv/from_chars_result.h>
0016 #include <__charconv/traits.h>
0017 #include <__config>
0018 #include <__memory/addressof.h>
0019 #include <__system_error/errc.h>
0020 #include <__type_traits/enable_if.h>
0021 #include <__type_traits/integral_constant.h>
0022 #include <__type_traits/is_integral.h>
0023 #include <__type_traits/is_unsigned.h>
0024 #include <__type_traits/make_unsigned.h>
0025 #include <limits>
0026 
0027 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0028 #  pragma GCC system_header
0029 #endif
0030 
0031 _LIBCPP_PUSH_MACROS
0032 #include <__undef_macros>
0033 
0034 _LIBCPP_BEGIN_NAMESPACE_STD
0035 
0036 #if _LIBCPP_STD_VER >= 17
0037 
0038 from_chars_result from_chars(const char*, const char*, bool, int = 10) = delete;
0039 
0040 template <typename _It, typename _Tp, typename _Fn, typename... _Ts>
0041 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
0042 __sign_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args) {
0043   using __tl = numeric_limits<_Tp>;
0044   decltype(std::__to_unsigned_like(__value)) __x;
0045 
0046   bool __neg = (__first != __last && *__first == '-');
0047   auto __r   = __f(__neg ? __first + 1 : __first, __last, __x, __args...);
0048   switch (__r.ec) {
0049   case errc::invalid_argument:
0050     return {__first, __r.ec};
0051   case errc::result_out_of_range:
0052     return __r;
0053   default:
0054     break;
0055   }
0056 
0057   if (__neg) {
0058     if (__x <= std::__complement(std::__to_unsigned_like(__tl::min()))) {
0059       __x = std::__complement(__x);
0060       std::copy_n(std::addressof(__x), 1, std::addressof(__value));
0061       return __r;
0062     }
0063   } else {
0064     if (__x <= std::__to_unsigned_like(__tl::max())) {
0065       __value = __x;
0066       return __r;
0067     }
0068   }
0069 
0070   return {__r.ptr, errc::result_out_of_range};
0071 }
0072 
0073 template <typename _Tp>
0074 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool __in_pattern(_Tp __c) {
0075   return '0' <= __c && __c <= '9';
0076 }
0077 
0078 struct _LIBCPP_HIDDEN __in_pattern_result {
0079   bool __ok;
0080   int __val;
0081 
0082   explicit _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI operator bool() const { return __ok; }
0083 };
0084 
0085 template <typename _Tp>
0086 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __in_pattern_result __in_pattern(_Tp __c, int __base) {
0087   if (__base <= 10)
0088     return {'0' <= __c && __c < '0' + __base, __c - '0'};
0089   else if (std::__in_pattern(__c))
0090     return {true, __c - '0'};
0091   else if ('a' <= __c && __c < 'a' + __base - 10)
0092     return {true, __c - 'a' + 10};
0093   else
0094     return {'A' <= __c && __c < 'A' + __base - 10, __c - 'A' + 10};
0095 }
0096 
0097 template <typename _It, typename _Tp, typename _Fn, typename... _Ts>
0098 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
0099 __subject_seq_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args) {
0100   auto __find_non_zero = [](_It __firstit, _It __lastit) {
0101     for (; __firstit != __lastit; ++__firstit)
0102       if (*__firstit != '0')
0103         break;
0104     return __firstit;
0105   };
0106 
0107   auto __p = __find_non_zero(__first, __last);
0108   if (__p == __last || !std::__in_pattern(*__p, __args...)) {
0109     if (__p == __first)
0110       return {__first, errc::invalid_argument};
0111     else {
0112       __value = 0;
0113       return {__p, {}};
0114     }
0115   }
0116 
0117   auto __r = __f(__p, __last, __value, __args...);
0118   if (__r.ec == errc::result_out_of_range) {
0119     for (; __r.ptr != __last; ++__r.ptr) {
0120       if (!std::__in_pattern(*__r.ptr, __args...))
0121         break;
0122     }
0123   }
0124 
0125   return __r;
0126 }
0127 
0128 template <typename _Tp, __enable_if_t<is_unsigned<_Tp>::value, int> = 0>
0129 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
0130 __from_chars_atoi(const char* __first, const char* __last, _Tp& __value) {
0131   using __tx          = __itoa::__traits<_Tp>;
0132   using __output_type = typename __tx::type;
0133 
0134   return std::__subject_seq_combinator(
0135       __first, __last, __value, [](const char* __f, const char* __l, _Tp& __val) -> from_chars_result {
0136         __output_type __a, __b;
0137         auto __p = __tx::__read(__f, __l, __a, __b);
0138         if (__p == __l || !std::__in_pattern(*__p)) {
0139           __output_type __m = numeric_limits<_Tp>::max();
0140           if (__m >= __a && __m - __a >= __b) {
0141             __val = __a + __b;
0142             return {__p, {}};
0143           }
0144         }
0145         return {__p, errc::result_out_of_range};
0146       });
0147 }
0148 
0149 template <typename _Tp, __enable_if_t<is_signed<_Tp>::value, int> = 0>
0150 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
0151 __from_chars_atoi(const char* __first, const char* __last, _Tp& __value) {
0152   using __t = decltype(std::__to_unsigned_like(__value));
0153   return std::__sign_combinator(__first, __last, __value, __from_chars_atoi<__t>);
0154 }
0155 
0156 /*
0157 // Code used to generate __from_chars_log2f_lut.
0158 #include <cmath>
0159 #include <format>
0160 #include <iostream>
0161 
0162 int main() {
0163   for (int i = 2; i <= 36; ++i)
0164     std::cout << std::format("{},\n", log2f(i));
0165 }
0166 */
0167 /// log2f table for bases [2, 36].
0168 inline constexpr float __from_chars_log2f_lut[35] = {
0169     1,         1.5849625, 2,         2.321928, 2.5849626, 2.807355, 3,        3.169925,  3.321928,
0170     3.4594316, 3.5849626, 3.7004397, 3.807355, 3.9068906, 4,        4.087463, 4.169925,  4.2479277,
0171     4.321928,  4.3923173, 4.4594316, 4.523562, 4.5849624, 4.643856, 4.70044,  4.7548876, 4.807355,
0172     4.857981,  4.9068904, 4.9541965, 5,        5.044394,  5.087463, 5.129283, 5.169925};
0173 
0174 template <typename _Tp, __enable_if_t<is_unsigned<_Tp>::value, int> = 0>
0175 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
0176 __from_chars_integral(const char* __first, const char* __last, _Tp& __value, int __base) {
0177   if (__base == 10)
0178     return std::__from_chars_atoi(__first, __last, __value);
0179 
0180   return std::__subject_seq_combinator(
0181       __first,
0182       __last,
0183       __value,
0184       [](const char* __p, const char* __lastp, _Tp& __val, int __b) -> from_chars_result {
0185         using __tl = numeric_limits<_Tp>;
0186         // __base is always between 2 and 36 inclusive.
0187         auto __digits = __tl::digits / __from_chars_log2f_lut[__b - 2];
0188         _Tp __x = __in_pattern(*__p++, __b).__val, __y = 0;
0189 
0190         for (int __i = 1; __p != __lastp; ++__i, ++__p) {
0191           if (auto __c = __in_pattern(*__p, __b)) {
0192             if (__i < __digits - 1)
0193               __x = __x * __b + __c.__val;
0194             else {
0195               if (!__itoa::__mul_overflowed(__x, __b, __x))
0196                 ++__p;
0197               __y = __c.__val;
0198               break;
0199             }
0200           } else
0201             break;
0202         }
0203 
0204         if (__p == __lastp || !__in_pattern(*__p, __b)) {
0205           if (__tl::max() - __x >= __y) {
0206             __val = __x + __y;
0207             return {__p, {}};
0208           }
0209         }
0210         return {__p, errc::result_out_of_range};
0211       },
0212       __base);
0213 }
0214 
0215 template <typename _Tp, __enable_if_t<is_signed<_Tp>::value, int> = 0>
0216 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
0217 __from_chars_integral(const char* __first, const char* __last, _Tp& __value, int __base) {
0218   using __t = decltype(std::__to_unsigned_like(__value));
0219   return std::__sign_combinator(__first, __last, __value, __from_chars_integral<__t>, __base);
0220 }
0221 
0222 template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
0223 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
0224 from_chars(const char* __first, const char* __last, _Tp& __value) {
0225   return std::__from_chars_atoi(__first, __last, __value);
0226 }
0227 
0228 template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
0229 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
0230 from_chars(const char* __first, const char* __last, _Tp& __value, int __base) {
0231   _LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base && __base <= 36, "base not in [2, 36]");
0232   return std::__from_chars_integral(__first, __last, __value, __base);
0233 }
0234 #endif // _LIBCPP_STD_VER >= 17
0235 
0236 _LIBCPP_END_NAMESPACE_STD
0237 
0238 _LIBCPP_POP_MACROS
0239 
0240 #endif // _LIBCPP___CHARCONV_FROM_CHARS_INTEGRAL_H