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