Path: blob/main/contrib/arm-optimized-routines/math/aarch64/experimental/atanf_2u9.c
48375 views
/*1* Single-precision atan(x) function.2*3* Copyright (c) 2022-2024, Arm Limited.4* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception5*/67#include "atanf_common.h"8#include "test_sig.h"9#include "test_defs.h"1011#define PiOver2 0x1.921fb6p+0f12#define AbsMask 0x7fffffff13#define TinyBound 0x30800000 /* asuint(0x1p-30). */14#define BigBound 0x4e800000 /* asuint(0x1p30). */15#define One 0x3f8000001617/* Approximation of single-precision atan(x) based on18atan(x) ~ shift + z + z^3 * P(z^2) with reduction to [0,1]19using z=-1/x and shift = pi/2.20Maximum error is 2.88 ulps:21atanf(0x1.0565ccp+0) got 0x1.97771p-122want 0x1.97770ap-1. */23float24atanf (float x)25{26uint32_t ix = asuint (x);27uint32_t sign = ix & ~AbsMask;28uint32_t ia = ix & AbsMask;2930if (unlikely (ia < TinyBound))31/* Avoid underflow by returning x. */32return x;3334if (unlikely (ia > BigBound))35{36if (ia > 0x7f800000)37/* Propagate NaN. */38return __math_invalidf (x);39/* atan(x) rounds to PiOver2 for large x. */40return asfloat (asuint (PiOver2) ^ sign);41}4243float z, az, shift;44if (ia > One)45{46/* For x > 1, use atan(x) = pi / 2 + atan(-1 / x). */47z = -1.0f / x;48shift = PiOver2;49/* Use absolute value only when needed (odd powers of z). */50az = -fabsf (z);51}52else53{54/* For x < 1, approximate atan(x) directly. */55z = x;56az = asfloat (ia);57shift = 0;58}5960/* Calculate polynomial, shift + z + z^3 * P(z^2). */61float y = eval_poly (z, az, shift);62/* Copy sign. */63return asfloat (asuint (y) ^ sign);64}6566TEST_SIG (S, F, 1, atan, -10.0, 10.0)67TEST_ULP (atanf, 2.38)68TEST_SYM_INTERVAL (atanf, 0, 0x1p-30, 5000)69TEST_SYM_INTERVAL (atanf, 0x1p-30, 1, 40000)70TEST_SYM_INTERVAL (atanf, 1, 0x1p30, 40000)71TEST_SYM_INTERVAL (atanf, 0x1p30, inf, 1000)727374