1/* Compute sine and cosine of argument.
2 Copyright (C) 1997-2016 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
25#define __sin __sin_local
26#define __cos __cos_local
27#define IN_SINCOS 1
28#include "s_sin.c"
29
30/* Consolidated version of reduce_and_compute in s_sin.c that does range
31 reduction only once and computes sin and cos together. */
32static inline void
33__always_inline
34reduce_and_compute_sincos (double x, double *sinx, double *cosx)
35{
36 double a, da;
37 unsigned int n = __branred (x, &a, &da);
38
39 n = n & 3;
40
41 if (n == 1 || n == 2)
42 {
43 a = -a;
44 da = -da;
45 }
46
47 if (n & 1)
48 {
49 double *temp = cosx;
50 cosx = sinx;
51 sinx = temp;
52 }
53
54 if (a * a < 0.01588)
55 *sinx = bsloww (a, da, x, n);
56 else
57 *sinx = bsloww1 (a, da, x, n);
58 *cosx = bsloww2 (a, da, x, n);
59}
60
61void
62__sincos (double x, double *sinx, double *cosx)
63{
64 mynumber u;
65 int k;
66
67 SET_RESTORE_ROUND_53BIT (FE_TONEAREST);
68
69 u.x = x;
70 k = 0x7fffffff & u.i[HIGH_HALF];
71
72 if (k < 0x400368fd)
73 {
74 *sinx = __sin_local (x);
75 *cosx = __cos_local (x);
76 return;
77 }
78 if (k < 0x419921FB)
79 {
80 double a, da;
81 int4 n = reduce_sincos_1 (x, &a, &da);
82
83 *sinx = do_sincos_1 (a, da, x, n, 0);
84 *cosx = do_sincos_1 (a, da, x, n, 1);
85
86 return;
87 }
88 if (k < 0x42F00000)
89 {
90 double a, da;
91 int4 n = reduce_sincos_2 (x, &a, &da);
92
93 *sinx = do_sincos_2 (a, da, x, n, 0);
94 *cosx = do_sincos_2 (a, da, x, n, 1);
95
96 return;
97 }
98 if (k < 0x7ff00000)
99 {
100 reduce_and_compute_sincos (x, sinx, cosx);
101 return;
102 }
103
104 if (isinf (x))
105 __set_errno (EDOM);
106
107 *sinx = *cosx = x / x;
108}
109weak_alias (__sincos, sincos)
110#ifdef NO_LONG_DOUBLE
111strong_alias (__sincos, __sincosl)
112weak_alias (__sincos, sincosl)
113#endif
114