(root)/
glibc-2.38/
sysdeps/
ieee754/
flt-32/
s_sinf.c
       1  /* Compute sine of argument.
       2     Copyright (C) 2018-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <stdint.h>
      20  #include <math.h>
      21  #include <math-barriers.h>
      22  #include <libm-alias-float.h>
      23  #include "math_config.h"
      24  #include "s_sincosf.h"
      25  
      26  #ifndef SECTION
      27  # define SECTION
      28  #endif
      29  
      30  #ifndef SINF
      31  # define SINF_FUNC __sinf
      32  #else
      33  # define SINF_FUNC SINF
      34  #endif
      35  
      36  /* Fast sinf implementation.  Worst-case ULP is 0.5607, maximum relative
      37     error is 0.5303 * 2^-23.  A single-step range reduction is used for
      38     small values.  Large inputs have their range reduced using fast integer
      39     arithmetic.
      40  */
      41  float
      42  SECTION
      43  SINF_FUNC (float y)
      44  {
      45    double x = y;
      46    double s;
      47    int n;
      48    const sincos_t *p = &__sincosf_table[0];
      49  
      50    if (abstop12 (y) < abstop12 (pio4))
      51      {
      52        s = x * x;
      53  
      54        if (__glibc_unlikely (abstop12 (y) < abstop12 (0x1p-12f)))
      55        {
      56  	/* Force underflow for tiny y.  */
      57  	if (__glibc_unlikely (abstop12 (y) < abstop12 (0x1p-126f)))
      58  	  math_force_eval ((float)s);
      59  	return y;
      60        }
      61  
      62        return sinf_poly (x, s, p, 0);
      63      }
      64    else if (__glibc_likely (abstop12 (y) < abstop12 (120.0f)))
      65      {
      66        x = reduce_fast (x, p, &n);
      67  
      68        /* Setup the signs for sin and cos.  */
      69        s = p->sign[n & 3];
      70  
      71        if (n & 2)
      72  	p = &__sincosf_table[1];
      73  
      74        return sinf_poly (x * s, x * x, p, n);
      75      }
      76    else if (abstop12 (y) < abstop12 (INFINITY))
      77      {
      78        uint32_t xi = asuint (y);
      79        int sign = xi >> 31;
      80  
      81        x = reduce_large (xi, &n);
      82  
      83        /* Setup signs for sin and cos - include original sign.  */
      84        s = p->sign[(n + sign) & 3];
      85  
      86        if ((n + sign) & 2)
      87  	p = &__sincosf_table[1];
      88  
      89        return sinf_poly (x * s, x * x, p, n);
      90      }
      91    else
      92      return __math_invalidf (y);
      93  }
      94  
      95  #ifndef SINF
      96  libm_alias_float (__sin, sin)
      97  #endif