1570af302Sopenharmony_ci/* origin: FreeBSD /usr/src/lib/msun/src/s_sin.c */
2570af302Sopenharmony_ci/*
3570af302Sopenharmony_ci * ====================================================
4570af302Sopenharmony_ci * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5570af302Sopenharmony_ci *
6570af302Sopenharmony_ci * Developed at SunPro, a Sun Microsystems, Inc. business.
7570af302Sopenharmony_ci * Permission to use, copy, modify, and distribute this
8570af302Sopenharmony_ci * software is freely granted, provided that this notice
9570af302Sopenharmony_ci * is preserved.
10570af302Sopenharmony_ci * ====================================================
11570af302Sopenharmony_ci */
12570af302Sopenharmony_ci
13570af302Sopenharmony_ci#define _GNU_SOURCE
14570af302Sopenharmony_ci#include "libm.h"
15570af302Sopenharmony_ci
16570af302Sopenharmony_civoid sincos(double x, double *sin, double *cos)
17570af302Sopenharmony_ci{
18570af302Sopenharmony_ci	double y[2], s, c;
19570af302Sopenharmony_ci	uint32_t ix;
20570af302Sopenharmony_ci	unsigned n;
21570af302Sopenharmony_ci
22570af302Sopenharmony_ci	GET_HIGH_WORD(ix, x);
23570af302Sopenharmony_ci	ix &= 0x7fffffff;
24570af302Sopenharmony_ci
25570af302Sopenharmony_ci	/* |x| ~< pi/4 */
26570af302Sopenharmony_ci	if (ix <= 0x3fe921fb) {
27570af302Sopenharmony_ci		/* if |x| < 2**-27 * sqrt(2) */
28570af302Sopenharmony_ci		if (ix < 0x3e46a09e) {
29570af302Sopenharmony_ci			/* raise inexact if x!=0 and underflow if subnormal */
30570af302Sopenharmony_ci			FORCE_EVAL(ix < 0x00100000 ? x/0x1p120f : x+0x1p120f);
31570af302Sopenharmony_ci			*sin = x;
32570af302Sopenharmony_ci			*cos = 1.0;
33570af302Sopenharmony_ci			return;
34570af302Sopenharmony_ci		}
35570af302Sopenharmony_ci		*sin = __sin(x, 0.0, 0);
36570af302Sopenharmony_ci		*cos = __cos(x, 0.0);
37570af302Sopenharmony_ci		return;
38570af302Sopenharmony_ci	}
39570af302Sopenharmony_ci
40570af302Sopenharmony_ci	/* sincos(Inf or NaN) is NaN */
41570af302Sopenharmony_ci	if (ix >= 0x7ff00000) {
42570af302Sopenharmony_ci		*sin = *cos = x - x;
43570af302Sopenharmony_ci		return;
44570af302Sopenharmony_ci	}
45570af302Sopenharmony_ci
46570af302Sopenharmony_ci	/* argument reduction needed */
47570af302Sopenharmony_ci	n = __rem_pio2(x, y);
48570af302Sopenharmony_ci	s = __sin(y[0], y[1], 1);
49570af302Sopenharmony_ci	c = __cos(y[0], y[1]);
50570af302Sopenharmony_ci	switch (n&3) {
51570af302Sopenharmony_ci	case 0:
52570af302Sopenharmony_ci		*sin = s;
53570af302Sopenharmony_ci		*cos = c;
54570af302Sopenharmony_ci		break;
55570af302Sopenharmony_ci	case 1:
56570af302Sopenharmony_ci		*sin = c;
57570af302Sopenharmony_ci		*cos = -s;
58570af302Sopenharmony_ci		break;
59570af302Sopenharmony_ci	case 2:
60570af302Sopenharmony_ci		*sin = -s;
61570af302Sopenharmony_ci		*cos = -c;
62570af302Sopenharmony_ci		break;
63570af302Sopenharmony_ci	case 3:
64570af302Sopenharmony_ci	default:
65570af302Sopenharmony_ci		*sin = -c;
66570af302Sopenharmony_ci		*cos = s;
67570af302Sopenharmony_ci		break;
68570af302Sopenharmony_ci	}
69570af302Sopenharmony_ci}
70