Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libc/config/linux/aarch64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/riscv/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,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
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,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
Expand Down
2 changes: 1 addition & 1 deletion libc/docs/headers/math/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
Expand Down
6 changes: 6 additions & 0 deletions libc/include/math.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion libc/shared/math.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,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
23 changes: 23 additions & 0 deletions libc/shared/math/rsqrtf.h
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion libc/shared/math/rsqrtf16.h
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
44 changes: 28 additions & 16 deletions libc/src/__support/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -775,6 +759,34 @@ add_header_library(
libc.src.__support.common
)

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.macros.optimization
Comment on lines +767 to +772
Copy link
Member

Choose a reason for hiding this comment

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

  • Nit: trailing whitespace (I wish GitHub would highlight it.).
  • Missing libc.src.__support.FPUtil.sqrt.
Suggested change
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.macros.optimization
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.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(
sincos_eval
HDRS
Expand Down
71 changes: 71 additions & 0 deletions libc/src/__support/math/rsqrtf.h
Original file line number Diff line number Diff line change
@@ -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.0f / 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
1 change: 1 addition & 0 deletions libc/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,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)
Expand Down
10 changes: 10 additions & 0 deletions libc/src/math/generic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,16 @@ add_entrypoint_object(
ROUND_OPT
)

add_entrypoint_object(
rsqrtf
SRCS
rsqrtf.cpp
HDRS
../rsqrtf.h
DEPENDS
libc.src.__support.math.rsqrtf
)

add_entrypoint_object(
rsqrtf16
SRCS
Expand Down
16 changes: 16 additions & 0 deletions libc/src/math/generic/rsqrtf.cpp
Original file line number Diff line number Diff line change
@@ -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
20 changes: 20 additions & 0 deletions libc/src/math/rsqrtf.h
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion libc/test/shared/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,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

)
1 change: 1 addition & 0 deletions libc/test/shared/shared_math_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ 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));
Copy link
Member

Choose a reason for hiding this comment

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

Nit: I would move this new test case above, just below the test case for expf.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just curious why - I think as of right now everything is in alphabetical order here for TEST(LlvmLibcSharedMathTest, AllFloat) test

Copy link
Member

Choose a reason for hiding this comment

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

Oh, I didn't notice the alphabetical order. It just looks kind of weird to me to have 2 test cases for ldexpf followed by a test case for rsqrtf with no blank line in between because it makes it look like these tests are related somehow. Lines 49-62 don't look weird to me because there's only 1 test case per function. But this is an extreme nitpick.

Copy link
Contributor Author

@amemov amemov Oct 4, 2025

Choose a reason for hiding this comment

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

I agree. I think to make it look better it would be a good idea to separate rsqrtf test from ldexpf by a new line

}

TEST(LlvmLibcSharedMathTest, AllDouble) {
Expand Down
11 changes: 11 additions & 0 deletions libc/test/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1678,6 +1678,17 @@ add_fp_unittest(
libc.src.math.sqrtl
)

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
Expand Down
74 changes: 74 additions & 0 deletions libc/test/src/math/RsqrtTest.h
Original file line number Diff line number Diff line change
@@ -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
Loading
Loading