Home | History | Annotate | Download | only in math
      1 /*
      2  * Single-precision sin function.
      3  *
      4  * Copyright (c) 2018, Arm Limited.
      5  * SPDX-License-Identifier: MIT
      6  */
      7 
      8 #if WANT_SINGLEPREC
      9 #include "single/s_sinf.c"
     10 #else
     11 
     12 #include <math.h>
     13 #include "math_config.h"
     14 #include "sincosf.h"
     15 
     16 /* Fast sinf implementation.  Worst-case ULP is 0.5607, maximum relative
     17    error is 0.5303 * 2^-23.  A single-step range reduction is used for
     18    small values.  Large inputs have their range reduced using fast integer
     19    arithmetic.  */
     20 float
     21 sinf (float y)
     22 {
     23   double x = y;
     24   double s;
     25   int n;
     26   const sincos_t *p = &__sincosf_table[0];
     27 
     28   if (abstop12 (y) < abstop12 (pio4))
     29     {
     30       s = x * x;
     31 
     32       if (unlikely (abstop12 (y) < abstop12 (0x1p-12f)))
     33 	{
     34 	  if (unlikely (abstop12 (y) < abstop12 (0x1p-126f)))
     35 	    /* Force underflow for tiny y.  */
     36 	    force_eval_float (s);
     37 	  return y;
     38 	}
     39 
     40       return sinf_poly (x, s, p, 0);
     41     }
     42   else if (likely (abstop12 (y) < abstop12 (120.0f)))
     43     {
     44       x = reduce_fast (x, p, &n);
     45 
     46       /* Setup the signs for sin and cos.  */
     47       s = p->sign[n & 3];
     48 
     49       if (n & 2)
     50 	p = &__sincosf_table[1];
     51 
     52       return sinf_poly (x * s, x * x, p, n);
     53     }
     54   else if (abstop12 (y) < abstop12 (INFINITY))
     55     {
     56       uint32_t xi = asuint (y);
     57       int sign = xi >> 31;
     58 
     59       x = reduce_large (xi, &n);
     60 
     61       /* Setup signs for sin and cos - include original sign.  */
     62       s = p->sign[(n + sign) & 3];
     63 
     64       if ((n + sign) & 2)
     65 	p = &__sincosf_table[1];
     66 
     67       return sinf_poly (x * s, x * x, p, n);
     68     }
     69   else
     70     return __math_invalidf (y);
     71 }
     72 
     73 #endif
     74