xref: /csrg-svn/lib/libm/common/tan.c (revision 32713)
1 /*
2  * Copyright (c) 1987 Regents of the University of California.
3  *
4  * Use and reproduction of this software are granted  in  accordance  with
5  * the terms and conditions specified in  the  Berkeley  Software  License
6  * Agreement (in particular, this entails acknowledgement of the programs'
7  * source, and inclusion of this notice) with the additional understanding
8  * that  all  recipients  should regard themselves as participants  in  an
9  * ongoing  research  project and hence should  feel  obligated  to report
10  * their  experiences (good or bad) with these elementary function  codes,
11  * using "sendbug 4bsd-bugs@BERKELEY", to the authors.
12  */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)tan.c	5.1	5.1 (ucb.elefunt) 11/30/87";
16 #endif	/* not lint */
17 
18 #include "trig.h"
19 double
20 tan(x)
21 double x;
22 {
23 	double a,z,ss,cc,c;
24 	int k;
25 
26 	if(!finite(x))		/* tan(NaN) and tan(INF) must be NaN */
27 		return x-x;
28 	x = drem(x,PI);			/* reduce x into [-PI/2, PI/2] */
29 	a = copysign(x,one);		/* ... = abs(x) */
30 	if (a >= PIo4) {
31 		k = 1;
32 		x = copysign(PIo2-a,x);
33 	}
34 	else {
35 		k = 0;
36 		if (a < small) {
37 			big+a;
38 			return x;
39 		}
40 	}
41 	z = x*x;
42 	cc = cos__C(z);
43 	ss = sin__S(z);
44 	z *= half;			/* Next get c = cos(x) accurately */
45 	c = (z >= thresh ? half-((z-half)-cc) : one-(z-cc));
46 	if (k == 0)
47 		return x+(x*(z-(cc-ss)))/c;	/* ... sin/cos */
48 #ifdef national
49 	else if (x == zero)
50 		return copysign(fmax,x);	/* no inf on 32k */
51 #endif	/* national */
52 	else
53 		return c/(x+x*ss);		/* ... cos/sin */
54 }
55