1 /* 2 * s_tanf.c - single precision tangent function 3 * 4 * Copyright (c) 2009-2018, Arm Limited. 5 * SPDX-License-Identifier: MIT 6 */ 7 8 /* 9 * Source: my own head, and Remez-generated polynomial approximations. 10 */ 11 12 #include <math.h> 13 #include "math_private.h" 14 #include <errno.h> 15 #include <fenv.h> 16 #include "rredf.h" 17 18 #ifdef __cplusplus 19 extern "C" { 20 #endif /* __cplusplus */ 21 22 float tanf(float x) 23 { 24 int q; 25 26 /* 27 * Range-reduce x to the range [-pi/4,pi/4]. 28 */ 29 { 30 /* 31 * I enclose the call to __mathlib_rredf in braces so that 32 * the address-taken-ness of qq does not propagate 33 * throughout the rest of the function, for what that might 34 * be worth. 35 */ 36 int qq; 37 x = __mathlib_rredf(x, &qq); 38 q = qq; 39 } 40 if (__builtin_expect(q < 0, 0)) { /* this signals tiny, inf, or NaN */ 41 unsigned k = fai(x) << 1; 42 if (k < 0xFF000000) /* tiny */ 43 return FLOAT_CHECKDENORM(x); 44 else if (k == 0xFF000000) /* inf */ 45 return MATHERR_TANF_INF(x); 46 else /* NaN */ 47 return FLOAT_INFNAN(x); 48 } 49 50 /* 51 * We use a direct polynomial approximation for tan(x) on 52 * [-pi/4,pi/4], and then take the negative reciprocal of the 53 * result if we're in an interval surrounding an odd rather than 54 * even multiple of pi/2. 55 * 56 * Coefficients generated by the command 57 58 ./auxiliary/remez.jl --variable=x2 --suffix=f -- '0' '(pi/BigFloat(4))^2' 5 0 'x==0 ? 1/BigFloat(3) : (tan(sqrt(x))-sqrt(x))/sqrt(x^3)' 'sqrt(x^3)' 59 60 */ 61 { 62 float x2 = x*x; 63 x += x * (x2 * ( 64 3.333294809182307633621540045249152105330074691488121206914336806061620616979305e-01f+x2*(1.334274588580033216191949445078951865160600494428914956688702429547258497367525e-01f+x2*(5.315177279765676178198868818834880279286012428084733419724267810723468887753723e-02f+x2*(2.520300881849204519070372772571624013984546591252791443673871814078418474596388e-02f+x2*(2.051177187082974766686645514206648277055233230110624602600687812103764075834307e-03f+x2*(9.943421494628597182458186353995299429948224864648292162238582752158235742046109e-03f))))) 65 )); 66 if (q & 1) 67 x = -1.0f/x; 68 69 return x; 70 } 71 } 72 73 #ifdef __cplusplus 74 } /* end of extern "C" */ 75 #endif /* __cplusplus */ 76 77 /* end of s_tanf.c */ 78