Skip to content

[libc][math][c23] Add fmodl and fmodf128 math functions. #84600

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 11, 2024
Merged

Conversation

lntue
Copy link
Contributor

@lntue lntue commented Mar 9, 2024

  • 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.

@llvmbot
Copy link
Member

llvmbot commented Mar 9, 2024

@llvm/pr-subscribers-libc

Author: None (lntue)

Changes
  • 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 --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]

@lntue lntue merged commit 4d21e75 into llvm:main Mar 11, 2024
@lntue lntue deleted the fmod branch March 11, 2024 20:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants