1*34127Sbostic /* 231930Szliu * Copyright (c) 1987 Regents of the University of California. 3*34127Sbostic * All rights reserved. 4*34127Sbostic * 5*34127Sbostic * Redistribution and use in source and binary forms are permitted 6*34127Sbostic * provided that this notice is preserved and that due credit is given 7*34127Sbostic * to the University of California at Berkeley. The name of the University 8*34127Sbostic * may not be used to endorse or promote products derived from this 9*34127Sbostic * software without specific prior written permission. This software 10*34127Sbostic * is provided ``as is'' without express or implied warranty. 11*34127Sbostic * 12*34127Sbostic * All recipients should regard themselves as participants in an ongoing 13*34127Sbostic * research project and hence should feel obligated to report their 14*34127Sbostic * experiences (good or bad) with these elementary function codes, using 15*34127Sbostic * the sendbug(8) program, to the authors. 1631930Szliu */ 1731930Szliu 1831930Szliu #ifndef lint 19*34127Sbostic static char sccsid[] = "@(#)tan.c 5.2 (Berkeley) 04/29/88"; 20*34127Sbostic #endif /* not lint */ 2131930Szliu 2231930Szliu #include "trig.h" 2331930Szliu double 2431930Szliu tan(x) 2531930Szliu double x; 2631930Szliu { 2731930Szliu double a,z,ss,cc,c; 2831930Szliu int k; 2931930Szliu 3031930Szliu if(!finite(x)) /* tan(NaN) and tan(INF) must be NaN */ 3131930Szliu return x-x; 3231930Szliu x = drem(x,PI); /* reduce x into [-PI/2, PI/2] */ 3331930Szliu a = copysign(x,one); /* ... = abs(x) */ 3431930Szliu if (a >= PIo4) { 3531930Szliu k = 1; 3631930Szliu x = copysign(PIo2-a,x); 3731930Szliu } 3831930Szliu else { 3931930Szliu k = 0; 4031930Szliu if (a < small) { 4131930Szliu big+a; 4231930Szliu return x; 4331930Szliu } 4431930Szliu } 4531930Szliu z = x*x; 4631930Szliu cc = cos__C(z); 4731930Szliu ss = sin__S(z); 4831930Szliu z *= half; /* Next get c = cos(x) accurately */ 4931930Szliu c = (z >= thresh ? half-((z-half)-cc) : one-(z-cc)); 5031930Szliu if (k == 0) 5131930Szliu return x+(x*(z-(cc-ss)))/c; /* ... sin/cos */ 5231930Szliu #ifdef national 5331930Szliu else if (x == zero) 5431930Szliu return copysign(fmax,x); /* no inf on 32k */ 5531930Szliu #endif /* national */ 5631930Szliu else 5731930Szliu return c/(x+x*ss); /* ... cos/sin */ 5831930Szliu } 59