Home | History | Annotate | Download | only in single
      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