diff --git a/libc/config/gpu/amdgpu/entrypoints.txt b/libc/config/gpu/amdgpu/entrypoints.txt index 291d86b4dd587..a5d32c8eda39f 100644 --- a/libc/config/gpu/amdgpu/entrypoints.txt +++ b/libc/config/gpu/amdgpu/entrypoints.txt @@ -548,6 +548,7 @@ if(LIBC_TYPES_HAS_FLOAT16) libc.src.math.fabsf16 libc.src.math.fdimf16 libc.src.math.floorf16 + libc.src.math.fmaf16 libc.src.math.fmaxf16 libc.src.math.fmaximum_mag_numf16 libc.src.math.fmaximum_magf16 diff --git a/libc/config/gpu/nvptx/entrypoints.txt b/libc/config/gpu/nvptx/entrypoints.txt index 1ea0d9b03b37e..f553f7cc2b210 100644 --- a/libc/config/gpu/nvptx/entrypoints.txt +++ b/libc/config/gpu/nvptx/entrypoints.txt @@ -550,6 +550,7 @@ if(LIBC_TYPES_HAS_FLOAT16) libc.src.math.fabsf16 libc.src.math.fdimf16 libc.src.math.floorf16 + libc.src.math.fmaf16 libc.src.math.fmaxf16 libc.src.math.fmaximum_mag_numf16 libc.src.math.fmaximum_magf16 diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 431975463fbad..e48122956ada0 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -676,6 +676,7 @@ if(LIBC_TYPES_HAS_FLOAT16) libc.src.math.ffma libc.src.math.ffmal libc.src.math.floorf16 + libc.src.math.fmaf16 libc.src.math.fmaxf16 libc.src.math.fmaximum_mag_numf16 libc.src.math.fmaximum_magf16 diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 5abe6957d2e3c..606e1c1de5e9c 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -686,6 +686,7 @@ if(LIBC_TYPES_HAS_FLOAT16) libc.src.math.fabsf16 libc.src.math.fdimf16 libc.src.math.floorf16 + libc.src.math.fmaf16 libc.src.math.fmaxf16 libc.src.math.fmaximum_mag_numf16 libc.src.math.fmaximum_magf16 diff --git a/libc/docs/headers/math/index.rst b/libc/docs/headers/math/index.rst index 5b855ce4881c3..dda8855df1a5a 100644 --- a/libc/docs/headers/math/index.rst +++ b/libc/docs/headers/math/index.rst @@ -299,7 +299,7 @@ Higher Math Functions +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | expm1 | |check| | |check| | | |check| | | 7.12.6.6 | F.10.3.6 | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ -| fma | |check| | |check| | | | | 7.12.13.1 | F.10.10.1 | +| fma | |check| | |check| | | |check| | | 7.12.13.1 | F.10.10.1 | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | f16sqrt | |check|\* | |check|\* | |check|\* | N/A | |check| | 7.12.14.6 | F.10.11 | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ diff --git a/libc/include/math.yaml b/libc/include/math.yaml index a66f981030864..08a28263a186d 100644 --- a/libc/include/math.yaml +++ b/libc/include/math.yaml @@ -736,6 +736,15 @@ functions: - type: float - type: float - type: float + - name: fmaf16 + standards: + - stdc + return_type: _Float16 + arguments: + - type: _Float16 + - type: _Float16 + - type: _Float16 + guard: LIBC_TYPES_HAS_FLOAT16 - name: fmax standards: - stdc diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt index f18a73d46f9aa..a42421614661a 100644 --- a/libc/src/math/CMakeLists.txt +++ b/libc/src/math/CMakeLists.txt @@ -209,6 +209,7 @@ add_math_entrypoint_object(floorf128) add_math_entrypoint_object(fma) add_math_entrypoint_object(fmaf) +add_math_entrypoint_object(fmaf16) add_math_entrypoint_object(fmax) add_math_entrypoint_object(fmaxf) diff --git a/libc/src/math/fmaf16.h b/libc/src/math/fmaf16.h new file mode 100644 index 0000000000000..1c4d468e67a7a --- /dev/null +++ b/libc/src/math/fmaf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for fmaf16 ------------------------*- 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_FMAF16_H +#define LLVM_LIBC_SRC_MATH_FMAF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +float16 fmaf16(float16 x, float16 y, float16 z); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_FMAF16_H diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index 3114289bad486..a929a8d9d06cd 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -4241,6 +4241,17 @@ add_entrypoint_object( libc.src.__support.FPUtil.fma ) +add_entrypoint_object( + fmaf16 + SRCS + fmaf16.cpp + HDRS + ../fmaf16.h + DEPENDS + libc.src.__support.FPUtil.fma + libc.src.__support.macros.properties.types +) + add_entrypoint_object( fma SRCS diff --git a/libc/src/math/generic/fmaf16.cpp b/libc/src/math/generic/fmaf16.cpp new file mode 100644 index 0000000000000..4f712f5de764f --- /dev/null +++ b/libc/src/math/generic/fmaf16.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of fmaf16 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/fmaf16.h" +#include "src/__support/FPUtil/FMA.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(float16, fmaf16, (float16 x, float16 y, float16 z)) { + return fputil::fma(x, y, z); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt index 032050bb06ec3..2c4d35c0c3c96 100644 --- a/libc/test/src/math/CMakeLists.txt +++ b/libc/test/src/math/CMakeLists.txt @@ -1776,6 +1776,21 @@ add_fp_unittest( FMA_OPT__ONLY ) +add_fp_unittest( + fmaf16_test + NEED_MPFR + SUITE + libc-math-unittests + SRCS + fmaf16_test.cpp + HDRS + FmaTest.h + DEPENDS + libc.src.math.fmaf16 + libc.src.stdlib.rand + libc.src.stdlib.srand +) + add_fp_unittest( fma_test NEED_MPFR diff --git a/libc/test/src/math/FmaTest.h b/libc/test/src/math/FmaTest.h index 01143331d4ab5..5c5419ce3ab4d 100644 --- a/libc/test/src/math/FmaTest.h +++ b/libc/test/src/math/FmaTest.h @@ -58,8 +58,9 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest { void test_subnormal_range(FmaFunc func) { constexpr InStorageType COUNT = 100'001; - constexpr InStorageType STEP = + constexpr InStorageType RAW_STEP = (IN_MAX_SUBNORMAL_U - IN_MIN_SUBNORMAL_U) / COUNT; + constexpr InStorageType STEP = (RAW_STEP == 0 ? 1 : RAW_STEP); LIBC_NAMESPACE::srand(1); for (InStorageType v = IN_MIN_SUBNORMAL_U, w = IN_MAX_SUBNORMAL_U; v <= IN_MAX_SUBNORMAL_U && w >= IN_MIN_SUBNORMAL_U; @@ -75,7 +76,9 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest { void test_normal_range(FmaFunc func) { constexpr InStorageType COUNT = 100'001; - constexpr InStorageType STEP = (IN_MAX_NORMAL_U - IN_MIN_NORMAL_U) / COUNT; + constexpr InStorageType RAW_STEP = + (IN_MAX_NORMAL_U - IN_MIN_NORMAL_U) / COUNT; + constexpr InStorageType STEP = (RAW_STEP == 0 ? 1 : RAW_STEP); LIBC_NAMESPACE::srand(1); for (InStorageType v = IN_MIN_NORMAL_U, w = IN_MAX_NORMAL_U; v <= IN_MAX_NORMAL_U && w >= IN_MIN_NORMAL_U; v += STEP, w -= STEP) { diff --git a/libc/test/src/math/fmaf16_test.cpp b/libc/test/src/math/fmaf16_test.cpp new file mode 100644 index 0000000000000..233d3a7c54cf4 --- /dev/null +++ b/libc/test/src/math/fmaf16_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmaf16 ----------------------------------------------===// +// +// 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 "FmaTest.h" + +#include "src/math/fmaf16.h" + +LIST_FMA_TESTS(float16, LIBC_NAMESPACE::fmaf16) diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt index aef7c83ba0215..3601aca2400c9 100644 --- a/libc/test/src/math/smoke/CMakeLists.txt +++ b/libc/test/src/math/smoke/CMakeLists.txt @@ -3562,6 +3562,19 @@ add_fp_unittest( libc.src.__support.macros.properties.types ) +add_fp_unittest( + fmaf16_test + SUITE + libc-math-smoke-tests + SRCS + fmaf16_test.cpp + HDRS + FmaTest.h + DEPENDS + libc.src.math.fmaf16 + libc.src.__support.FPUtil.cast +) + add_fp_unittest( fma_test SUITE diff --git a/libc/test/src/math/smoke/FmaTest.h b/libc/test/src/math/smoke/FmaTest.h index 41093422d51b2..5d344d9e7ebe7 100644 --- a/libc/test/src/math/smoke/FmaTest.h +++ b/libc/test/src/math/smoke/FmaTest.h @@ -9,9 +9,7 @@ #ifndef LLVM_LIBC_TEST_SRC_MATH_FMATEST_H #define LLVM_LIBC_TEST_SRC_MATH_FMATEST_H -#include "src/__support/CPP/type_traits.h" #include "src/__support/FPUtil/cast.h" -#include "src/__support/macros/properties/types.h" #include "test/UnitTest/FEnvSafeTest.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" @@ -90,14 +88,8 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest { // Test overflow. OutType z = out.max_normal; InType in_z = LIBC_NAMESPACE::fputil::cast(out.max_normal); -#if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION) - // Rounding modes other than the default might not be usable with float16. - if constexpr (LIBC_NAMESPACE::cpp::is_same_v) - EXPECT_FP_EQ(OutType(0.75) * z, func(InType(1.75), in_z, -in_z)); - else -#endif - EXPECT_FP_EQ_ALL_ROUNDING(OutType(0.75) * z, - func(InType(1.75), in_z, -in_z)); + EXPECT_FP_EQ_ALL_ROUNDING(OutType(0.75) * z, + func(InType(1.75), in_z, -in_z)); // Exact cancellation. EXPECT_FP_EQ_ROUNDING_NEAREST( diff --git a/libc/test/src/math/smoke/fmaf16_test.cpp b/libc/test/src/math/smoke/fmaf16_test.cpp new file mode 100644 index 0000000000000..233d3a7c54cf4 --- /dev/null +++ b/libc/test/src/math/smoke/fmaf16_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmaf16 ----------------------------------------------===// +// +// 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 "FmaTest.h" + +#include "src/math/fmaf16.h" + +LIST_FMA_TESTS(float16, LIBC_NAMESPACE::fmaf16) diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp index fc260f4abed49..4a033dbc2049b 100644 --- a/libc/utils/MPFRWrapper/MPFRUtils.cpp +++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp @@ -454,6 +454,8 @@ explain_ternary_operation_one_output_error(Operation, long double, double, RoundingMode); #ifdef LIBC_TYPES_HAS_FLOAT16 +template void explain_ternary_operation_one_output_error( + Operation, const TernaryInput &, float16, double, RoundingMode); template void explain_ternary_operation_one_output_error( Operation, const TernaryInput &, float16, double, RoundingMode); template void explain_ternary_operation_one_output_error( @@ -672,6 +674,9 @@ compare_ternary_operation_one_output(Operation, long double, double, RoundingMode); #ifdef LIBC_TYPES_HAS_FLOAT16 +template bool +compare_ternary_operation_one_output(Operation, const TernaryInput &, + float16, double, RoundingMode); template bool compare_ternary_operation_one_output(Operation, const TernaryInput &, float16, double, diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 1bf884a785e64..e1ff3e389a7d6 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -2831,6 +2831,13 @@ libc_math_function(name = "floorf16") # TODO: Add fma, fmaf, fmal, fmaf128 functions. +libc_math_function( + name = "fmaf16", + additional_deps = [ + ":__support_fputil_fma", + ], +) + libc_math_function(name = "fmax") libc_math_function(name = "fmaxf") diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/math/smoke/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/math/smoke/BUILD.bazel index 803548178b0e3..29b3c5be157d7 100644 --- a/utils/bazel/llvm-project-overlay/libc/test/src/math/smoke/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/test/src/math/smoke/BUILD.bazel @@ -474,6 +474,11 @@ math_test( # TODO: Add fma, fmaf, fmal, fmaf128 tests. +math_test( + name = "fmaf16", + hdrs = ["FmaTest.h"], +) + math_test( name = "fmax", hdrs = ["FMaxTest.h"],