[libc][math][c++23] Add fmodbf16 math function (#155575)

This PR adds fmodbf16 basic math function for BFloat16 type along with
the tests.

---------

Signed-off-by: Krishna Pandey <kpandey81930@gmail.com>
This commit is contained in:
Krishna Pandey 2025-09-03 22:20:07 +05:30 committed by GitHub
parent c5a141bb8b
commit 96b1dfb57f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 193 additions and 25 deletions

View File

@ -788,6 +788,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.fminimum_magbf16
libc.src.math.fminimum_mag_numbf16
libc.src.math.fminimum_numbf16
libc.src.math.fmodbf16
libc.src.math.frexpbf16
libc.src.math.fromfpbf16
libc.src.math.fromfpxbf16

View File

@ -791,6 +791,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.fminimum_magbf16
libc.src.math.fminimum_mag_numbf16
libc.src.math.fminimum_numbf16
libc.src.math.fmodbf16
libc.src.math.frexpbf16
libc.src.math.fromfpbf16
libc.src.math.fromfpxbf16

View File

@ -791,6 +791,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.fminimum_magbf16
libc.src.math.fminimum_mag_numbf16
libc.src.math.fminimum_numbf16
libc.src.math.fmodbf16
libc.src.math.frexpbf16
libc.src.math.fromfpbf16
libc.src.math.fromfpxbf16

View File

@ -621,6 +621,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.fminimum_magbf16
libc.src.math.fminimum_mag_numbf16
libc.src.math.fminimum_numbf16
libc.src.math.fmodbf16
libc.src.math.frexpbf16
libc.src.math.fromfpbf16
libc.src.math.fromfpxbf16

View File

@ -264,6 +264,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.fminimum_magbf16
libc.src.math.fminimum_mag_numbf16
libc.src.math.fminimum_numbf16
libc.src.math.fmodbf16
libc.src.math.frexpbf16
libc.src.math.fromfpbf16
libc.src.math.fromfpxbf16

View File

@ -647,6 +647,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.fminimum_magbf16
libc.src.math.fminimum_mag_numbf16
libc.src.math.fminimum_numbf16
libc.src.math.fmodbf16
libc.src.math.frexpbf16
libc.src.math.fromfpbf16
libc.src.math.fromfpxbf16

View File

@ -649,6 +649,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.fminimum_magbf16
libc.src.math.fminimum_mag_numbf16
libc.src.math.fminimum_numbf16
libc.src.math.fmodbf16
libc.src.math.frexpbf16
libc.src.math.fromfpbf16
libc.src.math.fromfpxbf16

View File

@ -876,6 +876,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.fminimum_magbf16
libc.src.math.fminimum_mag_numbf16
libc.src.math.fminimum_numbf16
libc.src.math.fmodbf16
libc.src.math.frexpbf16
libc.src.math.fromfpbf16
libc.src.math.fromfpxbf16

View File

@ -491,6 +491,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.fminimum_magbf16
libc.src.math.fminimum_mag_numbf16
libc.src.math.fminimum_numbf16
libc.src.math.fmodbf16
libc.src.math.frexpbf16
libc.src.math.fromfpbf16
libc.src.math.fromfpxbf16

View File

@ -894,6 +894,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.fminimum_magbf16
libc.src.math.fminimum_mag_numbf16
libc.src.math.fminimum_numbf16
libc.src.math.fmodbf16
libc.src.math.frexpbf16
libc.src.math.fromfpbf16
libc.src.math.fromfpxbf16

View File

@ -929,6 +929,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.fminimum_magbf16
libc.src.math.fminimum_mag_numbf16
libc.src.math.fminimum_numbf16
libc.src.math.fmodbf16
libc.src.math.frexpbf16
libc.src.math.fromfpbf16
libc.src.math.fromfpxbf16

View File

@ -337,6 +337,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.fminimum_magbf16
libc.src.math.fminimum_mag_numbf16
libc.src.math.fminimum_numbf16
libc.src.math.fmodbf16
libc.src.math.frexpbf16
libc.src.math.fromfpbf16
libc.src.math.fromfpxbf16

View File

@ -175,7 +175,7 @@ Basic Operations
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| fminimum_num | |check| | |check| | |check| | |check| | |check| | |check| | 7.12.12.9 | F.10.9.5 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| fmod | |check| | |check| | |check| | |check| | |check| | | 7.12.10.1 | F.10.7.1 |
| fmod | |check| | |check| | |check| | |check| | |check| | |check| | 7.12.10.1 | F.10.7.1 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| fmul | N/A | |check| | |check| | N/A | |check|\* | N/A | 7.12.14.3 | F.10.11 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+

View File

@ -308,6 +308,7 @@ add_math_entrypoint_object(fmodf)
add_math_entrypoint_object(fmodl)
add_math_entrypoint_object(fmodf16)
add_math_entrypoint_object(fmodf128)
add_math_entrypoint_object(fmodbf16)
add_math_entrypoint_object(frexp)
add_math_entrypoint_object(frexpf)

21
libc/src/math/fmodbf16.h Normal file
View File

@ -0,0 +1,21 @@
//===-- Implementation header for fmodbf16 ----------------------*- 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_FMODBF16_H
#define LLVM_LIBC_SRC_MATH_FMODBF16_H
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/types.h"
namespace LIBC_NAMESPACE_DECL {
bfloat16 fmodbf16(bfloat16 x, bfloat16 y);
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_MATH_FMODBF16_H

View File

@ -4015,6 +4015,20 @@ add_entrypoint_object(
libc.src.__support.FPUtil.generic.fmod
)
add_entrypoint_object(
fmodbf16
SRCS
fmodbf16.cpp
HDRS
../fmodbf16.h
DEPENDS
libc.src.__support.common
libc.src.__support.macros.config
libc.src.__support.macros.properties.types
libc.src.__support.FPUtil.bfloat16
libc.src.__support.FPUtil.generic.fmod
)
add_entrypoint_object(
fromfp
SRCS

View File

@ -0,0 +1,21 @@
//===-- Implementation of fmodbf16 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/fmodbf16.h"
#include "src/__support/FPUtil/bfloat16.h"
#include "src/__support/FPUtil/generic/FMod.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(bfloat16, fmodbf16, (bfloat16 x, bfloat16 y)) {
return fputil::generic::FMod<bfloat16>::eval(x, y);
}
} // namespace LIBC_NAMESPACE_DECL

View File

@ -377,6 +377,22 @@ add_fp_unittest(
-lpthread
)
add_fp_unittest(
fmodbf16_test
NO_RUN_POSTBUILD
NEED_MPFR
SUITE
libc_math_exhaustive_tests
SRCS
fmodbf16_test.cpp
DEPENDS
.exhaustive_test
libc.src.math.fmodbf16
libc.src.__support.FPUtil.bfloat16
LINK_LIBRARIES
-lpthread
)
add_fp_unittest(
coshf_test
NO_RUN_POSTBUILD

View File

@ -0,0 +1,42 @@
//===-- Exhaustive test for fmodbf16 --------------------------------------===//
//
// 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 "exhaustive_test.h"
#include "src/__support/FPUtil/bfloat16.h"
#include "src/math/fmodbf16.h"
#include "utils/MPFRWrapper/MPFRUtils.h"
namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
using LlvmLibcFmodf16ExhaustiveTest =
LlvmLibcBinaryOpExhaustiveMathTest<bfloat16, mpfr::Operation::Fmod,
LIBC_NAMESPACE::fmodbf16>;
// range: [0, inf]
static constexpr uint16_t POS_START = 0x0000U;
static constexpr uint16_t POS_STOP = 0x7f80U;
// range: [-0, -inf]
static constexpr uint16_t NEG_START = 0x8000U;
static constexpr uint16_t NEG_STOP = 0xff80U;
TEST_F(LlvmLibcFmodf16ExhaustiveTest, PostivePositiveRange) {
test_full_range_all_roundings(POS_START, POS_STOP, POS_START, POS_STOP);
}
TEST_F(LlvmLibcFmodf16ExhaustiveTest, PostiveNegativeRange) {
test_full_range_all_roundings(POS_START, POS_STOP, NEG_START, NEG_STOP);
}
TEST_F(LlvmLibcFmodf16ExhaustiveTest, NegativePositiveRange) {
test_full_range_all_roundings(NEG_START, NEG_STOP, POS_START, POS_STOP);
}
TEST_F(LlvmLibcFmodf16ExhaustiveTest, NegativeNegativeRange) {
test_full_range_all_roundings(NEG_START, NEG_STOP, NEG_START, NEG_STOP);
}

View File

@ -4503,6 +4503,23 @@ add_fp_unittest(
UNIT_TEST_ONLY
)
add_fp_unittest(
fmodbf16_test
SUITE
libc-math-smoke-tests
SRCS
fmodbf16_test.cpp
HDRS
FModTest.h
DEPENDS
libc.hdr.fenv_macros
libc.src.errno.errno
libc.src.math.fmodbf16
libc.src.__support.FPUtil.bfloat16
libc.src.__support.FPUtil.fenv_impl
UNIT_TEST_ONLY
)
add_fp_unittest(
coshf_test
SUITE

View File

@ -31,12 +31,22 @@ class FmodTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
DECLARE_SPECIAL_CONSTANTS(T)
static constexpr T one = T(1.0);
static constexpr T two = T(2.0);
static constexpr T neg_two = T(-2.0);
static constexpr T three = T(3.0);
static constexpr T val_neg_1_1 = T(-1.1);
static constexpr T val_6_5 = T(6.5);
static constexpr T val_neg_6_5 = T(-6.5);
static constexpr T val_2_25 = T(2.25);
static constexpr T val_neg_2_25 = T(-2.25);
public:
typedef T (*FModFunc)(T, T);
void testSpecialNumbers(FModFunc f) {
// fmod (+0, y) == +0 for y != 0.
TEST_SPECIAL(zero, T(3.0), zero, false, 0);
TEST_SPECIAL(zero, three, zero, false, 0);
TEST_SPECIAL(zero, min_denormal, zero, false, 0);
TEST_SPECIAL(zero, -min_denormal, zero, false, 0);
TEST_SPECIAL(zero, min_normal, zero, false, 0);
@ -45,7 +55,7 @@ public:
TEST_SPECIAL(zero, -max_normal, zero, false, 0);
// fmod (-0, y) == -0 for y != 0.
TEST_SPECIAL(neg_zero, T(3.0), neg_zero, false, 0);
TEST_SPECIAL(neg_zero, three, neg_zero, false, 0);
TEST_SPECIAL(neg_zero, min_denormal, neg_zero, false, 0);
TEST_SPECIAL(neg_zero, -min_denormal, neg_zero, false, 0);
TEST_SPECIAL(neg_zero, min_normal, neg_zero, false, 0);
@ -54,8 +64,8 @@ public:
TEST_SPECIAL(neg_zero, -max_normal, neg_zero, false, 0);
// fmod (+inf, y) == aNaN plus invalid exception.
TEST_SPECIAL(inf, T(3.0), aNaN, true, FE_INVALID);
TEST_SPECIAL(inf, T(-1.1), aNaN, true, FE_INVALID);
TEST_SPECIAL(inf, three, aNaN, true, FE_INVALID);
TEST_SPECIAL(inf, val_neg_1_1, aNaN, true, FE_INVALID);
TEST_SPECIAL(inf, zero, aNaN, true, FE_INVALID);
TEST_SPECIAL(inf, neg_zero, aNaN, true, FE_INVALID);
TEST_SPECIAL(inf, min_denormal, aNaN, true, FE_INVALID);
@ -65,8 +75,8 @@ public:
TEST_SPECIAL(inf, neg_inf, aNaN, true, FE_INVALID);
// fmod (-inf, y) == aNaN plus invalid exception.
TEST_SPECIAL(neg_inf, T(3.0), aNaN, true, FE_INVALID);
TEST_SPECIAL(neg_inf, T(-1.1), aNaN, true, FE_INVALID);
TEST_SPECIAL(neg_inf, three, aNaN, true, FE_INVALID);
TEST_SPECIAL(neg_inf, val_neg_1_1, aNaN, true, FE_INVALID);
TEST_SPECIAL(neg_inf, zero, aNaN, true, FE_INVALID);
TEST_SPECIAL(neg_inf, neg_zero, aNaN, true, FE_INVALID);
TEST_SPECIAL(neg_inf, min_denormal, aNaN, true, FE_INVALID);
@ -76,8 +86,8 @@ public:
TEST_SPECIAL(neg_inf, neg_inf, aNaN, true, FE_INVALID);
// fmod (x, +0) == aNaN plus invalid exception.
TEST_SPECIAL(T(3.0), zero, aNaN, true, FE_INVALID);
TEST_SPECIAL(T(-1.1), zero, aNaN, true, FE_INVALID);
TEST_SPECIAL(three, zero, aNaN, true, FE_INVALID);
TEST_SPECIAL(val_neg_1_1, zero, aNaN, true, FE_INVALID);
TEST_SPECIAL(zero, zero, aNaN, true, FE_INVALID);
TEST_SPECIAL(neg_zero, zero, aNaN, true, FE_INVALID);
TEST_SPECIAL(min_denormal, zero, aNaN, true, FE_INVALID);
@ -85,8 +95,8 @@ public:
TEST_SPECIAL(max_normal, zero, aNaN, true, FE_INVALID);
// fmod (x, -0) == aNaN plus invalid exception.
TEST_SPECIAL(T(3.0), neg_zero, aNaN, true, FE_INVALID);
TEST_SPECIAL(T(-1.1), neg_zero, aNaN, true, FE_INVALID);
TEST_SPECIAL(three, neg_zero, aNaN, true, FE_INVALID);
TEST_SPECIAL(val_neg_1_1, neg_zero, aNaN, true, FE_INVALID);
TEST_SPECIAL(zero, neg_zero, aNaN, true, FE_INVALID);
TEST_SPECIAL(neg_zero, neg_zero, aNaN, true, FE_INVALID);
TEST_SPECIAL(min_denormal, neg_zero, aNaN, true, FE_INVALID);
@ -99,21 +109,21 @@ public:
TEST_SPECIAL(min_denormal, inf, min_denormal, false, 0);
TEST_SPECIAL(min_normal, inf, min_normal, false, 0);
TEST_SPECIAL(max_normal, inf, max_normal, false, 0);
TEST_SPECIAL(T(3.0), inf, T(3.0), false, 0);
TEST_SPECIAL(three, inf, three, false, 0);
// fmod (x, -inf) == x for x not infinite.
TEST_SPECIAL(zero, neg_inf, zero, false, 0);
TEST_SPECIAL(neg_zero, neg_inf, neg_zero, false, 0);
TEST_SPECIAL(min_denormal, neg_inf, min_denormal, false, 0);
TEST_SPECIAL(min_normal, neg_inf, min_normal, false, 0);
TEST_SPECIAL(max_normal, neg_inf, max_normal, false, 0);
TEST_SPECIAL(T(3.0), neg_inf, T(3.0), false, 0);
TEST_SPECIAL(three, neg_inf, three, false, 0);
TEST_SPECIAL(zero, aNaN, aNaN, false, 0);
TEST_SPECIAL(zero, neg_aNaN, aNaN, false, 0);
TEST_SPECIAL(neg_zero, aNaN, aNaN, false, 0);
TEST_SPECIAL(neg_zero, neg_aNaN, aNaN, false, 0);
TEST_SPECIAL(T(1.0), aNaN, aNaN, false, 0);
TEST_SPECIAL(T(1.0), neg_aNaN, aNaN, false, 0);
TEST_SPECIAL(one, aNaN, aNaN, false, 0);
TEST_SPECIAL(one, neg_aNaN, aNaN, false, 0);
TEST_SPECIAL(inf, aNaN, aNaN, false, 0);
TEST_SPECIAL(inf, neg_aNaN, aNaN, false, 0);
TEST_SPECIAL(neg_inf, aNaN, aNaN, false, 0);
@ -122,8 +132,8 @@ public:
TEST_SPECIAL(zero, neg_sNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(neg_zero, sNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(neg_zero, neg_sNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(T(1.0), sNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(T(1.0), neg_sNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(one, sNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(one, neg_sNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(inf, sNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(inf, neg_sNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(neg_inf, sNaN, aNaN, false, FE_INVALID);
@ -132,8 +142,8 @@ public:
TEST_SPECIAL(neg_aNaN, zero, aNaN, false, 0);
TEST_SPECIAL(aNaN, neg_zero, aNaN, false, 0);
TEST_SPECIAL(neg_aNaN, neg_zero, aNaN, false, 0);
TEST_SPECIAL(aNaN, T(1.0), aNaN, false, 0);
TEST_SPECIAL(neg_aNaN, T(1.0), aNaN, false, 0);
TEST_SPECIAL(aNaN, one, aNaN, false, 0);
TEST_SPECIAL(neg_aNaN, one, aNaN, false, 0);
TEST_SPECIAL(aNaN, inf, aNaN, false, 0);
TEST_SPECIAL(neg_aNaN, inf, aNaN, false, 0);
TEST_SPECIAL(aNaN, neg_inf, aNaN, false, 0);
@ -142,8 +152,8 @@ public:
TEST_SPECIAL(neg_sNaN, zero, aNaN, false, FE_INVALID);
TEST_SPECIAL(sNaN, neg_zero, aNaN, false, FE_INVALID);
TEST_SPECIAL(neg_sNaN, neg_zero, aNaN, false, FE_INVALID);
TEST_SPECIAL(sNaN, T(1.0), aNaN, false, FE_INVALID);
TEST_SPECIAL(neg_sNaN, T(1.0), aNaN, false, FE_INVALID);
TEST_SPECIAL(sNaN, one, aNaN, false, FE_INVALID);
TEST_SPECIAL(neg_sNaN, one, aNaN, false, FE_INVALID);
TEST_SPECIAL(sNaN, inf, aNaN, false, FE_INVALID);
TEST_SPECIAL(neg_sNaN, inf, aNaN, false, FE_INVALID);
TEST_SPECIAL(sNaN, neg_inf, aNaN, false, FE_INVALID);
@ -165,10 +175,10 @@ public:
TEST_SPECIAL(neg_sNaN, sNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(neg_sNaN, neg_sNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(T(6.5), T(2.25), T(2.0), false, 0);
TEST_SPECIAL(T(-6.5), T(2.25), T(-2.0), false, 0);
TEST_SPECIAL(T(6.5), T(-2.25), T(2.0), false, 0);
TEST_SPECIAL(T(-6.5), T(-2.25), T(-2.0), false, 0);
TEST_SPECIAL(val_6_5, val_2_25, two, false, 0);
TEST_SPECIAL(val_neg_6_5, val_2_25, neg_two, false, 0);
TEST_SPECIAL(val_6_5, val_neg_2_25, two, false, 0);
TEST_SPECIAL(val_neg_6_5, val_neg_2_25, neg_two, false, 0);
TEST_SPECIAL(max_normal, max_normal, zero, false, 0);
TEST_SPECIAL(max_normal, -max_normal, zero, false, 0);

View File

@ -0,0 +1,14 @@
//===-- Unittests for fmodbf16 --------------------------------------------===//
//
// 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 "FModTest.h"
#include "src/__support/FPUtil/bfloat16.h"
#include "src/math/fmodbf16.h"
LIST_FMOD_TESTS(bfloat16, LIBC_NAMESPACE::fmodbf16)