Path: blob/main/contrib/arm-optimized-routines/math/aarch64/experimental/erfcf_1u7.c
48375 views
/*1* Single-precision erfc(x) function.2*3* Copyright (c) 2023-2024, Arm Limited.4* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception5*/67#include "math_config.h"8#include "test_sig.h"9#include "test_defs.h"1011#define Shift 0x1p17f12#define OneThird 0x1.555556p-2f13#define TwoThird 0x1.555556p-1f1415#define TwoOverFifteen 0x1.111112p-3f16#define TwoOverFive 0x1.99999ap-2f17#define Tenth 0x1.99999ap-4f1819#define SignMask 0x7fffffff2021/* Fast erfcf approximation based on series expansion near x rounded to22nearest multiple of 1/64.23Let d = x - r, and scale = 2 / sqrt(pi) * exp(-r^2). For x near r,2425erfc(x) ~ erfc(r) - scale * d * poly(r, d), with2627poly(r, d) = 1 - r d + (2/3 r^2 - 1/3) d^2 - r (1/3 r^2 - 1/2) d^328+ (2/15 r^4 - 2/5 r^2 + 1/10) d^42930Values of erfc(r) and scale are read from lookup tables. Stored values31are scaled to avoid hitting the subnormal range.3233Note that for x < 0, erfc(x) = 2.0 - erfc(-x).3435Maximum error: 1.63 ULP (~1.0 ULP for x < 0.0).36erfcf(0x1.1dbf7ap+3) got 0x1.f51212p-12037want 0x1.f51216p-120. */38float39erfcf (float x)40{41/* Get top words and sign. */42uint32_t ix = asuint (x);43uint32_t ia = ix & SignMask;44uint32_t sign = ix & ~SignMask;4546/* |x| < 0x1.0p-26 => accurate to 0.5 ULP (top12(0x1p-26) = 0x328). */47if (unlikely (ia < 0x32800000))48return 1.0f - x; /* Small case. */4950/* For |x| < 10.0625, the following approximation holds. */51if (likely (ia < 0x41210000))52{53/* Lookup erfc(r) and scale(r) in tables, e.g. set erfc(r) to 1 and scale54to 2/sqrt(pi), when x reduced to r = 0. */55float a = asfloat (ia);56float z = a + Shift;57uint32_t i = asuint (z) - asuint (Shift);58float r = z - Shift;5960/* These values are scaled by 2^-47. */61float erfcr = __v_erfcf_data.tab[i].erfc;62float scale = __v_erfcf_data.tab[i].scale;6364/* erfc(x) ~ erfc(r) - scale * d * poly (r, d). */65float d = a - r;66float d2 = d * d;67float r2 = r * r;68float p1 = -r;69float p2 = fmaf (TwoThird, r2, -OneThird);70float p3 = -r * fmaf (OneThird, r2, -0.5f);71float p4 = fmaf (fmaf (TwoOverFifteen, r2, -TwoOverFive), r2, Tenth);72float y = fmaf (p4, d, p3);73y = fmaf (y, d, p2);74y = fmaf (y, d, p1);75y = fmaf (-fmaf (y, d2, d), scale, erfcr);76/* Handle sign and scale back in a single fma. */77float off = asfloat (sign >> 1);78float fac = asfloat (asuint (0x1p-47f) | sign);79y = fmaf (y, fac, off);80/* The underflow exception needs to be signaled explicitly when81result gets into subormnal range. */82if (x >= 0x1.2639cp+3f)83force_eval_float (opt_barrier_float (0x1p-123f) * 0x1p-123f);84return y;85}8687/* erfcf(nan)=nan, erfcf(+inf)=0 and erfcf(-inf)=2. */88if (unlikely (ia >= 0x7f800000))89return asfloat (sign >> 1) + 1.0f / x; /* Special cases. */9091/* Above this threshold erfcf is constant and needs to raise underflow92exception for positive x. */93return sign ? 2.0f : __math_uflowf (0);94}9596TEST_SIG (S, F, 1, erfc, -4.0, 10.0)97TEST_ULP (erfcf, 1.14)98TEST_SYM_INTERVAL (erfcf, 0, 0x1p-26, 40000)99TEST_INTERVAL (erfcf, 0x1p-26, 10.0625, 40000)100TEST_INTERVAL (erfcf, -0x1p-26, -4.0, 40000)101TEST_INTERVAL (erfcf, 10.0625, inf, 40000)102TEST_INTERVAL (erfcf, -4.0, -inf, 40000)103104105