[libc-commits] [libc] [libc][math] Implement C23 half precision erfc function (PR #180930)

via libc-commits libc-commits at lists.llvm.org
Sat Mar 21 09:21:49 PDT 2026


https://github.com/AnonMiraj updated https://github.com/llvm/llvm-project/pull/180930

>From 6f952a3e1fb42c66fccc9223409e5c02ef6dea1e Mon Sep 17 00:00:00 2001
From: Ezzeldin Ibrahim <ezzibrahimx at gmail.com>
Date: Wed, 11 Feb 2026 13:01:50 +0200
Subject: [PATCH 1/6] [libc][math] Implement C23 half precision erfc 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/arm/entrypoints.txt     |   1 +
 libc/config/linux/riscv/entrypoints.txt   |   1 +
 libc/config/linux/x86_64/entrypoints.txt  |   1 +
 libc/config/windows/entrypoints.txt       |   1 +
 libc/include/math.yaml                    |   7 +
 libc/shared/math.h                        |   1 +
 libc/shared/math/erfcf16.h                |  27 +++
 libc/src/__support/math/CMakeLists.txt    |  12 ++
 libc/src/__support/math/erfcf16.h         | 196 ++++++++++++++++++++++
 libc/src/math/CMakeLists.txt              |   2 +
 libc/src/math/erfcf16.h                   |  21 +++
 libc/src/math/generic/CMakeLists.txt      |  11 +-
 libc/src/math/generic/erfcf16.cpp         |  16 ++
 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/erfcf16_test.cpp       |  43 +++++
 libc/test/src/math/smoke/CMakeLists.txt   |  10 ++
 libc/test/src/math/smoke/erfcf16_test.cpp |  51 ++++++
 libc/utils/MPFRWrapper/MPCommon.cpp       |   6 +
 libc/utils/MPFRWrapper/MPCommon.h         |   1 +
 libc/utils/MPFRWrapper/MPFRUtils.cpp      |   2 +
 libc/utils/MPFRWrapper/MPFRUtils.h        |   1 +
 26 files changed, 427 insertions(+), 1 deletion(-)
 create mode 100644 libc/shared/math/erfcf16.h
 create mode 100644 libc/src/__support/math/erfcf16.h
 create mode 100644 libc/src/math/erfcf16.h
 create mode 100644 libc/src/math/generic/erfcf16.cpp
 create mode 100644 libc/test/src/math/erfcf16_test.cpp
 create mode 100644 libc/test/src/math/smoke/erfcf16_test.cpp

diff --git a/libc/config/gpu/amdgpu/entrypoints.txt b/libc/config/gpu/amdgpu/entrypoints.txt
index 98c27d300ad9d..1f9c8eeabdadc 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -314,6 +314,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.dfmal
     libc.src.math.dmull
     libc.src.math.dsqrtl
+    libc.src.math.erfcf16
     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 532fcda9ab3be..e5c2c96917403 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -314,6 +314,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.dfmal
     libc.src.math.dmull
     libc.src.math.dsqrtl
+    libc.src.math.erfcf16
     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 380c91e1ac396..facdfa9412e58 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -468,6 +468,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.dmull
     libc.src.math.dsqrtl
     libc.src.math.dsubl
+    libc.src.math.erfcf16
     libc.src.math.erff
     libc.src.math.exp
     libc.src.math.exp10
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 8611082f87003..ac6f841e094a9 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -286,6 +286,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.coshf
     libc.src.math.dfmal
     libc.src.math.dsqrtl
+    libc.src.math.erfcf16
     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 ddb24c3eea178..d7048c286c045 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -472,6 +472,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.dmull
     libc.src.math.dsqrtl
     libc.src.math.dsubl
+    libc.src.math.erfcf16
     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 9102de9bf0417..cc924088a39b1 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -517,6 +517,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.daddl
     libc.src.math.ddivl
     libc.src.math.dsubl
+    libc.src.math.erfcf16
     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 02b56ab01081b..ed1f02f92ec94 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -168,6 +168,7 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.ddivl
     libc.src.math.dfmal
     libc.src.math.dsubl
+    libc.src.math.erfcf16
     libc.src.math.erff
     libc.src.math.exp
     libc.src.math.expf
diff --git a/libc/include/math.yaml b/libc/include/math.yaml
index 8cf29c1a8cff1..055149a6a4e3c 100644
--- a/libc/include/math.yaml
+++ b/libc/include/math.yaml
@@ -403,6 +403,13 @@ functions:
     arguments:
       - type: _Float16
     guard: LIBC_TYPES_HAS_FLOAT16
+  - name: erfcf16
+    standards:
+      - stdc
+    return_type: _Float16
+    arguments:
+      - type: _Float16
+    guard: LIBC_TYPES_HAS_FLOAT16
   - name: exp
     standards:
       - stdc
diff --git a/libc/shared/math.h b/libc/shared/math.h
index 61c3ddffd74e5..07a836bb066c4 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -75,6 +75,7 @@
 #include "math/dfmaf128.h"
 #include "math/dfmal.h"
 #include "math/dsqrtl.h"
+#include "math/erfcf16.h"
 #include "math/erff.h"
 #include "math/erff16.h"
 #include "math/exp.h"
diff --git a/libc/shared/math/erfcf16.h b/libc/shared/math/erfcf16.h
new file mode 100644
index 0000000000000..779401fe5dc09
--- /dev/null
+++ b/libc/shared/math/erfcf16.h
@@ -0,0 +1,27 @@
+//===-- Shared erfcf16 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_ERFCF16_H
+#define LLVM_LIBC_SHARED_MATH_ERFCF16_H
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#include "shared/libc_common.h"
+#include "src/__support/math/erfcf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::erfcf16;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+#endif // LLVM_LIBC_SHARED_MATH_ERFCF16_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 8bb935d863a9b..4c04d1af9e23d 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -884,6 +884,18 @@ add_header_library(
     libc.src.__support.macros.properties.cpu_features
 )
 
+add_header_library(
+  erfcf16
+  HDRS
+    erfcf16.h
+  DEPENDS
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.multiply_add
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+)
+
 add_header_library(
   erff
   HDRS
diff --git a/libc/src/__support/math/erfcf16.h b/libc/src/__support/math/erfcf16.h
new file mode 100644
index 0000000000000..a1e39521a8483
--- /dev/null
+++ b/libc/src/__support/math/erfcf16.h
@@ -0,0 +1,196 @@
+//===-- Implementation header for erfcf16 -----------------------*- 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_ERFCF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ERFCF16_H
+
+#include "include/llvm-libc-macros/float16-macros.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE float16 erfcf16(float16 x) {
+  // Polynomials approximating erfc(|x|) on ( k/8, (k + 1)/8 ) generated by
+  // Sollya with: > P = fpminimax(erfc(x), [|0, 1, 2, 3, 4, 5, 6, 7|], [|D...|],
+  //                             [k/8, (k + 1)/8]);
+  // for k = 0..31.
+  constexpr double COEFFS[32][8] = {
+      {0x1.000000000001ap0, -0x1.20dd75042fe11p0, 0x1.eedc6f1918987p-31,
+       0x1.812743003751cp-2, 0x1.b64a20332eb3dp-20, -0x1.ce4a3020c5e8dp-4,
+       0x1.c23deea13dadap-13, 0x1.ab4a28f5e2202p-6},
+      {0x1.000000261e1a9p0, -0x1.20dd7ba6be17dp0, 0x1.feaa7936695dep-18,
+       0x1.8111aee222bb3p-2, 0x1.1e49370dc07e5p-11, -0x1.d7628d2f099dfp-4,
+       0x1.64a9012704b63p-8, 0x1.507b7d761dbbdp-6},
+      {0x1.00000e7d6c906p0, -0x1.20deeb74e7ceep0, 0x1.06dc8c97aa061p-12,
+       0x1.7f85253e7aa3fp-2, 0x1.9a4f9aedbda2ap-8, -0x1.06934bb956303p-3,
+       0x1.6f9b296bf2cp-6, 0x1.6725f01ebef61p-7},
+      {0x1.0000f0d17e652p0, -0x1.20eec49f1bb9fp0, 0x1.15bf700a3afecp-9,
+       0x1.7742179b9b76p-2, 0x1.bf4cf873dfcc7p-6, -0x1.4a7453b65895cp-3,
+       0x1.a7171b2b94f65p-5, -0x1.3db6226bfb07ep-13},
+      {0x1.00064f5d99b02p0, -0x1.21388015af14dp0, 0x1.1f337b73afb37p-7,
+       0x1.60d75bce880c8p-2, 0x1.21bee64bd2bfep-4, -0x1.b4c9b7cc4d861p-3,
+       0x1.6156b46d67517p-4, -0x1.4a6ad4a1a9a6dp-7},
+      {0x1.001646fa41f93p0, -0x1.21ea485326f4dp0, 0x1.64386e40081f9p-6,
+       0x1.3d6f1181dc1f2p-2, 0x1.025fb3fbb9694p-3, -0x1.111c22989270ep-2,
+       0x1.d6df1d011e6a5p-4, -0x1.11af42f321738p-6},
+      {0x1.00277226071fep0, -0x1.228d8a26ceba9p0, 0x1.056317058c132p-5,
+       0x1.25cda1a141e98p-2, 0x1.42d4218a6d87p-3, -0x1.2b8395261188dp-2,
+       0x1.038075602477dp-3, -0x1.3754fc0d6d03dp-6},
+      {0x1.ffdf656fd5544p-1, -0x1.20dbf015167a4p0, 0x1.426f915ba02ccp-7,
+       0x1.4fb39034f18e7p-2, 0x1.cb1896449b52p-4, -0x1.0c5791c048cfbp-2,
+       0x1.d8acdd7692448p-4, -0x1.19cd761c2fcbfp-6},
+      {0x1.fd52aab04431fp-1, -0x1.18084cdb7869fp0, -0x1.7b239d67be2f2p-4,
+       0x1.fce1bd937aa95p-2, -0x1.c7f53c1a8860cp-5, -0x1.4c0be3dd60746p-3,
+       0x1.511a1822165ccp-4, -0x1.997b355ae9313p-7},
+      {0x1.f630da3ca180fp-1, -0x1.01f9cdebb8a42p0, -0x1.48d5e3d9e3bbbp-2,
+       0x1.ab0c1d54fd42p-1, -0x1.6abcd4a981266p-2, -0x1.b62df36853d2ap-9,
+       0x1.219207ea8070cp-5, -0x1.acb65c612c3cbp-8},
+      {0x1.e8518d1829bdep-1, -0x1.b680bb7f5ca05p-1, -0x1.5dd957f485f26p-1,
+       0x1.50ed752c29101p0, -0x1.7a989bc66b636p-1, 0x1.73a7c29911c75p-3,
+       -0x1.c8f687bc29284p-7, -0x1.d9a2c5e81906dp-11},
+      {0x1.d455b8759924bp-1, -0x1.50d550bd0031ap-1, -0x1.1dd31217d772dp0,
+       0x1.d768acdc964e1p0, -0x1.1f325385cfea3p0, 0x1.64f5ef1e1b149p-2,
+       -0x1.becf19e32832cp-5, 0x1.b3d95b8249dc2p-9},
+      {0x1.c03fc3d1dfd52p-1, -0x1.e5be0a5eb8ea1p-2, -0x1.7c0ea4743a94ap0,
+       0x1.203ad2e0bb23dp1, -0x1.657e5f6a3a7bfp0, 0x1.d5e86ba1d05p-2,
+       -0x1.44444f5e3e2f1p-4, 0x1.7465b9882b39bp-8},
+      {0x1.b82e3874361f8p-1, -0x1.9f1c5ba9f25b5p-2, -0x1.9d2f419b75126p0,
+       0x1.317ed738c38e5p1, -0x1.7b17d3b23fc5cp0, 0x1.f656370d9a5a4p-2,
+       -0x1.5f519dd3bee19p-4, 0x1.9b165d0ccb0fep-8},
+      {0x1.cba592d21041ap-1, -0x1.1c9e2f4ac28efp-1, -0x1.5bcbe8415d66fp0,
+       0x1.12aa2de5d021cp1, -0x1.58324c5f23234p0, 0x1.c6ed4ac6a2edfp-2,
+       -0x1.3b86d3a3e85c9p-4, 0x1.6cc0ec77d11b9p-8},
+      {0x1.03caf33285512p0, -0x1.fb887e48a3eedp-1, -0x1.5431e46bb9a3fp-1,
+       0x1.87e44d6713845p0, -0x1.047b2b206c351p0, 0x1.5c0fe8541e1e5p-2,
+       -0x1.df700bfe6dee5p-5, 0x1.1089feecce9f6p-8},
+      {0x1.37baad7246b3cp0, -0x1.b333d66d61c0cp0, 0x1.9673eefbcd456p-2,
+       0x1.4b8e581c9bd57p-1, -0x1.271a5001975b3p-1, 0x1.a9544c9bc6f69p-3,
+       -0x1.2b04fcf02cfe4p-5, 0x1.52f61b5bf2013p-9},
+      {0x1.7c8089dfc728fp0, -0x1.4aca78f669032p1, 0x1.a50b5166895f1p0,
+       -0x1.52bccda96d2ddp-2, -0x1.db1a7723e7021p-4, 0x1.3e221766f1413p-4,
+       -0x1.07c689c1529d4p-6, 0x1.3e28897c72f86p-10},
+      {0x1.c677ecd59f0c9p0, -0x1.bddee5876d025p1, 0x1.6c05470bf9855p1,
+       -0x1.3838ea389805p0, 0x1.1e0da063ba588p-2, -0x1.c8701de42abb8p-6,
+       -0x1.d505f665736f4p-12, 0x1.ca3e25ddd2f8ep-13},
+      {0x1.0346dd8ccf496p1, -0x1.0e36567843072p2, 0x1.e39ee1779480ap1,
+       -0x1.e05781af98971p0, 0x1.1cd860f207bc6p-1, -0x1.91471b20d7ea7p-4,
+       0x1.3472b380bd896p-7, -0x1.8a32a1c029365p-12},
+      {0x1.175cf188a8137p1, -0x1.2a6aea014a1a7p2, 0x1.13c3894652ae3p2,
+       -0x1.1d97a2368998p1, 0x1.65c57ae4f9a2ep-1, -0x1.0ee6b7e8303e8p-3,
+       0x1.cae7deaf84ca3p-7, -0x1.4f32ea2cd38e3p-11},
+      {0x1.1b0bf6d5ea90bp1, -0x1.2f6bcdbfd2bf8p2, 0x1.199682b413d76p2,
+       -0x1.251f9f5a8b0dap1, 0x1.7174a7ecafc0ep-1, -0x1.19c6a1d04557fp-3,
+       0x1.e164b9a559bfdp-7, -0x1.6320142d50654p-11},
+      {0x1.0d8865040d536p1, -0x1.1e4d7b5aadcb3p2, 0x1.06ffcd830db2p2,
+       -0x1.0eb1633113f1fp1, 0x1.50f8dac72a8f9p-1, -0x1.fb183d2925a88p-4,
+       0x1.aadfbeb9cff03p-7, -0x1.35fe3091fd72bp-11},
+      {0x1.e30746fa5c05ap0, -0x1.f8814cab9a532p1, 0x1.c70d7871e1e66p1,
+       -0x1.cb40d988d46f7p0, 0x1.17ea520e30ee5p-1, -0x1.9bf4656539b33p-4,
+       0x1.52ba88a712da3p-7, -0x1.dff8c68511d54p-12},
+      {0x1.980594d76c9c6p0, -0x1.a1111fecc5d33p1, 0x1.6fac90467734ap1,
+       -0x1.6a38a8cadbc1dp0, 0x1.ae83820056a13p-2, -0x1.3489645378924p-4,
+       0x1.eda542162eab4p-8, -0x1.53f0f5d191e15p-12},
+      {0x1.4593f0667381p0, -0x1.44c18f230e828p1, 0x1.17126063fa673p1,
+       -0x1.0bb8315d99e44p0, 0x1.358c4f8bf482ep-2, -0x1.af3eebe9cb455p-5,
+       0x1.4f090acf146ep-8, -0x1.bfc7954478304p-13},
+      {0x1.ebcae3fdca674p-1, -0x1.dde1bcf5a5146p0, 0x1.8fb142f724b27p0,
+       -0x1.74e2bafe8789fp-1, 0x1.a2f67a40275d7p-3, -0x1.1b6406e10fca4p-5,
+       0x1.ab4ed0d6da84fp-9, -0x1.14f03579c96fep-13},
+      {0x1.6038027133b66p-1, -0x1.4d18991ed6939p0, 0x1.0ef1d6fa80951p0,
+       -0x1.eb55a8112702cp-2, 0x1.0c19cb48e5a46p-3, -0x1.60151a50d69f3p-6,
+       0x1.018b2a2cf7aa6p-9, -0x1.43bda617ae0e6p-14},
+      {0x1.df3b0de232601p-2, -0x1.b8e05100448c4p-1, 0x1.5ca6e2528e8d1p-1,
+       -0x1.332de46c2acb5p-2, 0x1.4595849385e42p-4, -0x1.9f152046c7178p-7,
+       0x1.26a2e0a31e9fp-10, -0x1.67436e13d44ddp-15},
+      {0x1.3628cccb902e9p-2, -0x1.1587e442957f9p-1, 0x1.aabedffc2818p-2,
+       -0x1.6d5f4f24a94a1p-3, 0x1.782f957586c48p-5, -0x1.d1b4c8cd3d9ap-8,
+       0x1.40e4007f68b4dp-11, -0x1.7bb3eac541f35p-16},
+      {0x1.7e774f23dd5d8p-3, -0x1.4ce552c93ab17p-2, 0x1.f1ba61425c57ap-3,
+       -0x1.9e391990469f7p-4, 0x1.9e6adf17223b9p-6, -0x1.f2601fc8d5f7ep-9,
+       0x1.4d7f6c4dab8cap-12, -0x1.7f24e1a9c9b8ap-17},
+      {0x1.c0bbabb6ec859p-4, -0x1.7bf5902ff3dfcp-3, 0x1.143e24f2802a6p-3,
+       -0x1.bf08869d7e41p-5, 0x1.b2b78fe704f97p-7, -0x1.fc05ca0a46accp-10,
+       0x1.4a472fc484f8ap-13, -0x1.7091cb146f95ap-18},
+  };
+
+  using FPBits = typename fputil::FPBits<float16>;
+  FPBits xbits(x);
+  uint16_t x_abs = xbits.abs().uintval();
+
+  // Special cases: NaN and Inf
+  if (LIBC_UNLIKELY(x_abs >= 0x7c00U)) {
+    if (x_abs > 0x7c00U) {
+      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() ? static_cast<float16>(2.0)
+                          : static_cast<float16>(0.0);
+  }
+
+  if (LIBC_UNLIKELY(x_abs == 0))
+    return 1.0f16;
+
+  // Asymptotic behavior: erfc(x) rounds to 0 or 2 for |x| >= 4.0.
+  if (LIBC_UNLIKELY(x_abs >= 0x4400U)) { // |x| >= 4.0
+    if (xbits.is_neg()) {
+      // 0x1.0p-12 is ~0.25 ULP of 2.0 in float16, small enough to round
+      // to 2.0 in RN, but large enough to round down in RD/RZ.
+      double xd = static_cast<double>(x);
+      return static_cast<float16>(2.0 - 0x1.0p-12 * (4.0 / -xd));
+    }
+    return 0.0f16;
+  }
+
+  // Polynomial approximation:
+  //   erfc(x) ~ erfc(|x|)      if x >= 0
+  //   erfc(x) ~ 2 - erfc(|x|)  if x < 0
+  // erfc(|x|) is evaluated using a degree-7 polynomial on each sub-interval.
+
+  float xf = static_cast<float>(xbits.abs().get_val());
+  int idx = static_cast<int>(xf * 8.0f);
+
+  double xd = static_cast<double>(xbits.abs().get_val());
+  double xsq = xd * xd;
+  double x4 = xsq * xsq;
+
+  double p01 = fputil::multiply_add(xd, COEFFS[idx][1], COEFFS[idx][0]);
+  double p23 = fputil::multiply_add(xd, COEFFS[idx][3], COEFFS[idx][2]);
+  double p45 = fputil::multiply_add(xd, COEFFS[idx][5], COEFFS[idx][4]);
+  double p67 = fputil::multiply_add(xd, COEFFS[idx][7], COEFFS[idx][6]);
+
+  double p03 = fputil::multiply_add(xsq, p23, p01);
+  double p47 = fputil::multiply_add(xsq, p67, p45);
+
+  double erfc_abs = fputil::multiply_add(x4, p47, p03);
+
+  if (xbits.is_neg())
+    return static_cast<float16>(2.0 - erfc_abs);
+
+  return static_cast<float16>(erfc_abs);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ERFCF16_H
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 98dba11f34c86..235025b7e1717 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -141,6 +141,8 @@ add_math_entrypoint_object(erf)
 add_math_entrypoint_object(erff)
 add_math_entrypoint_object(erff16)
 
+add_math_entrypoint_object(erfcf16)
+
 add_math_entrypoint_object(exp)
 add_math_entrypoint_object(expf)
 add_math_entrypoint_object(expf16)
diff --git a/libc/src/math/erfcf16.h b/libc/src/math/erfcf16.h
new file mode 100644
index 0000000000000..9f6f983e7000d
--- /dev/null
+++ b/libc/src/math/erfcf16.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for erfcf16 -----------------------*- 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_ERFCF16_H
+#define LLVM_LIBC_SRC_MATH_ERFCF16_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float16 erfcf16(float16 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_ERFCF16_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 07c48c9a04c98..3bd7ddf58c177 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -1293,7 +1293,16 @@ add_entrypoint_object(
     ../erff16.h
   DEPENDS
     libc.src.__support.math.erff16
-    libc.src.errno.errno
+)
+
+add_entrypoint_object(
+  erfcf16
+  SRCS
+    erfcf16.cpp
+  HDRS
+    ../erfcf16.h
+  DEPENDS
+    libc.src.__support.math.erfcf16
 )
 
 add_entrypoint_object(
diff --git a/libc/src/math/generic/erfcf16.cpp b/libc/src/math/generic/erfcf16.cpp
new file mode 100644
index 0000000000000..a1f7397c3b58c
--- /dev/null
+++ b/libc/src/math/generic/erfcf16.cpp
@@ -0,0 +1,16 @@
+//===-- Half-precision erfc(x) 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/erfcf16.h"
+#include "src/__support/math/erfcf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(float16, erfcf16, (float16 x)) { return math::erfcf16(x); }
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index 2e351d8051bed..778f626293227 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -74,6 +74,7 @@ add_fp_unittest(
     libc.src.__support.math.dsqrtl
     libc.src.__support.math.exp10m1f
     libc.src.__support.math.exp10m1f16
+    libc.src.__support.math.erfcf16
     libc.src.__support.math.erff
     libc.src.__support.math.erff16
     libc.src.__support.math.exp
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index 4eb950f030a1a..fa302b5f96dd5 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -31,6 +31,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat16) {
   EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::coshf16(0.0f16));
   EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::cospif16(0.0f16));
   EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::erff16(0.0f16));
+  EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::erfcf16(0.0f));
   EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::exp10f16(0.0f16));
   EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::exp10m1f16(0.0f16));
   EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::exp2f16(0.0f16));
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 2710f4cbdbe31..626dd280cf0f0 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2711,6 +2711,18 @@ add_fp_unittest(
     libc.src.__support.FPUtil.fp_bits
 )
 
+add_fp_unittest(
+  erfcf16_test
+  NEED_MPFR
+  SUITE
+    libc-math-unittests
+  SRCS
+    erfcf16_test.cpp
+  DEPENDS
+    libc.src.math.erfcf16
+    libc.src.__support.FPUtil.fp_bits
+)
+
 add_fp_unittest(
   pow_test
   NEED_MPFR
diff --git a/libc/test/src/math/erfcf16_test.cpp b/libc/test/src/math/erfcf16_test.cpp
new file mode 100644
index 0000000000000..d06bca5dc23a6
--- /dev/null
+++ b/libc/test/src/math/erfcf16_test.cpp
@@ -0,0 +1,43 @@
+//===-- Exhaustive test for erfcf16 ---------------------------------------===//
+//
+// 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/__support/macros/optimization.h"
+#include "src/math/erfcf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+using LlvmLibcErfcf16Test = LIBC_NAMESPACE::testing::FPTest<float16>;
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+// Range: [0, Inf];
+// 0x0000 is +0.0, 0x7c00 is +Inf.
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7c00U;
+
+// Range: [-0, -Inf];
+// 0x8000 is -0.0, 0xfc00 is -Inf.
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xfc00U;
+
+TEST_F(LlvmLibcErfcf16Test, PositiveRange) {
+  for (uint16_t v = POS_START; v <= POS_STOP; ++v) {
+    float16 x = FPBits(v).get_val();
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Erfc, x,
+                                   LIBC_NAMESPACE::erfcf16(x), 0.5);
+  }
+}
+
+TEST_F(LlvmLibcErfcf16Test, NegativeRange) {
+  for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) {
+    float16 x = FPBits(v).get_val();
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Erfc, x,
+                                   LIBC_NAMESPACE::erfcf16(x), 0.5);
+  }
+}
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index d92e6b728b63e..7c56e188ba35e 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -5169,6 +5169,16 @@ add_fp_unittest(
     libc.src.math.erff16
 )
 
+add_fp_unittest(
+  erfcf16_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    erfcf16_test.cpp
+  DEPENDS
+    libc.src.math.erfcf16
+)
+
 add_fp_unittest(
   pow_test
   SUITE
diff --git a/libc/test/src/math/smoke/erfcf16_test.cpp b/libc/test/src/math/smoke/erfcf16_test.cpp
new file mode 100644
index 0000000000000..f6e11da360f4e
--- /dev/null
+++ b/libc/test/src/math/smoke/erfcf16_test.cpp
@@ -0,0 +1,51 @@
+//===-- Unittests for erfcf16 ---------------------------------------------===//
+//
+// 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/math/erfcf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcErfcTest = LIBC_NAMESPACE::testing::FPTest<float16>;
+
+TEST_F(LlvmLibcErfcTest, SpecialNumbers) {
+  EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::erfcf16(sNaN), FE_INVALID);
+  EXPECT_MATH_ERRNO(0);
+
+  EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::erfcf16(aNaN));
+  EXPECT_FP_EQ_ALL_ROUNDING(0.0f16, LIBC_NAMESPACE::erfcf16(inf));
+  EXPECT_FP_EQ_ALL_ROUNDING(2.0f16, LIBC_NAMESPACE::erfcf16(neg_inf));
+  EXPECT_FP_EQ_ALL_ROUNDING(1.0f16, LIBC_NAMESPACE::erfcf16(zero));
+  EXPECT_FP_EQ_ALL_ROUNDING(1.0f16, LIBC_NAMESPACE::erfcf16(neg_zero));
+}
+
+#ifdef LIBC_TEST_FTZ_DAZ
+
+using namespace LIBC_NAMESPACE::testing;
+
+TEST_F(LlvmLibcErfcTest, FTZMode) {
+  ModifyMXCSR mxcsr(FTZ);
+  EXPECT_FP_EQ(1.0f16, LIBC_NAMESPACE::erfcf16(min_denormal));
+  EXPECT_FP_EQ(1.0f16, LIBC_NAMESPACE::erfcf16(max_denormal));
+}
+
+TEST_F(LlvmLibcErfcTest, DAZMode) {
+  ModifyMXCSR mxcsr(DAZ);
+  EXPECT_FP_EQ(1.0f16, LIBC_NAMESPACE::erfcf16(min_denormal));
+  EXPECT_FP_EQ(1.0f16, LIBC_NAMESPACE::erfcf16(max_denormal));
+}
+
+TEST_F(LlvmLibcErfcTest, FTZDAZMode) {
+  ModifyMXCSR mxcsr(FTZ | DAZ);
+
+  EXPECT_FP_EQ(1.0f16, LIBC_NAMESPACE::erfcf16(min_denormal));
+  EXPECT_FP_EQ(1.0f16, LIBC_NAMESPACE::erfcf16(max_denormal));
+}
+
+#endif
diff --git a/libc/utils/MPFRWrapper/MPCommon.cpp b/libc/utils/MPFRWrapper/MPCommon.cpp
index 47d15b3981efe..9fa50b9187dff 100644
--- a/libc/utils/MPFRWrapper/MPCommon.cpp
+++ b/libc/utils/MPFRWrapper/MPCommon.cpp
@@ -210,6 +210,12 @@ MPFRNumber MPFRNumber::erf() const {
   return result;
 }
 
+MPFRNumber MPFRNumber::erfc() const {
+  MPFRNumber result(*this);
+  mpfr_erfc(result.value, value, mpfr_rounding);
+  return result;
+}
+
 MPFRNumber MPFRNumber::exp() const {
   MPFRNumber result(*this);
   mpfr_exp(result.value, value, mpfr_rounding);
diff --git a/libc/utils/MPFRWrapper/MPCommon.h b/libc/utils/MPFRWrapper/MPCommon.h
index cb39735ca0bc6..b8d144e1582b4 100644
--- a/libc/utils/MPFRWrapper/MPCommon.h
+++ b/libc/utils/MPFRWrapper/MPCommon.h
@@ -200,6 +200,7 @@ class MPFRNumber {
   MPFRNumber cosh() const;
   MPFRNumber cospi() const;
   MPFRNumber erf() const;
+  MPFRNumber erfc() const;
   MPFRNumber exp() const;
   MPFRNumber exp2() const;
   MPFRNumber exp2m1() const;
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index d9f444cfa8a76..1f63962216647 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -59,6 +59,8 @@ unary_operation(Operation op, InputType input, unsigned int precision,
     return mpfrInput.cospi();
   case Operation::Erf:
     return mpfrInput.erf();
+  case Operation::Erfc:
+    return mpfrInput.erfc();
   case Operation::Exp:
     return mpfrInput.exp();
   case Operation::Exp2:
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.h b/libc/utils/MPFRWrapper/MPFRUtils.h
index 6c24b66324c1a..9bfc5be507a59 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.h
+++ b/libc/utils/MPFRWrapper/MPFRUtils.h
@@ -40,6 +40,7 @@ enum class Operation : int {
   Cosh,
   Cospi,
   Erf,
+  Erfc,
   Exp,
   Exp2,
   Exp2m1,

>From a471c8dfd386669d16c552b34a54e77627aedb12 Mon Sep 17 00:00:00 2001
From: Ezzeldin Ibrahim <ezzibrahimx at gmail.com>
Date: Sun, 15 Feb 2026 08:07:27 +0200
Subject: [PATCH 2/6] fix windows build fail

---
 libc/config/windows/entrypoints.txt | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index ed1f02f92ec94..02b56ab01081b 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -168,7 +168,6 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.ddivl
     libc.src.math.dfmal
     libc.src.math.dsubl
-    libc.src.math.erfcf16
     libc.src.math.erff
     libc.src.math.exp
     libc.src.math.expf

>From 6b373e0706828692e2968d9109672d93a03a6791 Mon Sep 17 00:00:00 2001
From: Ezzeldin Ibrahim <ezzibrahimx at gmail.com>
Date: Tue, 17 Feb 2026 18:19:52 +0200
Subject: [PATCH 3/6] guard float16 entrypoints

---
 libc/config/gpu/amdgpu/entrypoints.txt    | 2 +-
 libc/config/gpu/nvptx/entrypoints.txt     | 2 +-
 libc/config/linux/aarch64/entrypoints.txt | 2 +-
 libc/config/linux/arm/entrypoints.txt     | 1 -
 libc/config/linux/riscv/entrypoints.txt   | 2 +-
 libc/config/linux/x86_64/entrypoints.txt  | 2 +-
 6 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/libc/config/gpu/amdgpu/entrypoints.txt b/libc/config/gpu/amdgpu/entrypoints.txt
index 1f9c8eeabdadc..b6a792c588cf5 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -314,7 +314,6 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.dfmal
     libc.src.math.dmull
     libc.src.math.dsqrtl
-    libc.src.math.erfcf16
     libc.src.math.erff
     libc.src.math.exp
     libc.src.math.exp10
@@ -533,6 +532,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.coshf16
     libc.src.math.cospif16
     libc.src.math.erff16
+    libc.src.math.erfcf16
     libc.src.math.exp10f16
     libc.src.math.exp10m1f16
     libc.src.math.exp2f16
diff --git a/libc/config/gpu/nvptx/entrypoints.txt b/libc/config/gpu/nvptx/entrypoints.txt
index e5c2c96917403..e94ae4324f8f0 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -314,7 +314,6 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.dfmal
     libc.src.math.dmull
     libc.src.math.dsqrtl
-    libc.src.math.erfcf16
     libc.src.math.erff
     libc.src.math.exp
     libc.src.math.exp10
@@ -535,6 +534,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.coshf16
     libc.src.math.cospif16
     libc.src.math.erff16
+    libc.src.math.erfcf16
     libc.src.math.exp10f16
     libc.src.math.exp10m1f16
     libc.src.math.exp2f16
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index facdfa9412e58..84ae96c68b7b1 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -468,7 +468,6 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.dmull
     libc.src.math.dsqrtl
     libc.src.math.dsubl
-    libc.src.math.erfcf16
     libc.src.math.erff
     libc.src.math.exp
     libc.src.math.exp10
@@ -689,6 +688,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.copysignf16
     libc.src.math.cospif16
     libc.src.math.erff16
+    libc.src.math.erfcf16
     libc.src.math.expf16
     libc.src.math.f16add
     libc.src.math.f16addf
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index ac6f841e094a9..8611082f87003 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -286,7 +286,6 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.coshf
     libc.src.math.dfmal
     libc.src.math.dsqrtl
-    libc.src.math.erfcf16
     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 d7048c286c045..2fd2b8df41e4b 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -472,7 +472,6 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.dmull
     libc.src.math.dsqrtl
     libc.src.math.dsubl
-    libc.src.math.erfcf16
     libc.src.math.erff
     libc.src.math.exp
     libc.src.math.exp10
@@ -703,6 +702,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.coshf16
     libc.src.math.cospif16
     libc.src.math.erff16
+    libc.src.math.erfcf16
     libc.src.math.exp10f16
     libc.src.math.exp10m1f16
     libc.src.math.exp2f16
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index cc924088a39b1..ef4daea525de4 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -517,7 +517,6 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.daddl
     libc.src.math.ddivl
     libc.src.math.dsubl
-    libc.src.math.erfcf16
     libc.src.math.erff
     libc.src.math.exp
     libc.src.math.exp10
@@ -752,6 +751,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.coshf16
     libc.src.math.cospif16
     libc.src.math.erff16
+    libc.src.math.erfcf16
     libc.src.math.exp10f16
     libc.src.math.exp10m1f16
     libc.src.math.exp2f16

>From e110eb0371900d308382c917198ce564462f7bb0 Mon Sep 17 00:00:00 2001
From: Anonmiraj <ezzibrahimx at gmail.com>
Date: Fri, 13 Mar 2026 06:14:31 +0200
Subject: [PATCH 4/6] fix nits

---
 libc/src/__support/math/CMakeLists.txt |  1 +
 libc/src/__support/math/erfcf16.h      | 19 +++++++++----------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 4c04d1af9e23d..030fa1b4ace36 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -889,6 +889,7 @@ add_header_library(
   HDRS
     erfcf16.h
   DEPENDS
+    libc.src.__support.FPUtil.cast
     libc.src.__support.FPUtil.fenv_impl
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.multiply_add
diff --git a/libc/src/__support/math/erfcf16.h b/libc/src/__support/math/erfcf16.h
index a1e39521a8483..510017f7d1aea 100644
--- a/libc/src/__support/math/erfcf16.h
+++ b/libc/src/__support/math/erfcf16.h
@@ -15,6 +15,7 @@
 
 #include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/cast.h"
 #include "src/__support/FPUtil/multiply_add.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
@@ -141,8 +142,8 @@ LIBC_INLINE float16 erfcf16(float16 x) {
       return x;
     }
     // erfc(+Inf) = 0, erfc(-Inf) = 2
-    return xbits.is_neg() ? static_cast<float16>(2.0)
-                          : static_cast<float16>(0.0);
+    return xbits.is_neg() ? fputil::cast<float16>(2.0)
+                          : fputil::cast<float16>(0.0);
   }
 
   if (LIBC_UNLIKELY(x_abs == 0))
@@ -153,8 +154,8 @@ LIBC_INLINE float16 erfcf16(float16 x) {
     if (xbits.is_neg()) {
       // 0x1.0p-12 is ~0.25 ULP of 2.0 in float16, small enough to round
       // to 2.0 in RN, but large enough to round down in RD/RZ.
-      double xd = static_cast<double>(x);
-      return static_cast<float16>(2.0 - 0x1.0p-12 * (4.0 / -xd));
+      double xd = fputil::cast<double>(x);
+      return fputil::cast<float16>(2.0 - 0x1.0p-12 * (4.0 / -xd));
     }
     return 0.0f16;
   }
@@ -164,10 +165,8 @@ LIBC_INLINE float16 erfcf16(float16 x) {
   //   erfc(x) ~ 2 - erfc(|x|)  if x < 0
   // erfc(|x|) is evaluated using a degree-7 polynomial on each sub-interval.
 
-  float xf = static_cast<float>(xbits.abs().get_val());
-  int idx = static_cast<int>(xf * 8.0f);
-
-  double xd = static_cast<double>(xbits.abs().get_val());
+  int idx = static_cast<int>(xbits.abs().get_val() * 8.0f16);
+  double xd = fputil::cast<double>(xbits.abs().get_val());
   double xsq = xd * xd;
   double x4 = xsq * xsq;
 
@@ -182,9 +181,9 @@ LIBC_INLINE float16 erfcf16(float16 x) {
   double erfc_abs = fputil::multiply_add(x4, p47, p03);
 
   if (xbits.is_neg())
-    return static_cast<float16>(2.0 - erfc_abs);
+    return fputil::cast<float16>(2.0 - erfc_abs);
 
-  return static_cast<float16>(erfc_abs);
+  return fputil::cast<float16>(erfc_abs);
 }
 
 } // namespace math

>From 153b86833feb17e13df6cf8c521e28fa361a5a29 Mon Sep 17 00:00:00 2001
From: Anonmiraj <ezzibrahimx at gmail.com>
Date: Mon, 16 Mar 2026 05:48:23 +0200
Subject: [PATCH 5/6] fix underflow excpetion

---
 libc/src/__support/math/erfcf16.h         |  4 ++++
 libc/test/src/math/smoke/CMakeLists.txt   |  1 +
 libc/test/src/math/smoke/erfcf16_test.cpp | 15 +++++++++++++++
 3 files changed, 20 insertions(+)

diff --git a/libc/src/__support/math/erfcf16.h b/libc/src/__support/math/erfcf16.h
index 510017f7d1aea..2306e4981d572 100644
--- a/libc/src/__support/math/erfcf16.h
+++ b/libc/src/__support/math/erfcf16.h
@@ -157,6 +157,10 @@ LIBC_INLINE float16 erfcf16(float16 x) {
       double xd = fputil::cast<double>(x);
       return fputil::cast<float16>(2.0 - 0x1.0p-12 * (4.0 / -xd));
     }
+    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.0f16;
   }
 
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 7c56e188ba35e..2e001ee848313 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -5176,6 +5176,7 @@ add_fp_unittest(
   SRCS
     erfcf16_test.cpp
   DEPENDS
+    libc.hdr.errno_macros
     libc.src.math.erfcf16
 )
 
diff --git a/libc/test/src/math/smoke/erfcf16_test.cpp b/libc/test/src/math/smoke/erfcf16_test.cpp
index f6e11da360f4e..22df1bcbb0d29 100644
--- a/libc/test/src/math/smoke/erfcf16_test.cpp
+++ b/libc/test/src/math/smoke/erfcf16_test.cpp
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "hdr/errno_macros.h"
 #include "hdr/math_macros.h"
 #include "hdr/stdint_proxy.h"
 #include "src/math/erfcf16.h"
@@ -25,6 +26,20 @@ TEST_F(LlvmLibcErfcTest, SpecialNumbers) {
   EXPECT_FP_EQ_ALL_ROUNDING(1.0f16, LIBC_NAMESPACE::erfcf16(neg_zero));
 }
 
+TEST_F(LlvmLibcErfcTest, Underflow) {
+  EXPECT_FP_EQ_WITH_EXCEPTION(zero, LIBC_NAMESPACE::erfcf16(4.0f16),
+                              FE_UNDERFLOW | FE_INEXACT);
+  EXPECT_MATH_ERRNO(ERANGE);
+
+  EXPECT_FP_EQ_WITH_EXCEPTION(zero, LIBC_NAMESPACE::erfcf16(5.75f16),
+                              FE_UNDERFLOW | FE_INEXACT);
+  EXPECT_MATH_ERRNO(ERANGE);
+
+  EXPECT_FP_EQ_WITH_EXCEPTION(zero, LIBC_NAMESPACE::erfcf16(11.25f16),
+                              FE_UNDERFLOW | FE_INEXACT);
+  EXPECT_MATH_ERRNO(ERANGE);
+}
+
 #ifdef LIBC_TEST_FTZ_DAZ
 
 using namespace LIBC_NAMESPACE::testing;

>From 11593612142cbe2e83ba6a4bafebd3d46ba6dab1 Mon Sep 17 00:00:00 2001
From: Anonmiraj <ezzibrahimx at gmail.com>
Date: Sat, 21 Mar 2026 18:21:33 +0200
Subject: [PATCH 6/6] fix nits

---
 libc/src/__support/math/erfcf16.h | 152 ++++++++++--------------------
 1 file changed, 49 insertions(+), 103 deletions(-)

diff --git a/libc/src/__support/math/erfcf16.h b/libc/src/__support/math/erfcf16.h
index 2306e4981d572..6fc37d7467de7 100644
--- a/libc/src/__support/math/erfcf16.h
+++ b/libc/src/__support/math/erfcf16.h
@@ -16,6 +16,7 @@
 #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/config.h"
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
@@ -25,111 +26,56 @@ namespace LIBC_NAMESPACE_DECL {
 namespace math {
 
 LIBC_INLINE float16 erfcf16(float16 x) {
-  // Polynomials approximating erfc(|x|) on ( k/8, (k + 1)/8 ) generated by
+  // Polynomials approximating erfc(|x|) on ( k/2, (k+1)/2 ) generated by
   // Sollya with: > P = fpminimax(erfc(x), [|0, 1, 2, 3, 4, 5, 6, 7|], [|D...|],
-  //                             [k/8, (k + 1)/8]);
-  // for k = 0..31.
-  constexpr double COEFFS[32][8] = {
-      {0x1.000000000001ap0, -0x1.20dd75042fe11p0, 0x1.eedc6f1918987p-31,
-       0x1.812743003751cp-2, 0x1.b64a20332eb3dp-20, -0x1.ce4a3020c5e8dp-4,
-       0x1.c23deea13dadap-13, 0x1.ab4a28f5e2202p-6},
-      {0x1.000000261e1a9p0, -0x1.20dd7ba6be17dp0, 0x1.feaa7936695dep-18,
-       0x1.8111aee222bb3p-2, 0x1.1e49370dc07e5p-11, -0x1.d7628d2f099dfp-4,
-       0x1.64a9012704b63p-8, 0x1.507b7d761dbbdp-6},
-      {0x1.00000e7d6c906p0, -0x1.20deeb74e7ceep0, 0x1.06dc8c97aa061p-12,
-       0x1.7f85253e7aa3fp-2, 0x1.9a4f9aedbda2ap-8, -0x1.06934bb956303p-3,
-       0x1.6f9b296bf2cp-6, 0x1.6725f01ebef61p-7},
-      {0x1.0000f0d17e652p0, -0x1.20eec49f1bb9fp0, 0x1.15bf700a3afecp-9,
-       0x1.7742179b9b76p-2, 0x1.bf4cf873dfcc7p-6, -0x1.4a7453b65895cp-3,
-       0x1.a7171b2b94f65p-5, -0x1.3db6226bfb07ep-13},
-      {0x1.00064f5d99b02p0, -0x1.21388015af14dp0, 0x1.1f337b73afb37p-7,
-       0x1.60d75bce880c8p-2, 0x1.21bee64bd2bfep-4, -0x1.b4c9b7cc4d861p-3,
-       0x1.6156b46d67517p-4, -0x1.4a6ad4a1a9a6dp-7},
-      {0x1.001646fa41f93p0, -0x1.21ea485326f4dp0, 0x1.64386e40081f9p-6,
-       0x1.3d6f1181dc1f2p-2, 0x1.025fb3fbb9694p-3, -0x1.111c22989270ep-2,
-       0x1.d6df1d011e6a5p-4, -0x1.11af42f321738p-6},
-      {0x1.00277226071fep0, -0x1.228d8a26ceba9p0, 0x1.056317058c132p-5,
-       0x1.25cda1a141e98p-2, 0x1.42d4218a6d87p-3, -0x1.2b8395261188dp-2,
-       0x1.038075602477dp-3, -0x1.3754fc0d6d03dp-6},
-      {0x1.ffdf656fd5544p-1, -0x1.20dbf015167a4p0, 0x1.426f915ba02ccp-7,
-       0x1.4fb39034f18e7p-2, 0x1.cb1896449b52p-4, -0x1.0c5791c048cfbp-2,
-       0x1.d8acdd7692448p-4, -0x1.19cd761c2fcbfp-6},
-      {0x1.fd52aab04431fp-1, -0x1.18084cdb7869fp0, -0x1.7b239d67be2f2p-4,
-       0x1.fce1bd937aa95p-2, -0x1.c7f53c1a8860cp-5, -0x1.4c0be3dd60746p-3,
-       0x1.511a1822165ccp-4, -0x1.997b355ae9313p-7},
-      {0x1.f630da3ca180fp-1, -0x1.01f9cdebb8a42p0, -0x1.48d5e3d9e3bbbp-2,
-       0x1.ab0c1d54fd42p-1, -0x1.6abcd4a981266p-2, -0x1.b62df36853d2ap-9,
-       0x1.219207ea8070cp-5, -0x1.acb65c612c3cbp-8},
-      {0x1.e8518d1829bdep-1, -0x1.b680bb7f5ca05p-1, -0x1.5dd957f485f26p-1,
-       0x1.50ed752c29101p0, -0x1.7a989bc66b636p-1, 0x1.73a7c29911c75p-3,
-       -0x1.c8f687bc29284p-7, -0x1.d9a2c5e81906dp-11},
-      {0x1.d455b8759924bp-1, -0x1.50d550bd0031ap-1, -0x1.1dd31217d772dp0,
-       0x1.d768acdc964e1p0, -0x1.1f325385cfea3p0, 0x1.64f5ef1e1b149p-2,
-       -0x1.becf19e32832cp-5, 0x1.b3d95b8249dc2p-9},
-      {0x1.c03fc3d1dfd52p-1, -0x1.e5be0a5eb8ea1p-2, -0x1.7c0ea4743a94ap0,
-       0x1.203ad2e0bb23dp1, -0x1.657e5f6a3a7bfp0, 0x1.d5e86ba1d05p-2,
-       -0x1.44444f5e3e2f1p-4, 0x1.7465b9882b39bp-8},
-      {0x1.b82e3874361f8p-1, -0x1.9f1c5ba9f25b5p-2, -0x1.9d2f419b75126p0,
-       0x1.317ed738c38e5p1, -0x1.7b17d3b23fc5cp0, 0x1.f656370d9a5a4p-2,
-       -0x1.5f519dd3bee19p-4, 0x1.9b165d0ccb0fep-8},
-      {0x1.cba592d21041ap-1, -0x1.1c9e2f4ac28efp-1, -0x1.5bcbe8415d66fp0,
-       0x1.12aa2de5d021cp1, -0x1.58324c5f23234p0, 0x1.c6ed4ac6a2edfp-2,
-       -0x1.3b86d3a3e85c9p-4, 0x1.6cc0ec77d11b9p-8},
-      {0x1.03caf33285512p0, -0x1.fb887e48a3eedp-1, -0x1.5431e46bb9a3fp-1,
-       0x1.87e44d6713845p0, -0x1.047b2b206c351p0, 0x1.5c0fe8541e1e5p-2,
-       -0x1.df700bfe6dee5p-5, 0x1.1089feecce9f6p-8},
-      {0x1.37baad7246b3cp0, -0x1.b333d66d61c0cp0, 0x1.9673eefbcd456p-2,
-       0x1.4b8e581c9bd57p-1, -0x1.271a5001975b3p-1, 0x1.a9544c9bc6f69p-3,
-       -0x1.2b04fcf02cfe4p-5, 0x1.52f61b5bf2013p-9},
-      {0x1.7c8089dfc728fp0, -0x1.4aca78f669032p1, 0x1.a50b5166895f1p0,
-       -0x1.52bccda96d2ddp-2, -0x1.db1a7723e7021p-4, 0x1.3e221766f1413p-4,
-       -0x1.07c689c1529d4p-6, 0x1.3e28897c72f86p-10},
-      {0x1.c677ecd59f0c9p0, -0x1.bddee5876d025p1, 0x1.6c05470bf9855p1,
-       -0x1.3838ea389805p0, 0x1.1e0da063ba588p-2, -0x1.c8701de42abb8p-6,
-       -0x1.d505f665736f4p-12, 0x1.ca3e25ddd2f8ep-13},
-      {0x1.0346dd8ccf496p1, -0x1.0e36567843072p2, 0x1.e39ee1779480ap1,
-       -0x1.e05781af98971p0, 0x1.1cd860f207bc6p-1, -0x1.91471b20d7ea7p-4,
-       0x1.3472b380bd896p-7, -0x1.8a32a1c029365p-12},
-      {0x1.175cf188a8137p1, -0x1.2a6aea014a1a7p2, 0x1.13c3894652ae3p2,
-       -0x1.1d97a2368998p1, 0x1.65c57ae4f9a2ep-1, -0x1.0ee6b7e8303e8p-3,
-       0x1.cae7deaf84ca3p-7, -0x1.4f32ea2cd38e3p-11},
-      {0x1.1b0bf6d5ea90bp1, -0x1.2f6bcdbfd2bf8p2, 0x1.199682b413d76p2,
-       -0x1.251f9f5a8b0dap1, 0x1.7174a7ecafc0ep-1, -0x1.19c6a1d04557fp-3,
-       0x1.e164b9a559bfdp-7, -0x1.6320142d50654p-11},
-      {0x1.0d8865040d536p1, -0x1.1e4d7b5aadcb3p2, 0x1.06ffcd830db2p2,
-       -0x1.0eb1633113f1fp1, 0x1.50f8dac72a8f9p-1, -0x1.fb183d2925a88p-4,
-       0x1.aadfbeb9cff03p-7, -0x1.35fe3091fd72bp-11},
-      {0x1.e30746fa5c05ap0, -0x1.f8814cab9a532p1, 0x1.c70d7871e1e66p1,
-       -0x1.cb40d988d46f7p0, 0x1.17ea520e30ee5p-1, -0x1.9bf4656539b33p-4,
-       0x1.52ba88a712da3p-7, -0x1.dff8c68511d54p-12},
-      {0x1.980594d76c9c6p0, -0x1.a1111fecc5d33p1, 0x1.6fac90467734ap1,
-       -0x1.6a38a8cadbc1dp0, 0x1.ae83820056a13p-2, -0x1.3489645378924p-4,
-       0x1.eda542162eab4p-8, -0x1.53f0f5d191e15p-12},
-      {0x1.4593f0667381p0, -0x1.44c18f230e828p1, 0x1.17126063fa673p1,
-       -0x1.0bb8315d99e44p0, 0x1.358c4f8bf482ep-2, -0x1.af3eebe9cb455p-5,
-       0x1.4f090acf146ep-8, -0x1.bfc7954478304p-13},
-      {0x1.ebcae3fdca674p-1, -0x1.dde1bcf5a5146p0, 0x1.8fb142f724b27p0,
-       -0x1.74e2bafe8789fp-1, 0x1.a2f67a40275d7p-3, -0x1.1b6406e10fca4p-5,
-       0x1.ab4ed0d6da84fp-9, -0x1.14f03579c96fep-13},
-      {0x1.6038027133b66p-1, -0x1.4d18991ed6939p0, 0x1.0ef1d6fa80951p0,
-       -0x1.eb55a8112702cp-2, 0x1.0c19cb48e5a46p-3, -0x1.60151a50d69f3p-6,
-       0x1.018b2a2cf7aa6p-9, -0x1.43bda617ae0e6p-14},
-      {0x1.df3b0de232601p-2, -0x1.b8e05100448c4p-1, 0x1.5ca6e2528e8d1p-1,
-       -0x1.332de46c2acb5p-2, 0x1.4595849385e42p-4, -0x1.9f152046c7178p-7,
-       0x1.26a2e0a31e9fp-10, -0x1.67436e13d44ddp-15},
-      {0x1.3628cccb902e9p-2, -0x1.1587e442957f9p-1, 0x1.aabedffc2818p-2,
-       -0x1.6d5f4f24a94a1p-3, 0x1.782f957586c48p-5, -0x1.d1b4c8cd3d9ap-8,
-       0x1.40e4007f68b4dp-11, -0x1.7bb3eac541f35p-16},
-      {0x1.7e774f23dd5d8p-3, -0x1.4ce552c93ab17p-2, 0x1.f1ba61425c57ap-3,
-       -0x1.9e391990469f7p-4, 0x1.9e6adf17223b9p-6, -0x1.f2601fc8d5f7ep-9,
-       0x1.4d7f6c4dab8cap-12, -0x1.7f24e1a9c9b8ap-17},
-      {0x1.c0bbabb6ec859p-4, -0x1.7bf5902ff3dfcp-3, 0x1.143e24f2802a6p-3,
-       -0x1.bf08869d7e41p-5, 0x1.b2b78fe704f97p-7, -0x1.fc05ca0a46accp-10,
-       0x1.4a472fc484f8ap-13, -0x1.7091cb146f95ap-18},
+  //                             [k/2, (k+1)/2]);
+  //
+  // for k = 0..7.
+  constexpr double COEFFS[8][8] = {
+      {0x1.00000006e5898p0, -0x1.20dd7b4435481p0, 0x1.e2ffc0264c37cp-17,
+       0x1.80ef5566d3135p-2, 0x1.96ef459387c13p-10, -0x1.e6f847a52d3fep-4,
+       0x1.9a59af64a5dfap-7, 0x1.f652f3b14963bp-7},
+      {0x1.001a9f1d3c0b4p0, -0x1.221a42637ae8p0, 0x1.9c3ddc1e5d176p-6,
+       0x1.347481936316bp-2, 0x1.1db66a2746b8bp-3, -0x1.1d7a264182166p-2,
+       0x1.ef858095e1609p-4, -0x1.26936198d6b07p-6},
+      {0x1.f08a38741577bp-1, -0x1.e26ae90822fp-1, -0x1.f300a88478724p-2,
+       0x1.115a0580ba3f8p0, -0x1.1a1c2bc3ffcdap-1, 0x1.888d0c9a082b8p-4,
+       0x1.f41c9f1877fdfp-8, -0x1.a72fb878df30bp-9},
+      {0x1.c1cabe622be64p-1, -0x1.ee19257d1037ap-2, -0x1.7a725229a24b8p0,
+       0x1.2089bc62b1069p1, -0x1.673f1b9fbced5p0, 0x1.da7db686b0475p-2,
+       -0x1.49a292662ca6ap-4, 0x1.7e2b298da504dp-8},
+      {0x1.a466e958ca525p0, -0x1.8a850d50339a9p1, 0x1.29b741ccfdd3ap1,
+       -0x1.b250e97982f77p-1, 0x1.ea6896c5fa419p-4, 0x1.b332978509bf1p-7,
+       -0x1.9f1c5d9122108p-8, 0x1.2fb4d83883203p-11},
+      {0x1.12fb16acc5644p1, -0x1.25003c37e1b24p2, 0x1.0e0dc863b2f12p2,
+       -0x1.16f179d8797a6p1, 0x1.5c8b140bf43f8p-1, -0x1.07473d994c2edp-3,
+       0x1.bd0c1c2d2a9e3p-7, -0x1.448767255aabbp-11},
+      {0x1.13a691333e22ap0, -0x1.0e2a642d8d318p1, 0x1.c7d88193df94bp0,
+       -0x1.acf7c7b79498fp-1, 0x1.e626f6202a127p-3, -0x1.4babcc8609859p-5,
+       0x1.f860060a3658p-9, -0x1.49a4190580d4p-13},
+      {0x1.cf3a84bf655afp-3, -0x1.968e6988b5cep-2, 0x1.326f1f9499739p-2,
+       -0x1.011785d112c9bp-3, 0x1.0343a0c05e285p-5, -0x1.3a3ae5e48130ep-8,
+       0x1.a7c5af0484892p-12, -0x1.ea82a062010c3p-17},
   };
 
+  static constexpr size_t N_ERFCF16_EXCEPTS = 3;
+  static constexpr fputil::ExceptValues<float16, N_ERFCF16_EXCEPTS>
+      ERFCF16_EXCEPTS = {{
+          // (input, RZ output, RU offset, RD offset, RN offset)
+          // x = 0x0.000216, erfc(x) = 0x1.000
+          {0x0B17, 0x3BFF, 1, 0, 0},
+          // x = 0x0.00346, erfc(x) = 0x0.ff8
+          {0x1B17, 0x3BF7, 1, 0, 1},
+          // x = -0x0.00346, erfc(x) = 0x1.00c
+          {0x9B17, 0x3C04, 1, 0, 0},
+      }};
   using FPBits = typename fputil::FPBits<float16>;
   FPBits xbits(x);
+  uint16_t x_u = xbits.uintval();
+
+  if (auto r = ERFCF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
+    return r.value();
+
   uint16_t x_abs = xbits.abs().uintval();
 
   // Special cases: NaN and Inf
@@ -154,8 +100,8 @@ LIBC_INLINE float16 erfcf16(float16 x) {
     if (xbits.is_neg()) {
       // 0x1.0p-12 is ~0.25 ULP of 2.0 in float16, small enough to round
       // to 2.0 in RN, but large enough to round down in RD/RZ.
-      double xd = fputil::cast<double>(x);
-      return fputil::cast<float16>(2.0 - 0x1.0p-12 * (4.0 / -xd));
+      float xf = fputil::cast<float>(x);
+      return fputil::cast<float16>(2.0 - 0x1.0p-12 * (-4.0 / xf));
     }
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
@@ -169,7 +115,7 @@ LIBC_INLINE float16 erfcf16(float16 x) {
   //   erfc(x) ~ 2 - erfc(|x|)  if x < 0
   // erfc(|x|) is evaluated using a degree-7 polynomial on each sub-interval.
 
-  int idx = static_cast<int>(xbits.abs().get_val() * 8.0f16);
+  int idx = static_cast<int>(xbits.abs().get_val() * 2.0f);
   double xd = fputil::cast<double>(xbits.abs().get_val());
   double xsq = xd * xd;
   double x4 = xsq * xsq;



More information about the libc-commits mailing list