[libc-commits] [libc] [libc][math][c23] Add fmodl and fmodf128 math functions. (PR #84600)
via libc-commits
libc-commits at lists.llvm.org
Fri Mar 8 20:23:52 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: None (lntue)
<details>
<summary>Changes</summary>
- Allow `FMod` template to have different computational types and make it work for 80-bit long double.
- Switch to use `uint64_t` as the intermediate computational types for `float`, significantly reduce the latency of `fmodf` when the exponent difference is large.
---
Patch is 29.11 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/84600.diff
23 Files Affected:
- (modified) libc/config/linux/aarch64/entrypoints.txt (+2)
- (modified) libc/config/linux/riscv/entrypoints.txt (+2)
- (modified) libc/config/linux/x86_64/entrypoints.txt (+2)
- (modified) libc/config/windows/entrypoints.txt (+1)
- (modified) libc/docs/math/index.rst (+3-1)
- (modified) libc/spec/stdc.td (+2-1)
- (modified) libc/src/__support/FPUtil/FPBits.h (+10-7)
- (modified) libc/src/__support/FPUtil/generic/FMod.h (+64-87)
- (modified) libc/src/math/CMakeLists.txt (+2)
- (added) libc/src/math/fmodf128.h (+20)
- (added) libc/src/math/fmodl.h (+18)
- (modified) libc/src/math/generic/CMakeLists.txt (+25-2)
- (modified) libc/src/math/generic/fmodf.cpp (+1-1)
- (added) libc/src/math/generic/fmodf128.cpp (+19)
- (added) libc/src/math/generic/fmodl.cpp (+19)
- (modified) libc/test/src/math/differential_testing/BinaryOpSingleOutputDiff.h (+7-7)
- (modified) libc/test/src/math/differential_testing/CMakeLists.txt (+22)
- (added) libc/test/src/math/differential_testing/fmodf128_perf.cpp (+16)
- (added) libc/test/src/math/differential_testing/fmodl_perf.cpp (+16)
- (modified) libc/test/src/math/exhaustive/fmod_generic_impl_test.cpp (+4-5)
- (modified) libc/test/src/math/smoke/CMakeLists.txt (+36)
- (added) libc/test/src/math/smoke/fmodf128_test.cpp (+13)
- (added) libc/test/src/math/smoke/fmodl_test.cpp (+13)
``````````diff
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index fa15ddd17aefee..4e29cfda7741fa 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -334,6 +334,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.fminl
libc.src.math.fmod
libc.src.math.fmodf
+ libc.src.math.fmodl
libc.src.math.frexp
libc.src.math.frexpf
libc.src.math.frexpl
@@ -425,6 +426,7 @@ if(LIBC_TYPES_HAS_FLOAT128)
libc.src.math.floorf128
libc.src.math.fmaxf128
libc.src.math.fminf128
+ libc.src.math.fmodf128
libc.src.math.frexpf128
libc.src.math.ilogbf128
libc.src.math.ldexpf128
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 924cf2f1d68b10..85fec5dacb36f1 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -342,6 +342,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.fmaxl
libc.src.math.fmod
libc.src.math.fmodf
+ libc.src.math.fmodl
libc.src.math.frexp
libc.src.math.frexpf
libc.src.math.frexpl
@@ -433,6 +434,7 @@ if(LIBC_TYPES_HAS_FLOAT128)
libc.src.math.floorf128
libc.src.math.fmaxf128
libc.src.math.fminf128
+ libc.src.math.fmodf128
libc.src.math.frexpf128
libc.src.math.ilogbf128
libc.src.math.ldexpf128
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 0880c372b37390..cae38a83ce742c 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -370,6 +370,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.fmaxl
libc.src.math.fmod
libc.src.math.fmodf
+ libc.src.math.fmodl
libc.src.math.frexp
libc.src.math.frexpf
libc.src.math.frexpl
@@ -463,6 +464,7 @@ if(LIBC_TYPES_HAS_FLOAT128)
libc.src.math.floorf128
libc.src.math.fmaxf128
libc.src.math.fminf128
+ libc.src.math.fmodf128
libc.src.math.frexpf128
libc.src.math.ilogbf128
libc.src.math.ldexpf128
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index 1c9ed7bbcfed69..d6227a427afe2b 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -155,6 +155,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.fmaxl
libc.src.math.fmod
libc.src.math.fmodf
+ libc.src.math.fmodl
libc.src.math.frexp
libc.src.math.frexpf
libc.src.math.frexpl
diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst
index 81d95d9b6cfa66..a64fe93decd72d 100644
--- a/libc/docs/math/index.rst
+++ b/libc/docs/math/index.rst
@@ -169,7 +169,9 @@ Basic Operations
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| fmodf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
-| fmodl | | | | | | | | | | | | |
+| fmodl | |check| | |check| | | |check| | |check| | | | |check| | | | | |
++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
+| fmodf128 | |check| | |check| | | |check| | | | | | | | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| frexp | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index cc845a93a3330b..d1a400aa9028d8 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -405,8 +405,9 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"fmaf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>, ArgSpec<FloatType>]>,
FunctionSpec<"fmod", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
-
FunctionSpec<"fmodf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"fmodl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"fmodf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
FunctionSpec<"frexp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntPtr>]>,
FunctionSpec<"frexpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntPtr>]>,
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 7b3882dde1b72b..b06b3f7b73959a 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -640,6 +640,7 @@ struct FPRepImpl : public FPRepSem<fp_type, RetT> {
using UP::EXP_MASK;
using UP::FRACTION_MASK;
using UP::SIG_LEN;
+ using UP::SIG_MASK;
using UP::SIGN_MASK;
LIBC_INLINE_VAR static constexpr int MAX_BIASED_EXPONENT =
(1 << UP::EXP_LEN) - 1;
@@ -729,6 +730,9 @@ struct FPRepImpl : public FPRepSem<fp_type, RetT> {
bits = UP::merge(bits, mantVal, FRACTION_MASK);
}
+ LIBC_INLINE constexpr void set_significand(StorageType sigVal) {
+ bits = UP::merge(bits, sigVal, SIG_MASK);
+ }
// Unsafe function to create a floating point representation.
// It simply packs the sign, biased exponent and mantissa values without
// checking bound nor normalization.
@@ -755,20 +759,19 @@ struct FPRepImpl : public FPRepSem<fp_type, RetT> {
// 4) "number" zero value is not processed correctly.
// 5) Number is unsigned, so the result can be only positive.
LIBC_INLINE static constexpr RetT make_value(StorageType number, int ep) {
- static_assert(fp_type != FPType::X86_Binary80,
- "This function is not tested for X86 Extended Precision");
- FPRepImpl result;
- // offset: +1 for sign, but -1 for implicit first bit
- int lz = cpp::countl_zero(number) - UP::EXP_LEN;
+ FPRepImpl result(0);
+ int lz =
+ UP::FRACTION_LEN + 1 - (UP::STORAGE_LEN - cpp::countl_zero(number));
+
number <<= lz;
ep -= lz;
if (LIBC_LIKELY(ep >= 0)) {
// Implicit number bit will be removed by mask
- result.set_mantissa(number);
+ result.set_significand(number);
result.set_biased_exponent(ep + 1);
} else {
- result.set_mantissa(number >> -ep);
+ result.set_significand(number >> -ep);
}
return RetT(result.uintval());
}
diff --git a/libc/src/__support/FPUtil/generic/FMod.h b/libc/src/__support/FPUtil/generic/FMod.h
index 2d31290bc4bc2c..2cbbc5932345c3 100644
--- a/libc/src/__support/FPUtil/generic/FMod.h
+++ b/libc/src/__support/FPUtil/generic/FMod.h
@@ -117,63 +117,9 @@ namespace generic {
// be implemented in another handler.
// Signaling NaN converted to quiet NaN with FE_INVALID exception.
// https://www.open-std.org/JTC1/SC22/WG14/www/docs/n1011.htm
-template <typename T> struct FModExceptionalInputHandler {
-
- static_assert(cpp::is_floating_point_v<T>,
- "FModCStandardWrapper instantiated with invalid type.");
-
- LIBC_INLINE static bool pre_check(T x, T y, T &out) {
- using FPB = fputil::FPBits<T>;
- const T quiet_nan = FPB::quiet_nan().get_val();
- FPB sx(x), sy(y);
- if (LIBC_LIKELY(!sy.is_zero() && !sy.is_inf_or_nan() &&
- !sx.is_inf_or_nan())) {
- return false;
- }
-
- if (sx.is_nan() || sy.is_nan()) {
- if ((sx.is_nan() && !sx.is_quiet_nan()) ||
- (sy.is_nan() && !sy.is_quiet_nan()))
- fputil::raise_except_if_required(FE_INVALID);
- out = quiet_nan;
- return true;
- }
-
- if (sx.is_inf() || sy.is_zero()) {
- fputil::raise_except_if_required(FE_INVALID);
- fputil::set_errno_if_required(EDOM);
- out = quiet_nan;
- return true;
- }
-
- if (sy.is_inf()) {
- out = x;
- return true;
- }
-
- // case where x == 0
- out = x;
- return true;
- }
-};
-
-template <typename T> struct FModFastMathWrapper {
-
- static_assert(cpp::is_floating_point_v<T>,
- "FModFastMathWrapper instantiated with invalid type.");
-
- static bool pre_check(T, T, T &) { return false; }
-};
-
-template <typename T> class FModDivisionSimpleHelper {
-private:
- using StorageType = typename FPBits<T>::StorageType;
-
-public:
- LIBC_INLINE constexpr static StorageType execute(int exp_diff,
- int sides_zeroes_count,
- StorageType m_x,
- StorageType m_y) {
+template <typename T> struct FModDivisionSimpleHelper {
+ LIBC_INLINE constexpr static T execute(int exp_diff, int sides_zeroes_count,
+ T m_x, T m_y) {
while (exp_diff > sides_zeroes_count) {
exp_diff -= sides_zeroes_count;
m_x <<= sides_zeroes_count;
@@ -185,28 +131,21 @@ template <typename T> class FModDivisionSimpleHelper {
}
};
-template <typename T> class FModDivisionInvMultHelper {
-private:
- using FPB = FPBits<T>;
- using StorageType = typename FPB::StorageType;
-
-public:
- LIBC_INLINE constexpr static StorageType execute(int exp_diff,
- int sides_zeroes_count,
- StorageType m_x,
- StorageType m_y) {
+template <typename T> struct FModDivisionInvMultHelper {
+ LIBC_INLINE constexpr static T execute(int exp_diff, int sides_zeroes_count,
+ T m_x, T m_y) {
+ constexpr int LENGTH = sizeof(T) * CHAR_BIT;
if (exp_diff > sides_zeroes_count) {
- StorageType inv_hy = (cpp::numeric_limits<StorageType>::max() / m_y);
+ T inv_hy = (cpp::numeric_limits<T>::max() / m_y);
while (exp_diff > sides_zeroes_count) {
exp_diff -= sides_zeroes_count;
- StorageType hd =
- (m_x * inv_hy) >> (FPB::TOTAL_LEN - sides_zeroes_count);
+ T hd = (m_x * inv_hy) >> (LENGTH - sides_zeroes_count);
m_x <<= sides_zeroes_count;
m_x -= hd * m_y;
while (LIBC_UNLIKELY(m_x > m_y))
m_x -= m_y;
}
- StorageType hd = (m_x * inv_hy) >> (FPB::TOTAL_LEN - exp_diff);
+ T hd = (m_x * inv_hy) >> (LENGTH - exp_diff);
m_x <<= exp_diff;
m_x -= hd * m_y;
while (LIBC_UNLIKELY(m_x > m_y))
@@ -219,22 +158,57 @@ template <typename T> class FModDivisionInvMultHelper {
}
};
-template <typename T, class Wrapper = FModExceptionalInputHandler<T>,
- class DivisionHelper = FModDivisionSimpleHelper<T>>
+template <typename T, typename U = typename FPBits<T>::StorageType,
+ typename DivisionHelper = FModDivisionSimpleHelper<U>>
class FMod {
- static_assert(cpp::is_floating_point_v<T>,
+ static_assert(cpp::is_floating_point_v<T> && cpp::is_unsigned_v<U> &&
+ (sizeof(U) * CHAR_BIT > FPBits<T>::FRACTION_LEN),
"FMod instantiated with invalid type.");
private:
using FPB = FPBits<T>;
using StorageType = typename FPB::StorageType;
+ LIBC_INLINE static bool pre_check(T x, T y, T &out) {
+ using FPB = fputil::FPBits<T>;
+ const T quiet_nan = FPB::quiet_nan().get_val();
+ FPB sx(x), sy(y);
+ if (LIBC_LIKELY(!sy.is_zero() && !sy.is_inf_or_nan() &&
+ !sx.is_inf_or_nan())) {
+ return false;
+ }
+
+ if (sx.is_nan() || sy.is_nan()) {
+ if ((sx.is_nan() && !sx.is_quiet_nan()) ||
+ (sy.is_nan() && !sy.is_quiet_nan()))
+ fputil::raise_except_if_required(FE_INVALID);
+ out = quiet_nan;
+ return true;
+ }
+
+ if (sx.is_inf() || sy.is_zero()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ fputil::set_errno_if_required(EDOM);
+ out = quiet_nan;
+ return true;
+ }
+
+ if (sy.is_inf()) {
+ out = x;
+ return true;
+ }
+
+ // case where x == 0
+ out = x;
+ return true;
+ }
+
LIBC_INLINE static constexpr FPB eval_internal(FPB sx, FPB sy) {
if (LIBC_LIKELY(sx.uintval() <= sy.uintval())) {
if (sx.uintval() < sy.uintval())
return sx; // |x|<|y| return x
- return FPB(FPB::zero()); // |x|=|y| return 0.0
+ return FPB::zero(); // |x|=|y| return 0.0
}
int e_x = sx.get_biased_exponent();
@@ -247,11 +221,11 @@ class FMod {
StorageType m_y = sy.get_explicit_mantissa();
StorageType d = (e_x == e_y) ? (m_x - m_y) : (m_x << (e_x - e_y)) % m_y;
if (d == 0)
- return FPB(FPB::zero());
+ return FPB::zero();
// iy - 1 because of "zero power" for number with power 1
return FPB::make_value(d, e_y - 1);
}
- /* Both subnormal special case. */
+ // Both subnormal special case.
if (LIBC_UNLIKELY(e_x == 0 && e_y == 0)) {
FPB d;
d.set_mantissa(sx.uintval() % sy.uintval());
@@ -259,15 +233,17 @@ class FMod {
}
// Note that hx is not subnormal by conditions above.
- StorageType m_x = sx.get_explicit_mantissa();
+ U m_x = static_cast<U>(sx.get_explicit_mantissa());
e_x--;
- StorageType m_y = sy.get_explicit_mantissa();
- int lead_zeros_m_y = FPB::EXP_LEN;
+ U m_y = static_cast<U>(sy.get_explicit_mantissa());
+ constexpr int DEFAULT_LEAD_ZEROS =
+ sizeof(U) * CHAR_BIT - FPB::FRACTION_LEN - 1;
+ int lead_zeros_m_y = DEFAULT_LEAD_ZEROS;
if (LIBC_LIKELY(e_y > 0)) {
e_y--;
} else {
- m_y = sy.get_mantissa();
+ m_y = static_cast<U>(sy.get_mantissa());
lead_zeros_m_y = cpp::countl_zero(m_y);
}
@@ -286,26 +262,27 @@ class FMod {
{
// Shift hx left until the end or n = 0
- int left_shift = exp_diff < int(FPB::EXP_LEN) ? exp_diff : FPB::EXP_LEN;
+ int left_shift =
+ exp_diff < DEFAULT_LEAD_ZEROS ? exp_diff : DEFAULT_LEAD_ZEROS;
m_x <<= left_shift;
exp_diff -= left_shift;
}
m_x %= m_y;
if (LIBC_UNLIKELY(m_x == 0))
- return FPB(FPB::zero());
+ return FPB::zero();
if (exp_diff == 0)
- return FPB::make_value(m_x, e_y);
+ return FPB::make_value(static_cast<StorageType>(m_x), e_y);
- /* hx next can't be 0, because hx < hy, hy % 2 == 1 hx * 2^i % hy != 0 */
+ // hx next can't be 0, because hx < hy, hy % 2 == 1 hx * 2^i % hy != 0
m_x = DivisionHelper::execute(exp_diff, sides_zeroes_count, m_x, m_y);
- return FPB::make_value(m_x, e_y);
+ return FPB::make_value(static_cast<StorageType>(m_x), e_y);
}
public:
LIBC_INLINE static T eval(T x, T y) {
- if (T out; Wrapper::pre_check(x, y, out))
+ if (T out; LIBC_UNLIKELY(pre_check(x, y, out)))
return out;
FPB sx(x), sy(y);
Sign sign = sx.sign();
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 035eefd82d3653..8caa6027e67929 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -119,6 +119,8 @@ add_math_entrypoint_object(fminf128)
add_math_entrypoint_object(fmod)
add_math_entrypoint_object(fmodf)
+add_math_entrypoint_object(fmodl)
+add_math_entrypoint_object(fmodf128)
add_math_entrypoint_object(frexp)
add_math_entrypoint_object(frexpf)
diff --git a/libc/src/math/fmodf128.h b/libc/src/math/fmodf128.h
new file mode 100644
index 00000000000000..b3242705f025ee
--- /dev/null
+++ b/libc/src/math/fmodf128.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for fmodf128 ----------------------*- 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_FMODF128_H
+#define LLVM_LIBC_SRC_MATH_FMODF128_H
+
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE {
+
+float128 fmodf128(float128 x, float128 y);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_FMODF128_H
diff --git a/libc/src/math/fmodl.h b/libc/src/math/fmodl.h
new file mode 100644
index 00000000000000..f259ddb238a8e4
--- /dev/null
+++ b/libc/src/math/fmodl.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for fmodl -------------------------*- 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_FMODL_H
+#define LLVM_LIBC_SRC_MATH_FMODL_H
+
+namespace LIBC_NAMESPACE {
+
+long double fmodl(long double x, long double y);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_FMODL_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index a7b7065980b1f1..b405204782d552 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -1846,7 +1846,6 @@ add_entrypoint_object(
HDRS
../fmod.h
DEPENDS
- libc.include.math
libc.src.__support.FPUtil.generic.fmod
COMPILE_OPTIONS
-O3
@@ -1859,7 +1858,31 @@ add_entrypoint_object(
HDRS
../fmodf.h
DEPENDS
- libc.include.math
+ libc.src.__support.FPUtil.generic.fmod
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ fmodl
+ SRCS
+ fmodl.cpp
+ HDRS
+ ../fmodl.h
+ DEPENDS
+ libc.src.__support.FPUtil.generic.fmod
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ fmodf128
+ SRCS
+ fmodf128.cpp
+ HDRS
+ ../fmodf128.h
+ DEPENDS
+ libc.src.__support.macros.properties.types
libc.src.__support.FPUtil.generic.fmod
COMPILE_OPTIONS
-O3
diff --git a/libc/src/math/generic/fmodf.cpp b/libc/src/math/generic/fmodf.cpp
index 7a29ff1f18d319..9a9e46e29b4662 100644
--- a/libc/src/math/generic/fmodf.cpp
+++ b/libc/src/math/generic/fmodf.cpp
@@ -13,7 +13,7 @@
namespace LIBC_NAMESPACE {
LLVM_LIBC_FUNCTION(float, fmodf, (float x, float y)) {
- return fputil::generic::FMod<float>::eval(x, y);
+ return fputil::generic::FMod<float, uint64_t>::eval(x, y);
}
} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/fmodf128.cpp b/libc/src/math/generic/fmodf128.cpp
new file mode 100644
index 00000000000000..08a379702d889b
--- /dev/null
+++ b/libc/src/math/generic/fmodf128.cpp
@@ -0,0 +1,19 @@
+//===-- Single-precision fmodf128 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/fmodf128.h"
+#include "src/__support/FPUtil/generic/FMod.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float128, fmodf128, (float128 x, float128 y)) {
+ return fputil::generic::FMod<float128>::eval(x, y);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/fmodl.cpp b/libc/src/math/generic/fmodl.cpp
new file mode 100644
index 00000000000000..23a37028905573
--- /dev/null
+++ b/libc/src/math/generic/fmodl.cpp
@@ -0,0 +1,19 @@
+//===-- Single-precision fmodl 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
+//
+//===----------------------------------------------------------------------===...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/84600
More information about the libc-commits
mailing list