Path: blob/main/contrib/arm-optimized-routines/math/aarch64/tanpif_3u1.c
48255 views
/*1* Single-precision scalar tanpi(x) function.2*3* Copyright (c) 2024, Arm Limited.4* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception5*/6#include "mathlib.h"7#include "math_config.h"8#include "test_sig.h"9#include "test_defs.h"10#include "poly_scalar_f32.h"1112const static struct tanpif_data13{14float tan_poly[6], cot_poly[4], pi, invpi;15} tanpif_data = {16/* Coefficents for tan(pi * x). */17.tan_poly = {180x1.4abbc8p3,190x1.467284p5,200x1.44cf12p7,210x1.596b5p9,220x1.753858p10,230x1.76ff52p14,24},25/* Coefficents for cot(pi * x). */26.cot_poly = {27-0x1.0c1522p0,28-0x1.60ce32p-1,29-0x1.49cd42p-1,30-0x1.73f786p-1,31},32.pi = 0x1.921fb6p1f,33.invpi = 0x1.45f308p-2f,34};3536/* Single-precision scalar tanpi(x) implementation.37Maximum error 2.56 ULP:38tanpif(0x1.4bf948p-1) got -0x1.fcc9ep+039want -0x1.fcc9e6p+0. */40float41arm_math_tanpif (float x)42{43uint32_t xabs_12 = asuint (x) >> 20 & 0x7f8;4445/* x >= 0x1p24f. */46if (unlikely (xabs_12 >= 0x4b1))47{48/* tanpif(+/-inf) and tanpif(+/-nan) = nan. */49if (unlikely (xabs_12 == 0x7f8))50{51return __math_invalidf (x);52}5354uint32_t x_sign = asuint (x) & 0x80000000;55return asfloat (x_sign);56}5758const struct tanpif_data *d = ptr_barrier (&tanpif_data);5960/* Prevent underflow exceptions. x <= 0x1p-31. */61if (unlikely (xabs_12 < 0x300))62{63return d->pi * x;64}6566float rounded = roundf (x);67if (unlikely (rounded == x))68{69/* If x == 0, return with sign. */70if (x == 0)71{72return x;73}74/* Otherwise, return zero with alternating sign. */75int32_t m = (int32_t) rounded;76if (x < 0)77{78return m & 1 ? 0.0f : -0.0f;79}80else81{82return m & 1 ? -0.0f : 0.0f;83}84}8586float x_reduced = x - rounded;87float abs_x_reduced = 0.5f - asfloat (asuint (x_reduced) & 0x7fffffff);8889float result, offset, scale;9091/* Test 0.25 < abs_x < 0.5 independent from abs_x_reduced. */92float x2 = x + x;93int32_t rounded_x2 = (int32_t) roundf (x2);94if (rounded_x2 & 1)95{96float r_x = abs_x_reduced;9798float r_x2 = r_x * r_x;99float r_x4 = r_x2 * r_x2;100101uint32_t sign = asuint (x_reduced) & 0x80000000;102r_x = asfloat (asuint (r_x) ^ sign);103104// calculate sign for half-fractional inf values105uint32_t is_finite = asuint (abs_x_reduced);106uint32_t is_odd = (rounded_x2 & 2) << 30;107uint32_t is_neg = rounded_x2 & 0x80000000;108uint32_t keep_sign = is_finite | (is_odd ^ is_neg);109offset = d->invpi / (keep_sign ? r_x : -r_x);110scale = r_x;111112result = pairwise_poly_3_f32 (r_x2, r_x4, d->cot_poly);113}114else115{116float r_x = x_reduced;117118float r_x2 = r_x * r_x;119float r_x4 = r_x2 * r_x2;120121offset = d->pi * r_x;122scale = r_x * r_x2;123124result = pw_horner_5_f32 (r_x2, r_x4, d->tan_poly);125}126127return fmaf (scale, result, offset);128}129130#if WANT_EXPERIMENTAL_MATH131float132tanpif (float x)133{134return arm_math_tanpif (x);135}136#endif137138#if WANT_TRIGPI_TESTS139TEST_ULP (arm_math_tanpif, 2.57)140TEST_SYM_INTERVAL (arm_math_tanpif, 0, 0x1p-31f, 50000)141TEST_SYM_INTERVAL (arm_math_tanpif, 0x1p-31f, 0.5, 100000)142TEST_SYM_INTERVAL (arm_math_tanpif, 0.5, 0x1p23f, 100000)143TEST_SYM_INTERVAL (arm_math_tanpif, 0x1p23f, inf, 100000)144#endif145146147