Skip to content
Merged
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 @@ -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
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 @@ -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
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 @@ -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
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 @@ -866,6 +850,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.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
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.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
1 change: 1 addition & 0 deletions libc/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
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 @@ -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

)
2 changes: 2 additions & 0 deletions libc/test/shared/shared_math_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
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