1*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric
9*700637cbSDimitry Andric #ifndef _LIBCPP_SRC_INCLUDE_FROM_CHARS_FLOATING_POINT_H
10*700637cbSDimitry Andric #define _LIBCPP_SRC_INCLUDE_FROM_CHARS_FLOATING_POINT_H
11*700637cbSDimitry Andric
12*700637cbSDimitry Andric // These headers are in the shared LLVM-libc header library.
13*700637cbSDimitry Andric #include "shared/fp_bits.h"
14*700637cbSDimitry Andric #include "shared/str_to_float.h"
15*700637cbSDimitry Andric #include "shared/str_to_integer.h"
16*700637cbSDimitry Andric
17*700637cbSDimitry Andric #include <__assert>
18*700637cbSDimitry Andric #include <__config>
19*700637cbSDimitry Andric #include <cctype>
20*700637cbSDimitry Andric #include <charconv>
21*700637cbSDimitry Andric #include <concepts>
22*700637cbSDimitry Andric #include <limits>
23*700637cbSDimitry Andric
24*700637cbSDimitry Andric // Included for the _Floating_type_traits class
25*700637cbSDimitry Andric #include "to_chars_floating_point.h"
26*700637cbSDimitry Andric
27*700637cbSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
28*700637cbSDimitry Andric
29*700637cbSDimitry Andric // Parses an infinity string.
30*700637cbSDimitry Andric // Valid strings are case insensitive and contain INF or INFINITY.
31*700637cbSDimitry Andric //
32*700637cbSDimitry Andric // - __first is the first argument to std::from_chars. When the string is invalid
33*700637cbSDimitry Andric // this value is returned as ptr in the result.
34*700637cbSDimitry Andric // - __last is the last argument of std::from_chars.
35*700637cbSDimitry Andric // - __value is the value argument of std::from_chars,
36*700637cbSDimitry Andric // - __ptr is the current position is the input string. This is points beyond
37*700637cbSDimitry Andric // the initial I character.
38*700637cbSDimitry Andric // - __negative whether a valid string represents -inf or +inf.
39*700637cbSDimitry Andric template <floating_point _Fp>
40*700637cbSDimitry Andric __from_chars_result<_Fp>
__from_chars_floating_point_inf(const char * const __first,const char * __last,const char * __ptr,bool __negative)41*700637cbSDimitry Andric __from_chars_floating_point_inf(const char* const __first, const char* __last, const char* __ptr, bool __negative) {
42*700637cbSDimitry Andric if (__last - __ptr < 2) [[unlikely]]
43*700637cbSDimitry Andric return {_Fp{0}, 0, errc::invalid_argument};
44*700637cbSDimitry Andric
45*700637cbSDimitry Andric if (std::tolower(__ptr[0]) != 'n' || std::tolower(__ptr[1]) != 'f') [[unlikely]]
46*700637cbSDimitry Andric return {_Fp{0}, 0, errc::invalid_argument};
47*700637cbSDimitry Andric
48*700637cbSDimitry Andric __ptr += 2;
49*700637cbSDimitry Andric
50*700637cbSDimitry Andric // At this point the result is valid and contains INF.
51*700637cbSDimitry Andric // When the remaining part contains INITY this will be consumed. Otherwise
52*700637cbSDimitry Andric // only INF is consumed. For example INFINITZ will consume INF and ignore
53*700637cbSDimitry Andric // INITZ.
54*700637cbSDimitry Andric
55*700637cbSDimitry Andric if (__last - __ptr >= 5 //
56*700637cbSDimitry Andric && std::tolower(__ptr[0]) == 'i' //
57*700637cbSDimitry Andric && std::tolower(__ptr[1]) == 'n' //
58*700637cbSDimitry Andric && std::tolower(__ptr[2]) == 'i' //
59*700637cbSDimitry Andric && std::tolower(__ptr[3]) == 't' //
60*700637cbSDimitry Andric && std::tolower(__ptr[4]) == 'y')
61*700637cbSDimitry Andric __ptr += 5;
62*700637cbSDimitry Andric
63*700637cbSDimitry Andric if constexpr (numeric_limits<_Fp>::has_infinity) {
64*700637cbSDimitry Andric if (__negative)
65*700637cbSDimitry Andric return {-std::numeric_limits<_Fp>::infinity(), __ptr - __first, std::errc{}};
66*700637cbSDimitry Andric
67*700637cbSDimitry Andric return {std::numeric_limits<_Fp>::infinity(), __ptr - __first, std::errc{}};
68*700637cbSDimitry Andric } else {
69*700637cbSDimitry Andric return {_Fp{0}, __ptr - __first, errc::result_out_of_range};
70*700637cbSDimitry Andric }
71*700637cbSDimitry Andric }
72*700637cbSDimitry Andric
73*700637cbSDimitry Andric // Parses a nan string.
74*700637cbSDimitry Andric // Valid strings are case insensitive and contain INF or INFINITY.
75*700637cbSDimitry Andric //
76*700637cbSDimitry Andric // - __first is the first argument to std::from_chars. When the string is invalid
77*700637cbSDimitry Andric // this value is returned as ptr in the result.
78*700637cbSDimitry Andric // - __last is the last argument of std::from_chars.
79*700637cbSDimitry Andric // - __value is the value argument of std::from_chars,
80*700637cbSDimitry Andric // - __ptr is the current position is the input string. This is points beyond
81*700637cbSDimitry Andric // the initial N character.
82*700637cbSDimitry Andric // - __negative whether a valid string represents -nan or +nan.
83*700637cbSDimitry Andric template <floating_point _Fp>
84*700637cbSDimitry Andric __from_chars_result<_Fp>
__from_chars_floating_point_nan(const char * const __first,const char * __last,const char * __ptr,bool __negative)85*700637cbSDimitry Andric __from_chars_floating_point_nan(const char* const __first, const char* __last, const char* __ptr, bool __negative) {
86*700637cbSDimitry Andric if (__last - __ptr < 2) [[unlikely]]
87*700637cbSDimitry Andric return {_Fp{0}, 0, errc::invalid_argument};
88*700637cbSDimitry Andric
89*700637cbSDimitry Andric if (std::tolower(__ptr[0]) != 'a' || std::tolower(__ptr[1]) != 'n') [[unlikely]]
90*700637cbSDimitry Andric return {_Fp{0}, 0, errc::invalid_argument};
91*700637cbSDimitry Andric
92*700637cbSDimitry Andric __ptr += 2;
93*700637cbSDimitry Andric
94*700637cbSDimitry Andric // At this point the result is valid and contains NAN. When the remaining
95*700637cbSDimitry Andric // part contains ( n-char-sequence_opt ) this will be consumed. Otherwise
96*700637cbSDimitry Andric // only NAN is consumed. For example NAN(abcd will consume NAN and ignore
97*700637cbSDimitry Andric // (abcd.
98*700637cbSDimitry Andric if (__last - __ptr >= 2 && __ptr[0] == '(') {
99*700637cbSDimitry Andric size_t __offset = 1;
100*700637cbSDimitry Andric do {
101*700637cbSDimitry Andric if (__ptr[__offset] == ')') {
102*700637cbSDimitry Andric __ptr += __offset + 1;
103*700637cbSDimitry Andric break;
104*700637cbSDimitry Andric }
105*700637cbSDimitry Andric if (__ptr[__offset] != '_' && !std::isalnum(__ptr[__offset]))
106*700637cbSDimitry Andric break;
107*700637cbSDimitry Andric ++__offset;
108*700637cbSDimitry Andric } while (__ptr + __offset != __last);
109*700637cbSDimitry Andric }
110*700637cbSDimitry Andric
111*700637cbSDimitry Andric if (__negative)
112*700637cbSDimitry Andric return {-std::numeric_limits<_Fp>::quiet_NaN(), __ptr - __first, std::errc{}};
113*700637cbSDimitry Andric
114*700637cbSDimitry Andric return {std::numeric_limits<_Fp>::quiet_NaN(), __ptr - __first, std::errc{}};
115*700637cbSDimitry Andric }
116*700637cbSDimitry Andric
117*700637cbSDimitry Andric template <class _Tp>
118*700637cbSDimitry Andric struct __fractional_constant_result {
119*700637cbSDimitry Andric size_t __offset{size_t(-1)};
120*700637cbSDimitry Andric _Tp __mantissa{0};
121*700637cbSDimitry Andric int __exponent{0};
122*700637cbSDimitry Andric bool __truncated{false};
123*700637cbSDimitry Andric bool __is_valid{false};
124*700637cbSDimitry Andric };
125*700637cbSDimitry Andric
126*700637cbSDimitry Andric // Parses the hex constant part of the hexadecimal floating-point value.
127*700637cbSDimitry Andric // - input start of buffer given to from_chars
128*700637cbSDimitry Andric // - __n the number of elements in the buffer
129*700637cbSDimitry Andric // - __offset where to start parsing. The input can have an optional sign, the
130*700637cbSDimitry Andric // offset starts after this sign.
131*700637cbSDimitry Andric template <class _Tp>
__parse_fractional_hex_constant(const char * __input,size_t __n,size_t __offset)132*700637cbSDimitry Andric __fractional_constant_result<_Tp> __parse_fractional_hex_constant(const char* __input, size_t __n, size_t __offset) {
133*700637cbSDimitry Andric __fractional_constant_result<_Tp> __result;
134*700637cbSDimitry Andric
135*700637cbSDimitry Andric const _Tp __mantissa_truncate_threshold = numeric_limits<_Tp>::max() / 16;
136*700637cbSDimitry Andric bool __fraction = false;
137*700637cbSDimitry Andric for (; __offset < __n; ++__offset) {
138*700637cbSDimitry Andric if (std::isxdigit(__input[__offset])) {
139*700637cbSDimitry Andric __result.__is_valid = true;
140*700637cbSDimitry Andric
141*700637cbSDimitry Andric uint32_t __digit = __input[__offset] - '0';
142*700637cbSDimitry Andric switch (std::tolower(__input[__offset])) {
143*700637cbSDimitry Andric case 'a':
144*700637cbSDimitry Andric __digit = 10;
145*700637cbSDimitry Andric break;
146*700637cbSDimitry Andric case 'b':
147*700637cbSDimitry Andric __digit = 11;
148*700637cbSDimitry Andric break;
149*700637cbSDimitry Andric case 'c':
150*700637cbSDimitry Andric __digit = 12;
151*700637cbSDimitry Andric break;
152*700637cbSDimitry Andric case 'd':
153*700637cbSDimitry Andric __digit = 13;
154*700637cbSDimitry Andric break;
155*700637cbSDimitry Andric case 'e':
156*700637cbSDimitry Andric __digit = 14;
157*700637cbSDimitry Andric break;
158*700637cbSDimitry Andric case 'f':
159*700637cbSDimitry Andric __digit = 15;
160*700637cbSDimitry Andric break;
161*700637cbSDimitry Andric }
162*700637cbSDimitry Andric
163*700637cbSDimitry Andric if (__result.__mantissa < __mantissa_truncate_threshold) {
164*700637cbSDimitry Andric __result.__mantissa = (__result.__mantissa * 16) + __digit;
165*700637cbSDimitry Andric if (__fraction)
166*700637cbSDimitry Andric __result.__exponent -= 4;
167*700637cbSDimitry Andric } else {
168*700637cbSDimitry Andric if (__digit > 0)
169*700637cbSDimitry Andric __result.__truncated = true;
170*700637cbSDimitry Andric if (!__fraction)
171*700637cbSDimitry Andric __result.__exponent += 4;
172*700637cbSDimitry Andric }
173*700637cbSDimitry Andric } else if (__input[__offset] == '.') {
174*700637cbSDimitry Andric if (__fraction)
175*700637cbSDimitry Andric break; // this means that __input[__offset] points to a second decimal point, ending the number.
176*700637cbSDimitry Andric
177*700637cbSDimitry Andric __fraction = true;
178*700637cbSDimitry Andric } else
179*700637cbSDimitry Andric break;
180*700637cbSDimitry Andric }
181*700637cbSDimitry Andric
182*700637cbSDimitry Andric __result.__offset = __offset;
183*700637cbSDimitry Andric return __result;
184*700637cbSDimitry Andric }
185*700637cbSDimitry Andric
186*700637cbSDimitry Andric struct __exponent_result {
187*700637cbSDimitry Andric size_t __offset{size_t(-1)};
188*700637cbSDimitry Andric int __value{0};
189*700637cbSDimitry Andric bool __present{false};
190*700637cbSDimitry Andric };
191*700637cbSDimitry Andric
192*700637cbSDimitry Andric // When the exponent is not present the result of the struct contains
193*700637cbSDimitry Andric // __offset, 0, false. This allows using the results unconditionally, the
194*700637cbSDimitry Andric // __present is important for the scientific notation, where the value is
195*700637cbSDimitry Andric // mandatory.
__parse_exponent(const char * __input,size_t __n,size_t __offset,char __marker)196*700637cbSDimitry Andric __exponent_result __parse_exponent(const char* __input, size_t __n, size_t __offset, char __marker) {
197*700637cbSDimitry Andric if (__offset + 1 < __n && // an exponent always needs at least one digit.
198*700637cbSDimitry Andric std::tolower(__input[__offset]) == __marker && //
199*700637cbSDimitry Andric !std::isspace(__input[__offset + 1]) // leading whitespace is not allowed.
200*700637cbSDimitry Andric ) {
201*700637cbSDimitry Andric ++__offset;
202*700637cbSDimitry Andric LIBC_NAMESPACE::shared::StrToNumResult<int32_t> __e =
203*700637cbSDimitry Andric LIBC_NAMESPACE::shared::strtointeger<int32_t>(__input + __offset, 10, __n - __offset);
204*700637cbSDimitry Andric // __result.error contains the errno value, 0 or ERANGE these are not interesting.
205*700637cbSDimitry Andric // If the number of characters parsed is 0 it means there was no number.
206*700637cbSDimitry Andric if (__e.parsed_len != 0)
207*700637cbSDimitry Andric return {__offset + __e.parsed_len, __e.value, true};
208*700637cbSDimitry Andric else
209*700637cbSDimitry Andric --__offset; // the assumption of a valid exponent was not true, undo eating the exponent character.
210*700637cbSDimitry Andric }
211*700637cbSDimitry Andric
212*700637cbSDimitry Andric return {__offset, 0, false};
213*700637cbSDimitry Andric }
214*700637cbSDimitry Andric
215*700637cbSDimitry Andric // Here we do this operation as int64 to avoid overflow.
__merge_exponents(int64_t __fractional,int64_t __exponent,int __max_biased_exponent)216*700637cbSDimitry Andric int32_t __merge_exponents(int64_t __fractional, int64_t __exponent, int __max_biased_exponent) {
217*700637cbSDimitry Andric int64_t __sum = __fractional + __exponent;
218*700637cbSDimitry Andric
219*700637cbSDimitry Andric if (__sum > __max_biased_exponent)
220*700637cbSDimitry Andric return __max_biased_exponent;
221*700637cbSDimitry Andric
222*700637cbSDimitry Andric if (__sum < -__max_biased_exponent)
223*700637cbSDimitry Andric return -__max_biased_exponent;
224*700637cbSDimitry Andric
225*700637cbSDimitry Andric return __sum;
226*700637cbSDimitry Andric }
227*700637cbSDimitry Andric
228*700637cbSDimitry Andric template <class _Fp, class _Tp>
229*700637cbSDimitry Andric __from_chars_result<_Fp>
__calculate_result(_Tp __mantissa,int __exponent,bool __negative,__from_chars_result<_Fp> __result)230*700637cbSDimitry Andric __calculate_result(_Tp __mantissa, int __exponent, bool __negative, __from_chars_result<_Fp> __result) {
231*700637cbSDimitry Andric auto __r = LIBC_NAMESPACE::shared::FPBits<_Fp>();
232*700637cbSDimitry Andric __r.set_mantissa(__mantissa);
233*700637cbSDimitry Andric __r.set_biased_exponent(__exponent);
234*700637cbSDimitry Andric
235*700637cbSDimitry Andric // C17 7.12.1/6
236*700637cbSDimitry Andric // The result underflows if the magnitude of the mathematical result is so
237*700637cbSDimitry Andric // small that the mathematical result cannot be represented, without
238*700637cbSDimitry Andric // extraordinary roundoff error, in an object of the specified type.237) If
239*700637cbSDimitry Andric // the result underflows, the function returns an implementation-defined
240*700637cbSDimitry Andric // value whose magnitude is no greater than the smallest normalized positive
241*700637cbSDimitry Andric // number in the specified type; if the integer expression math_errhandling
242*700637cbSDimitry Andric // & MATH_ERRNO is nonzero, whether errno acquires the value ERANGE is
243*700637cbSDimitry Andric // implementation-defined; if the integer expression math_errhandling &
244*700637cbSDimitry Andric // MATH_ERREXCEPT is nonzero, whether the "underflow" floating-point
245*700637cbSDimitry Andric // exception is raised is implementation-defined.
246*700637cbSDimitry Andric //
247*700637cbSDimitry Andric // LLVM-LIBC sets ERAGNE for subnormal values
248*700637cbSDimitry Andric //
249*700637cbSDimitry Andric // [charconv.from.chars]/1
250*700637cbSDimitry Andric // ... If the parsed value is not in the range representable by the type of
251*700637cbSDimitry Andric // value, value is unmodified and the member ec of the return value is
252*700637cbSDimitry Andric // equal to errc::result_out_of_range. ...
253*700637cbSDimitry Andric //
254*700637cbSDimitry Andric // Undo the ERANGE for subnormal values.
255*700637cbSDimitry Andric if (__result.__ec == errc::result_out_of_range && __r.is_subnormal() && !__r.is_zero())
256*700637cbSDimitry Andric __result.__ec = errc{};
257*700637cbSDimitry Andric
258*700637cbSDimitry Andric if (__negative)
259*700637cbSDimitry Andric __result.__value = -__r.get_val();
260*700637cbSDimitry Andric else
261*700637cbSDimitry Andric __result.__value = __r.get_val();
262*700637cbSDimitry Andric
263*700637cbSDimitry Andric return __result;
264*700637cbSDimitry Andric }
265*700637cbSDimitry Andric
266*700637cbSDimitry Andric // Implements from_chars for decimal floating-point values.
267*700637cbSDimitry Andric // __first forwarded from from_chars
268*700637cbSDimitry Andric // __last forwarded from from_chars
269*700637cbSDimitry Andric // __value forwarded from from_chars
270*700637cbSDimitry Andric // __fmt forwarded from from_chars
271*700637cbSDimitry Andric // __ptr the start of the buffer to parse. This is after the optional sign character.
272*700637cbSDimitry Andric // __negative should __value be set to a negative value?
273*700637cbSDimitry Andric //
274*700637cbSDimitry Andric // This function and __from_chars_floating_point_decimal are similar. However
275*700637cbSDimitry Andric // the similar parts are all in helper functions. So the amount of code
276*700637cbSDimitry Andric // duplication is minimal.
277*700637cbSDimitry Andric template <floating_point _Fp>
278*700637cbSDimitry Andric __from_chars_result<_Fp>
__from_chars_floating_point_hex(const char * const __first,const char * __last,const char * __ptr,bool __negative)279*700637cbSDimitry Andric __from_chars_floating_point_hex(const char* const __first, const char* __last, const char* __ptr, bool __negative) {
280*700637cbSDimitry Andric size_t __n = __last - __first;
281*700637cbSDimitry Andric ptrdiff_t __offset = __ptr - __first;
282*700637cbSDimitry Andric
283*700637cbSDimitry Andric auto __fractional =
284*700637cbSDimitry Andric std::__parse_fractional_hex_constant<typename _Floating_type_traits<_Fp>::_Uint_type>(__first, __n, __offset);
285*700637cbSDimitry Andric if (!__fractional.__is_valid)
286*700637cbSDimitry Andric return {_Fp{0}, 0, errc::invalid_argument};
287*700637cbSDimitry Andric
288*700637cbSDimitry Andric auto __parsed_exponent = std::__parse_exponent(__first, __n, __fractional.__offset, 'p');
289*700637cbSDimitry Andric __offset = __parsed_exponent.__offset;
290*700637cbSDimitry Andric int __exponent = std::__merge_exponents(
291*700637cbSDimitry Andric __fractional.__exponent, __parsed_exponent.__value, LIBC_NAMESPACE::shared::FPBits<_Fp>::MAX_BIASED_EXPONENT);
292*700637cbSDimitry Andric
293*700637cbSDimitry Andric __from_chars_result<_Fp> __result{_Fp{0}, __offset, {}};
294*700637cbSDimitry Andric LIBC_NAMESPACE::shared::ExpandedFloat<_Fp> __expanded_float = {0, 0};
295*700637cbSDimitry Andric if (__fractional.__mantissa != 0) {
296*700637cbSDimitry Andric auto __temp = LIBC_NAMESPACE::shared::binary_exp_to_float<_Fp>(
297*700637cbSDimitry Andric {__fractional.__mantissa, __exponent},
298*700637cbSDimitry Andric __fractional.__truncated,
299*700637cbSDimitry Andric LIBC_NAMESPACE::shared::RoundDirection::Nearest);
300*700637cbSDimitry Andric __expanded_float = __temp.num;
301*700637cbSDimitry Andric if (__temp.error == ERANGE) {
302*700637cbSDimitry Andric __result.__ec = errc::result_out_of_range;
303*700637cbSDimitry Andric }
304*700637cbSDimitry Andric }
305*700637cbSDimitry Andric
306*700637cbSDimitry Andric return std::__calculate_result<_Fp>(__expanded_float.mantissa, __expanded_float.exponent, __negative, __result);
307*700637cbSDimitry Andric }
308*700637cbSDimitry Andric
309*700637cbSDimitry Andric // Parses the hex constant part of the decimal float value.
310*700637cbSDimitry Andric // - input start of buffer given to from_chars
311*700637cbSDimitry Andric // - __n the number of elements in the buffer
312*700637cbSDimitry Andric // - __offset where to start parsing. The input can have an optional sign, the
313*700637cbSDimitry Andric // offset starts after this sign.
314*700637cbSDimitry Andric template <class _Tp>
315*700637cbSDimitry Andric __fractional_constant_result<_Tp>
__parse_fractional_decimal_constant(const char * __input,ptrdiff_t __n,ptrdiff_t __offset)316*700637cbSDimitry Andric __parse_fractional_decimal_constant(const char* __input, ptrdiff_t __n, ptrdiff_t __offset) {
317*700637cbSDimitry Andric __fractional_constant_result<_Tp> __result;
318*700637cbSDimitry Andric
319*700637cbSDimitry Andric const _Tp __mantissa_truncate_threshold = numeric_limits<_Tp>::max() / 10;
320*700637cbSDimitry Andric bool __fraction = false;
321*700637cbSDimitry Andric for (; __offset < __n; ++__offset) {
322*700637cbSDimitry Andric if (std::isdigit(__input[__offset])) {
323*700637cbSDimitry Andric __result.__is_valid = true;
324*700637cbSDimitry Andric
325*700637cbSDimitry Andric uint32_t __digit = __input[__offset] - '0';
326*700637cbSDimitry Andric if (__result.__mantissa < __mantissa_truncate_threshold) {
327*700637cbSDimitry Andric __result.__mantissa = (__result.__mantissa * 10) + __digit;
328*700637cbSDimitry Andric if (__fraction)
329*700637cbSDimitry Andric --__result.__exponent;
330*700637cbSDimitry Andric } else {
331*700637cbSDimitry Andric if (__digit > 0)
332*700637cbSDimitry Andric __result.__truncated = true;
333*700637cbSDimitry Andric if (!__fraction)
334*700637cbSDimitry Andric ++__result.__exponent;
335*700637cbSDimitry Andric }
336*700637cbSDimitry Andric } else if (__input[__offset] == '.') {
337*700637cbSDimitry Andric if (__fraction)
338*700637cbSDimitry Andric break; // this means that __input[__offset] points to a second decimal point, ending the number.
339*700637cbSDimitry Andric
340*700637cbSDimitry Andric __fraction = true;
341*700637cbSDimitry Andric } else
342*700637cbSDimitry Andric break;
343*700637cbSDimitry Andric }
344*700637cbSDimitry Andric
345*700637cbSDimitry Andric __result.__offset = __offset;
346*700637cbSDimitry Andric return __result;
347*700637cbSDimitry Andric }
348*700637cbSDimitry Andric
349*700637cbSDimitry Andric // Implements from_chars for decimal floating-point values.
350*700637cbSDimitry Andric // __first forwarded from from_chars
351*700637cbSDimitry Andric // __last forwarded from from_chars
352*700637cbSDimitry Andric // __value forwarded from from_chars
353*700637cbSDimitry Andric // __fmt forwarded from from_chars
354*700637cbSDimitry Andric // __ptr the start of the buffer to parse. This is after the optional sign character.
355*700637cbSDimitry Andric // __negative should __value be set to a negative value?
356*700637cbSDimitry Andric template <floating_point _Fp>
__from_chars_floating_point_decimal(const char * const __first,const char * __last,chars_format __fmt,const char * __ptr,bool __negative)357*700637cbSDimitry Andric __from_chars_result<_Fp> __from_chars_floating_point_decimal(
358*700637cbSDimitry Andric const char* const __first, const char* __last, chars_format __fmt, const char* __ptr, bool __negative) {
359*700637cbSDimitry Andric ptrdiff_t __n = __last - __first;
360*700637cbSDimitry Andric ptrdiff_t __offset = __ptr - __first;
361*700637cbSDimitry Andric
362*700637cbSDimitry Andric auto __fractional =
363*700637cbSDimitry Andric std::__parse_fractional_decimal_constant<typename _Floating_type_traits<_Fp>::_Uint_type>(__first, __n, __offset);
364*700637cbSDimitry Andric if (!__fractional.__is_valid)
365*700637cbSDimitry Andric return {_Fp{0}, 0, errc::invalid_argument};
366*700637cbSDimitry Andric
367*700637cbSDimitry Andric __offset = __fractional.__offset;
368*700637cbSDimitry Andric
369*700637cbSDimitry Andric // LWG3456 Pattern used by std::from_chars is underspecified
370*700637cbSDimitry Andric // This changes fixed to ignore a possible exponent instead of making its
371*700637cbSDimitry Andric // existance an error.
372*700637cbSDimitry Andric int __exponent;
373*700637cbSDimitry Andric if (__fmt == chars_format::fixed) {
374*700637cbSDimitry Andric __exponent =
375*700637cbSDimitry Andric std::__merge_exponents(__fractional.__exponent, 0, LIBC_NAMESPACE::shared::FPBits<_Fp>::MAX_BIASED_EXPONENT);
376*700637cbSDimitry Andric } else {
377*700637cbSDimitry Andric auto __parsed_exponent = std::__parse_exponent(__first, __n, __offset, 'e');
378*700637cbSDimitry Andric if (__fmt == chars_format::scientific && !__parsed_exponent.__present) {
379*700637cbSDimitry Andric // [charconv.from.chars]/6.2 if fmt has chars_format::scientific set but not chars_format::fixed,
380*700637cbSDimitry Andric // the otherwise optional exponent part shall appear;
381*700637cbSDimitry Andric return {_Fp{0}, 0, errc::invalid_argument};
382*700637cbSDimitry Andric }
383*700637cbSDimitry Andric
384*700637cbSDimitry Andric __offset = __parsed_exponent.__offset;
385*700637cbSDimitry Andric __exponent = std::__merge_exponents(
386*700637cbSDimitry Andric __fractional.__exponent, __parsed_exponent.__value, LIBC_NAMESPACE::shared::FPBits<_Fp>::MAX_BIASED_EXPONENT);
387*700637cbSDimitry Andric }
388*700637cbSDimitry Andric
389*700637cbSDimitry Andric __from_chars_result<_Fp> __result{_Fp{0}, __offset, {}};
390*700637cbSDimitry Andric LIBC_NAMESPACE::shared::ExpandedFloat<_Fp> __expanded_float = {0, 0};
391*700637cbSDimitry Andric if (__fractional.__mantissa != 0) {
392*700637cbSDimitry Andric // This function expects to parse a positive value. This means it does not
393*700637cbSDimitry Andric // take a __first, __n as arguments, since __first points to '-' for
394*700637cbSDimitry Andric // negative values.
395*700637cbSDimitry Andric auto __temp = LIBC_NAMESPACE::shared::decimal_exp_to_float<_Fp>(
396*700637cbSDimitry Andric {__fractional.__mantissa, __exponent},
397*700637cbSDimitry Andric __fractional.__truncated,
398*700637cbSDimitry Andric LIBC_NAMESPACE::shared::RoundDirection::Nearest,
399*700637cbSDimitry Andric __ptr,
400*700637cbSDimitry Andric __last - __ptr);
401*700637cbSDimitry Andric __expanded_float = __temp.num;
402*700637cbSDimitry Andric if (__temp.error == ERANGE) {
403*700637cbSDimitry Andric __result.__ec = errc::result_out_of_range;
404*700637cbSDimitry Andric }
405*700637cbSDimitry Andric }
406*700637cbSDimitry Andric
407*700637cbSDimitry Andric return std::__calculate_result(__expanded_float.mantissa, __expanded_float.exponent, __negative, __result);
408*700637cbSDimitry Andric }
409*700637cbSDimitry Andric
410*700637cbSDimitry Andric template <floating_point _Fp>
411*700637cbSDimitry Andric __from_chars_result<_Fp>
__from_chars_floating_point_impl(const char * const __first,const char * __last,chars_format __fmt)412*700637cbSDimitry Andric __from_chars_floating_point_impl(const char* const __first, const char* __last, chars_format __fmt) {
413*700637cbSDimitry Andric if (__first == __last) [[unlikely]]
414*700637cbSDimitry Andric return {_Fp{0}, 0, errc::invalid_argument};
415*700637cbSDimitry Andric
416*700637cbSDimitry Andric const char* __ptr = __first;
417*700637cbSDimitry Andric bool __negative = *__ptr == '-';
418*700637cbSDimitry Andric if (__negative) {
419*700637cbSDimitry Andric ++__ptr;
420*700637cbSDimitry Andric if (__ptr == __last) [[unlikely]]
421*700637cbSDimitry Andric return {_Fp{0}, 0, errc::invalid_argument};
422*700637cbSDimitry Andric }
423*700637cbSDimitry Andric
424*700637cbSDimitry Andric // [charconv.from.chars]
425*700637cbSDimitry Andric // [Note 1: If the pattern allows for an optional sign, but the string has
426*700637cbSDimitry Andric // no digit characters following the sign, no characters match the pattern.
427*700637cbSDimitry Andric // -- end note]
428*700637cbSDimitry Andric // This is true for integrals, floating point allows -.0
429*700637cbSDimitry Andric
430*700637cbSDimitry Andric // [charconv.from.chars]/6.2
431*700637cbSDimitry Andric // if fmt has chars_format::scientific set but not chars_format::fixed, the
432*700637cbSDimitry Andric // otherwise optional exponent part shall appear;
433*700637cbSDimitry Andric // Since INF/NAN do not have an exponent this value is not valid.
434*700637cbSDimitry Andric //
435*700637cbSDimitry Andric // LWG3456 Pattern used by std::from_chars is underspecified
436*700637cbSDimitry Andric // Does not address this point, but proposed option B does solve this issue,
437*700637cbSDimitry Andric // Both MSVC STL and libstdc++ implement this this behaviour.
438*700637cbSDimitry Andric switch (std::tolower(*__ptr)) {
439*700637cbSDimitry Andric case 'i':
440*700637cbSDimitry Andric return std::__from_chars_floating_point_inf<_Fp>(__first, __last, __ptr + 1, __negative);
441*700637cbSDimitry Andric case 'n':
442*700637cbSDimitry Andric if constexpr (numeric_limits<_Fp>::has_quiet_NaN)
443*700637cbSDimitry Andric // NOTE: The pointer passed here will be parsed in the default C locale.
444*700637cbSDimitry Andric // This is standard behavior (see https://eel.is/c++draft/charconv.from.chars), but may be unexpected.
445*700637cbSDimitry Andric return std::__from_chars_floating_point_nan<_Fp>(__first, __last, __ptr + 1, __negative);
446*700637cbSDimitry Andric return {_Fp{0}, 0, errc::invalid_argument};
447*700637cbSDimitry Andric }
448*700637cbSDimitry Andric
449*700637cbSDimitry Andric if (__fmt == chars_format::hex)
450*700637cbSDimitry Andric return std::__from_chars_floating_point_hex<_Fp>(__first, __last, __ptr, __negative);
451*700637cbSDimitry Andric
452*700637cbSDimitry Andric return std::__from_chars_floating_point_decimal<_Fp>(__first, __last, __fmt, __ptr, __negative);
453*700637cbSDimitry Andric }
454*700637cbSDimitry Andric
455*700637cbSDimitry Andric _LIBCPP_END_NAMESPACE_STD
456*700637cbSDimitry Andric
457*700637cbSDimitry Andric #endif //_LIBCPP_SRC_INCLUDE_FROM_CHARS_FLOATING_POINT_H
458