Skip to content
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

[libc][math][c23] Add f16{add,sub}f C23 math functions #96787

Merged
merged 6 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
[libc][math][c23] Add f16subf C23 math function
  • Loading branch information
overmighty committed Jul 2, 2024
commit 6879c2a0f21e47b57a95c3718828c63fd544c622
1 change: 1 addition & 0 deletions libc/config/linux/aarch64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.f16fmaf
libc.src.math.f16sqrt
libc.src.math.f16sqrtf
libc.src.math.f16subf
libc.src.math.fabsf16
libc.src.math.fdimf16
libc.src.math.floorf16
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 @@ -548,6 +548,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.f16sqrt
libc.src.math.f16sqrtf
libc.src.math.f16sqrtl
libc.src.math.f16subf
libc.src.math.fabsf16
libc.src.math.fdimf16
libc.src.math.floorf16
Expand Down
2 changes: 2 additions & 0 deletions libc/docs/math/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ Basic Operations
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| f16fma | |check| | |check| | |check| | N/A | |check| | 7.12.14.5 | F.10.11 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| f16sub | |check| | | | N/A | | 7.12.14.2 | F.10.11 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| fabs | |check| | |check| | |check| | |check| | |check| | 7.12.7.3 | F.10.4.3 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| fadd | N/A | | | N/A | | 7.12.14.1 | F.10.11 |
Expand Down
2 changes: 2 additions & 0 deletions libc/spec/stdc.td
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,8 @@ def StdC : StandardSpec<"stdc"> {

GuardedFunctionSpec<"f16addf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,

GuardedFunctionSpec<"f16subf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,

GuardedFunctionSpec<"f16divf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,

GuardedFunctionSpec<"f16sqrtf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
Expand Down
4 changes: 2 additions & 2 deletions libc/src/__support/FPUtil/generic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ add_header_library(
)

add_header_library(
add
add_sub
HDRS
add.h
add_sub.h
DEPENDS
libc.hdr.errno_macros
libc.hdr.fenv_macros
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//===-- Addition of IEEE 754 floating-point numbers -------------*- C++ -*-===//
//===-- Add and subtract IEEE 754 floating-point numbers --------*- 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_FPUTIL_GENERIC_ADD_H
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_ADD_H
#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_ADD_SUB_H
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_ADD_SUB_H

#include "hdr/errno_macros.h"
#include "hdr/fenv_macros.h"
Expand All @@ -24,12 +24,12 @@

namespace LIBC_NAMESPACE::fputil::generic {

template <typename OutType, typename InType>
template <bool IsSub, typename OutType, typename InType>
LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<OutType> &&
cpp::is_floating_point_v<InType> &&
sizeof(OutType) <= sizeof(InType),
OutType>
add(InType x, InType y) {
add_or_sub(InType x, InType y) {
using OutFPBits = FPBits<OutType>;
using OutStorageType = typename OutFPBits::StorageType;
using InFPBits = FPBits<InType>;
Expand All @@ -45,6 +45,8 @@ add(InType x, InType y) {
InFPBits x_bits(x);
InFPBits y_bits(y);

bool is_effectively_add = (x_bits.sign() == y_bits.sign()) ^ IsSub;

if (LIBC_UNLIKELY(x_bits.is_inf_or_nan() || y_bits.is_inf_or_nan() ||
x_bits.is_zero() || y_bits.is_zero())) {
if (x_bits.is_nan() || y_bits.is_nan()) {
Expand Down Expand Up @@ -72,7 +74,7 @@ add(InType x, InType y) {

if (x_bits.is_inf()) {
if (y_bits.is_inf()) {
if (x_bits.sign() != y_bits.sign()) {
if (!is_effectively_add) {
raise_except_if_required(FE_INVALID);
return OutFPBits::quiet_nan().get_val();
}
Expand Down Expand Up @@ -106,7 +108,7 @@ add(InType x, InType y) {
InType x_abs = x_bits.abs().get_val();
InType y_abs = y_bits.abs().get_val();

if (x_abs == y_abs && x_bits.sign() != y_bits.sign()) {
if (x_abs == y_abs && !is_effectively_add) {
switch (quick_get_round()) {
case FE_DOWNWARD:
return OutFPBits::zero(Sign::NEG).get_val();
Expand All @@ -117,12 +119,16 @@ add(InType x, InType y) {

Sign result_sign = Sign::POS;

if (x_abs > y_abs)
if (x_abs > y_abs) {
result_sign = x_bits.sign();
else if (x_abs < y_abs)
result_sign = y_bits.sign();
else if (x_bits.sign() == y_bits.sign())
} else if (x_abs < y_abs) {
if (is_effectively_add)
result_sign = y_bits.sign();
else if (y_bits.is_pos())
result_sign = Sign::NEG;
} else if (is_effectively_add) {
result_sign = x_bits.sign();
}

InFPBits max_bits(cpp::max(x_abs, y_abs));
InFPBits min_bits(cpp::min(x_abs, y_abs));
Expand All @@ -131,7 +137,8 @@ add(InType x, InType y) {

if (max_bits.is_subnormal()) {
// min_bits must be subnormal too.
if (max_bits.sign() == min_bits.sign())

if (is_effectively_add)
result_mant = max_bits.get_mantissa() + min_bits.get_mantissa();
else
result_mant = max_bits.get_mantissa() - min_bits.get_mantissa();
Expand All @@ -155,7 +162,7 @@ add(InType x, InType y) {
else
aligned_min_mant_sticky = true;

if (max_bits.sign() == min_bits.sign())
if (is_effectively_add)
result_mant = max_mant + (aligned_min_mant | aligned_min_mant_sticky);
else
result_mant = max_mant - (aligned_min_mant | aligned_min_mant_sticky);
Expand All @@ -166,6 +173,24 @@ add(InType x, InType y) {
return result.template as<OutType, /*ShouldSignalExceptions=*/true>();
}

template <typename OutType, typename InType>
LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<OutType> &&
cpp::is_floating_point_v<InType> &&
sizeof(OutType) <= sizeof(InType),
OutType>
add(InType x, InType y) {
return add_or_sub</*IsSub=*/false, OutType>(x, y);
}

template <typename OutType, typename InType>
LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<OutType> &&
cpp::is_floating_point_v<InType> &&
sizeof(OutType) <= sizeof(InType),
OutType>
sub(InType x, InType y) {
return add_or_sub</*IsSub=*/true, OutType>(x, y);
}

} // namespace LIBC_NAMESPACE::fputil::generic

#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_ADD_H
#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_ADD_SUB_H
2 changes: 2 additions & 0 deletions libc/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ add_math_entrypoint_object(f16sqrtf)
add_math_entrypoint_object(f16sqrtl)
add_math_entrypoint_object(f16sqrtf128)

add_math_entrypoint_object(f16subf)

add_math_entrypoint_object(fabs)
add_math_entrypoint_object(fabsf)
add_math_entrypoint_object(fabsl)
Expand Down
20 changes: 20 additions & 0 deletions libc/src/math/f16subf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for f16subf -----------------------*- 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_F16SUBF_H
#define LLVM_LIBC_SRC_MATH_F16SUBF_H

#include "src/__support/macros/properties/types.h"

namespace LIBC_NAMESPACE {

float16 f16subf(float x, float y);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_MATH_F16SUBF_H
15 changes: 14 additions & 1 deletion libc/src/math/generic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3803,7 +3803,20 @@ add_entrypoint_object(
../f16addf.h
DEPENDS
libc.src.__support.macros.properties.types
libc.src.__support.FPUtil.generic.add
libc.src.__support.FPUtil.generic.add_sub
COMPILE_OPTIONS
-O3
)

add_entrypoint_object(
f16subf
SRCS
f16subf.cpp
HDRS
../f16subf.h
DEPENDS
libc.src.__support.macros.properties.types
libc.src.__support.FPUtil.generic.add_sub
COMPILE_OPTIONS
-O3
)
Expand Down
2 changes: 1 addition & 1 deletion libc/src/math/generic/f16addf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//

#include "src/math/f16addf.h"
#include "src/__support/FPUtil/generic/add.h"
#include "src/__support/FPUtil/generic/add_sub.h"
#include "src/__support/common.h"

namespace LIBC_NAMESPACE {
Expand Down
19 changes: 19 additions & 0 deletions libc/src/math/generic/f16subf.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//===-- Implementation of f16subf 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/f16subf.h"
#include "src/__support/FPUtil/generic/add_sub.h"
#include "src/__support/common.h"

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(float16, f16subf, (float x, float y)) {
return fputil::generic::sub<float16>(x, y);
}

} // namespace LIBC_NAMESPACE
13 changes: 13 additions & 0 deletions libc/test/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2009,6 +2009,19 @@ add_fp_unittest(
libc.src.math.f16addf
)

add_fp_unittest(
f16subf_test
NEED_MPFR
SUITE
libc-math-unittests
SRCS
f16subf_test.cpp
HDRS
SubTest.h
DEPENDS
libc.src.math.f16subf
)

add_fp_unittest(
f16div_test
NEED_MPFR
Expand Down
73 changes: 73 additions & 0 deletions libc/test/src/math/SubTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//===-- Utility class to test different flavors of float sub ----*- 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_SUBTEST_H
#define LLVM_LIBC_TEST_SRC_MATH_SUBTEST_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>
class SubTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {

struct InConstants {
DECLARE_SPECIAL_CONSTANTS(InType)
};

using InFPBits = typename InConstants::FPBits;
using InStorageType = typename InConstants::StorageType;

static constexpr InStorageType IN_MAX_NORMAL_U =
InFPBits::max_normal().uintval();
static constexpr InStorageType IN_MIN_NORMAL_U =
InFPBits::min_normal().uintval();
static constexpr InStorageType IN_MAX_SUBNORMAL_U =
InFPBits::max_subnormal().uintval();
static constexpr InStorageType IN_MIN_SUBNORMAL_U =
InFPBits::min_subnormal().uintval();

public:
typedef OutType (*AddFunc)(InType, InType);

void test_subnormal_range(AddFunc func) {
constexpr InStorageType STEP =
(IN_MAX_SUBNORMAL_U - IN_MIN_SUBNORMAL_U) / COUNT;
for (InStorageType i = 0, v = 0, w = IN_MAX_SUBNORMAL_U; i <= COUNT;
++i, v += STEP, w -= STEP) {
InType x = InFPBits(v).get_val();
InType y = InFPBits(w).get_val();
mpfr::BinaryInput<InType> input{x, y};
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Sub, input, func(x, y),
0.5);
}
}

void test_normal_range(AddFunc func) {
constexpr InStorageType COUNT = 100'001;
constexpr InStorageType STEP = (IN_MAX_NORMAL_U - IN_MIN_NORMAL_U) / COUNT;
for (InStorageType i = 0, v = 0, w = IN_MAX_NORMAL_U; i <= COUNT;
++i, v += STEP, w -= STEP) {
InType x = InFPBits(v).get_val();
InType y = InFPBits(w).get_val();
mpfr::BinaryInput<InType> input{x, y};
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Sub, input, func(x, y),
0.5);
}
}
};

#define LIST_SUB_TESTS(OutType, InType, func) \
using LlvmLibcSubTest = SubTest<OutType, InType>; \
TEST_F(LlvmLibcSubTest, SubnormalRange) { test_subnormal_range(&func); } \
TEST_F(LlvmLibcSubTest, NormalRange) { test_normal_range(&func); }

#endif // LLVM_LIBC_TEST_SRC_MATH_ADDTEST_H
13 changes: 13 additions & 0 deletions libc/test/src/math/f16subf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for f16subf ---------------------------------------------===//
//
// 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 "SubTest.h"

#include "src/math/f16subf.h"

LIST_SUB_TESTS(float16, float, LIBC_NAMESPACE::f16subf)
14 changes: 14 additions & 0 deletions libc/test/src/math/smoke/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3658,6 +3658,20 @@ add_fp_unittest(
libc.src.math.f16addf
)

add_fp_unittest(
f16subf_test
SUITE
libc-math-smoke-tests
SRCS
f16subf_test.cpp
HDRS
SubTest.h
DEPENDS
libc.hdr.fenv_macros
libc.src.__support.FPUtil.basic_operations
libc.src.math.f16subf
)

add_fp_unittest(
f16div_test
SUITE
Expand Down
Loading