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
sinf(float y)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