Skip to content

Commit 0504e93

Browse files
authored
[libc][math] Implement nan(f|l) functions (#76690)
Specification: https://en.cppreference.com/w/c/numeric/math/nan
1 parent f7f7574 commit 0504e93

File tree

23 files changed

+451
-20
lines changed

23 files changed

+451
-20
lines changed

libc/config/darwin/arm/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,9 @@ set(TARGET_LIBM_ENTRYPOINTS
193193
libc.src.math.modf
194194
libc.src.math.modff
195195
libc.src.math.modfl
196+
libc.src.math.nan
197+
libc.src.math.nanf
198+
libc.src.math.nanl
196199
libc.src.math.nearbyint
197200
libc.src.math.nearbyintf
198201
libc.src.math.nearbyintl

libc/config/darwin/x86_64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ set(TARGET_LIBM_ENTRYPOINTS
172172
#libc.src.math.modf
173173
#libc.src.math.modff
174174
#libc.src.math.modfl
175+
#libc.src.math.nan
176+
#libc.src.math.nanf
177+
#libc.src.math.nanl
175178
#libc.src.math.nearbyint
176179
#libc.src.math.nearbyintf
177180
#libc.src.math.nearbyintl

libc/config/gpu/entrypoints.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ set(TARGET_LIBM_ENTRYPOINTS
215215
libc.src.math.lroundf
216216
libc.src.math.modf
217217
libc.src.math.modff
218+
libc.src.math.nan
219+
libc.src.math.nanf
218220
libc.src.math.nearbyint
219221
libc.src.math.nearbyintf
220222
libc.src.math.nextafter

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,9 @@ set(TARGET_LIBM_ENTRYPOINTS
313313
libc.src.math.modf
314314
libc.src.math.modff
315315
libc.src.math.modfl
316+
libc.src.math.nan
317+
libc.src.math.nanf
318+
libc.src.math.nanl
316319
libc.src.math.nearbyint
317320
libc.src.math.nearbyintf
318321
libc.src.math.nearbyintl

libc/config/linux/riscv/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,9 @@ set(TARGET_LIBM_ENTRYPOINTS
322322
libc.src.math.modf
323323
libc.src.math.modff
324324
libc.src.math.modfl
325+
libc.src.math.nan
326+
libc.src.math.nanf
327+
libc.src.math.nanl
325328
libc.src.math.nearbyint
326329
libc.src.math.nearbyintf
327330
libc.src.math.nearbyintl

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,9 @@ set(TARGET_LIBM_ENTRYPOINTS
323323
libc.src.math.modf
324324
libc.src.math.modff
325325
libc.src.math.modfl
326+
libc.src.math.nan
327+
libc.src.math.nanf
328+
libc.src.math.nanl
326329
libc.src.math.nearbyint
327330
libc.src.math.nearbyintf
328331
libc.src.math.nearbyintl

libc/config/windows/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ set(TARGET_LIBM_ENTRYPOINTS
192192
libc.src.math.modf
193193
libc.src.math.modff
194194
libc.src.math.modfl
195+
libc.src.math.nan
196+
libc.src.math.nanf
197+
libc.src.math.nanl
195198
libc.src.math.nearbyint
196199
libc.src.math.nearbyintf
197200
libc.src.math.nearbyintl

libc/docs/math/index.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -212,11 +212,11 @@ Basic Operations
212212
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
213213
| modfl | |check| | |check| | | |check| | |check| | | | |check| | | | | |
214214
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
215-
| nan | | | | | | | | | | | | |
215+
| nan | |check| | |check| | | |check| | |check| | | | |check| | | | | |
216216
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
217-
| nanf | | | | | | | | | | | | |
217+
| nanf | |check| | |check| | | |check| | |check| | | | |check| | | | | |
218218
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
219-
| nanl | | | | | | | | | | | | |
219+
| nanl | |check| | |check| | | |check| | |check| | | | |check| | | | | |
220220
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
221221
| nearbyint | |check| | |check| | | |check| | |check| | | | |check| | | | | |
222222
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+

libc/spec/stdc.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,10 @@ def StdC : StandardSpec<"stdc"> {
515515
FunctionSpec<"scalbn", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>]>,
516516
FunctionSpec<"scalbnf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>]>,
517517
FunctionSpec<"scalbnl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>]>,
518+
519+
FunctionSpec<"nanf", RetValSpec<FloatType>, [ArgSpec<ConstCharPtr>]>,
520+
FunctionSpec<"nan", RetValSpec<DoubleType>, [ArgSpec<ConstCharPtr>]>,
521+
FunctionSpec<"nanl", RetValSpec<LongDoubleType>, [ArgSpec<ConstCharPtr>]>,
518522
]
519523
>;
520524

libc/src/__support/str_to_float.h

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "src/__support/CPP/bit.h"
1313
#include "src/__support/CPP/limits.h"
1414
#include "src/__support/CPP/optional.h"
15+
#include "src/__support/CPP/string_view.h"
1516
#include "src/__support/FPUtil/FEnvImpl.h"
1617
#include "src/__support/FPUtil/FPBits.h"
1718
#include "src/__support/FPUtil/dyadic_float.h"
@@ -1044,6 +1045,27 @@ hexadecimal_string_to_float(const char *__restrict src,
10441045
return output;
10451046
}
10461047

1048+
LIBC_INLINE uint64_t
1049+
nan_mantissa_from_ncharseq(const cpp::string_view ncharseq) {
1050+
uint64_t nan_mantissa = 0;
1051+
1052+
if (ncharseq.data() != nullptr && isdigit(ncharseq[0])) {
1053+
// This is to prevent errors when StorageType is larger than 64
1054+
// bits, since strtointeger only supports up to 64 bits. This is
1055+
// actually more than is required by the specification, which says
1056+
// for the input type "NAN(n-char-sequence)" that "the meaning of
1057+
// the n-char sequence is implementation-defined."
1058+
auto strtoint_result = strtointeger<uint64_t>(ncharseq.data(), 0);
1059+
if (!strtoint_result.has_error())
1060+
nan_mantissa = strtoint_result.value;
1061+
1062+
if (strtoint_result.parsed_len != static_cast<ptrdiff_t>(ncharseq.size()))
1063+
nan_mantissa = 0;
1064+
}
1065+
1066+
return nan_mantissa;
1067+
}
1068+
10471069
// Takes a pointer to a string and a pointer to a string pointer. This function
10481070
// is used as the backend for all of the string to float functions.
10491071
template <class T>
@@ -1136,31 +1158,18 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
11361158
++index;
11371159
if (src[index] == ')') {
11381160
++index;
1139-
if (isdigit(src[left_paren + 1])) {
1140-
// This is to prevent errors when StorageType is larger than 64
1141-
// bits, since strtointeger only supports up to 64 bits. This is
1142-
// actually more than is required by the specification, which says
1143-
// for the input type "NAN(n-char-sequence)" that "the meaning of
1144-
// the n-char sequence is implementation-defined."
1145-
1146-
auto strtoint_result =
1147-
strtointeger<uint64_t>(src + (left_paren + 1), 0);
1148-
if (strtoint_result.has_error()) {
1149-
error = strtoint_result.error;
1150-
}
1151-
nan_mantissa = static_cast<StorageType>(strtoint_result.value);
1152-
if (src[left_paren + 1 + strtoint_result.parsed_len] != ')')
1153-
nan_mantissa = 0;
1154-
}
1161+
auto nan_mantissa_result = nan_mantissa_from_ncharseq(
1162+
cpp::string_view(src + (left_paren + 1), index - left_paren - 2));
1163+
nan_mantissa = static_cast<StorageType>(nan_mantissa_result);
11551164
} else {
11561165
index = left_paren;
11571166
}
11581167
}
1168+
11591169
if (result.get_sign()) {
11601170
result = FPBits(result.build_quiet_nan(nan_mantissa));
11611171
result.set_sign(true);
11621172
} else {
1163-
result.set_sign(false);
11641173
result = FPBits(result.build_quiet_nan(nan_mantissa));
11651174
}
11661175
}
@@ -1195,6 +1204,28 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
11951204
return {T(result), index, error};
11961205
}
11971206

1207+
template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) {
1208+
using FPBits = typename fputil::FPBits<T>;
1209+
using StorageType = typename FPBits::StorageType;
1210+
1211+
FPBits result;
1212+
int error = 0;
1213+
StorageType nan_mantissa = 0;
1214+
1215+
ptrdiff_t index = 0;
1216+
while (isalnum(arg[index]) || arg[index] == '_')
1217+
++index;
1218+
1219+
if (arg[index] == '\0') {
1220+
auto nan_mantissa_result =
1221+
nan_mantissa_from_ncharseq(cpp::string_view(arg, index));
1222+
nan_mantissa = static_cast<StorageType>(nan_mantissa_result);
1223+
}
1224+
1225+
result = FPBits(result.build_quiet_nan(nan_mantissa));
1226+
return {T(result), 0, error};
1227+
}
1228+
11981229
} // namespace internal
11991230
} // namespace LIBC_NAMESPACE
12001231

0 commit comments

Comments
 (0)