-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[libc][math][c23] Add rsqrtf() function #159615
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
base: main
Are you sure you want to change the base?
Changes from all commits
e84a1e6
5b8b21a
26674a6
0d8e57a
1cc47f3
0faacb6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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 |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -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 | ||||||||||||||||||||||||||||
|
@@ -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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
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 | ||||||||||||||||||||||||||||
amemov marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
add_header_library( | ||||||||||||||||||||||||||||
sincos_eval | ||||||||||||||||||||||||||||
HDRS | ||||||||||||||||||||||||||||
|
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 |
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 |
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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
//===-- Utility class to test rsqrt[f|l] ------------------------*- C++ -*-===// | ||
amemov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// | ||
// 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 |
Uh oh!
There was an error while loading. Please reload this page.