1/* Used by sinf, cosf and sincosf functions. X86-64 version.
2 Copyright (C) 2018-2022 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
19typedef double v2df_t __attribute__ ((vector_size (2 * sizeof (double))));
20
21#ifdef __SSE2_MATH__
22typedef float v4sf_t __attribute__ ((vector_size (4 * sizeof (float))));
23
24static inline void
25v2df_to_sf (v2df_t v2df, float *f0p, float *f1p)
26{
27 v4sf_t v4sf = __builtin_ia32_cvtpd2ps (v2df);
28 *f0p = v4sf[0];
29 *f1p = v4sf[1];
30}
31#else
32static inline void
33v2df_to_sf (v2df_t v2df, float *f0p, float *f1p)
34{
35 *f0p = (float) v2df[0];
36 *f1p = (float) v2df[1];
37}
38#endif
39
40/* The constants and polynomials for sine and cosine. */
41typedef struct
42{
43 double sign[4]; /* Sign of sine in quadrants 0..3. */
44 double hpi_inv; /* 2 / PI ( * 2^24 if !TOINT_INTRINSICS). */
45 double hpi; /* PI / 2. */
46 /* Cosine polynomial: c0, c1, c2, c3, c4.
47 Sine polynomial: s1, s2, s3. */
48 double c0, c1;
49 v2df_t s1c2, s2c3, s3c4;
50} sincos_t;
51
52/* Compute the sine and cosine of inputs X and X2 (X squared), using the
53 polynomial P and store the results in SINP and COSP. N is the quadrant,
54 if odd the cosine and sine polynomials are swapped. */
55static inline void
56sincosf_poly (double x, double x2, const sincos_t *p, int n, float *sinp,
57 float *cosp)
58{
59 v2df_t vx2x2 = { x2, x2 };
60 v2df_t vxx2 = { x, x2 };
61 v2df_t vx3x4, vs1c2;
62
63 vx3x4 = vx2x2 * vxx2;
64 vs1c2 = p->s2c3 + vx2x2 * p->s3c4;
65
66 /* Swap sin/cos result based on quadrant. */
67 if (n & 1)
68 {
69 float *tmp = cosp;
70 cosp = sinp;
71 sinp = tmp;
72 }
73
74 double c1 = p->c0 + x2 * p->c1;
75 v2df_t vxc1 = { x, c1 };
76 v2df_t vx5x6 = vx3x4 * vx2x2;
77
78 v2df_t vsincos = vxc1 + vx3x4 * p->s1c2;
79 vsincos = vsincos + vx5x6 * vs1c2;
80 v2df_to_sf (v2df: vsincos, f0p: sinp, f1p: cosp);
81}
82
83/* Return the sine of inputs X and X2 (X squared) using the polynomial P.
84 N is the quadrant, and if odd the cosine polynomial is used. */
85static inline float
86sinf_poly (double x, double x2, const sincos_t *p, int n)
87{
88 double x3, x4, x6, x7, s, c, c1, c2, s1;
89
90 if ((n & 1) == 0)
91 {
92 x3 = x * x2;
93 s1 = p->s2c3[0] + x2 * p->s3c4[0];
94
95 x7 = x3 * x2;
96 s = x + x3 * p->s1c2[0];
97
98 return s + x7 * s1;
99 }
100 else
101 {
102 x4 = x2 * x2;
103 c2 = p->s2c3[1] + x2 * p->s3c4[1];
104 c1 = p->c0 + x2 * p->c1;
105
106 x6 = x4 * x2;
107 c = c1 + x4 * p->s1c2[1];
108
109 return c + x6 * c2;
110 }
111}
112

source code of glibc/sysdeps/x86/fpu/sincosf_poly.h