Path: blob/main/contrib/llvm-project/libcxx/src/include/from_chars_floating_point.h
213766 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef _LIBCPP_SRC_INCLUDE_FROM_CHARS_FLOATING_POINT_H9#define _LIBCPP_SRC_INCLUDE_FROM_CHARS_FLOATING_POINT_H1011// These headers are in the shared LLVM-libc header library.12#include "shared/fp_bits.h"13#include "shared/str_to_float.h"14#include "shared/str_to_integer.h"1516#include <__assert>17#include <__config>18#include <cctype>19#include <charconv>20#include <concepts>21#include <limits>2223// Included for the _Floating_type_traits class24#include "to_chars_floating_point.h"2526_LIBCPP_BEGIN_NAMESPACE_STD2728// Parses an infinity string.29// Valid strings are case insensitive and contain INF or INFINITY.30//31// - __first is the first argument to std::from_chars. When the string is invalid32// this value is returned as ptr in the result.33// - __last is the last argument of std::from_chars.34// - __value is the value argument of std::from_chars,35// - __ptr is the current position is the input string. This is points beyond36// the initial I character.37// - __negative whether a valid string represents -inf or +inf.38template <floating_point _Fp>39__from_chars_result<_Fp>40__from_chars_floating_point_inf(const char* const __first, const char* __last, const char* __ptr, bool __negative) {41if (__last - __ptr < 2) [[unlikely]]42return {_Fp{0}, 0, errc::invalid_argument};4344if (std::tolower(__ptr[0]) != 'n' || std::tolower(__ptr[1]) != 'f') [[unlikely]]45return {_Fp{0}, 0, errc::invalid_argument};4647__ptr += 2;4849// At this point the result is valid and contains INF.50// When the remaining part contains INITY this will be consumed. Otherwise51// only INF is consumed. For example INFINITZ will consume INF and ignore52// INITZ.5354if (__last - __ptr >= 5 //55&& std::tolower(__ptr[0]) == 'i' //56&& std::tolower(__ptr[1]) == 'n' //57&& std::tolower(__ptr[2]) == 'i' //58&& std::tolower(__ptr[3]) == 't' //59&& std::tolower(__ptr[4]) == 'y')60__ptr += 5;6162if constexpr (numeric_limits<_Fp>::has_infinity) {63if (__negative)64return {-std::numeric_limits<_Fp>::infinity(), __ptr - __first, std::errc{}};6566return {std::numeric_limits<_Fp>::infinity(), __ptr - __first, std::errc{}};67} else {68return {_Fp{0}, __ptr - __first, errc::result_out_of_range};69}70}7172// Parses a nan string.73// Valid strings are case insensitive and contain INF or INFINITY.74//75// - __first is the first argument to std::from_chars. When the string is invalid76// this value is returned as ptr in the result.77// - __last is the last argument of std::from_chars.78// - __value is the value argument of std::from_chars,79// - __ptr is the current position is the input string. This is points beyond80// the initial N character.81// - __negative whether a valid string represents -nan or +nan.82template <floating_point _Fp>83__from_chars_result<_Fp>84__from_chars_floating_point_nan(const char* const __first, const char* __last, const char* __ptr, bool __negative) {85if (__last - __ptr < 2) [[unlikely]]86return {_Fp{0}, 0, errc::invalid_argument};8788if (std::tolower(__ptr[0]) != 'a' || std::tolower(__ptr[1]) != 'n') [[unlikely]]89return {_Fp{0}, 0, errc::invalid_argument};9091__ptr += 2;9293// At this point the result is valid and contains NAN. When the remaining94// part contains ( n-char-sequence_opt ) this will be consumed. Otherwise95// only NAN is consumed. For example NAN(abcd will consume NAN and ignore96// (abcd.97if (__last - __ptr >= 2 && __ptr[0] == '(') {98size_t __offset = 1;99do {100if (__ptr[__offset] == ')') {101__ptr += __offset + 1;102break;103}104if (__ptr[__offset] != '_' && !std::isalnum(__ptr[__offset]))105break;106++__offset;107} while (__ptr + __offset != __last);108}109110if (__negative)111return {-std::numeric_limits<_Fp>::quiet_NaN(), __ptr - __first, std::errc{}};112113return {std::numeric_limits<_Fp>::quiet_NaN(), __ptr - __first, std::errc{}};114}115116template <class _Tp>117struct __fractional_constant_result {118size_t __offset{size_t(-1)};119_Tp __mantissa{0};120int __exponent{0};121bool __truncated{false};122bool __is_valid{false};123};124125// Parses the hex constant part of the hexadecimal floating-point value.126// - input start of buffer given to from_chars127// - __n the number of elements in the buffer128// - __offset where to start parsing. The input can have an optional sign, the129// offset starts after this sign.130template <class _Tp>131__fractional_constant_result<_Tp> __parse_fractional_hex_constant(const char* __input, size_t __n, size_t __offset) {132__fractional_constant_result<_Tp> __result;133134const _Tp __mantissa_truncate_threshold = numeric_limits<_Tp>::max() / 16;135bool __fraction = false;136for (; __offset < __n; ++__offset) {137if (std::isxdigit(__input[__offset])) {138__result.__is_valid = true;139140uint32_t __digit = __input[__offset] - '0';141switch (std::tolower(__input[__offset])) {142case 'a':143__digit = 10;144break;145case 'b':146__digit = 11;147break;148case 'c':149__digit = 12;150break;151case 'd':152__digit = 13;153break;154case 'e':155__digit = 14;156break;157case 'f':158__digit = 15;159break;160}161162if (__result.__mantissa < __mantissa_truncate_threshold) {163__result.__mantissa = (__result.__mantissa * 16) + __digit;164if (__fraction)165__result.__exponent -= 4;166} else {167if (__digit > 0)168__result.__truncated = true;169if (!__fraction)170__result.__exponent += 4;171}172} else if (__input[__offset] == '.') {173if (__fraction)174break; // this means that __input[__offset] points to a second decimal point, ending the number.175176__fraction = true;177} else178break;179}180181__result.__offset = __offset;182return __result;183}184185struct __exponent_result {186size_t __offset{size_t(-1)};187int __value{0};188bool __present{false};189};190191// When the exponent is not present the result of the struct contains192// __offset, 0, false. This allows using the results unconditionally, the193// __present is important for the scientific notation, where the value is194// mandatory.195__exponent_result __parse_exponent(const char* __input, size_t __n, size_t __offset, char __marker) {196if (__offset + 1 < __n && // an exponent always needs at least one digit.197std::tolower(__input[__offset]) == __marker && //198!std::isspace(__input[__offset + 1]) // leading whitespace is not allowed.199) {200++__offset;201LIBC_NAMESPACE::shared::StrToNumResult<int32_t> __e =202LIBC_NAMESPACE::shared::strtointeger<int32_t>(__input + __offset, 10, __n - __offset);203// __result.error contains the errno value, 0 or ERANGE these are not interesting.204// If the number of characters parsed is 0 it means there was no number.205if (__e.parsed_len != 0)206return {__offset + __e.parsed_len, __e.value, true};207else208--__offset; // the assumption of a valid exponent was not true, undo eating the exponent character.209}210211return {__offset, 0, false};212}213214// Here we do this operation as int64 to avoid overflow.215int32_t __merge_exponents(int64_t __fractional, int64_t __exponent, int __max_biased_exponent) {216int64_t __sum = __fractional + __exponent;217218if (__sum > __max_biased_exponent)219return __max_biased_exponent;220221if (__sum < -__max_biased_exponent)222return -__max_biased_exponent;223224return __sum;225}226227template <class _Fp, class _Tp>228__from_chars_result<_Fp>229__calculate_result(_Tp __mantissa, int __exponent, bool __negative, __from_chars_result<_Fp> __result) {230auto __r = LIBC_NAMESPACE::shared::FPBits<_Fp>();231__r.set_mantissa(__mantissa);232__r.set_biased_exponent(__exponent);233234// C17 7.12.1/6235// The result underflows if the magnitude of the mathematical result is so236// small that the mathematical result cannot be represented, without237// extraordinary roundoff error, in an object of the specified type.237) If238// the result underflows, the function returns an implementation-defined239// value whose magnitude is no greater than the smallest normalized positive240// number in the specified type; if the integer expression math_errhandling241// & MATH_ERRNO is nonzero, whether errno acquires the value ERANGE is242// implementation-defined; if the integer expression math_errhandling &243// MATH_ERREXCEPT is nonzero, whether the "underflow" floating-point244// exception is raised is implementation-defined.245//246// LLVM-LIBC sets ERAGNE for subnormal values247//248// [charconv.from.chars]/1249// ... If the parsed value is not in the range representable by the type of250// value, value is unmodified and the member ec of the return value is251// equal to errc::result_out_of_range. ...252//253// Undo the ERANGE for subnormal values.254if (__result.__ec == errc::result_out_of_range && __r.is_subnormal() && !__r.is_zero())255__result.__ec = errc{};256257if (__negative)258__result.__value = -__r.get_val();259else260__result.__value = __r.get_val();261262return __result;263}264265// Implements from_chars for decimal floating-point values.266// __first forwarded from from_chars267// __last forwarded from from_chars268// __value forwarded from from_chars269// __fmt forwarded from from_chars270// __ptr the start of the buffer to parse. This is after the optional sign character.271// __negative should __value be set to a negative value?272//273// This function and __from_chars_floating_point_decimal are similar. However274// the similar parts are all in helper functions. So the amount of code275// duplication is minimal.276template <floating_point _Fp>277__from_chars_result<_Fp>278__from_chars_floating_point_hex(const char* const __first, const char* __last, const char* __ptr, bool __negative) {279size_t __n = __last - __first;280ptrdiff_t __offset = __ptr - __first;281282auto __fractional =283std::__parse_fractional_hex_constant<typename _Floating_type_traits<_Fp>::_Uint_type>(__first, __n, __offset);284if (!__fractional.__is_valid)285return {_Fp{0}, 0, errc::invalid_argument};286287auto __parsed_exponent = std::__parse_exponent(__first, __n, __fractional.__offset, 'p');288__offset = __parsed_exponent.__offset;289int __exponent = std::__merge_exponents(290__fractional.__exponent, __parsed_exponent.__value, LIBC_NAMESPACE::shared::FPBits<_Fp>::MAX_BIASED_EXPONENT);291292__from_chars_result<_Fp> __result{_Fp{0}, __offset, {}};293LIBC_NAMESPACE::shared::ExpandedFloat<_Fp> __expanded_float = {0, 0};294if (__fractional.__mantissa != 0) {295auto __temp = LIBC_NAMESPACE::shared::binary_exp_to_float<_Fp>(296{__fractional.__mantissa, __exponent},297__fractional.__truncated,298LIBC_NAMESPACE::shared::RoundDirection::Nearest);299__expanded_float = __temp.num;300if (__temp.error == ERANGE) {301__result.__ec = errc::result_out_of_range;302}303}304305return std::__calculate_result<_Fp>(__expanded_float.mantissa, __expanded_float.exponent, __negative, __result);306}307308// Parses the hex constant part of the decimal float value.309// - input start of buffer given to from_chars310// - __n the number of elements in the buffer311// - __offset where to start parsing. The input can have an optional sign, the312// offset starts after this sign.313template <class _Tp>314__fractional_constant_result<_Tp>315__parse_fractional_decimal_constant(const char* __input, ptrdiff_t __n, ptrdiff_t __offset) {316__fractional_constant_result<_Tp> __result;317318const _Tp __mantissa_truncate_threshold = numeric_limits<_Tp>::max() / 10;319bool __fraction = false;320for (; __offset < __n; ++__offset) {321if (std::isdigit(__input[__offset])) {322__result.__is_valid = true;323324uint32_t __digit = __input[__offset] - '0';325if (__result.__mantissa < __mantissa_truncate_threshold) {326__result.__mantissa = (__result.__mantissa * 10) + __digit;327if (__fraction)328--__result.__exponent;329} else {330if (__digit > 0)331__result.__truncated = true;332if (!__fraction)333++__result.__exponent;334}335} else if (__input[__offset] == '.') {336if (__fraction)337break; // this means that __input[__offset] points to a second decimal point, ending the number.338339__fraction = true;340} else341break;342}343344__result.__offset = __offset;345return __result;346}347348// Implements from_chars for decimal floating-point values.349// __first forwarded from from_chars350// __last forwarded from from_chars351// __value forwarded from from_chars352// __fmt forwarded from from_chars353// __ptr the start of the buffer to parse. This is after the optional sign character.354// __negative should __value be set to a negative value?355template <floating_point _Fp>356__from_chars_result<_Fp> __from_chars_floating_point_decimal(357const char* const __first, const char* __last, chars_format __fmt, const char* __ptr, bool __negative) {358ptrdiff_t __n = __last - __first;359ptrdiff_t __offset = __ptr - __first;360361auto __fractional =362std::__parse_fractional_decimal_constant<typename _Floating_type_traits<_Fp>::_Uint_type>(__first, __n, __offset);363if (!__fractional.__is_valid)364return {_Fp{0}, 0, errc::invalid_argument};365366__offset = __fractional.__offset;367368// LWG3456 Pattern used by std::from_chars is underspecified369// This changes fixed to ignore a possible exponent instead of making its370// existance an error.371int __exponent;372if (__fmt == chars_format::fixed) {373__exponent =374std::__merge_exponents(__fractional.__exponent, 0, LIBC_NAMESPACE::shared::FPBits<_Fp>::MAX_BIASED_EXPONENT);375} else {376auto __parsed_exponent = std::__parse_exponent(__first, __n, __offset, 'e');377if (__fmt == chars_format::scientific && !__parsed_exponent.__present) {378// [charconv.from.chars]/6.2 if fmt has chars_format::scientific set but not chars_format::fixed,379// the otherwise optional exponent part shall appear;380return {_Fp{0}, 0, errc::invalid_argument};381}382383__offset = __parsed_exponent.__offset;384__exponent = std::__merge_exponents(385__fractional.__exponent, __parsed_exponent.__value, LIBC_NAMESPACE::shared::FPBits<_Fp>::MAX_BIASED_EXPONENT);386}387388__from_chars_result<_Fp> __result{_Fp{0}, __offset, {}};389LIBC_NAMESPACE::shared::ExpandedFloat<_Fp> __expanded_float = {0, 0};390if (__fractional.__mantissa != 0) {391// This function expects to parse a positive value. This means it does not392// take a __first, __n as arguments, since __first points to '-' for393// negative values.394auto __temp = LIBC_NAMESPACE::shared::decimal_exp_to_float<_Fp>(395{__fractional.__mantissa, __exponent},396__fractional.__truncated,397LIBC_NAMESPACE::shared::RoundDirection::Nearest,398__ptr,399__last - __ptr);400__expanded_float = __temp.num;401if (__temp.error == ERANGE) {402__result.__ec = errc::result_out_of_range;403}404}405406return std::__calculate_result(__expanded_float.mantissa, __expanded_float.exponent, __negative, __result);407}408409template <floating_point _Fp>410__from_chars_result<_Fp>411__from_chars_floating_point_impl(const char* const __first, const char* __last, chars_format __fmt) {412if (__first == __last) [[unlikely]]413return {_Fp{0}, 0, errc::invalid_argument};414415const char* __ptr = __first;416bool __negative = *__ptr == '-';417if (__negative) {418++__ptr;419if (__ptr == __last) [[unlikely]]420return {_Fp{0}, 0, errc::invalid_argument};421}422423// [charconv.from.chars]424// [Note 1: If the pattern allows for an optional sign, but the string has425// no digit characters following the sign, no characters match the pattern.426// -- end note]427// This is true for integrals, floating point allows -.0428429// [charconv.from.chars]/6.2430// if fmt has chars_format::scientific set but not chars_format::fixed, the431// otherwise optional exponent part shall appear;432// Since INF/NAN do not have an exponent this value is not valid.433//434// LWG3456 Pattern used by std::from_chars is underspecified435// Does not address this point, but proposed option B does solve this issue,436// Both MSVC STL and libstdc++ implement this this behaviour.437switch (std::tolower(*__ptr)) {438case 'i':439return std::__from_chars_floating_point_inf<_Fp>(__first, __last, __ptr + 1, __negative);440case 'n':441if constexpr (numeric_limits<_Fp>::has_quiet_NaN)442// NOTE: The pointer passed here will be parsed in the default C locale.443// This is standard behavior (see https://eel.is/c++draft/charconv.from.chars), but may be unexpected.444return std::__from_chars_floating_point_nan<_Fp>(__first, __last, __ptr + 1, __negative);445return {_Fp{0}, 0, errc::invalid_argument};446}447448if (__fmt == chars_format::hex)449return std::__from_chars_floating_point_hex<_Fp>(__first, __last, __ptr, __negative);450451return std::__from_chars_floating_point_decimal<_Fp>(__first, __last, __fmt, __ptr, __negative);452}453454_LIBCPP_END_NAMESPACE_STD455456#endif //_LIBCPP_SRC_INCLUDE_FROM_CHARS_FLOATING_POINT_H457458459