Path: blob/main/contrib/arm-optimized-routines/math/aarch64/experimental/atan_2u5.c
48375 views
/*1* Double-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 "test_sig.h"8#include "test_defs.h"9#include "atan_common.h"1011#define AbsMask 0x7fffffffffffffff12#define PiOver2 0x1.921fb54442d18p+013#define TinyBound 0x3e1 /* top12(asuint64(0x1p-30)). */14#define BigBound 0x434 /* top12(asuint64(0x1p53)). */15#define OneTop 0x3ff1617/* Fast implementation of double-precision atan.18Based on atan(x) ~ shift + z + z^3 * P(z^2) with reduction to [0,1] using19z=1/x and shift = pi/2. Maximum observed error is 2.27 ulps:20atan(0x1.0005af27c23e9p+0) got 0x1.9225645bdd7c1p-121want 0x1.9225645bdd7c3p-1. */22double23atan (double x)24{25uint64_t ix = asuint64 (x);26uint64_t sign = ix & ~AbsMask;27uint64_t ia = ix & AbsMask;28uint32_t ia12 = ia >> 52;2930if (unlikely (ia12 >= BigBound || ia12 < TinyBound))31{32if (ia12 < TinyBound)33/* Avoid underflow by returning x. */34return x;35if (ia > 0x7ff0000000000000)36/* Propagate NaN. */37return __math_invalid (x);38/* atan(x) rounds to PiOver2 for large x. */39return asdouble (asuint64 (PiOver2) ^ sign);40}4142double z, az, shift;43if (ia12 >= OneTop)44{45/* For x > 1, use atan(x) = pi / 2 + atan(-1 / x). */46z = -1.0 / x;47shift = PiOver2;48/* Use absolute value only when needed (odd powers of z). */49az = -fabs (z);50}51else52{53/* For x < 1, approximate atan(x) directly. */54z = x;55shift = 0;56az = asdouble (ia);57}5859/* Calculate polynomial, shift + z + z^3 * P(z^2). */60double y = eval_poly (z, az, shift);61/* Copy sign. */62return asdouble (asuint64 (y) ^ sign);63}6465TEST_SIG (S, D, 1, atan, -10.0, 10.0)66TEST_ULP (atan, 1.78)67TEST_INTERVAL (atan, 0, 0x1p-30, 10000)68TEST_INTERVAL (atan, -0, -0x1p-30, 1000)69TEST_INTERVAL (atan, 0x1p-30, 0x1p53, 900000)70TEST_INTERVAL (atan, -0x1p-30, -0x1p53, 90000)71TEST_INTERVAL (atan, 0x1p53, inf, 10000)72TEST_INTERVAL (atan, -0x1p53, -inf, 1000)737475