1/* Compute sine and cosine of argument.
2 Copyright (C) 1997-2018 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
19
20#include <errno.h>
21#include <math.h>
22
23#include <math_private.h>
24#include <libm-alias-double.h>
25
26#define __sin __sin_local
27#define __cos __cos_local
28#define IN_SINCOS 1
29#include "s_sin.c"
30
31/* Consolidated version of reduce_and_compute in s_sin.c that does range
32 reduction only once and computes sin and cos together. */
33static inline void
34__always_inline
35reduce_and_compute_sincos (double x, double *sinx, double *cosx)
36{
37 double a, da;
38 unsigned int n = __branred (x, &a, &da);
39
40 n = n & 3;
41
42 if (n == 1 || n == 2)
43 {
44 a = -a;
45 da = -da;
46 }
47
48 if (n & 1)
49 {
50 double *temp = cosx;
51 cosx = sinx;
52 sinx = temp;
53 }
54
55 if (a * a < 0.01588)
56 *sinx = bsloww (a, da, x, n);
57 else
58 *sinx = bsloww1 (a, da, x, n);
59 *cosx = bsloww2 (a, da, x, n);
60}
61
62void
63__sincos (double x, double *sinx, double *cosx)
64{
65 mynumber u;
66 int k;
67
68 SET_RESTORE_ROUND_53BIT (FE_TONEAREST);
69
70 u.x = x;
71 k = 0x7fffffff & u.i[HIGH_HALF];
72
73 if (k < 0x400368fd)
74 {
75 *sinx = __sin_local (x);
76 *cosx = __cos_local (x);
77 return;
78 }
79 if (k < 0x419921FB)
80 {
81 double a, da;
82 int4 n = reduce_sincos_1 (x, &a, &da);
83
84 *sinx = do_sincos_1 (a, da, x, n, false);
85 *cosx = do_sincos_1 (a, da, x, n, true);
86
87 return;
88 }
89 if (k < 0x42F00000)
90 {
91 double a, da;
92 int4 n = reduce_sincos_2 (x, &a, &da);
93
94 *sinx = do_sincos_2 (a, da, x, n, false);
95 *cosx = do_sincos_2 (a, da, x, n, true);
96
97 return;
98 }
99 if (k < 0x7ff00000)
100 {
101 reduce_and_compute_sincos (x, sinx, cosx);
102 return;
103 }
104
105 if (isinf (x))
106 __set_errno (EDOM);
107
108 *sinx = *cosx = x / x;
109}
110libm_alias_double (__sincos, sincos)
111