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