1 /* origin: FreeBSD /usr/src/lib/msun/src/s_sin.c */
2 /*
3  * ====================================================
4  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5  *
6  * Developed at SunPro, a Sun Microsystems, Inc. business.
7  * Permission to use, copy, modify, and distribute this
8  * software is freely granted, provided that this notice
9  * is preserved.
10  * ====================================================
11  */
12 
13 #define _GNU_SOURCE
14 #include "libm.h"
15 
sincos(double x,double * sin,double * cos)16 void sincos(double x, double *sin, double *cos)
17 {
18 	double y[2], s, c;
19 	uint32_t ix;
20 	unsigned n;
21 
22 	GET_HIGH_WORD(ix, x);
23 	ix &= 0x7fffffff;
24 
25 	/* |x| ~< pi/4 */
26 	if (ix <= 0x3fe921fb) {
27 		/* if |x| < 2**-27 * sqrt(2) */
28 		if (ix < 0x3e46a09e) {
29 			/* raise inexact if x!=0 and underflow if subnormal */
30 			FORCE_EVAL(ix < 0x00100000 ? x/0x1p120f : x+0x1p120f);
31 			*sin = x;
32 			*cos = 1.0;
33 			return;
34 		}
35 		*sin = __sin(x, 0.0, 0);
36 		*cos = __cos(x, 0.0);
37 		return;
38 	}
39 
40 	/* sincos(Inf or NaN) is NaN */
41 	if (ix >= 0x7ff00000) {
42 		*sin = *cos = x - x;
43 		return;
44 	}
45 
46 	/* argument reduction needed */
47 	n = __rem_pio2(x, y);
48 	s = __sin(y[0], y[1], 1);
49 	c = __cos(y[0], y[1]);
50 	switch (n&3) {
51 	case 0:
52 		*sin = s;
53 		*cos = c;
54 		break;
55 	case 1:
56 		*sin = c;
57 		*cos = -s;
58 		break;
59 	case 2:
60 		*sin = -s;
61 		*cos = -c;
62 		break;
63 	case 3:
64 	default:
65 		*sin = -c;
66 		*cos = s;
67 		break;
68 	}
69 }
70