aboutsummaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
Diffstat (limited to 'libc')
-rw-r--r--libc/config/linux/aarch64/entrypoints.txt1
-rw-r--r--libc/config/linux/riscv/entrypoints.txt1
-rw-r--r--libc/config/linux/x86_64/entrypoints.txt1
-rw-r--r--libc/docs/build_and_test.rst16
-rw-r--r--libc/docs/headers/math/index.rst2
-rw-r--r--libc/include/math.yaml6
-rw-r--r--libc/shared/math.h2
-rw-r--r--libc/shared/math/rsqrtf.h23
-rw-r--r--libc/shared/math/rsqrtf16.h2
-rw-r--r--libc/src/__support/OSUtil/linux/auxv.h3
-rw-r--r--libc/src/__support/OSUtil/linux/syscall.h14
-rw-r--r--libc/src/__support/math/CMakeLists.txt44
-rw-r--r--libc/src/__support/math/rsqrtf.h71
-rw-r--r--libc/src/__support/threads/linux/thread.cpp2
-rw-r--r--libc/src/math/CMakeLists.txt1
-rw-r--r--libc/src/math/generic/CMakeLists.txt10
-rw-r--r--libc/src/math/generic/rsqrtf.cpp16
-rw-r--r--libc/src/math/rsqrtf.h20
-rw-r--r--libc/src/sys/mman/linux/mmap.cpp2
-rw-r--r--libc/startup/linux/aarch64/tls.cpp2
-rw-r--r--libc/startup/linux/riscv/tls.cpp2
-rw-r--r--libc/startup/linux/x86_64/tls.cpp2
-rw-r--r--libc/test/shared/CMakeLists.txt2
-rw-r--r--libc/test/shared/shared_math_test.cpp2
-rw-r--r--libc/test/src/math/CMakeLists.txt11
-rw-r--r--libc/test/src/math/RsqrtTest.h74
-rw-r--r--libc/test/src/math/exhaustive/CMakeLists.txt15
-rw-r--r--libc/test/src/math/exhaustive/rsqrtf_test.cpp27
-rw-r--r--libc/test/src/math/rsqrtf_test.cpp12
-rw-r--r--libc/test/src/math/smoke/CMakeLists.txt15
-rw-r--r--libc/test/src/math/smoke/rsqrtf16_test.cpp1
-rw-r--r--libc/test/src/math/smoke/rsqrtf_test.cpp41
32 files changed, 411 insertions, 32 deletions
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 4824684..8bf6c44 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -735,6 +735,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.rintf16
libc.src.math.roundevenf16
libc.src.math.roundf16
+ libc.src.math.rsqrtf
libc.src.math.rsqrtf16
libc.src.math.scalblnf16
libc.src.math.scalbnf16
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 99c9d3d..dffccba 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -750,6 +750,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.rintf16
libc.src.math.roundevenf16
libc.src.math.roundf16
+ libc.src.math.rsqrtf
libc.src.math.rsqrtf16
libc.src.math.scalblnf16
libc.src.math.scalbnf16
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 82a83a2..b4ab073 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -786,6 +786,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.rintf16
libc.src.math.roundevenf16
libc.src.math.roundf16
+ libc.src.math.rsqrtf
libc.src.math.rsqrtf16
libc.src.math.scalblnf16
libc.src.math.scalbnf16
diff --git a/libc/docs/build_and_test.rst b/libc/docs/build_and_test.rst
index dfdd965..d608591 100644
--- a/libc/docs/build_and_test.rst
+++ b/libc/docs/build_and_test.rst
@@ -47,12 +47,18 @@ and put the following in your settings.json file:
.. code-block:: javascript
{
- "cmake.sourceDirectory": "${workspaceFolder}/llvm",
+ "cmake.sourceDirectory": "${workspaceFolder}/runtimes",
"cmake.configureSettings": {
- "LLVM_ENABLE_PROJECTS" : "libc",
- "LLVM_LIBC_FULL_BUILD" : true,
- "LLVM_ENABLE_SPHINX" : true,
- "LIBC_INCLUDE_DOCS" : true
+ "LLVM_ENABLE_RUNTIMES" : ["libc", "compiler-rt"],
+ "LLVM_LIBC_FULL_BUILD" : true,
+ "LLVM_ENABLE_SPHINX" : true,
+ "LIBC_INCLUDE_DOCS" : true,
+ "LLVM_LIBC_INCLUDE_SCUDO" : true,
+ "COMPILER_RT_BUILD_SCUDO_STANDALONE_WITH_LLVM_LIBC": true,
+ "COMPILER_RT_BUILD_GWP_ASAN" : false,
+ "COMPILER_RT_SCUDO_STANDALONE_BUILD_SHARED" : false,
+ "CMAKE_EXPORT_COMPILE_COMMANDS" : true,
+ "LIBC_CMAKE_VERBOSE_LOGGING" : true
}
}
diff --git a/libc/docs/headers/math/index.rst b/libc/docs/headers/math/index.rst
index 51bf238..51bb17f 100644
--- a/libc/docs/headers/math/index.rst
+++ b/libc/docs/headers/math/index.rst
@@ -343,7 +343,7 @@ Higher Math Functions
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| rootn | | | | | | | 7.12.7.8 | F.10.4.8 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
-| rsqrt | | | | |check| | | | 7.12.7.9 | F.10.4.9 |
+| rsqrt | |check| | | | |check| | | | 7.12.7.9 | F.10.4.9 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| sin | |check| | |check| | | |check| | | | 7.12.4.6 | F.10.1.6 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
diff --git a/libc/include/math.yaml b/libc/include/math.yaml
index 6c800a0..afd3ae3 100644
--- a/libc/include/math.yaml
+++ b/libc/include/math.yaml
@@ -2349,6 +2349,12 @@ functions:
return_type: long double
arguments:
- type: long double
+ - name: rsqrtf
+ standards:
+ - stdc
+ return_type: float
+ arguments:
+ - type: float
- name: rsqrtf16
standards:
- stdc
diff --git a/libc/shared/math.h b/libc/shared/math.h
index 1262fa6..82b9250 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -57,7 +57,7 @@
#include "math/ldexpf.h"
#include "math/ldexpf128.h"
#include "math/ldexpf16.h"
-
+#include "math/rsqrtf.h"
#include "math/rsqrtf16.h"
#endif // LLVM_LIBC_SHARED_MATH_H
diff --git a/libc/shared/math/rsqrtf.h b/libc/shared/math/rsqrtf.h
new file mode 100644
index 0000000..32d0a61
--- /dev/null
+++ b/libc/shared/math/rsqrtf.h
@@ -0,0 +1,23 @@
+//===-- Shared rsqrtf function ----------------------------------*- 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_SHARED_MATH_RSQRTF_H
+#define LLVM_LIBC_SHARED_MATH_RSQRTF_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/rsqrtf.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::rsqrtf;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_RSQRTF_H
diff --git a/libc/shared/math/rsqrtf16.h b/libc/shared/math/rsqrtf16.h
index 54c7499..8dbf065 100644
--- a/libc/shared/math/rsqrtf16.h
+++ b/libc/shared/math/rsqrtf16.h
@@ -1,4 +1,4 @@
-//===-- Shared rsqrtf16 function -------------------------------*- C++ -*-===//
+//===-- Shared rsqrtf16 function --------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/libc/src/__support/OSUtil/linux/auxv.h b/libc/src/__support/OSUtil/linux/auxv.h
index 894868a..9c07c54 100644
--- a/libc/src/__support/OSUtil/linux/auxv.h
+++ b/libc/src/__support/OSUtil/linux/auxv.h
@@ -16,6 +16,7 @@
#include <linux/auxvec.h> // For AT_ macros
#include <linux/mman.h> // For mmap flags
+#include <linux/param.h> // For EXEC_PAGESIZE
#include <linux/prctl.h> // For prctl
#include <sys/syscall.h> // For syscall numbers
@@ -90,7 +91,7 @@ LIBC_INLINE void Vector::fallback_initialize_unsync() {
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
// We do not proceed if mmap fails.
- if (mmap_ret <= 0)
+ if (!linux_utils::is_valid_mmap(mmap_ret))
return;
// Initialize the auxv array with AT_NULL entries.
diff --git a/libc/src/__support/OSUtil/linux/syscall.h b/libc/src/__support/OSUtil/linux/syscall.h
index 24e0fca..0e25618 100644
--- a/libc/src/__support/OSUtil/linux/syscall.h
+++ b/libc/src/__support/OSUtil/linux/syscall.h
@@ -12,6 +12,7 @@
#include "src/__support/CPP/bit.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
#include "src/__support/macros/properties/architectures.h"
#ifdef LIBC_TARGET_ARCH_IS_X86_32
@@ -34,6 +35,19 @@ LIBC_INLINE R syscall_impl(long __number, Ts... ts) {
return cpp::bit_or_static_cast<R>(syscall_impl(__number, (long)ts...));
}
+// Linux-specific function for checking
+namespace linux_utils {
+LIBC_INLINE_VAR constexpr unsigned long MAX_ERRNO = 4095;
+// Ideally, this should be defined using PAGE_OFFSET
+// However, that is a configurable parameter. We mimic kernel's behavior
+// by checking against MAX_ERRNO.
+template <typename PointerLike>
+LIBC_INLINE constexpr bool is_valid_mmap(PointerLike ptr) {
+ long addr = cpp::bit_cast<long>(ptr);
+ return LIBC_LIKELY(addr > 0 || addr < -static_cast<long>(MAX_ERRNO));
+}
+} // namespace linux_utils
+
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_SYSCALL_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 203ebb4..61253de 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -109,22 +109,6 @@ add_header_library(
libc.src.__support.macros.properties.types
)
-
-add_header_library(
- rsqrtf16
- HDRS
- rsqrtf16.h
- DEPENDS
- libc.src.__support.FPUtil.cast
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.FPUtil.manipulation_functions
- libc.src.__support.macros.optimization
- libc.src.__support.macros.properties.types
-)
-
add_header_library(
asin_utils
HDRS
@@ -867,6 +851,34 @@ add_header_library(
)
add_header_library(
+ rsqrtf
+ HDRS
+ rsqrtf.h
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.cast
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.sqrt
+ libc.src.__support.macros.optimization
+)
+
+add_header_library(
+ rsqrtf16
+ HDRS
+ rsqrtf16.h
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.cast
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.sqrt
+ libc.src.__support.macros.optimization
+)
+
+add_header_library(
sincos_eval
HDRS
sincos_eval.h
diff --git a/libc/src/__support/math/rsqrtf.h b/libc/src/__support/math/rsqrtf.h
new file mode 100644
index 0000000..5da1e73
--- /dev/null
+++ b/libc/src/__support/math/rsqrtf.h
@@ -0,0 +1,71 @@
+//===-- Implementation header for rsqrtf ------------------------*- 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___SUPPORT_MATH_RSQRTF_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_RSQRTF_H
+
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/sqrt.h"
+#include "src/__support/macros/optimization.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace math {
+
+LIBC_INLINE static constexpr float rsqrtf(float x) {
+ using FPBits = fputil::FPBits<float>;
+ FPBits xbits(x);
+
+ uint32_t x_u = xbits.uintval();
+ uint32_t x_abs = x_u & 0x7fff'ffffU;
+
+ constexpr uint32_t INF_BITS = FPBits::inf().uintval();
+
+ // x is 0, inf/nan, or negative.
+ if (LIBC_UNLIKELY(x_u == 0 || x_u >= INF_BITS)) {
+ // x is NaN
+ if (x_abs > INF_BITS) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+ return x;
+ }
+
+ // |x| = 0
+ if (x_abs == 0) {
+ fputil::raise_except_if_required(FE_DIVBYZERO);
+ fputil::set_errno_if_required(ERANGE);
+ return FPBits::inf(xbits.sign()).get_val();
+ }
+
+ // -inf <= x < 0
+ if (x_u > 0x7fff'ffffU) {
+ fputil::raise_except_if_required(FE_INVALID);
+ fputil::set_errno_if_required(EDOM);
+ return FPBits::quiet_nan().get_val();
+ }
+
+ // x = +inf => rsqrt(x) = 0
+ return FPBits::zero(xbits.sign()).get_val();
+ }
+
+ // TODO: add float based approximation when
+ // LIBC_TARGET_CPU_HAS_FPU_DOUBLE is not defined
+ double result = 1.0 / fputil::sqrt<double>(fputil::cast<double>(x));
+
+ return fputil::cast<float>(result);
+}
+
+} // namespace math
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_RSQRTF_H
diff --git a/libc/src/__support/threads/linux/thread.cpp b/libc/src/__support/threads/linux/thread.cpp
index d9e479ee..4f1e911 100644
--- a/libc/src/__support/threads/linux/thread.cpp
+++ b/libc/src/__support/threads/linux/thread.cpp
@@ -100,7 +100,7 @@ LIBC_INLINE ErrorOr<void *> alloc_stack(size_t stacksize, size_t guardsize) {
-1, // Not backed by any file
0 // No offset
);
- if (mmap_result < 0 && (uintptr_t(mmap_result) >= UINTPTR_MAX - size))
+ if (!linux_utils::is_valid_mmap(mmap_result))
return Error{int(-mmap_result)};
if (guardsize) {
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 3c7e99f..e37e22f 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -517,6 +517,7 @@ add_math_entrypoint_object(roundevenf16)
add_math_entrypoint_object(roundevenf128)
add_math_entrypoint_object(roundevenbf16)
+add_math_entrypoint_object(rsqrtf)
add_math_entrypoint_object(rsqrtf16)
add_math_entrypoint_object(scalbln)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 5738fe8..55f4aaf 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -989,6 +989,16 @@ add_entrypoint_object(
)
add_entrypoint_object(
+ rsqrtf
+ SRCS
+ rsqrtf.cpp
+ HDRS
+ ../rsqrtf.h
+ DEPENDS
+ libc.src.__support.math.rsqrtf
+)
+
+add_entrypoint_object(
rsqrtf16
SRCS
rsqrtf16.cpp
diff --git a/libc/src/math/generic/rsqrtf.cpp b/libc/src/math/generic/rsqrtf.cpp
new file mode 100644
index 0000000..6a38fa7
--- /dev/null
+++ b/libc/src/math/generic/rsqrtf.cpp
@@ -0,0 +1,16 @@
+//===-- Single-precision rsqrt 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/rsqrtf.h"
+#include "src/__support/math/rsqrtf.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(float, rsqrtf, (float x)) { return math::rsqrtf(x); }
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/rsqrtf.h b/libc/src/math/rsqrtf.h
new file mode 100644
index 0000000..bc55904
--- /dev/null
+++ b/libc/src/math/rsqrtf.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for rsqrtf ------------------------*- 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_RSQRTF_H
+#define LLVM_LIBC_SRC_MATH_RSQRTF_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float rsqrtf(float x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_RSQRTF_H
diff --git a/libc/src/sys/mman/linux/mmap.cpp b/libc/src/sys/mman/linux/mmap.cpp
index 33f9fe8..76a6611 100644
--- a/libc/src/sys/mman/linux/mmap.cpp
+++ b/libc/src/sys/mman/linux/mmap.cpp
@@ -56,7 +56,7 @@ LLVM_LIBC_FUNCTION(void *, mmap,
// However, since a valid return address cannot be within the last page, a
// return value corresponding to a location in the last page is an error
// value.
- if (ret < 0 && ret > -EXEC_PAGESIZE) {
+ if (!linux_utils::is_valid_mmap(ret)) {
libc_errno = static_cast<int>(-ret);
return MAP_FAILED;
}
diff --git a/libc/startup/linux/aarch64/tls.cpp b/libc/startup/linux/aarch64/tls.cpp
index ea1b50c..7847797 100644
--- a/libc/startup/linux/aarch64/tls.cpp
+++ b/libc/startup/linux/aarch64/tls.cpp
@@ -62,7 +62,7 @@ void init_tls(TLSDescriptor &tls_descriptor) {
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
// We cannot check the return value with MAP_FAILED as that is the return
// of the mmap function and not the mmap syscall.
- if (mmap_ret_val < 0 && static_cast<uintptr_t>(mmap_ret_val) > -app.page_size)
+ if (!linux_utils::is_valid_mmap(mmap_ret_val))
syscall_impl<long>(SYS_exit, 1);
uintptr_t thread_ptr = uintptr_t(reinterpret_cast<uintptr_t *>(mmap_ret_val));
uintptr_t tls_addr = thread_ptr + size_of_pointers + padding;
diff --git a/libc/startup/linux/riscv/tls.cpp b/libc/startup/linux/riscv/tls.cpp
index 04d44e6..e9d23c5 100644
--- a/libc/startup/linux/riscv/tls.cpp
+++ b/libc/startup/linux/riscv/tls.cpp
@@ -50,7 +50,7 @@ void init_tls(TLSDescriptor &tls_descriptor) {
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
// We cannot check the return value with MAP_FAILED as that is the return
// of the mmap function and not the mmap syscall.
- if (mmap_ret_val < 0 && static_cast<uintptr_t>(mmap_ret_val) > -app.page_size)
+ if (!linux_utils::is_valid_mmap(mmap_ret_val))
syscall_impl<long>(SYS_exit, 1);
uintptr_t thread_ptr = uintptr_t(reinterpret_cast<uintptr_t *>(mmap_ret_val));
uintptr_t tls_addr = thread_ptr + size_of_pointers + padding;
diff --git a/libc/startup/linux/x86_64/tls.cpp b/libc/startup/linux/x86_64/tls.cpp
index d6b549a..497f744 100644
--- a/libc/startup/linux/x86_64/tls.cpp
+++ b/libc/startup/linux/x86_64/tls.cpp
@@ -53,7 +53,7 @@ void init_tls(TLSDescriptor &tls_descriptor) {
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
// We cannot check the return value with MAP_FAILED as that is the return
// of the mmap function and not the mmap syscall.
- if (mmap_retval < 0 && static_cast<uintptr_t>(mmap_retval) > -app.page_size)
+ if (!linux_utils::is_valid_mmap(mmap_retval))
syscall_impl<long>(SYS_exit, 1);
uintptr_t *tls_addr = reinterpret_cast<uintptr_t *>(mmap_retval);
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index dbc3889c..f341d3f 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -53,6 +53,6 @@ add_fp_unittest(
libc.src.__support.math.ldexpf
libc.src.__support.math.ldexpf128
libc.src.__support.math.ldexpf16
+ libc.src.__support.math.rsqrtf
libc.src.__support.math.rsqrtf16
-
)
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index d118d96..477b7ec 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -70,6 +70,8 @@ TEST(LlvmLibcSharedMathTest, AllFloat) {
ASSERT_FP_EQ(float(8 << 5), LIBC_NAMESPACE::shared::ldexpf(8.0f, 5));
ASSERT_FP_EQ(float(-1 * (8 << 5)), LIBC_NAMESPACE::shared::ldexpf(-8.0f, 5));
+
+ EXPECT_FP_EQ(0x1p+0f, LIBC_NAMESPACE::shared::rsqrtf(1.0f));
}
TEST(LlvmLibcSharedMathTest, AllDouble) {
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 2d2d528..b3f54ab 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -1679,6 +1679,17 @@ add_fp_unittest(
)
add_fp_unittest(
+ rsqrtf_test
+ NEED_MPFR
+ SUITE
+ libc-math-unittests
+ SRCS
+ rsqrtf_test.cpp
+ DEPENDS
+ libc.src.math.rsqrtf
+)
+
+add_fp_unittest(
rsqrtf16_test
NEED_MPFR
SUITE
diff --git a/libc/test/src/math/RsqrtTest.h b/libc/test/src/math/RsqrtTest.h
new file mode 100644
index 0000000..d11d708
--- /dev/null
+++ b/libc/test/src/math/RsqrtTest.h
@@ -0,0 +1,74 @@
+//===-- Utility class to test rsqrt[f|l] ------------------------*- 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_TEST_SRC_MATH_RSQRTTEST_H
+#define LLVM_LIBC_TEST_SRC_MATH_RSQRTTEST_H
+
+#include "test/UnitTest/FEnvSafeTest.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+template <typename OutType, typename InType = OutType>
+class RsqrtTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+
+ DECLARE_SPECIAL_CONSTANTS(InType)
+
+ static constexpr StorageType HIDDEN_BIT =
+ StorageType(1) << LIBC_NAMESPACE::fputil::FPBits<InType>::FRACTION_LEN;
+
+public:
+ using RsqrtFunc = OutType (*)(InType);
+
+ // Subnormal inputs: probe both power-of-two mantissas and an even sampling
+ // across the subnormal range.
+ void test_denormal_values(RsqrtFunc func) {
+ // Powers of two in the subnormal mantissa space.
+ for (StorageType mant = 1; mant < HIDDEN_BIT; mant <<= 1) {
+ FPBits denormal(zero);
+ denormal.set_mantissa(mant);
+ InType x = denormal.get_val();
+ ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Rsqrt, x, func(x), 0.5);
+ }
+
+ // Even sampling across all subnormals.
+ constexpr StorageType COUNT = 200'001;
+ constexpr StorageType STEP = HIDDEN_BIT / COUNT;
+ for (StorageType i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
+ InType x = FPBits(i).get_val();
+ ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Rsqrt, x, func(x), 0.5);
+ }
+ }
+
+ // Positive normal range sampling: skip NaNs and negative values.
+ void test_normal_range(RsqrtFunc func) {
+ constexpr StorageType COUNT = 200'001;
+ constexpr StorageType STEP = STORAGE_MAX / COUNT;
+ for (StorageType i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
+ FPBits x_bits(v);
+ InType x = x_bits.get_val();
+ if (x_bits.is_nan() || x_bits.is_neg())
+ continue;
+ ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Rsqrt, x, func(x), 0.5);
+ }
+ }
+};
+
+#define LIST_RSQRT_TESTS(T, func) \
+ using LlvmLibcRsqrtTest = RsqrtTest<T, T>; \
+ TEST_F(LlvmLibcRsqrtTest, DenormalValues) { test_denormal_values(&func); } \
+ TEST_F(LlvmLibcRsqrtTest, NormalRange) { test_normal_range(&func); }
+
+#define LIST_NARROWING_RSQRT_TESTS(OutType, InType, func) \
+ using LlvmLibcRsqrtTest = RsqrtTest<OutType, InType>; \
+ TEST_F(LlvmLibcRsqrtTest, DenormalValues) { test_denormal_values(&func); } \
+ TEST_F(LlvmLibcRsqrtTest, NormalRange) { test_normal_range(&func); }
+
+#endif // LLVM_LIBC_TEST_SRC_MATH_RSQRTTEST_H
diff --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt
index 07c36f424..1583ab6 100644
--- a/libc/test/src/math/exhaustive/CMakeLists.txt
+++ b/libc/test/src/math/exhaustive/CMakeLists.txt
@@ -27,6 +27,21 @@ add_fp_unittest(
)
add_fp_unittest(
+ rsqrtf_test
+ NO_RUN_POSTBUILD
+ NEED_MPFR
+ SUITE
+ libc_math_exhaustive_tests
+ SRCS
+ rsqrtf_test.cpp
+ DEPENDS
+ .exhaustive_test
+ libc.src.math.rsqrtf
+ LINK_LIBRARIES
+ -lpthread
+)
+
+add_fp_unittest(
sinf_test
NO_RUN_POSTBUILD
NEED_MPFR
diff --git a/libc/test/src/math/exhaustive/rsqrtf_test.cpp b/libc/test/src/math/exhaustive/rsqrtf_test.cpp
new file mode 100644
index 0000000..803c9b4
--- /dev/null
+++ b/libc/test/src/math/exhaustive/rsqrtf_test.cpp
@@ -0,0 +1,27 @@
+//===-- Exhaustive test for rsqrtf ----------------------------------------===//
+//
+// 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 "exhaustive_test.h"
+#include "src/math/rsqrtf.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+using LlvmLibcRsqrtfTest = LIBC_NAMESPACE::testing::FPTest<float>;
+
+using LlvmLibcRsqrtfExhaustiveTest =
+ LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Rsqrt,
+ LIBC_NAMESPACE::rsqrtf>;
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+// Range: [0, Inf]
+static constexpr uint32_t POS_START = 0x0000'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
+
+TEST_F(LlvmLibcRsqrtfExhaustiveTest, PositiveRange) {
+ test_full_range_all_roundings(POS_START, POS_STOP);
+}
diff --git a/libc/test/src/math/rsqrtf_test.cpp b/libc/test/src/math/rsqrtf_test.cpp
new file mode 100644
index 0000000..4e476c0
--- /dev/null
+++ b/libc/test/src/math/rsqrtf_test.cpp
@@ -0,0 +1,12 @@
+//===-- Unittests for rsqrtf ----------------------------------------------===//
+// 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 "RsqrtTest.h"
+
+#include "src/math/rsqrtf.h"
+
+LIST_RSQRT_TESTS(float, LIBC_NAMESPACE::rsqrtf)
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 42a97ba..5afd3a9 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -3503,14 +3503,27 @@ add_fp_unittest(
)
add_fp_unittest(
+ rsqrtf_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ rsqrtf_test.cpp
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.math.rsqrtf
+)
+
+add_fp_unittest(
rsqrtf16_test
SUITE
libc-math-smoke-tests
SRCS
rsqrtf16_test.cpp
DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
libc.src.math.rsqrtf16
- libc.hdr.errno_macros
)
add_fp_unittest(
diff --git a/libc/test/src/math/smoke/rsqrtf16_test.cpp b/libc/test/src/math/smoke/rsqrtf16_test.cpp
index e103e73..13d9a33 100644
--- a/libc/test/src/math/smoke/rsqrtf16_test.cpp
+++ b/libc/test/src/math/smoke/rsqrtf16_test.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
#include "src/__support/FPUtil/cast.h"
#include "src/__support/macros/properties/architectures.h"
#include "src/math/rsqrtf16.h"
diff --git a/libc/test/src/math/smoke/rsqrtf_test.cpp b/libc/test/src/math/smoke/rsqrtf_test.cpp
new file mode 100644
index 0000000..d71b82c
--- /dev/null
+++ b/libc/test/src/math/smoke/rsqrtf_test.cpp
@@ -0,0 +1,41 @@
+//===-- Unittests for rsqrtf --------------------------------------------===//
+//
+// 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 "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
+#include "src/math/rsqrtf.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcRsqrtfTest = LIBC_NAMESPACE::testing::FPTest<float>;
+
+TEST_F(LlvmLibcRsqrtfTest, SpecialNumbers) {
+ EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::rsqrtf(aNaN));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(LIBC_NAMESPACE::rsqrtf(sNaN), FE_INVALID);
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ(inf, LIBC_NAMESPACE::rsqrtf(zero));
+ EXPECT_MATH_ERRNO(ERANGE);
+
+ EXPECT_FP_EQ(neg_inf, LIBC_NAMESPACE::rsqrtf(neg_zero));
+ EXPECT_MATH_ERRNO(ERANGE);
+
+ EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::rsqrtf(1.0f));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ(zero, LIBC_NAMESPACE::rsqrtf(inf));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::rsqrtf(neg_inf));
+ EXPECT_MATH_ERRNO(EDOM);
+
+ EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::rsqrtf(-2.0f));
+ EXPECT_MATH_ERRNO(EDOM);
+}