[libc-commits] [libc] [llvm] [libc][math] Implement single-precision erfcf (PR #190061)
via libc-commits
libc-commits at lists.llvm.org
Wed Sep 23 04:48:30 PDT 2026
https://github.com/AnonMiraj updated https://github.com/llvm/llvm-project/pull/190061
>From 968587bc1dc2f82e1cb9fe0000ef1278b58c9d27 Mon Sep 17 00:00:00 2001
From: Anonmiraj <ezzibrahimx at gmail.com>
Date: Wed, 1 Apr 2026 22:33:44 +0200
Subject: [PATCH 1/8] [libc][math] Implement single precision erfcf function
---
libc/config/gpu/amdgpu/entrypoints.txt | 1 +
libc/config/gpu/nvptx/entrypoints.txt | 1 +
libc/config/linux/aarch64/entrypoints.txt | 1 +
libc/config/linux/riscv/entrypoints.txt | 1 +
libc/config/linux/x86_64/entrypoints.txt | 1 +
libc/include/math.yaml | 6 +
libc/shared/math.h | 1 +
libc/shared/math/erfcf.h | 23 ++
libc/src/__support/math/CMakeLists.txt | 16 +
libc/src/__support/math/erfcf.h | 301 ++++++++++++++++++
libc/src/math/CMakeLists.txt | 1 +
libc/src/math/erfcf.h | 20 ++
libc/src/math/generic/CMakeLists.txt | 11 +
libc/src/math/generic/erfcf.cpp | 17 +
libc/test/shared/CMakeLists.txt | 1 +
libc/test/shared/shared_math_test.cpp | 1 +
libc/test/src/math/CMakeLists.txt | 12 +
libc/test/src/math/erfcf_test.cpp | 110 +++++++
libc/test/src/math/exhaustive/CMakeLists.txt | 16 +
libc/test/src/math/exhaustive/erfcf_test.cpp | 33 ++
libc/test/src/math/smoke/CMakeLists.txt | 11 +
libc/test/src/math/smoke/erfcf_test.cpp | 54 ++++
.../llvm-project-overlay/libc/BUILD.bazel | 23 ++
23 files changed, 662 insertions(+)
create mode 100644 libc/shared/math/erfcf.h
create mode 100644 libc/src/__support/math/erfcf.h
create mode 100644 libc/src/math/erfcf.h
create mode 100644 libc/src/math/generic/erfcf.cpp
create mode 100644 libc/test/src/math/erfcf_test.cpp
create mode 100644 libc/test/src/math/exhaustive/erfcf_test.cpp
create mode 100644 libc/test/src/math/smoke/erfcf_test.cpp
diff --git a/libc/config/gpu/amdgpu/entrypoints.txt b/libc/config/gpu/amdgpu/entrypoints.txt
index 5c5e5891da8227..a612f85d488af8 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -337,6 +337,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.dfmal
libc.src.math.dmull
libc.src.math.dsqrtl
+ libc.src.math.erfcf
libc.src.math.erff
libc.src.math.exp
libc.src.math.exp10
diff --git a/libc/config/gpu/nvptx/entrypoints.txt b/libc/config/gpu/nvptx/entrypoints.txt
index afae725484a891..e8982da587b5cc 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -333,6 +333,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.dfmal
libc.src.math.dmull
libc.src.math.dsqrtl
+ libc.src.math.erfcf
libc.src.math.erff
libc.src.math.exp
libc.src.math.exp10
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 03053ac04f743d..e66209db63c32d 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -577,6 +577,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.dmull
libc.src.math.dsqrtl
libc.src.math.dsubl
+ libc.src.math.erfcf
libc.src.math.erff
libc.src.math.exp
libc.src.math.exp10
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 5db369a9d871db..742cd9dd6475b4 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -642,6 +642,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.dmull
libc.src.math.dsqrtl
libc.src.math.dsubl
+ libc.src.math.erfcf
libc.src.math.erff
libc.src.math.exp
libc.src.math.exp10
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 3cbbb7b3e9f794..703c88d34c2c2e 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -651,6 +651,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.dmull
libc.src.math.dsqrtl
libc.src.math.dsubl
+ libc.src.math.erfcf
libc.src.math.erff
libc.src.math.exp
libc.src.math.exp10
diff --git a/libc/include/math.yaml b/libc/include/math.yaml
index 006233e579f86c..3465a1f4f5cd45 100644
--- a/libc/include/math.yaml
+++ b/libc/include/math.yaml
@@ -439,6 +439,12 @@ functions:
arguments:
- type: long double
- type: long double
+ - name: erfcf
+ standards:
+ - stdc
+ return_type: float
+ arguments:
+ - type: float
- name: erff
standards:
- stdc
diff --git a/libc/shared/math.h b/libc/shared/math.h
index 7b52cedf99c245..7a5bc0f635a87f 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -100,6 +100,7 @@
#include "math/dsqrtl.h"
#include "math/dsubf128.h"
#include "math/dsubl.h"
+#include "math/erfcf.h"
#include "math/erfcf16.h"
#include "math/erff.h"
#include "math/erff16.h"
diff --git a/libc/shared/math/erfcf.h b/libc/shared/math/erfcf.h
new file mode 100644
index 00000000000000..15b9c8277af42f
--- /dev/null
+++ b/libc/shared/math/erfcf.h
@@ -0,0 +1,23 @@
+//===-- Shared erfcf function -----------------------------------*- 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_SHARED_MATH_ERFCF_H
+#define LLVM_LIBC_SHARED_MATH_ERFCF_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/erfcf.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::erfcf;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_ERFCF_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index cf9bc11fce8242..194a03ea0b0132 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -3025,6 +3025,22 @@ add_header_library(
libc.src.__support.macros.properties.cpu_features
)
+add_header_library(
+ erfcf
+ HDRS
+ erfcf.h
+ DEPENDS
+ libc.src.__support.FPUtil.cast
+ libc.src.__support.FPUtil.except_value_utils
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.macros.attributes
+ libc.src.__support.macros.config
+ libc.src.__support.macros.optimization
+ libc.src.__support.math.exp
+)
+
add_header_library(
erfcf16
HDRS
diff --git a/libc/src/__support/math/erfcf.h b/libc/src/__support/math/erfcf.h
new file mode 100644
index 00000000000000..f166da9d3ded83
--- /dev/null
+++ b/libc/src/__support/math/erfcf.h
@@ -0,0 +1,301 @@
+//===-- Implementation header for erfcf -------------------------*- 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_ERFCF_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ERFCF_H
+
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/except_value_utils.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+#include "src/__support/math/exp.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE float erfcf(float x) {
+ // Polynomials approximating erfc(|x|) on ( k/8, (k+1)/8 ) generated by
+ // Sollya with: > P = fpminimax(erfc(x), 10, [|D...|], [k/8, (k+1)/8]);
+ // for k = 0..31.
+ constexpr double COEFFS[32][11] = {
+ {0x1p0, -0x1.20dd750429b6dp0, 0x1.7112720c8ba45p-48, 0x1.812746b031144p-2,
+ 0x1.222514285ab0dp-33, -0x1.ce2f2335e679fp-4, 0x1.4b61403cf653ep-23,
+ 0x1.b82263f5c7f38p-6, 0x1.ac9c9b798c1efp-16, -0x1.60d7a2758fd51p-8,
+ 0x1.26e595feee3cdp-11},
+ {0x1.b82879728f11ep-1, -0x1.1c62fa1e86a2p0, 0x1.1c62fa1eaa08dp-3,
+ 0x1.6f552db750199p-2, -0x1.196c992766a4ep-4, -0x1.aabac2bf59268p-4,
+ 0x1.73676ae99c457p-6, 0x1.88239613f7488p-6, -0x1.557641bb56776p-8,
+ -0x1.86cd9135cc86dp-8, 0x1.d2dfe9a011161p-9},
+ {0x1.728558ee694fcp-1, -0x1.0f5d1602f7e93p0, 0x1.0f5d160305a8p-2,
+ 0x1.3c97445490146p-2, -0x1.040e88feae5b7p-3, -0x1.47e61aa7d843fp-4,
+ 0x1.4c14b33c12167p-5, 0x1.0813624bf8053p-6, -0x1.33dc8eb36a748p-7,
+ -0x1.e3508ce7c1243p-9, 0x1.d73a7a0da8387p-9},
+ {0x1.311796a46f064p-1, -0x1.f5f0cdaf153e4p-1, 0x1.78749a436137fp-2,
+ 0x1.e106c5128ef88p-3, -0x1.5529aa072e883p-3, -0x1.74896ff63fd4cp-5,
+ 0x1.9a84e098f157ep-5, 0x1.620ba3a3d5d5ep-8, -0x1.650155e4f6006p-7,
+ -0x1.633c365eb4f97p-10, 0x1.f20567b3e72e5p-9},
+ {0x1.eb02147ce245cp-2, -0x1.c1efca49a5073p-1, 0x1.c1efca49ad0d4p-2,
+ 0x1.2bf531818ea5ap-3, -0x1.76f27d186f571p-3, -0x1.dff14d5720b5cp-8,
+ 0x1.99f6682bf8fd4p-5, -0x1.63daa9ab40909p-8, -0x1.445cf3f9f807ap-7,
+ 0x1.badcb770290f2p-10, 0x1.1174fb01e6698p-9},
+ {0x1.81cd2465e1d96p-2, -0x1.86e9694134b12p-1, 0x1.e8a3c391764d7p-2,
+ 0x1.c810503dd433cp-5, -0x1.6963c9d6f4fcbp-3, 0x1.c12528c8239bap-6,
+ 0x1.52aa57c68f9c8p-5, -0x1.c67c4b6a1fd9p-7, -0x1.c75138cb5d6cfp-8,
+ 0x1.2e514c579a5e5p-8, -0x1.07fe13496794dp-10},
+ {0x1.27c6d14c5e341p-2, -0x1.492e42d78d298p-1, 0x1.edc5644350061p-2,
+ -0x1.b6e8590cf34d1p-6, -0x1.349b5f0ed8b05p-3, 0x1.b42a42369930cp-5,
+ 0x1.b842069dfb4e1p-6, -0x1.2dd078b748381p-6, -0x1.3a14a6bd993e6p-9,
+ 0x1.1d0541da7a108p-8, -0x1.024d4d28887c2p-10},
+ {0x1.ba36dab91c0e9p-3, -0x1.0cab61f084b7dp-1, 0x1.d62beb64e66cdp-2,
+ -0x1.7c9d7567cde58p-4, -0x1.cc6056e010c19p-4, 0x1.1350fedc7c8d4p-4,
+ 0x1.53b5fa5002e8dp-7, -0x1.308f9a3a15148p-6, 0x1.d7d8ba40072f3p-10,
+ 0x1.c38fae1003e4ap-9, -0x1.5731dcef3635ap-10},
+ {0x1.4226162fbddd5p-3, -0x1.a911f096fbc44p-2, 0x1.a911f096fd02p-2,
+ -0x1.1b614b101514ep-3, -0x1.1b614acdf645cp-4, 0x1.1b61447098344p-4,
+ -0x1.2e3ee72cc54cfp-8, -0x1.f0b9c4004e99ep-7, 0x1.3ac97256e2bffp-8,
+ 0x1.d602e98b4b3f8p-10, -0x1.1fe3083e3949dp-10},
+ {0x1.c9296beb09cf1p-4, -0x1.45e99bcbb792dp-2, 0x1.6ea6cf452f804p-2,
+ -0x1.4cb3cf0b3d596p-3, -0x1.ca50823eddc83p-6, 0x1.f65d0aa94b23cp-5,
+ -0x1.fd196a6987475p-7, -0x1.3aed937418987p-7, 0x1.8d13b74d7478p-8,
+ 0x1.fea855dfc40abp-13, -0x1.d5b41ac1c75p-11},
+ {0x1.3bcd133aa0ffcp-4, -0x1.e4652fadcb6bap-3, 0x1.2ebf3dcc9f547p-2,
+ -0x1.571d01c5e8c08p-3, 0x1.93a9a89cbd372p-8, 0x1.8281ca9a40a1p-5,
+ -0x1.5cff78e5e2ef3p-6, -0x1.db7d47bbfd40cp-9, 0x1.76601dde9691cp-8,
+ -0x1.f67319b06ddedp-11, -0x1.1d6660796d9dfp-11},
+ {0x1.a8973c4b5c03ep-5, -0x1.5ce595c455acbp-3, 0x1.dfbbadedf34bap-3,
+ -0x1.4374d82d467fep-3, 0x1.f3b8d4383b809p-6, 0x1.f572dc4041a58p-6,
+ -0x1.6b1856b171392p-6, 0x1.74c906da034dcp-10, 0x1.164472ab539c6p-8,
+ -0x1.96e8164e48141p-10, -0x1.f23662919ef35p-13},
+ {0x1.15aaa8ec85205p-5, -0x1.e723726b824ccp-4, 0x1.6d5a95d0a2785p-3,
+ -0x1.1c2a02bef3ca7p-3, 0x1.6d5a95fbf61c9p-5, 0x1.e7235f9ad34fdp-7,
+ -0x1.3ca32f0bf75bap-6, 0x1.36b86f8f5629dp-8, 0x1.37856e26c43c5p-9,
+ -0x1.d1fb032fd3658p-10, 0x1.28ab82b6ede4p-12},
+ {0x1.612d893085125p-6, -0x1.499d478bca742p-4, 0x1.0bcfca2194c2fp-3,
+ -0x1.d6631e1a5458cp-4, 0x1.974c0377acd1bp-5, 0x1.17d416544c048p-9,
+ -0x1.d8577cd47d84bp-7, 0x1.953fd61239f87p-8, 0x1.30e61f779ae49p-11,
+ -0x1.7860aa19f2f2bp-10, 0x1.c51c72e186623p-12},
+ {0x1.b4be201caa4b4p-7, -0x1.b055303221047p-5, 0x1.7a4a8a2bdde0cp-4,
+ -0x1.7148c3d5c7dcdp-4, 0x1.8a0da55ba5b6bp-5, -0x1.b2226b1319984p-8,
+ -0x1.25b2e37b0cfccp-7, 0x1.8d05b0147e821p-8, -0x1.7cb80598faceep-11,
+ -0x1.dafe289fe6dc7p-11, 0x1.ddb02c85e22bp-12},
+ {0x1.0678442cc256fp-7, -0x1.12ceb37ff9bf6p-5, 0x1.01a1c847fb207p-4,
+ -0x1.143d1c6f98f22p-4, 0x1.5a316537f539fp-5, -0x1.779b26f6c96ap-7,
+ -0x1.0d08a4de0f7bfp-8, 0x1.42f4a3c27232cp-8, -0x1.767cfe2314aa8p-10,
+ -0x1.7b505388abf2ep-12, 0x1.77461c55da518p-12},
+ {0x1.328f5ec350e67p-8, -0x1.529b9e8cf9a5ap-6, 0x1.529b9e8cfac67p-5,
+ -0x1.8b0ae3a4c97a8p-5, 0x1.1a2c59817055ap-5, -0x1.ace74450e5a3dp-7,
+ -0x1.e18d6c7410b76p-12, 0x1.badd28800e644p-9, -0x1.a13c9922134f3p-10,
+ 0x1.fff76a75ead39p-15, 0x1.b16cf61ec2dd2p-13},
+ {0x1.5bde729a6b60fp-9, -0x1.94624e78e0f9cp-7, 0x1.ada873606e8ccp-6,
+ -0x1.0ea475da23b64p-5, 0x1.afe553effdf82p-6, -0x1.9973b1e16eba8p-7,
+ 0x1.dd772aa53255dp-10, 0x1.ea1c42db10d19p-10, -0x1.6b818e3750232p-10,
+ 0x1.43cd402d760d3p-12, 0x1.f62a9b9e2b79ap-15},
+ {0x1.7f713f9cc9784p-10, -0x1.d4143a9dfe98bp-8, 0x1.074b60f8df85ep-6,
+ -0x1.63ef61e8360c2p-6, 0x1.38a98329164bp-6, -0x1.5d3b17ac398f3p-7,
+ 0x1.7cade7b6e3c8fp-9, 0x1.5f912c77e0c9cp-11, -0x1.065a339fc525fp-10,
+ 0x1.8d01ba06413c9p-12, -0x1.9f30fd338427fp-16},
+ {0x1.9a7c305336484p-11, -0x1.06918b635560ap-8, 0x1.37ccd585f4d01p-7,
+ -0x1.c1ec102e05347p-7, 0x1.ae5961566fe56p-7, -0x1.11dae36755887p-7,
+ 0x1.982ad75641d89p-9, -0x1.0244739cd9c83p-13, -0x1.3801f7b1ef4b1p-11,
+ 0x1.67a01f83d42a7p-12, -0x1.31172079a63b8p-14},
+ {0x1.aab859b20ac9ep-12, -0x1.1d83170fbf6e2p-9, 0x1.64e3dcd3aece2p-8,
+ -0x1.119da0c45b13cp-7, 0x1.1a89b97a2fc97p-7, -0x1.90e812044d8cap-8,
+ 0x1.6ecdb1263d601p-9, -0x1.1c5f1d9c7ca86p-11, -0x1.11689ad5d48efp-12,
+ 0x1.06ad3d0e7893cp-12, -0x1.4e2c3615c4c33p-14},
+ {0x1.aeb4423e690e7p-13, -0x1.2ce8988092463p-10, 0x1.8af14828c08d6p-9,
+ -0x1.407fbd190e60ep-8, 0x1.62d4c6daf915dp-8, -0x1.146c4c13fcf6fp-8,
+ 0x1.267f5f7f4e4eap-9, -0x1.650055947628fp-11, -0x1.1e4228a58be1fp-15,
+ 0x1.39f3a7152bf5cp-13, -0x1.10ca401654daap-14},
+ {0x1.a609f7584d32cp-14, -0x1.3360ccd23db6ep-11, 0x1.a6a519a1163e9p-10,
+ -0x1.69cf466d146e5p-9, 0x1.ab0c2749ee609p-9, -0x1.693598016257dp-9,
+ 0x1.b275b08a70196p-10, -0x1.52bf5b6c25969p-11, 0x1.77f30b334c832p-14,
+ 0x1.1bec6f126d145p-14, -0x1.6dbabae75ba64p-15},
+ {0x1.916f7c5f2f764p-15, -0x1.30538fbb77ed9p-12, 0x1.b5781e9d7d3cap-11,
+ -0x1.89e17c0789d3ep-10, 0x1.ed4ac7eadf2eap-10, -0x1.c11f2966da996p-10,
+ 0x1.2add54b32a56fp-10, -0x1.152601eff3211p-11, 0x1.1d5fb50237f1fp-13,
+ 0x1.bf38de649c0e2p-17, -0x1.8eb6ab7d24271p-16},
+ {0x1.729df6503422ap-16, -0x1.2408e9ba3329cp-13, 0x1.b60d5e974e1eap-12,
+ -0x1.9db74b1d7834bp-11, 0x1.11c85b29f8906p-10, -0x1.0a7b56efdf1dbp-10,
+ 0x1.82f2829bcc4edp-11, -0x1.9994395c8ff4ep-12, 0x1.1b5192cb88934p-13,
+ -0x1.09940ee068919p-16, -0x1.2c1365d1eeeafp-17},
+ {0x1.4c144d984e1b8p-17, -0x1.0f9e1b4dd36ffp-14, 0x1.a8670aa99bd8cp-13,
+ -0x1.a3737e2a8fd11p-12, 0x1.24544f0f00592p-11, -0x1.2e7e780322a4p-11,
+ 0x1.da49c094d9cbep-12, -0x1.1771c29da6d5bp-12, 0x1.d365b26dc63d5p-14,
+ -0x1.bc9452efb4d81p-16, -0x1.5242e0d796318p-23},
+ {0x1.20c1303550f0ep-18, -0x1.e9b5e8d00cebdp-16, 0x1.8de3cd290bcfdp-14,
+ -0x1.9aa489e41acc7p-13, 0x1.2c7d5efa0a9dap-12, -0x1.490a4e85f7136p-12,
+ 0x1.145484bf5179cp-12, -0x1.6483263df6976p-13, 0x1.56bc58061dacep-14,
+ -0x1.b9b157530f4f7p-16, 0x1.02372ad94723bp-18},
+ {0x1.e749309831666p-20, -0x1.abe09e9144b66p-17, 0x1.690585ca9211bp-15,
+ -0x1.84522fe886259p-14, 0x1.298f8d468914cp-13, -0x1.5775779f5bfffp-13,
+ 0x1.330aade71b1bdp-13, -0x1.ac99f25149457p-14, 0x1.cc1e74a8fb3a7p-15,
+ -0x1.655efd3cca343p-16, 0x1.4240672f45e3ap-18},
+ {0x1.8ef2a9a18d856p-21, -0x1.6a597219a9351p-18, 0x1.3d0e43d671ac5p-16,
+ -0x1.62ccea633f2b9p-15, 0x1.1c07720a51ea6p-14, -0x1.586bad828f8a8p-14,
+ 0x1.46150d2e2e10ap-14, -0x1.e82257fc23d66p-15, 0x1.1f2f71c915ddfp-15,
+ -0x1.fde2430bd9393p-17, 0x1.1bae788edb33fp-18},
+ {0x1.3ce784b41192fp-22, -0x1.296a70f413f1p-19, 0x1.0d88765d2c61cp-17,
+ -0x1.394b1fa52107cp-16, 0x1.05760aa9f7bebp-15, -0x1.4c1fdf0066b74p-15,
+ 0x1.4b97a44c00f95p-15, -0x1.08551293d164dp-15, 0x1.508819ed4456bp-16,
+ -0x1.4b804729d60a7p-17, 0x1.a5cb84361b63bp-19},
+ {0x1.e87470e4f4241p-24, -0x1.d9371e2ff7808p-21, 0x1.bba3ac4ce4ecdp-19,
+ -0x1.0b6a7b0ce3205p-17, 0x1.d06f57d98111dp-17, -0x1.3436b32f16b84p-16,
+ 0x1.4356e15a6fef4p-16, -0x1.1101e1b521bc5p-16, 0x1.74858f952f9d1p-17,
+ -0x1.8fa532c898418p-18, 0x1.1834c46dcd2e3p-19},
+ {0x1.6d3126d74b6c5p-25, -0x1.6ce1aa3fd75f4p-22, 0x1.617a9cedbd5d7p-20,
+ -0x1.b95fa394dd25dp-19, 0x1.8e1fc35332691p-18, -0x1.137164825dc8ap-17,
+ 0x1.2eb15f12aec0cp-17, -0x1.0d7ad988a5dc6p-17, 0x1.873ebecd2a922p-18,
+ -0x1.c34d814f00735p-19, 0x1.5563fbf293d8cp-20},
+ };
+
+ using FPBits = typename fputil::FPBits<float>;
+ FPBits xbits(x);
+ uint32_t x_abs = xbits.abs().uintval();
+
+ static constexpr size_t N_ERFCF_EXCEPTS = 2;
+ static constexpr fputil::ExceptValues<float, N_ERFCF_EXCEPTS> ERFCF_EXCEPTS =
+ {{
+ // (input, RZ output, RU offset, RD offset, RN offset)
+ // x = 0.000014103805, erfc(x) = 0.9999841...
+ {0x376C9F62, 0x3f7ffef5, 1, 0, 0},
+ // x = -0.000014103805, erfc(x) = 1.0000159...
+ {0xB76C9F62, 0x3F800085, 1, 0, 0},
+ }};
+
+ if (auto r = ERFCF_EXCEPTS.lookup(xbits.uintval());
+ LIBC_UNLIKELY(r.has_value()))
+ return r.value();
+
+ // Special cases: NaN and Inf
+ if (LIBC_UNLIKELY(x_abs >= 0x7f800000U)) {
+ if (x_abs > 0x7f800000U) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+ return x;
+ }
+ // erfc(+Inf) = 0, erfc(-Inf) = 2
+ return xbits.is_neg() ? fputil::cast<float>(2.0) : fputil::cast<float>(0.0);
+ }
+
+ if (LIBC_UNLIKELY(x_abs == 0))
+ return 1.0f;
+
+ if (LIBC_UNLIKELY(x_abs < 0x33000000U)) { // |x| < 2^-25
+ constexpr double NEG_TWO_OVER_SQRT_PI = -0x1.20dd750429b6dp0;
+ double xd = fputil::cast<double>(x);
+ return fputil::cast<float>(
+ fputil::multiply_add(xd, NEG_TWO_OVER_SQRT_PI, 1.0));
+ }
+
+ // erfc(x) rounds to 0 or 2 for |x| >= 10.125.
+ if (LIBC_UNLIKELY(x_abs >= 0x41220000U)) { // |x| >= 10.125
+ if (xbits.is_neg()) {
+ if (fputil::fenv_is_round_down() || fputil::fenv_is_round_to_zero())
+ return FPBits(0x3FFFFFFFU).get_val(); // next float below 2.0
+ return 2.0f;
+ }
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
+ if (fputil::fenv_is_round_up())
+ return FPBits::min_subnormal().get_val();
+ return 0.0f;
+ }
+
+ // Polynomial approximation:
+ // erfc(x) ~ erfc(|x|) if x >= 0
+ // erfc(x) ~ 2 - erfc(|x|) if x < 0
+
+ // erfc(|x|) is evaluated using a degree-10 polynomial on each sub-interval.
+
+ int shift = 147 - (x_abs >> 23);
+ uint64_t mantissa = (x_abs & 0x007FFFFFU) | 0x00800000U;
+ int idx = static_cast<int>(mantissa >> shift);
+
+ if (idx >= 32) {
+ // For |x| >= 4.0, we use an asymptotic expansion in terms of t = 1/x^2.
+ // This accurately computes the steep decay of erfc over the domain
+ // [4.0, 10.125].
+ double xd = fputil::cast<double>(xbits.abs().get_val());
+ double xsq = xd * xd;
+
+ // Asymptotic expansion (Minimax polynomial of degree 12 in 1/x^2):
+ // Generated by Sollya over [4, 10]:
+ // P = fpminimax(erfc(1/sqrt(t)) * (1/sqrt(t)) * exp(1/t) * sqrt(pi), 12,
+ // [|D...|], [1/100, 1/16], relative);
+ static constexpr double ASYMP_COEFFS[13] = {
+ 0x1.ffffffffff7ebp-1, -0x1.fffffffde50adp-2, 0x1.7fffff052b044p-1,
+ -0x1.dfffbad06922cp0, 0x1.a3f9ab8151a5cp2, -0x1.d817a02e83042p4,
+ 0x1.426451515fe5ap7, -0x1.f9da3719338bep9, 0x1.a3bffa01808f1p12,
+ -0x1.477cd9ce158b1p15, 0x1.a0922e919de1bp17, -0x1.699343d88926ep19,
+ 0x1.35159d114ab16p20,
+ };
+ double t = 1.0 / xsq;
+ double t2 = t * t;
+ double t4 = t2 * t2;
+ double t8 = t4 * t4;
+
+ double p01 = fputil::multiply_add(t, ASYMP_COEFFS[1], ASYMP_COEFFS[0]);
+ double p23 = fputil::multiply_add(t, ASYMP_COEFFS[3], ASYMP_COEFFS[2]);
+ double p45 = fputil::multiply_add(t, ASYMP_COEFFS[5], ASYMP_COEFFS[4]);
+ double p67 = fputil::multiply_add(t, ASYMP_COEFFS[7], ASYMP_COEFFS[6]);
+ double p89 = fputil::multiply_add(t, ASYMP_COEFFS[9], ASYMP_COEFFS[8]);
+ double p10_11 = fputil::multiply_add(t, ASYMP_COEFFS[11], ASYMP_COEFFS[10]);
+
+ double p03 = fputil::multiply_add(t2, p23, p01);
+ double p47 = fputil::multiply_add(t2, p67, p45);
+ double p8_11 = fputil::multiply_add(t2, p10_11, p89);
+
+ double p07 = fputil::multiply_add(t4, p47, p03);
+ double p8_12 = fputil::multiply_add(t4, ASYMP_COEFFS[12], p8_11);
+
+ double p = fputil::multiply_add(t8, p8_12, p07);
+
+ constexpr double ONE_OVER_SQRT_PI = 0.564189583547756286948;
+ double erfc_abs = (math::exp(-xsq) * p / xd) * ONE_OVER_SQRT_PI;
+
+ double res = xbits.is_neg() ? 2.0 - erfc_abs : erfc_abs;
+ return fputil::cast<float>(res);
+ }
+
+ double xd = fputil::cast<double>(xbits.abs().get_val());
+ double dx = xd - (idx / 8.0);
+
+ double dx2 = dx * dx;
+ double dx4 = dx2 * dx2;
+
+ double p01 = fputil::multiply_add(dx, COEFFS[idx][1], COEFFS[idx][0]);
+ double p23 = fputil::multiply_add(dx, COEFFS[idx][3], COEFFS[idx][2]);
+ double p45 = fputil::multiply_add(dx, COEFFS[idx][5], COEFFS[idx][4]);
+ double p67 = fputil::multiply_add(dx, COEFFS[idx][7], COEFFS[idx][6]);
+ double p89 = fputil::multiply_add(dx, COEFFS[idx][9], COEFFS[idx][8]);
+ double p10 = COEFFS[idx][10];
+
+ double p03 = fputil::multiply_add(dx2, p23, p01);
+ double p47 = fputil::multiply_add(dx2, p67, p45);
+ double p810 = fputil::multiply_add(dx2, p10, p89);
+
+ double p07 = fputil::multiply_add(dx4, p47, p03);
+
+ double erfc_abs = fputil::multiply_add(dx4 * dx4, p810, p07);
+
+ double res = xbits.is_neg() ? 2.0 - erfc_abs : erfc_abs;
+ return fputil::cast<float>(res);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ERFCF_H
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 2c7568f0b63618..735987ae6d38d0 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -146,6 +146,7 @@ add_math_entrypoint_object(erf)
add_math_entrypoint_object(erff)
add_math_entrypoint_object(erff16)
+add_math_entrypoint_object(erfcf)
add_math_entrypoint_object(erfcf16)
add_math_entrypoint_object(exp)
diff --git a/libc/src/math/erfcf.h b/libc/src/math/erfcf.h
new file mode 100644
index 00000000000000..39411953715db1
--- /dev/null
+++ b/libc/src/math/erfcf.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for erfcf -------------------------*- 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_ERFCF_H
+#define LLVM_LIBC_SRC_MATH_ERFCF_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float erfcf(float x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_ERFCF_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 28b8e954530ddf..baee4df5f9bad3 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -1211,6 +1211,17 @@ add_entrypoint_object(
libc.src.__support.math.erff16
)
+add_entrypoint_object(
+ erfcf
+ SRCS
+ erfcf.cpp
+ HDRS
+ ../erfcf.h
+ DEPENDS
+ libc.src.__support.math.erfcf
+ libc.src.errno.errno
+)
+
add_entrypoint_object(
erfcf16
SRCS
diff --git a/libc/src/math/generic/erfcf.cpp b/libc/src/math/generic/erfcf.cpp
new file mode 100644
index 00000000000000..4a086f6208a59c
--- /dev/null
+++ b/libc/src/math/generic/erfcf.cpp
@@ -0,0 +1,17 @@
+//===-- Single-precision erfc 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/erfcf.h"
+#include "src/__support/common.h"
+#include "src/__support/math/erfcf.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(float, erfcf, (float x)) { return math::erfcf(x); }
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index 74eda7cdaf065e..999eb61d6474fa 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -110,6 +110,7 @@ else()
libc.src.__support.math.dsubl
libc.src.__support.math.exp10m1f
libc.src.__support.math.exp10m1f16
+ libc.src.__support.math.erfcf
libc.src.__support.math.erfcf16
libc.src.__support.math.erff
libc.src.__support.math.erff16
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index 7b785331f36c6a..7bbce6fdee3b9a 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -183,6 +183,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat) {
EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::shared::coshf(0.0f));
EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::shared::cospif(0.0f));
EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::shared::exp10m1f(0.0f));
+ EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::shared::erfcf(0.0f));
EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::shared::erff(0.0f));
EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::shared::exp10f(0.0f));
EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::shared::exp2m1f(0.0f));
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 8f1a543de0a5e7..f94c83a4549c9b 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -3041,6 +3041,18 @@ add_fp_unittest(
libc.src.__support.FPUtil.fp_bits
)
+add_fp_unittest(
+ erfcf_test
+ NEED_MPFR
+ SUITE
+ libc-math-unittests
+ SRCS
+ erfcf_test.cpp
+ DEPENDS
+ libc.src.math.erfcf
+ libc.src.__support.FPUtil.fp_bits
+)
+
add_fp_unittest(
erfcf16_test
NEED_MPFR
diff --git a/libc/test/src/math/erfcf_test.cpp b/libc/test/src/math/erfcf_test.cpp
new file mode 100644
index 00000000000000..83fa20c999b331
--- /dev/null
+++ b/libc/test/src/math/erfcf_test.cpp
@@ -0,0 +1,110 @@
+//===-- Unittests for erfcf -----------------------------------------------===//
+//
+// 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 "hdr/math_macros.h"
+#include "hdr/stdint_proxy.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/macros/optimization.h"
+#include "src/math/erfcf.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+#define TOLERANCE 1
+#else
+#define TOLERANCE 0
+#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+using LlvmLibcErfcfTest = LIBC_NAMESPACE::testing::FPTest<float>;
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+using LIBC_NAMESPACE::testing::tlog;
+
+TEST_F(LlvmLibcErfcfTest, SpecialNumbers) {
+ EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::erfcf(aNaN));
+ EXPECT_FP_EQ_ALL_ROUNDING(0.0f, LIBC_NAMESPACE::erfcf(inf));
+ EXPECT_FP_EQ_ALL_ROUNDING(2.0f, LIBC_NAMESPACE::erfcf(neg_inf));
+ EXPECT_FP_EQ_ALL_ROUNDING(1.0f, LIBC_NAMESPACE::erfcf(zero));
+ EXPECT_FP_EQ_ALL_ROUNDING(1.0f, LIBC_NAMESPACE::erfcf(neg_zero));
+}
+
+TEST_F(LlvmLibcErfcfTest, TrickyInputs) {
+ constexpr int N = 1;
+ constexpr uint32_t INPUTS[N] = {
+ 0x376c9f62U, // |x| = 0x1.d93ec4p-17f
+ };
+ for (int i = 0; i < N; ++i) {
+ float x = FPBits(INPUTS[i]).get_val();
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Erfc, x,
+ LIBC_NAMESPACE::erfcf(x), TOLERANCE + 0.5);
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Erfc, -x,
+ LIBC_NAMESPACE::erfcf(-x), TOLERANCE + 0.5);
+ }
+}
+
+TEST_F(LlvmLibcErfcfTest, InFloatRange) {
+ constexpr uint32_t COUNT = 234561;
+ constexpr uint32_t START = 0; // 0
+ constexpr uint32_t STOP = 0x4120'0000U; // 10.0f
+
+ constexpr uint64_t STEP = (STOP - START) / COUNT;
+
+ auto test = [&](mpfr::RoundingMode rounding_mode) {
+ mpfr::ForceRoundingMode __r(rounding_mode);
+ if (!__r.success)
+ return;
+
+ uint32_t fails = 0;
+ uint32_t count = 0;
+ uint32_t cc = 0;
+ float mx, mr = 0.0;
+ double tol = 0.5;
+
+ for (uint32_t i = 0, v = START; i <= COUNT; ++i, v += STEP) {
+ float x = FPBits(v).get_val();
+ if (FPBits(v).is_nan())
+ continue;
+
+ float result = LIBC_NAMESPACE::erfcf(x);
+ ++cc;
+ if (FPBits(result).is_nan())
+ continue;
+
+ ++count;
+ if (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Erfc, x, result,
+ 0.5, rounding_mode)) {
+ ++fails;
+ while (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Erfc, x,
+ result, tol, rounding_mode)) {
+ mx = x;
+ mr = result;
+ tol *= 2.0;
+ }
+ }
+ }
+ if (fails) {
+ tlog << " Log failed: " << fails << "/" << count << "/" << cc
+ << " tests.\n";
+ tlog << " Max ULPs is at most: " << static_cast<uint64_t>(tol) << ".\n";
+ EXPECT_MPFR_MATCH(mpfr::Operation::Erfc, mx, mr, 0.5, rounding_mode);
+ }
+ };
+
+ tlog << " Test Rounding To Nearest...\n";
+ test(mpfr::RoundingMode::Nearest);
+
+ tlog << " Test Rounding Downward...\n";
+ test(mpfr::RoundingMode::Downward);
+
+ tlog << " Test Rounding Upward...\n";
+ test(mpfr::RoundingMode::Upward);
+
+ tlog << " Test Rounding Toward Zero...\n";
+ test(mpfr::RoundingMode::TowardZero);
+}
diff --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt
index 46b5b138cfb11d..878f71ac37e06d 100644
--- a/libc/test/src/math/exhaustive/CMakeLists.txt
+++ b/libc/test/src/math/exhaustive/CMakeLists.txt
@@ -193,6 +193,22 @@ add_fp_unittest(
-lpthread
)
+add_fp_unittest(
+ erfcf_test
+ NO_RUN_POSTBUILD
+ NEED_MPFR
+ SUITE
+ libc_math_exhaustive_tests
+ SRCS
+ erfcf_test.cpp
+ DEPENDS
+ .exhaustive_test
+ libc.src.math.erfcf
+ libc.src.__support.FPUtil.fp_bits
+ LINK_LIBRARIES
+ -lpthread
+)
+
add_fp_unittest(
erff_test
NO_RUN_POSTBUILD
diff --git a/libc/test/src/math/exhaustive/erfcf_test.cpp b/libc/test/src/math/exhaustive/erfcf_test.cpp
new file mode 100644
index 00000000000000..7b55223480f489
--- /dev/null
+++ b/libc/test/src/math/exhaustive/erfcf_test.cpp
@@ -0,0 +1,33 @@
+//===-- Exhaustive test for erfcf -----------------------------------------===//
+//
+// 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 "exhaustive_test.h"
+#include "src/math/erfcf.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+using LlvmLibcErfcfExhaustiveTest =
+ LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Erfc,
+ LIBC_NAMESPACE::erfcf>;
+
+// Range: [0, Inf];
+static constexpr uint32_t POS_START = 0x0000'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
+
+TEST_F(LlvmLibcErfcfExhaustiveTest, PositiveRange) {
+ test_full_range_all_roundings(POS_START, POS_STOP);
+}
+
+// Range: [-Inf, 0];
+static constexpr uint32_t NEG_START = 0x8000'0000U;
+static constexpr uint32_t NEG_STOP = 0xff80'0000U;
+
+TEST_F(LlvmLibcErfcfExhaustiveTest, NegativeRange) {
+ test_full_range_all_roundings(NEG_START, NEG_STOP);
+}
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index a61b854a85fb2b..2aab34a0ad3a57 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -5335,6 +5335,17 @@ add_fp_unittest(
libc.src.math.erff16
)
+add_fp_unittest(
+ erfcf_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ erfcf_test.cpp
+ DEPENDS
+ libc.src.math.erfcf
+ libc.src.__support.FPUtil.fp_bits
+)
+
add_fp_unittest(
erfcf16_test
SUITE
diff --git a/libc/test/src/math/smoke/erfcf_test.cpp b/libc/test/src/math/smoke/erfcf_test.cpp
new file mode 100644
index 00000000000000..4979069bd734ec
--- /dev/null
+++ b/libc/test/src/math/smoke/erfcf_test.cpp
@@ -0,0 +1,54 @@
+//===-- Unittests for erfcf -----------------------------------------------===//
+//
+// 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 "hdr/math_macros.h"
+#include "hdr/stdint_proxy.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/math/erfcf.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcErfcfTest = LIBC_NAMESPACE::testing::FPTest<float>;
+
+TEST_F(LlvmLibcErfcfTest, SpecialNumbers) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::erfcf(sNaN), FE_INVALID);
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::erfcf(aNaN));
+ EXPECT_FP_EQ_ALL_ROUNDING(0.0f, LIBC_NAMESPACE::erfcf(inf));
+ EXPECT_FP_EQ_ALL_ROUNDING(2.0f, LIBC_NAMESPACE::erfcf(neg_inf));
+ EXPECT_FP_EQ_ALL_ROUNDING(1.0f, LIBC_NAMESPACE::erfcf(zero));
+ EXPECT_FP_EQ_ALL_ROUNDING(1.0f, LIBC_NAMESPACE::erfcf(neg_zero));
+}
+
+#ifdef LIBC_TEST_FTZ_DAZ
+
+using namespace LIBC_NAMESPACE::testing;
+
+TEST_F(LlvmLibcErfcfTest, FTZMode) {
+ ModifyMXCSR mxcsr(FTZ);
+
+ EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::erfcf(min_denormal));
+ EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::erfcf(max_denormal));
+}
+
+TEST_F(LlvmLibcErfcfTest, DAZMode) {
+ ModifyMXCSR mxcsr(DAZ);
+
+ EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::erfcf(min_denormal));
+ EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::erfcf(max_denormal));
+}
+
+TEST_F(LlvmLibcErfcfTest, FTZDAZMode) {
+ ModifyMXCSR mxcsr(FTZ | DAZ);
+
+ EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::erfcf(min_denormal));
+ EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::erfcf(max_denormal));
+}
+
+#endif
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index fc1164d88d111f..5471915e86ad3e 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -7546,6 +7546,22 @@ libc_support_library(
],
)
+libc_support_library(
+ name = "__support_math_erfcf",
+ hdrs = ["src/__support/math/erfcf.h"],
+ deps = [
+ ":__support_fputil_cast",
+ ":__support_fputil_except_value_utils",
+ ":__support_fputil_fenv_impl",
+ ":__support_fputil_fp_bits",
+ ":__support_fputil_multiply_add",
+ ":__support_macros_attributes",
+ ":__support_macros_config",
+ ":__support_macros_optimization",
+ ":__support_math_exp",
+ ],
+)
+
libc_support_library(
name = "__support_math_erfcf16",
hdrs = ["src/__support/math/erfcf16.h"],
@@ -11387,6 +11403,13 @@ libc_math_function(
],
)
+libc_math_function(
+ name = "erfcf",
+ additional_deps = [
+ ":__support_math_erfcf",
+ ],
+)
+
libc_math_function(
name = "erfcf16",
additional_deps = [
>From 69ad394401d33b2c01b0a69da4136ff6f406792f Mon Sep 17 00:00:00 2001
From: Anonmiraj <ezzibrahimx at gmail.com>
Date: Fri, 3 Apr 2026 21:13:43 +0200
Subject: [PATCH 2/8] replace exp() call with a builtin table
remove exp debs
---
libc/src/__support/math/CMakeLists.txt | 1 -
libc/src/__support/math/erfcf.h | 175 ++++++++++++++++--
.../llvm-project-overlay/libc/BUILD.bazel | 1 -
3 files changed, 164 insertions(+), 13 deletions(-)
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 194a03ea0b0132..6d7265beb29dad 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -3038,7 +3038,6 @@ add_header_library(
libc.src.__support.macros.attributes
libc.src.__support.macros.config
libc.src.__support.macros.optimization
- libc.src.__support.math.exp
)
add_header_library(
diff --git a/libc/src/__support/math/erfcf.h b/libc/src/__support/math/erfcf.h
index f166da9d3ded83..5de555b75e425e 100644
--- a/libc/src/__support/math/erfcf.h
+++ b/libc/src/__support/math/erfcf.h
@@ -162,15 +162,14 @@ LIBC_INLINE float erfcf(float x) {
FPBits xbits(x);
uint32_t x_abs = xbits.abs().uintval();
- static constexpr size_t N_ERFCF_EXCEPTS = 2;
- static constexpr fputil::ExceptValues<float, N_ERFCF_EXCEPTS> ERFCF_EXCEPTS =
- {{
- // (input, RZ output, RU offset, RD offset, RN offset)
- // x = 0.000014103805, erfc(x) = 0.9999841...
- {0x376C9F62, 0x3f7ffef5, 1, 0, 0},
- // x = -0.000014103805, erfc(x) = 1.0000159...
- {0xB76C9F62, 0x3F800085, 1, 0, 0},
- }};
+ constexpr size_t N_ERFCF_EXCEPTS = 2;
+ constexpr fputil::ExceptValues<float, N_ERFCF_EXCEPTS> ERFCF_EXCEPTS = {{
+ // (input, RZ output, RU offset, RD offset, RN offset)
+ // x = 0.000014103805, erfc(x) = 0.9999841...
+ {0x376C9F62, 0x3f7ffef5, 1, 0, 0},
+ // x = -0.000014103805, erfc(x) = 1.0000159...
+ {0xB76C9F62, 0x3F800085, 1, 0, 0},
+ }};
if (auto r = ERFCF_EXCEPTS.lookup(xbits.uintval());
LIBC_UNLIKELY(r.has_value()))
@@ -234,7 +233,7 @@ LIBC_INLINE float erfcf(float x) {
// Generated by Sollya over [4, 10]:
// P = fpminimax(erfc(1/sqrt(t)) * (1/sqrt(t)) * exp(1/t) * sqrt(pi), 12,
// [|D...|], [1/100, 1/16], relative);
- static constexpr double ASYMP_COEFFS[13] = {
+ constexpr double ASYMP_COEFFS[13] = {
0x1.ffffffffff7ebp-1, -0x1.fffffffde50adp-2, 0x1.7fffff052b044p-1,
-0x1.dfffbad06922cp0, 0x1.a3f9ab8151a5cp2, -0x1.d817a02e83042p4,
0x1.426451515fe5ap7, -0x1.f9da3719338bep9, 0x1.a3bffa01808f1p12,
@@ -262,8 +261,162 @@ LIBC_INLINE float erfcf(float x) {
double p = fputil::multiply_add(t8, p8_12, p07);
+ // Lookup table for exp(-k * ln(2) / 128) generated by Sollya.
+ constexpr double EXP_TABLE[128] = {0x1p+0,
+ 0x1.0163da9fb3335p+0,
+ 0x1.02c9a3e778061p+0,
+ 0x1.04315e86e7f85p+0,
+ 0x1.059b0d3158574p+0,
+ 0x1.0706b29ddf6dep+0,
+ 0x1.0874518759bc8p+0,
+ 0x1.09e3ecac6f383p+0,
+ 0x1.0b5586cf9890fp+0,
+ 0x1.0cc922b7247f7p+0,
+ 0x1.0e3ec32d3d1a2p+0,
+ 0x1.0fb66affed31bp+0,
+ 0x1.11301d0125b51p+0,
+ 0x1.12abdc06c31ccp+0,
+ 0x1.1429aaea92dep+0,
+ 0x1.15a98c8a58e51p+0,
+ 0x1.172b83c7d517bp+0,
+ 0x1.18af9388c8deap+0,
+ 0x1.1a35beb6fcb75p+0,
+ 0x1.1bbe084045cd4p+0,
+ 0x1.1d4873168b9aap+0,
+ 0x1.1ed5022fcd91dp+0,
+ 0x1.2063b88628cd6p+0,
+ 0x1.21f49917ddc96p+0,
+ 0x1.2387a6e756238p+0,
+ 0x1.251ce4fb2a63fp+0,
+ 0x1.26b4565e27cddp+0,
+ 0x1.284dfe1f56381p+0,
+ 0x1.29e9df51fdee1p+0,
+ 0x1.2b87fd0dad99p+0,
+ 0x1.2d285a6e4030bp+0,
+ 0x1.2ecafa93e2f56p+0,
+ 0x1.306fe0a31b715p+0,
+ 0x1.32170fc4cd831p+0,
+ 0x1.33c08b26416ffp+0,
+ 0x1.356c55f929ff1p+0,
+ 0x1.371a7373aa9cbp+0,
+ 0x1.38cae6d05d866p+0,
+ 0x1.3a7db34e59ff7p+0,
+ 0x1.3c32dc313a8e5p+0,
+ 0x1.3dea64c123422p+0,
+ 0x1.3fa4504ac801cp+0,
+ 0x1.4160a21f72e2ap+0,
+ 0x1.431f5d950a897p+0,
+ 0x1.44e086061892dp+0,
+ 0x1.46a41ed1d0057p+0,
+ 0x1.486a2b5c13cdp+0,
+ 0x1.4a32af0d7d3dep+0,
+ 0x1.4bfdad5362a27p+0,
+ 0x1.4dcb299fddd0dp+0,
+ 0x1.4f9b2769d2ca7p+0,
+ 0x1.516daa2cf6642p+0,
+ 0x1.5342b569d4f82p+0,
+ 0x1.551a4ca5d920fp+0,
+ 0x1.56f4736b527dap+0,
+ 0x1.58d12d497c7fdp+0,
+ 0x1.5ab07dd485429p+0,
+ 0x1.5c9268a5946b7p+0,
+ 0x1.5e76f15ad2148p+0,
+ 0x1.605e1b976dc09p+0,
+ 0x1.6247eb03a5585p+0,
+ 0x1.6434634ccc32p+0,
+ 0x1.6623882552225p+0,
+ 0x1.68155d44ca973p+0,
+ 0x1.6a09e667f3bcdp+0,
+ 0x1.6c012750bdabfp+0,
+ 0x1.6dfb23c651a2fp+0,
+ 0x1.6ff7df9519484p+0,
+ 0x1.71f75e8ec5f74p+0,
+ 0x1.73f9a48a58174p+0,
+ 0x1.75feb564267c9p+0,
+ 0x1.780694fde5d3fp+0,
+ 0x1.7a11473eb0187p+0,
+ 0x1.7c1ed0130c132p+0,
+ 0x1.7e2f336cf4e62p+0,
+ 0x1.80427543e1a12p+0,
+ 0x1.82589994cce13p+0,
+ 0x1.8471a4623c7adp+0,
+ 0x1.868d99b4492edp+0,
+ 0x1.88ac7d98a6699p+0,
+ 0x1.8ace5422aa0dbp+0,
+ 0x1.8cf3216b5448cp+0,
+ 0x1.8f1ae99157736p+0,
+ 0x1.9145b0b91ffc6p+0,
+ 0x1.93737b0cdc5e5p+0,
+ 0x1.95a44cbc8520fp+0,
+ 0x1.97d829fde4e5p+0,
+ 0x1.9a0f170ca07bap+0,
+ 0x1.9c49182a3f09p+0,
+ 0x1.9e86319e32323p+0,
+ 0x1.a0c667b5de565p+0,
+ 0x1.a309bec4a2d33p+0,
+ 0x1.a5503b23e255dp+0,
+ 0x1.a799e1330b358p+0,
+ 0x1.a9e6b5579fdbfp+0,
+ 0x1.ac36bbfd3f37ap+0,
+ 0x1.ae89f995ad3adp+0,
+ 0x1.b0e07298db666p+0,
+ 0x1.b33a2b84f15fbp+0,
+ 0x1.b59728de5593ap+0,
+ 0x1.b7f76f2fb5e47p+0,
+ 0x1.ba5b030a1064ap+0,
+ 0x1.bcc1e904bc1d2p+0,
+ 0x1.bf2c25bd71e09p+0,
+ 0x1.c199bdd85529cp+0,
+ 0x1.c40ab5fffd07ap+0,
+ 0x1.c67f12e57d14bp+0,
+ 0x1.c8f6d9406e7b5p+0,
+ 0x1.cb720dcef9069p+0,
+ 0x1.cdf0b555dc3fap+0,
+ 0x1.d072d4a07897cp+0,
+ 0x1.d2f87080d89f2p+0,
+ 0x1.d5818dcfba487p+0,
+ 0x1.d80e316c98398p+0,
+ 0x1.da9e603db3285p+0,
+ 0x1.dd321f301b46p+0,
+ 0x1.dfc97337b9b5fp+0,
+ 0x1.e264614f5a129p+0,
+ 0x1.e502ee78b3ff6p+0,
+ 0x1.e7a51fbc74c83p+0,
+ 0x1.ea4afa2a490dap+0,
+ 0x1.ecf482d8e67f1p+0,
+ 0x1.efa1bee615a27p+0,
+ 0x1.f252b376bba97p+0,
+ 0x1.f50765b6e454p+0,
+ 0x1.f7bfdad9cbe14p+0,
+ 0x1.fa7c1819e90d8p+0,
+ 0x1.fd3c22b8f71f1p+0};
+
+ constexpr double ILN2 = 0x1.71547652b82fep+0;
+ constexpr double LN2H = 0x1.62e42fefap-8;
+ constexpr double LN2L = 0x1.cf79abd6f5dc8p-47;
+
+ uint64_t xsq_scaled_bits =
+ cpp::bit_cast<uint64_t>(xsq * ILN2 - 0x1.00004p+10);
+ int64_t exp_idx = static_cast<int64_t>(xsq_scaled_bits << 12) >> 48;
+ uint64_t scale_bits = static_cast<uint64_t>((exp_idx >> 7) + 0x3ff) << 52;
+ double scale_factor = cpp::bit_cast<double>(scale_bits);
+
+ // Polynomial approximating exp(-dx) - 1
+ constexpr double EXP_POLY[] = {-0x1.ffffffffff333p-2, 0x1.5555555556a14p-3,
+ -0x1.55556666659b4p-5, 0x1.1111074cc7b22p-7};
+
+ double exp_idx_d = static_cast<double>(exp_idx);
+ double dx = (xsq + LN2H * exp_idx_d) + LN2L * exp_idx_d;
+ double dx2 = dx * dx;
+ double exp_base = EXP_TABLE[exp_idx & 127];
+ double poly_eval =
+ dx + dx2 * (fputil::multiply_add(dx, EXP_POLY[1], EXP_POLY[0]) +
+ dx2 * fputil::multiply_add(dx, EXP_POLY[3], EXP_POLY[2]));
+
+ double exp_minus_xsq = scale_factor * (exp_base - poly_eval * exp_base);
+
constexpr double ONE_OVER_SQRT_PI = 0.564189583547756286948;
- double erfc_abs = (math::exp(-xsq) * p / xd) * ONE_OVER_SQRT_PI;
+ double erfc_abs = (exp_minus_xsq * p / xd) * ONE_OVER_SQRT_PI;
double res = xbits.is_neg() ? 2.0 - erfc_abs : erfc_abs;
return fputil::cast<float>(res);
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 5471915e86ad3e..f2f257ac29d187 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -7558,7 +7558,6 @@ libc_support_library(
":__support_macros_attributes",
":__support_macros_config",
":__support_macros_optimization",
- ":__support_math_exp",
],
)
>From 568d61a40ceae41e0baba09d58415d5552048178 Mon Sep 17 00:00:00 2001
From: Anonmiraj <ezzibrahimx at gmail.com>
Date: Sat, 4 Apr 2026 02:35:50 +0200
Subject: [PATCH 3/8] collapse exp_table into less lines
---
libc/src/__support/math/erfcf.h | 173 ++++++++------------------------
1 file changed, 44 insertions(+), 129 deletions(-)
diff --git a/libc/src/__support/math/erfcf.h b/libc/src/__support/math/erfcf.h
index 5de555b75e425e..393bbf06f0d09f 100644
--- a/libc/src/__support/math/erfcf.h
+++ b/libc/src/__support/math/erfcf.h
@@ -17,7 +17,6 @@
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
-#include "src/__support/math/exp.h"
namespace LIBC_NAMESPACE_DECL {
@@ -262,134 +261,50 @@ LIBC_INLINE float erfcf(float x) {
double p = fputil::multiply_add(t8, p8_12, p07);
// Lookup table for exp(-k * ln(2) / 128) generated by Sollya.
- constexpr double EXP_TABLE[128] = {0x1p+0,
- 0x1.0163da9fb3335p+0,
- 0x1.02c9a3e778061p+0,
- 0x1.04315e86e7f85p+0,
- 0x1.059b0d3158574p+0,
- 0x1.0706b29ddf6dep+0,
- 0x1.0874518759bc8p+0,
- 0x1.09e3ecac6f383p+0,
- 0x1.0b5586cf9890fp+0,
- 0x1.0cc922b7247f7p+0,
- 0x1.0e3ec32d3d1a2p+0,
- 0x1.0fb66affed31bp+0,
- 0x1.11301d0125b51p+0,
- 0x1.12abdc06c31ccp+0,
- 0x1.1429aaea92dep+0,
- 0x1.15a98c8a58e51p+0,
- 0x1.172b83c7d517bp+0,
- 0x1.18af9388c8deap+0,
- 0x1.1a35beb6fcb75p+0,
- 0x1.1bbe084045cd4p+0,
- 0x1.1d4873168b9aap+0,
- 0x1.1ed5022fcd91dp+0,
- 0x1.2063b88628cd6p+0,
- 0x1.21f49917ddc96p+0,
- 0x1.2387a6e756238p+0,
- 0x1.251ce4fb2a63fp+0,
- 0x1.26b4565e27cddp+0,
- 0x1.284dfe1f56381p+0,
- 0x1.29e9df51fdee1p+0,
- 0x1.2b87fd0dad99p+0,
- 0x1.2d285a6e4030bp+0,
- 0x1.2ecafa93e2f56p+0,
- 0x1.306fe0a31b715p+0,
- 0x1.32170fc4cd831p+0,
- 0x1.33c08b26416ffp+0,
- 0x1.356c55f929ff1p+0,
- 0x1.371a7373aa9cbp+0,
- 0x1.38cae6d05d866p+0,
- 0x1.3a7db34e59ff7p+0,
- 0x1.3c32dc313a8e5p+0,
- 0x1.3dea64c123422p+0,
- 0x1.3fa4504ac801cp+0,
- 0x1.4160a21f72e2ap+0,
- 0x1.431f5d950a897p+0,
- 0x1.44e086061892dp+0,
- 0x1.46a41ed1d0057p+0,
- 0x1.486a2b5c13cdp+0,
- 0x1.4a32af0d7d3dep+0,
- 0x1.4bfdad5362a27p+0,
- 0x1.4dcb299fddd0dp+0,
- 0x1.4f9b2769d2ca7p+0,
- 0x1.516daa2cf6642p+0,
- 0x1.5342b569d4f82p+0,
- 0x1.551a4ca5d920fp+0,
- 0x1.56f4736b527dap+0,
- 0x1.58d12d497c7fdp+0,
- 0x1.5ab07dd485429p+0,
- 0x1.5c9268a5946b7p+0,
- 0x1.5e76f15ad2148p+0,
- 0x1.605e1b976dc09p+0,
- 0x1.6247eb03a5585p+0,
- 0x1.6434634ccc32p+0,
- 0x1.6623882552225p+0,
- 0x1.68155d44ca973p+0,
- 0x1.6a09e667f3bcdp+0,
- 0x1.6c012750bdabfp+0,
- 0x1.6dfb23c651a2fp+0,
- 0x1.6ff7df9519484p+0,
- 0x1.71f75e8ec5f74p+0,
- 0x1.73f9a48a58174p+0,
- 0x1.75feb564267c9p+0,
- 0x1.780694fde5d3fp+0,
- 0x1.7a11473eb0187p+0,
- 0x1.7c1ed0130c132p+0,
- 0x1.7e2f336cf4e62p+0,
- 0x1.80427543e1a12p+0,
- 0x1.82589994cce13p+0,
- 0x1.8471a4623c7adp+0,
- 0x1.868d99b4492edp+0,
- 0x1.88ac7d98a6699p+0,
- 0x1.8ace5422aa0dbp+0,
- 0x1.8cf3216b5448cp+0,
- 0x1.8f1ae99157736p+0,
- 0x1.9145b0b91ffc6p+0,
- 0x1.93737b0cdc5e5p+0,
- 0x1.95a44cbc8520fp+0,
- 0x1.97d829fde4e5p+0,
- 0x1.9a0f170ca07bap+0,
- 0x1.9c49182a3f09p+0,
- 0x1.9e86319e32323p+0,
- 0x1.a0c667b5de565p+0,
- 0x1.a309bec4a2d33p+0,
- 0x1.a5503b23e255dp+0,
- 0x1.a799e1330b358p+0,
- 0x1.a9e6b5579fdbfp+0,
- 0x1.ac36bbfd3f37ap+0,
- 0x1.ae89f995ad3adp+0,
- 0x1.b0e07298db666p+0,
- 0x1.b33a2b84f15fbp+0,
- 0x1.b59728de5593ap+0,
- 0x1.b7f76f2fb5e47p+0,
- 0x1.ba5b030a1064ap+0,
- 0x1.bcc1e904bc1d2p+0,
- 0x1.bf2c25bd71e09p+0,
- 0x1.c199bdd85529cp+0,
- 0x1.c40ab5fffd07ap+0,
- 0x1.c67f12e57d14bp+0,
- 0x1.c8f6d9406e7b5p+0,
- 0x1.cb720dcef9069p+0,
- 0x1.cdf0b555dc3fap+0,
- 0x1.d072d4a07897cp+0,
- 0x1.d2f87080d89f2p+0,
- 0x1.d5818dcfba487p+0,
- 0x1.d80e316c98398p+0,
- 0x1.da9e603db3285p+0,
- 0x1.dd321f301b46p+0,
- 0x1.dfc97337b9b5fp+0,
- 0x1.e264614f5a129p+0,
- 0x1.e502ee78b3ff6p+0,
- 0x1.e7a51fbc74c83p+0,
- 0x1.ea4afa2a490dap+0,
- 0x1.ecf482d8e67f1p+0,
- 0x1.efa1bee615a27p+0,
- 0x1.f252b376bba97p+0,
- 0x1.f50765b6e454p+0,
- 0x1.f7bfdad9cbe14p+0,
- 0x1.fa7c1819e90d8p+0,
- 0x1.fd3c22b8f71f1p+0};
+ constexpr double EXP_TABLE[128] = {
+ 0x1.0000000000000p+0, 0x1.0163da9fb3335p+0, 0x1.02c9a3e778061p+0,
+ 0x1.04315e86e7f85p+0, 0x1.059b0d3158574p+0, 0x1.0706b29ddf6dep+0,
+ 0x1.0874518759bc8p+0, 0x1.09e3ecac6f383p+0, 0x1.0b5586cf9890fp+0,
+ 0x1.0cc922b7247f7p+0, 0x1.0e3ec32d3d1a2p+0, 0x1.0fb66affed31bp+0,
+ 0x1.11301d0125b51p+0, 0x1.12abdc06c31ccp+0, 0x1.1429aaea92dep+0,
+ 0x1.15a98c8a58e51p+0, 0x1.172b83c7d517bp+0, 0x1.18af9388c8deap+0,
+ 0x1.1a35beb6fcb75p+0, 0x1.1bbe084045cd4p+0, 0x1.1d4873168b9aap+0,
+ 0x1.1ed5022fcd91dp+0, 0x1.2063b88628cd6p+0, 0x1.21f49917ddc96p+0,
+ 0x1.2387a6e756238p+0, 0x1.251ce4fb2a63fp+0, 0x1.26b4565e27cddp+0,
+ 0x1.284dfe1f56381p+0, 0x1.29e9df51fdee1p+0, 0x1.2b87fd0dad99p+0,
+ 0x1.2d285a6e4030bp+0, 0x1.2ecafa93e2f56p+0, 0x1.306fe0a31b715p+0,
+ 0x1.32170fc4cd831p+0, 0x1.33c08b26416ffp+0, 0x1.356c55f929ff1p+0,
+ 0x1.371a7373aa9cbp+0, 0x1.38cae6d05d866p+0, 0x1.3a7db34e59ff7p+0,
+ 0x1.3c32dc313a8e5p+0, 0x1.3dea64c123422p+0, 0x1.3fa4504ac801cp+0,
+ 0x1.4160a21f72e2ap+0, 0x1.431f5d950a897p+0, 0x1.44e086061892dp+0,
+ 0x1.46a41ed1d0057p+0, 0x1.486a2b5c13cdp+0, 0x1.4a32af0d7d3dep+0,
+ 0x1.4bfdad5362a27p+0, 0x1.4dcb299fddd0dp+0, 0x1.4f9b2769d2ca7p+0,
+ 0x1.516daa2cf6642p+0, 0x1.5342b569d4f82p+0, 0x1.551a4ca5d920fp+0,
+ 0x1.56f4736b527dap+0, 0x1.58d12d497c7fdp+0, 0x1.5ab07dd485429p+0,
+ 0x1.5c9268a5946b7p+0, 0x1.5e76f15ad2148p+0, 0x1.605e1b976dc09p+0,
+ 0x1.6247eb03a5585p+0, 0x1.6434634ccc32p+0, 0x1.6623882552225p+0,
+ 0x1.68155d44ca973p+0, 0x1.6a09e667f3bcdp+0, 0x1.6c012750bdabfp+0,
+ 0x1.6dfb23c651a2fp+0, 0x1.6ff7df9519484p+0, 0x1.71f75e8ec5f74p+0,
+ 0x1.73f9a48a58174p+0, 0x1.75feb564267c9p+0, 0x1.780694fde5d3fp+0,
+ 0x1.7a11473eb0187p+0, 0x1.7c1ed0130c132p+0, 0x1.7e2f336cf4e62p+0,
+ 0x1.80427543e1a12p+0, 0x1.82589994cce13p+0, 0x1.8471a4623c7adp+0,
+ 0x1.868d99b4492edp+0, 0x1.88ac7d98a6699p+0, 0x1.8ace5422aa0dbp+0,
+ 0x1.8cf3216b5448cp+0, 0x1.8f1ae99157736p+0, 0x1.9145b0b91ffc6p+0,
+ 0x1.93737b0cdc5e5p+0, 0x1.95a44cbc8520fp+0, 0x1.97d829fde4e5p+0,
+ 0x1.9a0f170ca07bap+0, 0x1.9c49182a3f09p+0, 0x1.9e86319e32323p+0,
+ 0x1.a0c667b5de565p+0, 0x1.a309bec4a2d33p+0, 0x1.a5503b23e255dp+0,
+ 0x1.a799e1330b358p+0, 0x1.a9e6b5579fdbfp+0, 0x1.ac36bbfd3f37ap+0,
+ 0x1.ae89f995ad3adp+0, 0x1.b0e07298db666p+0, 0x1.b33a2b84f15fbp+0,
+ 0x1.b59728de5593ap+0, 0x1.b7f76f2fb5e47p+0, 0x1.ba5b030a1064ap+0,
+ 0x1.bcc1e904bc1d2p+0, 0x1.bf2c25bd71e09p+0, 0x1.c199bdd85529cp+0,
+ 0x1.c40ab5fffd07ap+0, 0x1.c67f12e57d14bp+0, 0x1.c8f6d9406e7b5p+0,
+ 0x1.cb720dcef9069p+0, 0x1.cdf0b555dc3fap+0, 0x1.d072d4a07897cp+0,
+ 0x1.d2f87080d89f2p+0, 0x1.d5818dcfba487p+0, 0x1.d80e316c98398p+0,
+ 0x1.da9e603db3285p+0, 0x1.dd321f301b46p+0, 0x1.dfc97337b9b5fp+0,
+ 0x1.e264614f5a129p+0, 0x1.e502ee78b3ff6p+0, 0x1.e7a51fbc74c83p+0,
+ 0x1.ea4afa2a490dap+0, 0x1.ecf482d8e67f1p+0, 0x1.efa1bee615a27p+0,
+ 0x1.f252b376bba97p+0, 0x1.f50765b6e454p+0, 0x1.f7bfdad9cbe14p+0,
+ 0x1.fa7c1819e90d8p+0, 0x1.fd3c22b8f71f1p+0};
constexpr double ILN2 = 0x1.71547652b82fep+0;
constexpr double LN2H = 0x1.62e42fefap-8;
>From 0ab9858ec692af50a3d629c57241ff6e9856ef05 Mon Sep 17 00:00:00 2001
From: Anonmiraj <ezzibrahimx at gmail.com>
Date: Mon, 18 May 2026 21:33:24 +0300
Subject: [PATCH 4/8] replace except table with an if
---
libc/src/__support/math/erfcf.h | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/libc/src/__support/math/erfcf.h b/libc/src/__support/math/erfcf.h
index 393bbf06f0d09f..4212d4a1008dfd 100644
--- a/libc/src/__support/math/erfcf.h
+++ b/libc/src/__support/math/erfcf.h
@@ -161,18 +161,12 @@ LIBC_INLINE float erfcf(float x) {
FPBits xbits(x);
uint32_t x_abs = xbits.abs().uintval();
- constexpr size_t N_ERFCF_EXCEPTS = 2;
- constexpr fputil::ExceptValues<float, N_ERFCF_EXCEPTS> ERFCF_EXCEPTS = {{
- // (input, RZ output, RU offset, RD offset, RN offset)
- // x = 0.000014103805, erfc(x) = 0.9999841...
- {0x376C9F62, 0x3f7ffef5, 1, 0, 0},
- // x = -0.000014103805, erfc(x) = 1.0000159...
- {0xB76C9F62, 0x3F800085, 1, 0, 0},
- }};
-
- if (auto r = ERFCF_EXCEPTS.lookup(xbits.uintval());
- LIBC_UNLIKELY(r.has_value()))
- return r.value();
+ if (LIBC_UNLIKELY(x_abs == 0x376C9F62U)) {
+ // x = +/-0.000014103805
+ uint32_t out = xbits.is_neg() ? 0x3F800085U : 0x3f7ffef5U;
+ return fputil::round_result_slightly_up(
+ fputil::FPBits<float>(out).get_val());
+ }
// Special cases: NaN and Inf
if (LIBC_UNLIKELY(x_abs >= 0x7f800000U)) {
>From a5b5f3222fb0415b7a2742a290fdb5c31e4c4283 Mon Sep 17 00:00:00 2001
From: Anonmiraj <ezzibrahimx at gmail.com>
Date: Mon, 18 May 2026 21:40:41 +0300
Subject: [PATCH 5/8] fix nits
---
libc/src/__support/math/erfcf.h | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/libc/src/__support/math/erfcf.h b/libc/src/__support/math/erfcf.h
index 4212d4a1008dfd..dc3d12b68ae485 100644
--- a/libc/src/__support/math/erfcf.h
+++ b/libc/src/__support/math/erfcf.h
@@ -181,10 +181,7 @@ LIBC_INLINE float erfcf(float x) {
return xbits.is_neg() ? fputil::cast<float>(2.0) : fputil::cast<float>(0.0);
}
- if (LIBC_UNLIKELY(x_abs == 0))
- return 1.0f;
-
- if (LIBC_UNLIKELY(x_abs < 0x33000000U)) { // |x| < 2^-25
+ if (LIBC_UNLIKELY(x_abs < 0x33000000U)) { // |x| < 2^-25, includes x = 0
constexpr double NEG_TWO_OVER_SQRT_PI = -0x1.20dd750429b6dp0;
double xd = fputil::cast<double>(x);
return fputil::cast<float>(
@@ -194,9 +191,7 @@ LIBC_INLINE float erfcf(float x) {
// erfc(x) rounds to 0 or 2 for |x| >= 10.125.
if (LIBC_UNLIKELY(x_abs >= 0x41220000U)) { // |x| >= 10.125
if (xbits.is_neg()) {
- if (fputil::fenv_is_round_down() || fputil::fenv_is_round_to_zero())
- return FPBits(0x3FFFFFFFU).get_val(); // next float below 2.0
- return 2.0f;
+ return fputil::round_result_slightly_down(2.0f);
}
fputil::set_errno_if_required(ERANGE);
fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
@@ -211,7 +206,7 @@ LIBC_INLINE float erfcf(float x) {
// erfc(|x|) is evaluated using a degree-10 polynomial on each sub-interval.
- int shift = 147 - (x_abs >> 23);
+ unsigned shift = 147 - (x_abs >> 23);
uint64_t mantissa = (x_abs & 0x007FFFFFU) | 0x00800000U;
int idx = static_cast<int>(mantissa >> shift);
>From 063e7685764a0510f13e3d75719ef7e291bab9ba Mon Sep 17 00:00:00 2001
From: Anonmiraj <ezzibrahimx at gmail.com>
Date: Fri, 26 Jun 2026 20:50:14 +0300
Subject: [PATCH 6/8] fix more nits
---
libc/src/__support/math/erfcf.h | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/libc/src/__support/math/erfcf.h b/libc/src/__support/math/erfcf.h
index dc3d12b68ae485..0778f70e1fd6bc 100644
--- a/libc/src/__support/math/erfcf.h
+++ b/libc/src/__support/math/erfcf.h
@@ -168,19 +168,6 @@ LIBC_INLINE float erfcf(float x) {
fputil::FPBits<float>(out).get_val());
}
- // Special cases: NaN and Inf
- if (LIBC_UNLIKELY(x_abs >= 0x7f800000U)) {
- if (x_abs > 0x7f800000U) {
- if (xbits.is_signaling_nan()) {
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
- return x;
- }
- // erfc(+Inf) = 0, erfc(-Inf) = 2
- return xbits.is_neg() ? fputil::cast<float>(2.0) : fputil::cast<float>(0.0);
- }
-
if (LIBC_UNLIKELY(x_abs < 0x33000000U)) { // |x| < 2^-25, includes x = 0
constexpr double NEG_TWO_OVER_SQRT_PI = -0x1.20dd750429b6dp0;
double xd = fputil::cast<double>(x);
@@ -189,7 +176,20 @@ LIBC_INLINE float erfcf(float x) {
}
// erfc(x) rounds to 0 or 2 for |x| >= 10.125.
- if (LIBC_UNLIKELY(x_abs >= 0x41220000U)) { // |x| >= 10.125
+ if (LIBC_UNLIKELY(x_abs >= 0x41220000U)) {
+ // Special cases: NaN and Inf
+ if (LIBC_UNLIKELY(x_abs >= 0x7f800000U)) {
+
+ if (x_abs > 0x7f800000U) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+ return x;
+ }
+ // erfc(+Inf) = 0, erfc(-Inf) = 2
+ return xbits.is_neg() ? 2.0f : 0.0f;
+ }
if (xbits.is_neg()) {
return fputil::round_result_slightly_down(2.0f);
}
@@ -207,7 +207,7 @@ LIBC_INLINE float erfcf(float x) {
// erfc(|x|) is evaluated using a degree-10 polynomial on each sub-interval.
unsigned shift = 147 - (x_abs >> 23);
- uint64_t mantissa = (x_abs & 0x007FFFFFU) | 0x00800000U;
+ uint32_t mantissa = (x_abs & 0x007FFFFFU) | 0x00800000U;
int idx = static_cast<int>(mantissa >> shift);
if (idx >= 32) {
>From 42c50d9f1f87537249d485fc62cfbac9cd307eb0 Mon Sep 17 00:00:00 2001
From: Anonmiraj <ezzibrahimx at gmail.com>
Date: Wed, 15 Jul 2026 07:58:55 +0300
Subject: [PATCH 7/8] Fix CI
---
libc/src/__support/math/erfcf.h | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/libc/src/__support/math/erfcf.h b/libc/src/__support/math/erfcf.h
index 0778f70e1fd6bc..f9c7bdf09c4b8d 100644
--- a/libc/src/__support/math/erfcf.h
+++ b/libc/src/__support/math/erfcf.h
@@ -168,7 +168,9 @@ LIBC_INLINE float erfcf(float x) {
fputil::FPBits<float>(out).get_val());
}
- if (LIBC_UNLIKELY(x_abs < 0x33000000U)) { // |x| < 2^-25, includes x = 0
+ // For |x| < 2^-10, erfc(|x|) is within ~0.0016 ULPs of 1 - 2x/sqrt(pi).
+ // Also catches all values where shift >= 32 would cause uint32_t UB.
+ if (LIBC_UNLIKELY(x_abs < 0x3A000000U)) { // |x| < 2^-10
constexpr double NEG_TWO_OVER_SQRT_PI = -0x1.20dd750429b6dp0;
double xd = fputil::cast<double>(x);
return fputil::cast<float>(
>From 775691aa516278fa15cb89473afad0be3e81631a Mon Sep 17 00:00:00 2001
From: Anonmiraj <ezzibrahimx at gmail.com>
Date: Wed, 23 Sep 2026 14:42:47 +0300
Subject: [PATCH 8/8] Fix erfcf rounding
---
libc/config/baremetal/aarch64/entrypoints.txt | 1 +
libc/config/baremetal/arm/entrypoints.txt | 1 +
libc/config/baremetal/riscv/entrypoints.txt | 1 +
libc/config/darwin/aarch64/entrypoints.txt | 1 +
libc/config/freebsd/x86_64/entrypoints.txt | 1 +
libc/config/linux/arm/entrypoints.txt | 1 +
libc/config/windows/entrypoints.txt | 1 +
libc/docs/headers/math/index.rst | 2 +-
libc/src/__support/math/CMakeLists.txt | 1 +
libc/src/__support/math/erfcf.h | 23 +++++++++++--------
libc/test/src/math/erfcf_test.cpp | 3 ++-
.../llvm-project-overlay/libc/BUILD.bazel | 1 +
.../libc/test/src/math/BUILD.bazel | 2 ++
.../libc/test/src/math/smoke/BUILD.bazel | 2 ++
14 files changed, 30 insertions(+), 11 deletions(-)
diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index 757e4729699d18..e098be8fcfa3ce 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -388,6 +388,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.daddl
libc.src.math.ddivl
libc.src.math.dsubl
+ libc.src.math.erfcf
libc.src.math.erff
libc.src.math.exp
libc.src.math.exp10
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 13d4f777650f75..8290d18f16805f 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -400,6 +400,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.daddl
libc.src.math.ddivl
libc.src.math.dsubl
+ libc.src.math.erfcf
libc.src.math.erff
libc.src.math.exp
libc.src.math.exp10
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 88613b39086a58..13c26c8d1c2918 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -396,6 +396,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.daddl
libc.src.math.ddivl
libc.src.math.dsubl
+ libc.src.math.erfcf
libc.src.math.erff
libc.src.math.exp
libc.src.math.exp10
diff --git a/libc/config/darwin/aarch64/entrypoints.txt b/libc/config/darwin/aarch64/entrypoints.txt
index c6c83572079596..d55a65ac5a70e7 100644
--- a/libc/config/darwin/aarch64/entrypoints.txt
+++ b/libc/config/darwin/aarch64/entrypoints.txt
@@ -207,6 +207,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.daddl
libc.src.math.ddivl
libc.src.math.dsubl
+ libc.src.math.erfcf
libc.src.math.erff
libc.src.math.exp
libc.src.math.exp10
diff --git a/libc/config/freebsd/x86_64/entrypoints.txt b/libc/config/freebsd/x86_64/entrypoints.txt
index 8f6c178301c2f2..e1b31ce09146d7 100644
--- a/libc/config/freebsd/x86_64/entrypoints.txt
+++ b/libc/config/freebsd/x86_64/entrypoints.txt
@@ -145,6 +145,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.ddivl
libc.src.math.dfmal
libc.src.math.dsubl
+ libc.src.math.erfcf
libc.src.math.erff
libc.src.math.exp
libc.src.math.expf
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index a3f387edc349b4..bbd954253b3b5d 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -399,6 +399,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.coshf
libc.src.math.dfmal
libc.src.math.dsqrtl
+ libc.src.math.erfcf
libc.src.math.erff
libc.src.math.exp
libc.src.math.exp10
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index 3a48b49e169b3a..1fff45aad9920b 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -177,6 +177,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.ddivl
libc.src.math.dfmal
libc.src.math.dsubl
+ libc.src.math.erfcf
libc.src.math.erff
libc.src.math.exp
libc.src.math.expf
diff --git a/libc/docs/headers/math/index.rst b/libc/docs/headers/math/index.rst
index 2d5e188e804d4c..183beb0d268a92 100644
--- a/libc/docs/headers/math/index.rst
+++ b/libc/docs/headers/math/index.rst
@@ -293,7 +293,7 @@ Higher Math Functions
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| erf | |check| | | | | | | 7.12.8.1 | F.10.5.1 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
-| erfc | | | | | | | 7.12.8.2 | F.10.5.2 |
+| erfc | |check| | | | | | | 7.12.8.2 | F.10.5.2 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| exp | |check| | |check| | | |check| | | |check| | 7.12.6.1 | F.10.3.1 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 6d7265beb29dad..b4535c564db48f 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -3030,6 +3030,7 @@ add_header_library(
HDRS
erfcf.h
DEPENDS
+ libc.src.__support.CPP.bit
libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.except_value_utils
libc.src.__support.FPUtil.fenv_impl
diff --git a/libc/src/__support/math/erfcf.h b/libc/src/__support/math/erfcf.h
index f9c7bdf09c4b8d..bcf3ddccb781af 100644
--- a/libc/src/__support/math/erfcf.h
+++ b/libc/src/__support/math/erfcf.h
@@ -9,6 +9,7 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_ERFCF_H
#define LLVM_LIBC_SRC___SUPPORT_MATH_ERFCF_H
+#include "src/__support/CPP/bit.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/cast.h"
@@ -25,7 +26,8 @@ namespace math {
LIBC_INLINE float erfcf(float x) {
// Polynomials approximating erfc(|x|) on ( k/8, (k+1)/8 ) generated by
// Sollya with: > P = fpminimax(erfc(x), 10, [|D...|], [k/8, (k+1)/8]);
- // for k = 0..31.
+ // for k = 0..31. All 32 polynomials have relative errors between 1e-16
+ // and 1e-15, i.e. well below the half-ULP of float.
constexpr double COEFFS[32][11] = {
{0x1p0, -0x1.20dd750429b6dp0, 0x1.7112720c8ba45p-48, 0x1.812746b031144p-2,
0x1.222514285ab0dp-33, -0x1.ce2f2335e679fp-4, 0x1.4b61403cf653ep-23,
@@ -168,13 +170,16 @@ LIBC_INLINE float erfcf(float x) {
fputil::FPBits<float>(out).get_val());
}
- // For |x| < 2^-10, erfc(|x|) is within ~0.0016 ULPs of 1 - 2x/sqrt(pi).
- // Also catches all values where shift >= 32 would cause uint32_t UB.
- if (LIBC_UNLIKELY(x_abs < 0x3A000000U)) { // |x| < 2^-10
- constexpr double NEG_TWO_OVER_SQRT_PI = -0x1.20dd750429b6dp0;
+ // For |x| < 2^-11, erfc(x) is evaluated to double precision using the first
+ // terms of its Taylor series. Also avoids the shift below being >= 32.
+ if (LIBC_UNLIKELY(x_abs < 0x3A000000U)) { // |x| < 2^-11
+ constexpr double TWO_OVER_SQRT_PI = 0x1.20dd750429b6dp0;
+ constexpr double TWO_OVER_THREE_SQRT_PI = 0x1.812746b0379e7p-2;
double xd = fputil::cast<double>(x);
- return fputil::cast<float>(
- fputil::multiply_add(xd, NEG_TWO_OVER_SQRT_PI, 1.0));
+ double xd2 = xd * xd;
+ double erf_x = xd * fputil::multiply_add(xd2, -TWO_OVER_THREE_SQRT_PI,
+ TWO_OVER_SQRT_PI);
+ return fputil::cast<float>(1.0 - erf_x);
}
// erfc(x) rounds to 0 or 2 for |x| >= 10.125.
@@ -210,9 +215,9 @@ LIBC_INLINE float erfcf(float x) {
unsigned shift = 147 - (x_abs >> 23);
uint32_t mantissa = (x_abs & 0x007FFFFFU) | 0x00800000U;
- int idx = static_cast<int>(mantissa >> shift);
+ uint32_t idx = mantissa >> shift;
- if (idx >= 32) {
+ if (idx >= 32U) {
// For |x| >= 4.0, we use an asymptotic expansion in terms of t = 1/x^2.
// This accurately computes the steep decay of erfc over the domain
// [4.0, 10.125].
diff --git a/libc/test/src/math/erfcf_test.cpp b/libc/test/src/math/erfcf_test.cpp
index 83fa20c999b331..a6c596e2259668 100644
--- a/libc/test/src/math/erfcf_test.cpp
+++ b/libc/test/src/math/erfcf_test.cpp
@@ -35,9 +35,10 @@ TEST_F(LlvmLibcErfcfTest, SpecialNumbers) {
}
TEST_F(LlvmLibcErfcfTest, TrickyInputs) {
- constexpr int N = 1;
+ constexpr int N = 2;
constexpr uint32_t INPUTS[N] = {
0x376c9f62U, // |x| = 0x1.d93ec4p-17f
+ 0x39d693e4U, // |x| = 0x1.ad27c8p-12f, near a rounding boundary
};
for (int i = 0; i < N; ++i) {
float x = FPBits(INPUTS[i]).get_val();
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index f2f257ac29d187..4279c4c81f47e3 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -7550,6 +7550,7 @@ libc_support_library(
name = "__support_math_erfcf",
hdrs = ["src/__support/math/erfcf.h"],
deps = [
+ ":__support_cpp_bit",
":__support_fputil_cast",
":__support_fputil_except_value_utils",
":__support_fputil_fenv_impl",
diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel
index d8914aa3b8ec7d..21c87d80bbf237 100644
--- a/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel
@@ -122,6 +122,8 @@ math_mpfr_test(
math_mpfr_test(name = "erff")
+math_mpfr_test(name = "erfcf")
+
math_mpfr_test(name = "exp")
math_mpfr_test(name = "expf")
diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/math/smoke/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/math/smoke/BUILD.bazel
index 1ea19f953e0adc..f245f640a13424 100644
--- a/utils/bazel/llvm-project-overlay/libc/test/src/math/smoke/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/test/src/math/smoke/BUILD.bazel
@@ -369,6 +369,8 @@ math_test(
math_test(name = "erff")
+math_test(name = "erfcf")
+
math_test(name = "exp")
math_test(name = "expf")
More information about the libc-commits
mailing list