s_tan.c revision 218509
1194084Sedwin/* @(#)s_tan.c 5.1 93/09/24 */
2194084Sedwin/*
3194084Sedwin * ====================================================
4194084Sedwin * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5194084Sedwin *
6194084Sedwin * Developed at SunPro, a Sun Microsystems, Inc. business.
7194084Sedwin * Permission to use, copy, modify, and distribute this
8194084Sedwin * software is freely granted, provided that this notice
9194084Sedwin * is preserved.
10194084Sedwin * ====================================================
11194084Sedwin */
12194084Sedwin
13194084Sedwin#include <sys/cdefs.h>
14194084Sedwin__FBSDID("$FreeBSD: head/lib/msun/src/s_tan.c 218509 2011-02-10 07:37:50Z das $");
15194084Sedwin
16194084Sedwin/* tan(x)
17194084Sedwin * Return tangent function of x.
18194084Sedwin *
19194084Sedwin * kernel function:
20194084Sedwin *	__kernel_tan		... tangent function on [-pi/4,pi/4]
21194084Sedwin *	__ieee754_rem_pio2	... argument reduction routine
22194084Sedwin *
23194084Sedwin * Method.
24194084Sedwin *      Let S,C and T denote the sin, cos and tan respectively on
25194084Sedwin *	[-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
26194084Sedwin *	in [-pi/4 , +pi/4], and let n = k mod 4.
27194084Sedwin *	We have
28194084Sedwin *
29194084Sedwin *          n        sin(x)      cos(x)        tan(x)
30194084Sedwin *     ----------------------------------------------------------
31194084Sedwin *	    0	       S	   C		 T
32194084Sedwin *	    1	       C	  -S		-1/T
33270114Sse *	    2	      -S	  -C		 T
34270114Sse *	    3	      -C	   S		-1/T
35270114Sse *     ----------------------------------------------------------
36270114Sse *
37194084Sedwin * Special cases:
38194084Sedwin *      Let trig be any of sin, cos, or tan.
39194084Sedwin *      trig(+-INF)  is NaN, with signals;
40194084Sedwin *      trig(NaN)    is that NaN;
41194084Sedwin *
42194084Sedwin * Accuracy:
43270114Sse *	TRIG(x) returns trig(x) nearly rounded
44194084Sedwin */
45194084Sedwin
46194084Sedwin#include <float.h>
47194084Sedwin
48194084Sedwin#include "math.h"
49270114Sse#define INLINE_REM_PIO2
50194084Sedwin#include "math_private.h"
51194084Sedwin#include "e_rem_pio2.c"
52194084Sedwin
53194084Sedwindouble
54194084Sedwintan(double x)
55194084Sedwin{
56194084Sedwin	double y[2],z=0.0;
57270114Sse	int32_t n, ix;
58270114Sse
59194084Sedwin    /* High word of x. */
60194084Sedwin	GET_HIGH_WORD(ix,x);
61194084Sedwin
62270114Sse    /* |x| ~< pi/4 */
63194084Sedwin	ix &= 0x7fffffff;
64194084Sedwin	if(ix <= 0x3fe921fb) {
65194084Sedwin	    if(ix<0x3e400000)			/* x < 2**-27 */
66194084Sedwin		if((int)x==0) return x;		/* generate inexact */
67194084Sedwin	    return __kernel_tan(x,z,1);
68194084Sedwin	}
69194084Sedwin
70270114Sse    /* tan(Inf or NaN) is NaN */
71270114Sse	else if (ix>=0x7ff00000) return x-x;		/* NaN */
72270114Sse
73194084Sedwin    /* argument reduction needed */
74194084Sedwin	else {
75194084Sedwin	    n = __ieee754_rem_pio2(x,y);
76194084Sedwin	    return __kernel_tan(y[0],y[1],1-((n&1)<<1)); /*   1 -- n even
77194084Sedwin							-1 -- n odd */
78194084Sedwin	}
79194084Sedwin}
80194084Sedwin
81194084Sedwin#if (LDBL_MANT_DIG == 53)
82194084Sedwin__weak_reference(tan, tanl);
83194084Sedwin#endif
84194084Sedwin