134127Sbostic /* 231930Szliu * Copyright (c) 1987 Regents of the University of California. 334127Sbostic * All rights reserved. 434127Sbostic * 5*42653Sbostic * %sccs.include.redist.c% 634127Sbostic * 734127Sbostic * All recipients should regard themselves as participants in an ongoing 834127Sbostic * research project and hence should feel obligated to report their 934127Sbostic * experiences (good or bad) with these elementary function codes, using 1034127Sbostic * the sendbug(8) program, to the authors. 1131930Szliu */ 1231930Szliu 1331930Szliu #ifndef lint 14*42653Sbostic static char sccsid[] = "@(#)tan.c 5.4 (Berkeley) 06/01/90"; 1534127Sbostic #endif /* not lint */ 1631930Szliu 1731930Szliu #include "trig.h" 1831930Szliu double 1931930Szliu tan(x) 2031930Szliu double x; 2131930Szliu { 2231930Szliu double a,z,ss,cc,c; 2331930Szliu int k; 2431930Szliu 2531930Szliu if(!finite(x)) /* tan(NaN) and tan(INF) must be NaN */ 2631930Szliu return x-x; 2731930Szliu x = drem(x,PI); /* reduce x into [-PI/2, PI/2] */ 2831930Szliu a = copysign(x,one); /* ... = abs(x) */ 2931930Szliu if (a >= PIo4) { 3031930Szliu k = 1; 3131930Szliu x = copysign(PIo2-a,x); 3231930Szliu } 3331930Szliu else { 3431930Szliu k = 0; 3531930Szliu if (a < small) { 3631930Szliu big+a; 3731930Szliu return x; 3831930Szliu } 3931930Szliu } 4031930Szliu z = x*x; 4131930Szliu cc = cos__C(z); 4231930Szliu ss = sin__S(z); 4331930Szliu z *= half; /* Next get c = cos(x) accurately */ 4431930Szliu c = (z >= thresh ? half-((z-half)-cc) : one-(z-cc)); 4531930Szliu if (k == 0) 4631930Szliu return x+(x*(z-(cc-ss)))/c; /* ... sin/cos */ 4731930Szliu #ifdef national 4831930Szliu else if (x == zero) 4931930Szliu return copysign(fmax,x); /* no inf on 32k */ 5031930Szliu #endif /* national */ 5131930Szliu else 5231930Szliu return c/(x+x*ss); /* ... cos/sin */ 5331930Szliu } 54