]>
Commit | Line | Data |
---|---|---|
8700a785 | 1 | /* Used by sinf, cosf and sincosf functions. X86-64 version. |
04277e02 | 2 | Copyright (C) 2018-2019 Free Software Foundation, Inc. |
8700a785 L |
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 | |
5a82c748 | 17 | <https://www.gnu.org/licenses/>. */ |
8700a785 L |
18 | |
19 | typedef double v2df_t __attribute__ ((vector_size (2 * sizeof (double)))); | |
20 | ||
21 | #ifdef __SSE2_MATH__ | |
22 | typedef float v4sf_t __attribute__ ((vector_size (4 * sizeof (float)))); | |
23 | ||
24 | static inline void | |
25 | v2df_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 | |
32 | static inline void | |
33 | v2df_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. */ | |
41 | typedef 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. */ | |
55 | static inline void | |
56 | sincosf_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 (vsincos, sinp, 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. */ | |
85 | static inline float | |
86 | sinf_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 | } |