diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index ca0418c3618ae..6151bee7c9f14 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -499,6 +499,7 @@ set(TARGET_LIBM_ENTRYPOINTS if(LIBC_TYPES_HAS_FLOAT16) list(APPEND TARGET_LIBM_ENTRYPOINTS # math.h C23 _Float16 entrypoints + libc.src.math.ceilf16 libc.src.math.fabsf16 ) endif() diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 699bb9dcdf3c9..f0c2b34b9fba3 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -531,6 +531,7 @@ set(TARGET_LIBM_ENTRYPOINTS if(LIBC_TYPES_HAS_FLOAT16) list(APPEND TARGET_LIBM_ENTRYPOINTS # math.h C23 _Float16 entrypoints + libc.src.math.ceilf16 libc.src.math.fabsf16 ) endif() diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index ff700255144e6..306d005d396ee 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -390,6 +390,7 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"ceil", RetValSpec, [ArgSpec]>, FunctionSpec<"ceilf", RetValSpec, [ArgSpec]>, FunctionSpec<"ceill", RetValSpec, [ArgSpec]>, + GuardedFunctionSpec<"ceilf16", RetValSpec, [ArgSpec], "LIBC_TYPES_HAS_FLOAT16">, GuardedFunctionSpec<"ceilf128", RetValSpec, [ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, FunctionSpec<"fabs", RetValSpec, [ArgSpec], [ConstAttr]>, diff --git a/libc/src/__support/FPUtil/NearestIntegerOperations.h b/libc/src/__support/FPUtil/NearestIntegerOperations.h index 4645ab0b5350b..93bf69c440239 100644 --- a/libc/src/__support/FPUtil/NearestIntegerOperations.h +++ b/libc/src/__support/FPUtil/NearestIntegerOperations.h @@ -49,6 +49,7 @@ LIBC_INLINE T trunc(T x) { template , int> = 0> LIBC_INLINE T ceil(T x) { + using StorageType = typename FPBits::StorageType; FPBits bits(x); // If x is infinity NaN or zero, return it. @@ -71,7 +72,9 @@ LIBC_INLINE T ceil(T x) { } uint32_t trim_size = FPBits::FRACTION_LEN - exponent; - bits.set_mantissa((bits.get_mantissa() >> trim_size) << trim_size); + StorageType trunc_mantissa = + static_cast((bits.get_mantissa() >> trim_size) << trim_size); + bits.set_mantissa(trunc_mantissa); T trunc_value = bits.get_val(); // If x is already an integer, return it. diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt index 31df5d0ab8809..77fa2edc141d2 100644 --- a/libc/src/math/CMakeLists.txt +++ b/libc/src/math/CMakeLists.txt @@ -67,6 +67,7 @@ add_math_entrypoint_object(canonicalizel) add_math_entrypoint_object(ceil) add_math_entrypoint_object(ceilf) add_math_entrypoint_object(ceill) +add_math_entrypoint_object(ceilf16) add_math_entrypoint_object(ceilf128) add_math_entrypoint_object(copysign) diff --git a/libc/src/math/ceilf16.h b/libc/src/math/ceilf16.h new file mode 100644 index 0000000000000..8263710cd183d --- /dev/null +++ b/libc/src/math/ceilf16.h @@ -0,0 +1,20 @@ +//===-- ceilf16 -------------------------------------------------*- 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_CEILF16_H +#define LLVM_LIBC_SRC_MATH_CEILF16_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float16 ceilf16(float16 x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_CEILF16_H diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index 04656e3186181..1a91e5a7b0e21 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -82,6 +82,19 @@ add_entrypoint_object( libc.src.__support.FPUtil.nearest_integer_operations ) +add_entrypoint_object( + ceilf16 + SRCS + ceilf16.cpp + HDRS + ../ceilf16.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.nearest_integer_operations +) + add_entrypoint_object( ceilf128 SRCS diff --git a/libc/src/math/generic/ceilf16.cpp b/libc/src/math/generic/ceilf16.cpp new file mode 100644 index 0000000000000..634fe3015f6ce --- /dev/null +++ b/libc/src/math/generic/ceilf16.cpp @@ -0,0 +1,17 @@ +//===-- ceilf16 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/ceilf16.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float16, ceilf16, (float16 x)) { return fputil::ceil(x); } + +} // namespace LIBC_NAMESPACE diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt index b46fe5e902c67..3c960c703c587 100644 --- a/libc/test/src/math/smoke/CMakeLists.txt +++ b/libc/test/src/math/smoke/CMakeLists.txt @@ -268,6 +268,18 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + ceilf16_test + SUITE + libc-math-smoke-tests + SRCS + ceilf16_test.cpp + HDRS + CeilTest.h + DEPENDS + libc.src.math.ceilf16 +) + add_fp_unittest( ceilf128_test SUITE diff --git a/libc/test/src/math/smoke/CeilTest.h b/libc/test/src/math/smoke/CeilTest.h index 5e108c0e0feea..7998eab62ec6b 100644 --- a/libc/test/src/math/smoke/CeilTest.h +++ b/libc/test/src/math/smoke/CeilTest.h @@ -59,10 +59,10 @@ class CeilTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { EXPECT_FP_EQ(T(-10.0), func(T(-10.32))); EXPECT_FP_EQ(T(11.0), func(T(10.65))); EXPECT_FP_EQ(T(-10.0), func(T(-10.65))); - EXPECT_FP_EQ(T(1235.0), func(T(1234.38))); - EXPECT_FP_EQ(T(-1234.0), func(T(-1234.38))); - EXPECT_FP_EQ(T(1235.0), func(T(1234.96))); - EXPECT_FP_EQ(T(-1234.0), func(T(-1234.96))); + EXPECT_FP_EQ(T(124.0), func(T(123.38))); + EXPECT_FP_EQ(T(-123.0), func(T(-123.38))); + EXPECT_FP_EQ(T(124.0), func(T(123.96))); + EXPECT_FP_EQ(T(-123.0), func(T(-123.96))); } }; diff --git a/libc/test/src/math/smoke/ceilf16_test.cpp b/libc/test/src/math/smoke/ceilf16_test.cpp new file mode 100644 index 0000000000000..a6ec922836a75 --- /dev/null +++ b/libc/test/src/math/smoke/ceilf16_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for ceilf16 ---------------------------------------------===// +// +// 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 "CeilTest.h" + +#include "src/math/ceilf16.h" + +LIST_CEIL_TESTS(float16, LIBC_NAMESPACE::ceilf16)