[libc][math] Add cbrtbf16 math function (#180327)

Add a bfloat16 implementation of cbrt along with corresponding smoke
tests and an MPFR-based exhaustive unit test.

Fixes #179729
This commit is contained in:
sohail 2026-03-10 22:29:26 +05:30 committed by GitHub
parent b0d9d4d240
commit cd7e200e42
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 200 additions and 1 deletions

View File

@ -355,6 +355,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizel
libc.src.math.cbrt
libc.src.math.cbrtf
libc.src.math.cbrtbf16
libc.src.math.ceil
libc.src.math.ceilf
libc.src.math.ceill

View File

@ -361,6 +361,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizel
libc.src.math.cbrt
libc.src.math.cbrtf
libc.src.math.cbrtbf16
libc.src.math.ceil
libc.src.math.ceilf
libc.src.math.ceill

View File

@ -356,6 +356,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizel
libc.src.math.cbrt
libc.src.math.cbrtf
libc.src.math.cbrtbf16
libc.src.math.ceil
libc.src.math.ceilf
libc.src.math.ceill

View File

@ -171,6 +171,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizel
libc.src.math.cbrt
libc.src.math.cbrtf
libc.src.math.cbrtbf16
libc.src.math.ceil
libc.src.math.ceilf
libc.src.math.ceill

View File

@ -277,6 +277,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.llrintbf16
libc.src.math.llroundbf16
libc.src.math.log_bf16
libc.src.math.cbrtbf16
libc.src.math.logbbf16
libc.src.math.lrintbf16
libc.src.math.lroundbf16

View File

@ -299,6 +299,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizel
libc.src.math.cbrt
libc.src.math.cbrtf
libc.src.math.cbrtbf16
libc.src.math.ceil
libc.src.math.ceilf
libc.src.math.ceill

View File

@ -299,6 +299,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizel
libc.src.math.cbrt
libc.src.math.cbrtf
libc.src.math.cbrtbf16
libc.src.math.ceil
libc.src.math.ceilf
libc.src.math.ceill

View File

@ -441,6 +441,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizel
libc.src.math.cbrt
libc.src.math.cbrtf
libc.src.math.cbrtbf16
libc.src.math.ceil
libc.src.math.ceilf
libc.src.math.ceill

View File

@ -268,6 +268,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.atanhf
libc.src.math.cbrt
libc.src.math.cbrtf
libc.src.math.cbrtbf16
libc.src.math.ceil
libc.src.math.ceilf
libc.src.math.ceill

View File

@ -445,6 +445,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizel
libc.src.math.cbrt
libc.src.math.cbrtf
libc.src.math.cbrtbf16
libc.src.math.ceil
libc.src.math.ceilf
libc.src.math.ceill

View File

@ -490,6 +490,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizel
libc.src.math.cbrt
libc.src.math.cbrtf
libc.src.math.cbrtbf16
libc.src.math.ceil
libc.src.math.ceilf
libc.src.math.ceill

View File

@ -147,6 +147,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.atanhf
libc.src.math.cbrt
libc.src.math.cbrtf
libc.src.math.cbrtbf16
libc.src.math.copysign
libc.src.math.copysignf
libc.src.math.copysignl

View File

@ -281,7 +281,7 @@ Higher Math Functions
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| atanpi | | | | |check| | | | 7.12.4.10 | F.10.1.10 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| cbrt | |check| | |check| | | | | | 7.12.7.1 | F.10.4.1 |
| cbrt | |check| | |check| | | | | |check| | 7.12.7.1 | F.10.4.1 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| compoundn | | | | | | | 7.12.7.2 | F.10.4.2 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+

View File

@ -93,6 +93,7 @@ add_math_entrypoint_object(iscanonicalbf16)
add_math_entrypoint_object(cbrt)
add_math_entrypoint_object(cbrtf)
add_math_entrypoint_object(cbrtbf16)
add_math_entrypoint_object(ceil)
add_math_entrypoint_object(ceilf)

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

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

View File

@ -4937,6 +4937,20 @@ add_entrypoint_object(
libc.src.__support.math.cbrt
)
add_entrypoint_object (
cbrtbf16
SRCS
cbrtbf16.cpp
HDRS
../cbrtbf16.h
DEPENDS
libc.src.__support.common
libc.src.__support.FPUtil.bfloat16
libc.src.math.generic.cbrt
libc.src.__support.macros.config
libc.src.__support.macros.properties.types
)
add_entrypoint_object(
dmull
SRCS

View File

@ -0,0 +1,18 @@
//===-- Implementation of cbrtbf16 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/cbrtbf16.h"
#include "src/__support/FPUtil/bfloat16.h"
#include "src/__support/macros/config.h"
#include "src/__support/math/cbrtf.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(bfloat16, cbrtbf16, (bfloat16 x)) {
return static_cast<bfloat16>(math::cbrtf(static_cast<float>(x)));
}
} // namespace LIBC_NAMESPACE_DECL

View File

@ -3011,6 +3011,18 @@ add_fp_unittest(
libc.src.__support.FPUtil.fp_bits
)
add_fp_unittest(
cbrtbf16_test
NEED_MPFR
SUITE
libc-math-unittests
SRCS
cbrtbf16_test.cpp
DEPENDS
libc.src.math.cbrtbf16
libc.src.__support.FPUtil.bfloat16
)
add_fp_unittest(
dmull_test
NEED_MPFR

View File

@ -0,0 +1,35 @@
//===-- Exhaustive test for cbrtbf16 --------------------------------------===//
//
// 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/__support/FPUtil/bfloat16.h"
#include "src/math/cbrtbf16.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include "utils/MPFRWrapper/MPFRUtils.h"
using LlvmLibcCbrtbf16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
// for the exhaustive test, we test with every 16-bit combination
// and skip NaN cases. v is uint32_t to prevent integer overflow and
// wraparound to 0.
TEST_F(LlvmLibcCbrtbf16Test, Exhaustive) {
for (uint32_t v = 0x00000; v < 0x10000; ++v) {
bfloat16 x =
LIBC_NAMESPACE::fputil::FPBits<bfloat16>(static_cast<uint16_t>(v))
.get_val();
LIBC_NAMESPACE::fputil::FPBits<bfloat16> bits(x); // NaN checking
if (bits.is_nan())
continue;
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Cbrt, x,
LIBC_NAMESPACE::cbrtbf16(x), 0.5);
}
}

View File

@ -6018,6 +6018,17 @@ add_fp_unittest(
libc.src.math.cbrt
)
add_fp_unittest(
cbrtbf16_test
SUITE
libc-math-smoke-tests
SRCS
cbrtbf16_test.cpp
DEPENDS
libc.src.math.cbrtbf16
libc.src.__support.FPUtil.bfloat16
)
add_fp_unittest(
dmull_test
SUITE

View File

@ -0,0 +1,75 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// Unittests for cbrtbf16
#include "src/__support/FPUtil/bfloat16.h"
#include "src/math/cbrtbf16.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
using LlvmLibcCbrtbf16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
using LIBC_NAMESPACE::testing::tlog;
TEST_F(LlvmLibcCbrtbf16Test, SpecialNumbers) {
EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::cbrtbf16(sNaN), FE_INVALID);
EXPECT_MATH_ERRNO(0);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::cbrtbf16(aNaN));
EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::cbrtbf16(inf));
EXPECT_FP_EQ_ALL_ROUNDING(neg_inf, LIBC_NAMESPACE::cbrtbf16(neg_inf));
EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::cbrtbf16(zero));
EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, LIBC_NAMESPACE::cbrtbf16(neg_zero));
EXPECT_FP_EQ_ALL_ROUNDING(bfloat16(1.0f),
LIBC_NAMESPACE::cbrtbf16(bfloat16(1.0f)));
EXPECT_FP_EQ_ALL_ROUNDING(bfloat16(-1.0f),
LIBC_NAMESPACE::cbrtbf16(bfloat16(-1.0f)));
EXPECT_FP_EQ_ALL_ROUNDING(bfloat16(2.0f),
LIBC_NAMESPACE::cbrtbf16(bfloat16(8.0f)));
EXPECT_FP_EQ_ALL_ROUNDING(bfloat16(-2.0f),
LIBC_NAMESPACE::cbrtbf16(bfloat16(-8.0f)));
EXPECT_FP_EQ_ALL_ROUNDING(bfloat16(3.0f),
LIBC_NAMESPACE::cbrtbf16(bfloat16(27.0f)));
EXPECT_FP_EQ_ALL_ROUNDING(bfloat16(-3.0f),
LIBC_NAMESPACE::cbrtbf16(bfloat16(-27.0f)));
EXPECT_FP_EQ_ALL_ROUNDING(bfloat16(5.0f),
LIBC_NAMESPACE::cbrtbf16(bfloat16(125.0f)));
EXPECT_FP_EQ_ALL_ROUNDING(bfloat16(-5.0f),
LIBC_NAMESPACE::cbrtbf16(bfloat16(-125.0f)));
EXPECT_FP_EQ_ALL_ROUNDING(bfloat16(0x1.0p42f),
LIBC_NAMESPACE::cbrtbf16(bfloat16(0x1.0p126f)));
EXPECT_FP_EQ_ALL_ROUNDING(bfloat16(-0x1.0p42f),
LIBC_NAMESPACE::cbrtbf16(bfloat16(-0x1.0p126f)));
}
#ifdef LIBC_TEST_FTZ_DAZ
using namespace LIBC_NAMESPACE::testing;
// the float version includes explicit FTZ-mode checks for subnormal
// outputs using hex expectations. for bfloat16, this is unnecessary.
// if x=2^e then cbrt(x)=2^(e/3). to produce a subnormal result, we would
// need e/3 < -126, i.e e<-378. Since the smallest representable exponent
// in bfloat16 is -133, no finite bfloat16 input can produce a subnormal
// cube root. therefore, explicit subnormal output checks are omitted here.
TEST_F(LlvmLibcCbrtbf16Test, DAZMode) {
ModifyMXCSR mxcsr(DAZ);
EXPECT_FP_EQ(bfloat16(0.0f), LIBC_NAMESPACE::cbrtbf16(min_denormal));
EXPECT_FP_EQ(bfloat16(0.0f), LIBC_NAMESPACE::cbrtbf16(max_denormal));
}
TEST_F(LlvmLibcCbrtbf16Test, FTZDAZMode) {
ModifyMXCSR mxcsr(FTZ | DAZ);
EXPECT_FP_EQ(bfloat16(0.0f), LIBC_NAMESPACE::cbrtbf16(min_denormal));
EXPECT_FP_EQ(bfloat16(0.0f), LIBC_NAMESPACE::cbrtbf16(max_denormal));
}
#endif