Skip to content

[libc][math] Implement nan(f|l) functions #76690

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jan 5, 2024
Merged

[libc][math] Implement nan(f|l) functions #76690

merged 9 commits into from
Jan 5, 2024

Conversation

nishantwrp
Copy link
Contributor

@nishantwrp nishantwrp commented Jan 1, 2024

@llvmbot llvmbot added the libc label Jan 1, 2024
@llvmbot
Copy link
Member

llvmbot commented Jan 1, 2024

@llvm/pr-subscribers-libc

Author: Nishant Mittal (nishantwrp)

Changes

Patch is 21.78 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/76690.diff

23 Files Affected:

  • (modified) libc/config/darwin/arm/entrypoints.txt (+3)
  • (modified) libc/config/darwin/x86_64/entrypoints.txt (+3)
  • (modified) libc/config/gpu/entrypoints.txt (+2)
  • (modified) libc/config/linux/aarch64/entrypoints.txt (+3)
  • (modified) libc/config/linux/riscv/entrypoints.txt (+3)
  • (modified) libc/config/linux/x86_64/entrypoints.txt (+3)
  • (modified) libc/config/windows/entrypoints.txt (+3)
  • (modified) libc/docs/math/index.rst (+3-3)
  • (modified) libc/spec/stdc.td (+4)
  • (modified) libc/src/__support/str_to_float.h (+28)
  • (modified) libc/src/math/CMakeLists.txt (+4)
  • (modified) libc/src/math/generic/CMakeLists.txt (+39)
  • (added) libc/src/math/generic/nan.cpp (+26)
  • (added) libc/src/math/generic/nanf.cpp (+26)
  • (added) libc/src/math/generic/nanl.cpp (+26)
  • (added) libc/src/math/nan.h (+18)
  • (added) libc/src/math/nanf.h (+18)
  • (added) libc/src/math/nanl.h (+18)
  • (modified) libc/test/src/math/smoke/CMakeLists.txt (+36)
  • (added) libc/test/src/math/smoke/nan_test.cpp (+40)
  • (added) libc/test/src/math/smoke/nanf_test.cpp (+40)
  • (added) libc/test/src/math/smoke/nanl_test.cpp (+64)
  • (modified) utils/bazel/llvm-project-overlay/libc/BUILD.bazel (+6)
diff --git a/libc/config/darwin/arm/entrypoints.txt b/libc/config/darwin/arm/entrypoints.txt
index da4a2345f389c4..02a09256606956 100644
--- a/libc/config/darwin/arm/entrypoints.txt
+++ b/libc/config/darwin/arm/entrypoints.txt
@@ -193,6 +193,9 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.modf
     libc.src.math.modff
     libc.src.math.modfl
+    libc.src.math.nan
+    libc.src.math.nanf
+    libc.src.math.nanl
     libc.src.math.nearbyint
     libc.src.math.nearbyintf
     libc.src.math.nearbyintl
diff --git a/libc/config/darwin/x86_64/entrypoints.txt b/libc/config/darwin/x86_64/entrypoints.txt
index e29e75ec92dadc..91493cb77b1d86 100644
--- a/libc/config/darwin/x86_64/entrypoints.txt
+++ b/libc/config/darwin/x86_64/entrypoints.txt
@@ -172,6 +172,9 @@ set(TARGET_LIBM_ENTRYPOINTS
     #libc.src.math.modf
     #libc.src.math.modff
     #libc.src.math.modfl
+    #libc.src.math.nan
+    #libc.src.math.nanf
+    #libc.src.math.nanl
     #libc.src.math.nearbyint
     #libc.src.math.nearbyintf
     #libc.src.math.nearbyintl
diff --git a/libc/config/gpu/entrypoints.txt b/libc/config/gpu/entrypoints.txt
index ba86e31ee0adcd..b333c6be144627 100644
--- a/libc/config/gpu/entrypoints.txt
+++ b/libc/config/gpu/entrypoints.txt
@@ -215,6 +215,8 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.lroundf
     libc.src.math.modf
     libc.src.math.modff
+    libc.src.math.nan
+    libc.src.math.nanf
     libc.src.math.nearbyint
     libc.src.math.nearbyintf
     libc.src.math.nextafter
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 77c9a50b8b7e5d..ce3f5eb40e38aa 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -313,6 +313,9 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.modf
     libc.src.math.modff
     libc.src.math.modfl
+    libc.src.math.nan
+    libc.src.math.nanf
+    libc.src.math.nanl
     libc.src.math.nearbyint
     libc.src.math.nearbyintf
     libc.src.math.nearbyintl
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index e389936ffca1ef..ec2a16f5cf473b 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -322,6 +322,9 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.modf
     libc.src.math.modff
     libc.src.math.modfl
+    libc.src.math.nan
+    libc.src.math.nanf
+    libc.src.math.nanl
     libc.src.math.nearbyint
     libc.src.math.nearbyintf
     libc.src.math.nearbyintl
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 3adcd57d0c0849..30900de365bf95 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -323,6 +323,9 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.modf
     libc.src.math.modff
     libc.src.math.modfl
+    libc.src.math.nan
+    libc.src.math.nanf
+    libc.src.math.nanl
     libc.src.math.nearbyint
     libc.src.math.nearbyintf
     libc.src.math.nearbyintl
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index 4c0a6ec37fe4cc..5c3a2e287b9529 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -192,6 +192,9 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.modf
     libc.src.math.modff
     libc.src.math.modfl
+    libc.src.math.nan
+    libc.src.math.nanf
+    libc.src.math.nanl
     libc.src.math.nearbyint
     libc.src.math.nearbyintf
     libc.src.math.nearbyintl
diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst
index eaa7a40a29ae73..3668524af03c27 100644
--- a/libc/docs/math/index.rst
+++ b/libc/docs/math/index.rst
@@ -212,11 +212,11 @@ Basic Operations
 +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
 | modfl        | |check| | |check| |         | |check| | |check| |         |         | |check| |         |         |         |         |
 +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
-| nan          |         |         |         |         |         |         |         |         |         |         |         |         |
+| nan          | |check| | |check| |         | |check| | |check| |         |         | |check| |         |         |         |         |
 +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
-| nanf         |         |         |         |         |         |         |         |         |         |         |         |         |
+| nanf         | |check| | |check| |         | |check| | |check| |         |         | |check| |         |         |         |         |
 +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
-| nanl         |         |         |         |         |         |         |         |         |         |         |         |         |
+| nanl         | |check| | |check| |         | |check| | |check| |         |         | |check| |         |         |         |         |
 +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
 | nearbyint    | |check| | |check| |         | |check| | |check| |         |         | |check| |         |         |         |         |
 +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 58c95b856535a1..78095eb23f0711 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -515,6 +515,10 @@ def StdC : StandardSpec<"stdc"> {
           FunctionSpec<"scalbn", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>]>,
           FunctionSpec<"scalbnf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>]>,
           FunctionSpec<"scalbnl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>]>,
+
+          FunctionSpec<"nanf", RetValSpec<FloatType>, [ArgSpec<ConstCharPtr>]>,
+          FunctionSpec<"nan", RetValSpec<DoubleType>, [ArgSpec<ConstCharPtr>]>,
+          FunctionSpec<"nanl", RetValSpec<LongDoubleType>, [ArgSpec<ConstCharPtr>]>,
       ]
   >;
 
diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h
index 36b512d6972a93..555f65707b4e41 100644
--- a/libc/src/__support/str_to_float.h
+++ b/libc/src/__support/str_to_float.h
@@ -1206,6 +1206,34 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
   return {T(result), index, error};
 }
 
+LIBC_INLINE const char *nan_str_to_floatingpoint_str(const char *arg) {
+  ptrdiff_t index = 0;
+  while (isalnum(arg[index]) || arg[index] == '_')
+    ++index;
+
+  if (arg[index] == '\0') {
+    // 5 is the number of characters in string "NAN()".
+    ptrdiff_t size = 5 + index;
+    char *output_str = new char[size + 1];
+
+    output_str[0] = 'N';
+    output_str[1] = 'A';
+    output_str[2] = 'N';
+    output_str[3] = '(';
+
+    for (ptrdiff_t i = 0; i < index; ++i) {
+      output_str[4 + i] = arg[i];
+    }
+
+    output_str[size - 1] = ')';
+    output_str[size] = '\0';
+
+    return output_str;
+  }
+
+  return "NAN";
+}
+
 } // namespace internal
 } // namespace LIBC_NAMESPACE
 
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index ffabc27bc00abc..e2b1026fcad7e5 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -179,6 +179,10 @@ add_math_entrypoint_object(modf)
 add_math_entrypoint_object(modff)
 add_math_entrypoint_object(modfl)
 
+add_math_entrypoint_object(nan)
+add_math_entrypoint_object(nanf)
+add_math_entrypoint_object(nanl)
+
 add_math_entrypoint_object(nearbyint)
 add_math_entrypoint_object(nearbyintf)
 add_math_entrypoint_object(nearbyintl)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 214d57842d93b5..eeb09652961fd5 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -1437,6 +1437,45 @@ add_entrypoint_object(
     -O3
 )
 
+add_entrypoint_object(
+  nan
+  SRCS
+    nan.cpp
+  HDRS
+    ../nan.h
+  DEPENDS
+    libc.src.__support.str_to_float
+    libc.src.errno.errno
+  COMPILE_OPTIONS
+    -O3
+)
+
+add_entrypoint_object(
+  nanf
+  SRCS
+    nanf.cpp
+  HDRS
+    ../nanf.h
+  DEPENDS
+    libc.src.__support.str_to_float
+    libc.src.errno.errno
+  COMPILE_OPTIONS
+    -O3
+)
+
+add_entrypoint_object(
+  nanl
+  SRCS
+    nanl.cpp
+  HDRS
+    ../nanl.h
+  DEPENDS
+    libc.src.__support.str_to_float
+    libc.src.errno.errno
+  COMPILE_OPTIONS
+    -O3
+)
+
 add_entrypoint_object(
   nextafter
   SRCS
diff --git a/libc/src/math/generic/nan.cpp b/libc/src/math/generic/nan.cpp
new file mode 100644
index 00000000000000..9d591dcd3d091b
--- /dev/null
+++ b/libc/src/math/generic/nan.cpp
@@ -0,0 +1,26 @@
+//===-- Implementation of nan function ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/nan.h"
+#include "src/__support/common.h"
+#include "src/__support/str_to_float.h"
+#include "src/errno/libc_errno.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(double, nan, (const char *arg)) {
+  const char *fp_str = internal::nan_str_to_floatingpoint_str(arg);
+  auto result = internal::strtofloatingpoint<double>(fp_str);
+
+  if (result.has_error())
+    libc_errno = result.error;
+
+  return result.value;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/nanf.cpp b/libc/src/math/generic/nanf.cpp
new file mode 100644
index 00000000000000..b83e715485e471
--- /dev/null
+++ b/libc/src/math/generic/nanf.cpp
@@ -0,0 +1,26 @@
+//===-- Implementation of nanf function -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/nanf.h"
+#include "src/__support/common.h"
+#include "src/__support/str_to_float.h"
+#include "src/errno/libc_errno.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float, nanf, (const char *arg)) {
+  const char *fp_str = internal::nan_str_to_floatingpoint_str(arg);
+  auto result = internal::strtofloatingpoint<float>(fp_str);
+
+  if (result.has_error())
+    libc_errno = result.error;
+
+  return result.value;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/nanl.cpp b/libc/src/math/generic/nanl.cpp
new file mode 100644
index 00000000000000..6f70af9957b426
--- /dev/null
+++ b/libc/src/math/generic/nanl.cpp
@@ -0,0 +1,26 @@
+//===-- Implementation of nanl function -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/nanl.h"
+#include "src/__support/common.h"
+#include "src/__support/str_to_float.h"
+#include "src/errno/libc_errno.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(long double, nanl, (const char *arg)) {
+  const char *fp_str = internal::nan_str_to_floatingpoint_str(arg);
+  auto result = internal::strtofloatingpoint<long double>(fp_str);
+
+  if (result.has_error())
+    libc_errno = result.error;
+
+  return result.value;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/nan.h b/libc/src/math/nan.h
new file mode 100644
index 00000000000000..463940b01a2720
--- /dev/null
+++ b/libc/src/math/nan.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for nan ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_NAN_H
+#define LLVM_LIBC_SRC_MATH_NAN_H
+
+namespace LIBC_NAMESPACE {
+
+double nan(const char *arg);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_NAN_H
diff --git a/libc/src/math/nanf.h b/libc/src/math/nanf.h
new file mode 100644
index 00000000000000..f05d60e3a96718
--- /dev/null
+++ b/libc/src/math/nanf.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for nanf --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_NANF_H
+#define LLVM_LIBC_SRC_MATH_NANF_H
+
+namespace LIBC_NAMESPACE {
+
+float nanf(const char *arg);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_NANF_H
diff --git a/libc/src/math/nanl.h b/libc/src/math/nanl.h
new file mode 100644
index 00000000000000..d8bbce7cc1bcc3
--- /dev/null
+++ b/libc/src/math/nanl.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for nanl --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_NANL_H
+#define LLVM_LIBC_SRC_MATH_NANL_H
+
+namespace LIBC_NAMESPACE {
+
+long double nanl(const char *arg);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_NANL_H
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 6ebd374d04a5ba..6488f9f86f1fd3 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -1203,6 +1203,42 @@ add_fp_unittest(
     libc.src.__support.FPUtil.fp_bits
 )
 
+add_fp_unittest(
+  nanf_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    nanf_test.cpp
+  DEPENDS
+    libc.include.math
+    libc.src.math.nanf
+    libc.src.__support.FPUtil.fp_bits
+)
+
+add_fp_unittest(
+  nan_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    nan_test.cpp
+  DEPENDS
+    libc.include.math
+    libc.src.math.nan
+    libc.src.__support.FPUtil.fp_bits
+)
+
+add_fp_unittest(
+  nanl_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    nanl_test.cpp
+  DEPENDS
+    libc.include.math
+    libc.src.math.nanl
+    libc.src.__support.FPUtil.fp_bits
+)
+
 # FIXME: These tests are currently spurious for NVPTX.
 if(NOT LIBC_GPU_TARGET_ARCHITECTURE_IS_NVPTX)
   add_fp_unittest(
diff --git a/libc/test/src/math/smoke/nan_test.cpp b/libc/test/src/math/smoke/nan_test.cpp
new file mode 100644
index 00000000000000..6ff60be92e045b
--- /dev/null
+++ b/libc/test/src/math/smoke/nan_test.cpp
@@ -0,0 +1,40 @@
+//===-- Unittests for nan -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/math/nan.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+class LlvmLibcNanTest : public LIBC_NAMESPACE::testing::Test {
+public:
+  using StorageType = LIBC_NAMESPACE::fputil::FPBits<double>::StorageType;
+
+  void run_test(const char *input_str, StorageType bits) {
+    double result = LIBC_NAMESPACE::nan(input_str);
+    auto actual_fp = LIBC_NAMESPACE::fputil::FPBits<double>(result);
+    auto expected_fp = LIBC_NAMESPACE::fputil::FPBits<double>(bits);
+    EXPECT_EQ(actual_fp.bits, expected_fp.bits);
+  };
+};
+
+TEST_F(LlvmLibcNanTest, NCharSeq) {
+  run_test("", 0x7ff8000000000000);
+  run_test("1234", 0x7ff80000000004d2);
+  run_test("0x1234", 0x7ff8000000001234);
+  run_test("1a", 0x7ff8000000000000);
+  run_test("1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_",
+           0x7ff8000000000000);
+}
+
+TEST_F(LlvmLibcNanTest, RandomString) {
+  run_test(" 1234", 0x7ff8000000000000);
+  run_test("-1234", 0x7ff8000000000000);
+  run_test("asd&f", 0x7ff8000000000000);
+  run_test("123 ", 0x7ff8000000000000);
+}
diff --git a/libc/test/src/math/smoke/nanf_test.cpp b/libc/test/src/math/smoke/nanf_test.cpp
new file mode 100644
index 00000000000000..a8ff2f6b019c49
--- /dev/null
+++ b/libc/test/src/math/smoke/nanf_test.cpp
@@ -0,0 +1,40 @@
+//===-- Unittests for nanf ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/math/nanf.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+class LlvmLibcNanfTest : public LIBC_NAMESPACE::testing::Test {
+public:
+  using StorageType = LIBC_NAMESPACE::fputil::FPBits<float>::StorageType;
+
+  void run_test(const char *input_str, StorageType bits) {
+    float result = LIBC_NAMESPACE::nanf(input_str);
+    auto actual_fp = LIBC_NAMESPACE::fputil::FPBits<float>(result);
+    auto expected_fp = LIBC_NAMESPACE::fputil::FPBits<float>(bits);
+    EXPECT_EQ(actual_fp.bits, expected_fp.bits);
+  };
+};
+
+TEST_F(LlvmLibcNanfTest, NCharSeq) {
+  run_test("", 0x7fc00000);
+  run_test("1234", 0x7fc004d2);
+  run_test("0x1234", 0x7fc01234);
+  run_test("1a", 0x7fc00000);
+  run_test("1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_",
+           0x7fc00000);
+}
+
+TEST_F(LlvmLibcNanfTest, RandomString) {
+  run_test(" 1234", 0x7fc00000);
+  run_test("-1234", 0x7fc00000);
+  run_test("asd&f", 0x7fc00000);
+  run_test("123 ", 0x7fc00000);
+}
diff --git a/libc/test/src/math/smoke/nanl_test.cpp b/libc/test/src/math/smoke/nanl_test.cpp
new file mode 100644
index 00000000000000..a4283b0dcabc25
--- /dev/null
+++ b/libc/test/src/math/smoke/nanl_test.cpp
@@ -0,0 +1,64 @@
+//===-- Unittests for nanl ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/math/nanl.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+#if defined(LIBC_LONG_DOUBLE_IS_FLOAT64)
+#define SELECT_LONG_DOUBLE(val, _, __) val
+#elif defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80)
+#define SELECT_LONG_DOUBLE(_, val, __) val
+#else
+#define SELECT_LONG_DOUBLE(_, __, val) val
+#endif
+
+class LlvmLibcNanlTest : public LIBC_NAMESPACE::testing::Test {
+public:
+  using StorageType = LIBC_NAMESPACE::fputil::FPBits<long double>::StorageType;
+
+  void run_test(const char *input_str, StorageType bits) {
+    long double result = LIBC_NAMESPACE::nanl(input_str);
+    auto actual_fp = LIBC_NAMESPACE::fputil::FPBits<long double>(result);
+    auto expected_fp = LIBC_NAMESPACE::fputil::FPBits<long double>(bits);
+    EXPECT_EQ(actual_fp.bits, expected_fp.bits);
+  };
+};
+
+TEST_F(LlvmLibcNanlTest, NCharSeq) {
+  run_test("",
+           SELECT_LONG_DOUBLE(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
+                              (UInt128(0x7fff800000000000) << 64)));
...
[truncated]

@nishantwrp
Copy link
Contributor Author

@lntue please review.

Copy link
Contributor

@michaelrj-google michaelrj-google left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The standard says that the implementation should be like passing "NAN(n-character-sequence)" to string to float, but actually generating the string to pass to string to float is not an efficient design. I'd recommend you look at str_to_float.h lines 1141-1169 to see how the n-character-sequence is currently parsed, then try to refactor that code into something that can be reused for these new functions.

Copy link

github-actions bot commented Jan 3, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Contributor

@michaelrj-google michaelrj-google left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once Tue's comments are addressed.

@nishantwrp
Copy link
Contributor Author

@lntue ptal!

@nishantwrp nishantwrp requested a review from lntue January 4, 2024 19:17
@lntue lntue requested a review from michaelrj-google January 4, 2024 19:38
Copy link
Contributor

@michaelrj-google michaelrj-google left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved with nits. Feel free to land after fixing.

nan_mantissa_from_ncharseq(const cpp::string_view ncharseq) {
uint64_t nan_mantissa = 0;

if (ncharseq.data() != nullptr && isdigit(*ncharseq.data())) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: *ncharseq.data() should be ncharseq[0]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

if (!strtoint_result.has_error())
nan_mantissa = strtoint_result.value;

if (strtoint_result.parsed_len != (ptrdiff_t)ncharseq.size())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This should be a C++ style cast

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@lntue lntue merged commit 0504e93 into llvm:main Jan 5, 2024
@nishantwrp nishantwrp deleted the nanfl branch January 5, 2024 15:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants