Skip to content

[libc][math] Add missing math.yaml entries for acospif and atan2f16#199442

Open
iamaayushrivastava wants to merge 1 commit into
llvm:mainfrom
iamaayushrivastava:libc-math-yaml-missing-functions
Open

[libc][math] Add missing math.yaml entries for acospif and atan2f16#199442
iamaayushrivastava wants to merge 1 commit into
llvm:mainfrom
iamaayushrivastava:libc-math-yaml-missing-functions

Conversation

@iamaayushrivastava
Copy link
Copy Markdown
Contributor

@iamaayushrivastava iamaayushrivastava commented May 24, 2026

Fixes #199266

This PR adds missing math.yaml entries for acospif and atan2f16.

@iamaayushrivastava iamaayushrivastava requested a review from a team as a code owner May 24, 2026 19:40
@llvmorg-github-actions
Copy link
Copy Markdown

@llvm/pr-subscribers-libc

Author: Aayush Shrivastava (iamaayushrivastava)

Changes

Add missing double-precision hyperbolic math functions to LLVM libc.


Patch is 56.17 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/199442.diff

30 Files Affected:

  • (modified) libc/config/linux/x86_64/entrypoints.txt (+6)
  • (modified) libc/include/math.yaml (+51-1)
  • (modified) libc/src/__support/math/CMakeLists.txt (+79)
  • (added) libc/src/__support/math/acosh.h (+70)
  • (added) libc/src/__support/math/asinh.h (+79)
  • (added) libc/src/__support/math/atanh.h (+71)
  • (added) libc/src/__support/math/cosh.h (+72)
  • (added) libc/src/__support/math/sinh.h (+88)
  • (added) libc/src/__support/math/tanh.h (+70)
  • (modified) libc/src/math/generic/CMakeLists.txt (+60)
  • (added) libc/src/math/generic/acosh.cpp (+16)
  • (added) libc/src/math/generic/asinh.cpp (+16)
  • (added) libc/src/math/generic/atanh.cpp (+16)
  • (added) libc/src/math/generic/cosh.cpp (+16)
  • (added) libc/src/math/generic/sinh.cpp (+16)
  • (added) libc/src/math/generic/tanh.cpp (+16)
  • (modified) libc/test/src/math/CMakeLists.txt (+76)
  • (added) libc/test/src/math/acosh_test.cpp (+52)
  • (added) libc/test/src/math/asinh_test.cpp (+41)
  • (added) libc/test/src/math/atanh_test.cpp (+57)
  • (added) libc/test/src/math/cosh_test.cpp (+55)
  • (added) libc/test/src/math/sinh_test.cpp (+55)
  • (modified) libc/test/src/math/smoke/CMakeLists.txt (+70)
  • (added) libc/test/src/math/smoke/acosh_test.cpp (+61)
  • (added) libc/test/src/math/smoke/asinh_test.cpp (+52)
  • (added) libc/test/src/math/smoke/atanh_test.cpp (+65)
  • (added) libc/test/src/math/smoke/cosh_test.cpp (+72)
  • (added) libc/test/src/math/smoke/sinh_test.cpp (+69)
  • (added) libc/test/src/math/smoke/tanh_test.cpp (+52)
  • (added) libc/test/src/math/tanh_test.cpp (+40)
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 5545790fecd85..16d733fdde948 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -534,10 +534,12 @@ set(TARGET_LIBM_ENTRYPOINTS
     # math.h entrypoints
     libc.src.math.acos
     libc.src.math.acosf
+    libc.src.math.acosh
     libc.src.math.acoshf
     libc.src.math.acospif
     libc.src.math.asin
     libc.src.math.asinf
+    libc.src.math.asinh
     libc.src.math.asinhf
     libc.src.math.asinpi
     libc.src.math.asinpif
@@ -545,6 +547,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.atan2f
     libc.src.math.atan
     libc.src.math.atanf
+    libc.src.math.atanh
     libc.src.math.atanhf
     libc.src.math.canonicalize
     libc.src.math.canonicalizef
@@ -560,6 +563,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.copysignl
     libc.src.math.cos
     libc.src.math.cosf
+    libc.src.math.cosh
     libc.src.math.coshf
     libc.src.math.cospif
     libc.src.math.dfmal
@@ -746,6 +750,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.sincos
     libc.src.math.sincosf
     libc.src.math.sinf
+    libc.src.math.sinh
     libc.src.math.sinhf
     libc.src.math.sinpif
     libc.src.math.sqrt
@@ -753,6 +758,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.sqrtl
     libc.src.math.tan
     libc.src.math.tanf
+    libc.src.math.tanh
     libc.src.math.tanhf
     libc.src.math.tanpif
     libc.src.math.totalorder
diff --git a/libc/include/math.yaml b/libc/include/math.yaml
index e50be8f05cc65..a0c05a7cbf7fb 100644
--- a/libc/include/math.yaml
+++ b/libc/include/math.yaml
@@ -27,6 +27,12 @@ functions:
     arguments:
       - type: _Float16
     guard: LIBC_TYPES_HAS_FLOAT16
+  - name: acosh
+    standards:
+      - stdc
+    return_type: double
+    arguments:
+      - type: double
   - name: acoshf
     standards:
       - stdc
@@ -40,6 +46,12 @@ functions:
     arguments:
       - type: _Float16
     guard: LIBC_TYPES_HAS_FLOAT16
+  - name: acospif
+    standards:
+      - stdc
+    return_type: float
+    arguments:
+      - type: float
   - name: acospif16
     standards:
       - stdc
@@ -66,6 +78,12 @@ functions:
     arguments:
       - type: _Float16
     guard: LIBC_TYPES_HAS_FLOAT16
+  - name: asinh
+    standards:
+      - stdc
+    return_type: double
+    arguments:
+      - type: double
   - name: asinhf
     standards:
       - stdc
@@ -133,6 +151,14 @@ functions:
       - type: float128
       - type: float128
     guard: LIBC_TYPES_HAS_FLOAT128
+  - name: atan2f16
+    standards:
+      - stdc
+    return_type: _Float16
+    arguments:
+      - type: _Float16
+      - type: _Float16
+    guard: LIBC_TYPES_HAS_FLOAT16
   - name: atanf
     standards:
       - stdc
@@ -146,6 +172,12 @@ functions:
     arguments:
       - type: _Float16
     guard: LIBC_TYPES_HAS_FLOAT16
+  - name: atanh
+    standards:
+      - stdc
+    return_type: double
+    arguments:
+      - type: double
   - name: atanhf
     standards:
       - stdc
@@ -153,7 +185,7 @@ functions:
     arguments:
       - type: float
   - name: atanhf16
-    standatds:
+    standards:
       - stdc
     return_type: _Float16
     arguments:
@@ -303,6 +335,12 @@ functions:
     arguments:
       - type: _Float16
     guard: LIBC_TYPES_HAS_FLOAT16
+  - name: cosh
+    standards:
+      - stdc
+    return_type: double
+    arguments:
+      - type: double
   - name: coshf
     standards:
       - stdc
@@ -2593,6 +2631,12 @@ functions:
       - type: float
       - type: float *
       - type: float *
+  - name: sinh
+    standards:
+      - stdc
+    return_type: double
+    arguments:
+      - type: double
   - name: sinhf
     standards:
       - stdc
@@ -2670,6 +2714,12 @@ functions:
     arguments:
       - type: _Float16
     guard: LIBC_TYPES_HAS_FLOAT16
+  - name: tanh
+    standards:
+      - stdc
+    return_type: double
+    arguments:
+      - type: double
   - name: tanhf
     standards:
       - stdc
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 9e3ec26cdc881..ba940e2f61e98 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -67,6 +67,19 @@ add_header_library(
     libc.src.__support.macros.optimization
 )
 
+add_header_library(
+  acosh
+  HDRS
+    acosh.h
+  DEPENDS
+    .log
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.sqrt
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+)
+
 add_header_library(
   acoshf
   HDRS
@@ -157,6 +170,20 @@ add_header_library(
     libc.src.__support.macros.properties.cpu_features
 )
 
+add_header_library(
+  asinh
+  HDRS
+    asinh.h
+  DEPENDS
+    .log
+    .log1p
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.sqrt
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+)
+
 add_header_library(
   asinhf
   HDRS
@@ -354,6 +381,18 @@ add_header_library(
     libc.src.__support.macros.optimization
 )
 
+add_header_library(
+  atanh
+  HDRS
+    atanh.h
+  DEPENDS
+    .log1p
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+)
+
 add_header_library(
   atanhf
   HDRS
@@ -2797,6 +2836,20 @@ add_header_library(
     libc.src.__support.macros.properties.types
 )
 
+add_header_library(
+  cosh
+  HDRS
+    cosh.h
+  DEPENDS
+    .exp
+    .expm1
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.rounding_mode
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+)
+
 add_header_library(
   coshf
   HDRS
@@ -5221,6 +5274,20 @@ add_header_library(
     libc.src.__support.macros.properties.types
 )
 
+add_header_library(
+  sinh
+  HDRS
+    sinh.h
+  DEPENDS
+    .exp
+    .expm1
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.rounding_mode
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+)
+
 add_header_library(
   sinhf
   HDRS
@@ -5371,6 +5438,18 @@ add_header_library(
     libc.include.llvm-libc-macros.float16_macros
 )
 
+add_header_library(
+  tanh
+  HDRS
+    tanh.h
+  DEPENDS
+    .expm1
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+)
+
 add_header_library(
   tanhf
   HDRS
diff --git a/libc/src/__support/math/acosh.h b/libc/src/__support/math/acosh.h
new file mode 100644
index 0000000000000..c25fed33f8791
--- /dev/null
+++ b/libc/src/__support/math/acosh.h
@@ -0,0 +1,70 @@
+//===-- Implementation header for acosh -------------------------*- 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___SUPPORT_MATH_ACOSH_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ACOSH_H
+
+#include "log.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/sqrt.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE double acosh(double x) {
+  using FPBits = fputil::FPBits<double>;
+  FPBits xbits(x);
+
+  // acosh is only defined for x >= 1.
+  if (LIBC_UNLIKELY(x < 1.0)) {
+    if (x == x) {
+      // x < 1 and x is not NaN: domain error.
+      fputil::set_errno_if_required(EDOM);
+      fputil::raise_except_if_required(FE_INVALID);
+    } else {
+      // x is NaN.
+      if (xbits.is_signaling_nan()) {
+        fputil::raise_except_if_required(FE_INVALID);
+        return FPBits::quiet_nan().get_val();
+      }
+      return x;
+    }
+    return FPBits::quiet_nan().get_val();
+  }
+
+  // acosh(1) = 0.
+  if (x == 1.0)
+    return 0.0;
+
+  // acosh(+inf) = +inf.
+  if (LIBC_UNLIKELY(xbits.is_inf()))
+    return x;
+
+  uint64_t x_u = xbits.uintval();
+
+  // For large x (x >= 2^28), acosh(x) ~ log(2x) = log(x) + log(2).
+  if (LIBC_UNLIKELY(x_u >= 0x41b0000000000000ULL)) {
+    // log(2x) = log(x) + log(2).
+    constexpr double LOG_2 = 0x1.62e42fefa39efp-1;
+    return math::log(x) + LOG_2;
+  }
+
+  // General case: acosh(x) = log(x + sqrt(x^2 - 1)).
+  double x2m1 = x * x - 1.0;
+  return math::log(x + fputil::sqrt<double>(x2m1));
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ACOSH_H
diff --git a/libc/src/__support/math/asinh.h b/libc/src/__support/math/asinh.h
new file mode 100644
index 0000000000000..73d920ed4874c
--- /dev/null
+++ b/libc/src/__support/math/asinh.h
@@ -0,0 +1,79 @@
+//===-- Implementation header for asinh -------------------------*- 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___SUPPORT_MATH_ASINH_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ASINH_H
+
+#include "log.h"
+#include "log1p.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/sqrt.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE double asinh(double x) {
+  using FPBits = fputil::FPBits<double>;
+  FPBits xbits(x);
+
+  // Handle NaN.
+  if (LIBC_UNLIKELY(xbits.is_nan())) {
+    if (xbits.is_signaling_nan()) {
+      fputil::raise_except_if_required(FE_INVALID);
+      return FPBits::quiet_nan().get_val();
+    }
+    return x;
+  }
+
+  // Handle +/-inf: asinh(+/-inf) = +/-inf.
+  if (LIBC_UNLIKELY(xbits.is_inf()))
+    return x;
+
+  uint64_t x_abs_u = xbits.abs().uintval();
+  double x_abs = xbits.abs().get_val();
+  bool is_neg = xbits.is_neg();
+
+  // For very small |x| (|x| <= 2^-26), asinh(x) ~ x.
+  // Use FP arithmetic to ensure FTZ/DAZ mode behavior.
+  if (LIBC_UNLIKELY(x_abs_u <= 0x3e50000000000000ULL)) {
+    // asinh(+/-0) = +/-0, preserve sign of zero exactly.
+    if (LIBC_UNLIKELY(x_abs_u == 0))
+      return x;
+    double x2 = x_abs * x_abs;
+    double result = x_abs - x2 * x_abs * (1.0 / 6.0);
+    return is_neg ? -result : result;
+  }
+
+  double result;
+  // For large |x| (|x| >= 2^28), asinh(x) ~ log(2|x|) = log(|x|) + log(2).
+  if (LIBC_UNLIKELY(x_abs_u >= 0x41b0000000000000ULL)) {
+    constexpr double LOG_2 = 0x1.62e42fefa39efp-1;
+    result = math::log(x_abs) + LOG_2;
+  } else if (x_abs_u >= 0x3fe0000000000000ULL) {
+    // |x| >= 0.5: asinh(x) = log(x + sqrt(x^2 + 1)).
+    result = math::log(x_abs + fputil::sqrt<double>(x_abs * x_abs + 1.0));
+  } else {
+    // |x| < 0.5: use log1p for better accuracy near 0.
+    // asinh(x) = log1p(x + x^2 / (1 + sqrt(1 + x^2)))
+    double x2 = x_abs * x_abs;
+    double sqrt1px2 = fputil::sqrt<double>(1.0 + x2);
+    result = math::log1p(x_abs + x2 / (1.0 + sqrt1px2));
+  }
+
+  return is_neg ? -result : result;
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ASINH_H
diff --git a/libc/src/__support/math/atanh.h b/libc/src/__support/math/atanh.h
new file mode 100644
index 0000000000000..cf85fe721505c
--- /dev/null
+++ b/libc/src/__support/math/atanh.h
@@ -0,0 +1,71 @@
+//===-- Implementation header for atanh -------------------------*- 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___SUPPORT_MATH_ATANH_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ATANH_H
+
+#include "log1p.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE double atanh(double x) {
+  using FPBits = fputil::FPBits<double>;
+  FPBits xbits(x);
+  Sign sign = xbits.sign();
+  uint64_t x_abs_u = xbits.abs().uintval();
+
+  // Handle NaN.
+  if (LIBC_UNLIKELY(xbits.is_nan())) {
+    if (xbits.is_signaling_nan()) {
+      fputil::raise_except_if_required(FE_INVALID);
+      return FPBits::quiet_nan().get_val();
+    }
+    return x;
+  }
+
+  // |x| >= 1.
+  if (LIBC_UNLIKELY(x_abs_u >= 0x3ff0000000000000ULL)) {
+    if (x_abs_u == 0x3ff0000000000000ULL) {
+      // |x| == 1: return +/-inf with ERANGE.
+      fputil::set_errno_if_required(ERANGE);
+      fputil::raise_except_if_required(FE_DIVBYZERO);
+      return FPBits::inf(sign).get_val();
+    }
+    // |x| > 1: domain error.
+    fputil::set_errno_if_required(EDOM);
+    fputil::raise_except_if_required(FE_INVALID);
+    return FPBits::quiet_nan().get_val();
+  }
+
+  // For very small |x| (|x| <= 2^-27), atanh(x) ~ x.
+  // Use FP arithmetic to ensure FTZ/DAZ mode behavior.
+  if (LIBC_UNLIKELY(x_abs_u <= 0x3e40000000000000ULL)) {
+    double x_abs = xbits.abs().get_val();
+    double x2 = x_abs * x_abs;
+    double result = x_abs + x2 * x_abs * (1.0 / 3.0);
+    return sign == Sign::NEG ? -result : result;
+  }
+
+  // General case: atanh(x) = 0.5 * log((1+x)/(1-x))
+  //                        = 0.5 * log1p(2x / (1-x))
+  double x_abs = xbits.abs().get_val();
+  double result = 0.5 * math::log1p(2.0 * x_abs / (1.0 - x_abs));
+  return sign == Sign::NEG ? -result : result;
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ATANH_H
diff --git a/libc/src/__support/math/cosh.h b/libc/src/__support/math/cosh.h
new file mode 100644
index 0000000000000..8c65e642b98c1
--- /dev/null
+++ b/libc/src/__support/math/cosh.h
@@ -0,0 +1,72 @@
+//===-- Implementation header for cosh --------------------------*- 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___SUPPORT_MATH_COSH_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_COSH_H
+
+#include "exp.h"
+#include "expm1.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/rounding_mode.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE double cosh(double x) {
+  using FPBits = fputil::FPBits<double>;
+  FPBits xbits(x);
+  // cosh is even, work with |x|.
+  xbits.set_sign(Sign::POS);
+  x = xbits.get_val();
+
+  uint64_t x_u = xbits.uintval();
+
+  // Handle NaN: cosh(NaN) = NaN.
+  if (LIBC_UNLIKELY(xbits.is_nan())) {
+    if (xbits.is_signaling_nan()) {
+      fputil::raise_except_if_required(FE_INVALID);
+      return FPBits::quiet_nan().get_val();
+    }
+    return x;
+  }
+
+  // cosh(+inf) = +inf.
+  if (LIBC_UNLIKELY(xbits.is_inf()))
+    return x + FPBits::inf().get_val();
+
+  // For very small |x| (|x| <= 2^-27), cosh(x) ~ 1.
+  if (LIBC_UNLIKELY(x_u <= 0x3e40000000000000ULL))
+    return 1.0 + x;
+
+  // For |x| >= 710, overflow.
+  // log(DBL_MAX) ~ 709.78, so exp overflows for x > ~709.78.
+  if (LIBC_UNLIKELY(x_u >= 0x4086340000000000ULL)) {
+    int rounding = fputil::quick_get_round();
+    if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
+      return FPBits::max_normal().get_val();
+    fputil::set_errno_if_required(ERANGE);
+    fputil::raise_except_if_required(FE_OVERFLOW);
+    return x + FPBits::inf().get_val();
+  }
+
+  // cosh(x) = (exp(x) + exp(-x)) / 2.
+  // Use expm1 for small x to avoid cancellation:
+  // cosh(x) = 1 + expm1(x)^2 / (2 * (1 + expm1(x))) ... but for simplicity:
+  double ex = math::exp(x);
+  return (ex + 1.0 / ex) * 0.5;
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_COSH_H
diff --git a/libc/src/__support/math/sinh.h b/libc/src/__support/math/sinh.h
new file mode 100644
index 0000000000000..bbc7af2a5cacd
--- /dev/null
+++ b/libc/src/__support/math/sinh.h
@@ -0,0 +1,88 @@
+//===-- Implementation header for sinh --------------------------*- 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___SUPPORT_MATH_SINH_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_SINH_H
+
+#include "exp.h"
+#include "expm1.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/rounding_mode.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE double sinh(double x) {
+  using FPBits = fputil::FPBits<double>;
+  FPBits xbits(x);
+  bool is_neg = xbits.is_neg();
+  // Work with |x|.
+  xbits.set_sign(Sign::POS);
+  double x_abs = xbits.get_val();
+  uint64_t x_abs_u = xbits.uintval();
+
+  // Handle NaN: sinh(NaN) = NaN.
+  if (LIBC_UNLIKELY(xbits.is_nan())) {
+    if (xbits.is_signaling_nan()) {
+      fputil::raise_except_if_required(FE_INVALID);
+      return FPBits::quiet_nan().get_val();
+    }
+    return x;
+  }
+
+  // sinh(+/-inf) = +/-inf.
+  if (LIBC_UNLIKELY(xbits.is_inf()))
+    return x;
+
+  // For very small |x| (|x| <= 2^-26), sinh(x) ~ x.
+  // Use FP arithmetic to ensure FTZ/DAZ mode behavior.
+  if (LIBC_UNLIKELY(x_abs_u <= 0x3e50000000000000ULL)) {
+    double x2 = x_abs * x_abs;
+    double result = x_abs + x2 * x_abs * (1.0 / 6.0);
+    return is_neg ? -result : result;
+  }
+
+  // For |x| >= 710, overflow.
+  if (LIBC_UNLIKELY(x_abs_u >= 0x4086340000000000ULL)) {
+    int rounding = fputil::quick_get_round();
+    if ((rounding == FE_DOWNWARD && !is_neg) ||
+        (rounding == FE_UPWARD && is_neg) || rounding == FE_TOWARDZERO)
+      return is_neg ? -FPBits::max_normal().get_val()
+                    : FPBits::max_normal().get_val();
+    fputil::set_errno_if_required(ERANGE);
+    fputil::raise_except_if_required(FE_OVERFLOW);
+    return x + (is_neg ? -FPBits::inf().get_val() : FPBits::inf().get_val());
+  }
+
+  double result;
+  // For small |x| (|x| < 1), use expm1 to avoid cancellation:
+  // sinh(x) = expm1(x) - expm1(x)^2 / (2*(1+expm1(x)))
+  //         = expm1(x) * (1 + expm1(x)) / (2*(1+expm1(x))) ... keep it simple:
+  // sinh(x) = (exp(x) - exp(-x)) / 2
+  if (x_abs_u < 0x3ff0000000000000ULL) {
+    // |x| < 1: use expm1 for accuracy.
+    double em1 = math::expm1(x_abs);
+    result = em1 / 2.0 + em1 / (2.0 * (1.0 + em1));
+  } else {
+    // |x| >= 1.
+    double ex = math::exp(x_abs);
+    result = (ex - 1.0 / ex) * 0.5;
+  }
+
+  return is_neg ? -result : result;
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_SINH_H
diff --git a/libc/src/__support/math/tanh.h b/libc/src/__support/math/tanh.h
new file mode 100644
index 0000000000000..7e0b47dac463f
--- /dev/null
+++ b/libc/src/__support/math/tanh.h
@@ -0,0 +1,70 @@
+//===-- Implementation header for tanh --------------------------*- 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
+//
+//===------------------...
[truncated]

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 24, 2026

✅ With the latest revision this PR passed the C/C++ code formatter.

@Sukumarsawant
Copy link
Copy Markdown
Contributor

Sukumarsawant commented May 24, 2026

@iamaayushrivastava some functions haven't been implemented yet, so we would have to hold that for now . Apologies for including them. Please make the PR for adding

  • acospif
  • atan2f16
    Also if you wish to implement those functions (hyperbolic), make a separate PR so it's easier for reviewing and do check if someone's working on them already.

@iamaayushrivastava iamaayushrivastava force-pushed the libc-math-yaml-missing-functions branch from 953f9f5 to c8168d2 Compare May 24, 2026 20:31
Comment thread libc/include/math.yaml
arguments:
- type: float
- name: atanhf16
standards:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a nit

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Thanks!

@iamaayushrivastava
Copy link
Copy Markdown
Contributor Author

@iamaayushrivastava some functions haven't been implemented yet, so we would have to hold that for now . Apologies for including them. Please make the PR for adding

  • acospif
  • atan2f16
    Also if you wish to implement those functions (hyperbolic), make a separate PR so it's easier for reviewing and do check if someone's working on them already.

Thank you @Sukumarsawant for the clarification! I have updated the PR to only include the math.yaml entries for acospif and atan2f16. All the hyperbolic function changes have been removed.

Please let me know if anything else needs to be changed. Thanks!

@Sukumarsawant
Copy link
Copy Markdown
Contributor

Do change the title and description accordingly.

@iamaayushrivastava iamaayushrivastava changed the title [libc][math] Add double-precision acosh, asinh, atanh, cosh, sinh, tanh [libc][math] Add missing math.yaml entries for acospif and atan2f16 May 24, 2026
@iamaayushrivastava
Copy link
Copy Markdown
Contributor Author

Do change the title and description accordingly.

Done. Thank you for pointing that out!

@Sukumarsawant
Copy link
Copy Markdown
Contributor

LGTM.
Also if you want to implement other functions you can do them in a separate PR
just make sure to adhere to LLVM AI Tool Use Policy.

@iamaayushrivastava
Copy link
Copy Markdown
Contributor Author

LGTM. Also if you want to implement other functions you can do them in a separate PR just make sure to adhere to LLVM AI Tool Use Policy.

Sure, thank you.

Should I go ahead and create a separate PR for the double-precision hyperbolic functions (acosh, asinh, atanh, cosh, sinh, tanh)?

@Sukumarsawant
Copy link
Copy Markdown
Contributor

Sukumarsawant commented May 24, 2026

LGTM. Also if you want to implement other functions you can do them in a separate PR just make sure to adhere to LLVM AI Tool Use Policy.

Sure, thank you.

Should I go ahead and create a separate PR for the double-precision hyperbolic functions (acosh, asinh, atanh, cosh, sinh, tanh)?

Yeah, you can ! Just make sure no one's working on them. Keeping in mind the AI disclosure, you could make a PR one at a time and get it reviewed so you can improve in the later ones (just my opinion) and you can refer the already merged PRs for reference.
Good luck!

@iamaayushrivastava
Copy link
Copy Markdown
Contributor Author

LGTM. Also if you want to implement other functions you can do them in a separate PR just make sure to adhere to LLVM AI Tool Use Policy.

Sure, thank you.
Should I go ahead and create a separate PR for the double-precision hyperbolic functions (acosh, asinh, atanh, cosh, sinh, tanh)?

Yeah, you can ! Just make sure no one's working on them. Keeping in mind the AI disclosure, you could make a PR one at a time and get it reviewed so you can improve in the later ones (just my opinion) and you can refer the already merged PRs for reference. Good luck!

Thank you for your valuable feedback. I’ve been referring to the merged PRs as well, they’re super helpful for understanding the expected style and workflow.

Really appreciate the advice and encouragement!

@Sukumarsawant
Copy link
Copy Markdown
Contributor

@iamaayushrivastava
Copy link
Copy Markdown
Contributor Author

Do refer this while implementing https://libc.llvm.org/headers/math/index.html#implementation-requirements-goals

Sure, I’ll keep this in mind while working on it.

@iamaayushrivastava
Copy link
Copy Markdown
Contributor Author

Thanks @Sukumarsawant for the review and suggestions. Could you please let me know if anything else is needed before merging?

Copy link
Copy Markdown
Contributor

@Sukumarsawant Sukumarsawant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, wait for someone to approve/merge

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.

[libc][math] Add Missing math functions to math.yaml

2 participants