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