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