xref: /original-bsd/usr.bin/f77/libF77/r_tan.c (revision f052b07a)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)r_tan.c	5.3	11/03/86
7  */
8 
9 #ifndef tahoe
10 float r_tan(x)
11 float *x;
12 {
13 double tan();
14 return( tan(*x) );
15 }
16 
17 #else tahoe
18 
19 /*
20 	SINGLE PRECISION floating point tangent
21 
22 	sin/cos is used after argument reduction to [0,pi/4] range.
23 	since x is in this range, tan(x) is in [0,1] range and
24 	no overflow can occur here.
25 */
26 
27 #include <errno.h>
28 
29 int	errno;
30 static double invpi = 1.27323954473516268;  /* 4/pi */
31 
32 float
33 r_tan(parg)
34 float *parg;
35 {
36 	double arg;
37 	fortran float sin(), cos();
38 	double modf();
39 	float flmax_();
40 	double temp, e, x, xsq;
41 	int sign;
42 	int flag, i;
43 
44 	arg = *parg;
45 	flag = 0;
46 	sign = 1.;
47 	if(arg < 0.){		/* tan(-arg) = -tan(arg) */
48 		arg = -arg;
49 		sign = -1.;
50 	}
51 	arg = arg*invpi;   /*overflow?*/
52 	x = modf(arg,&e);
53 	i = e;
54 	switch(i%4) {
55 	case 1:			/* 2nd octant: tan(x) = 1/tan(1-x) */
56 		x = 1. - x;
57 		flag = 1;
58 		break;
59 
60 	case 2:			/* 3rd octant: tan(x) = -1/tan(x) */
61 		sign = - sign;
62 		flag = 1;
63 		break;
64 
65 	case 3:			/* 4th octant: tan(x) = -tan(1-x) */
66 		x = 1. - x;
67 		sign = - sign;
68 		break;
69 
70 	case 0:			/* 1st octant */
71 		break;
72 	}
73 	x = x/invpi;
74 
75 	temp = sin(x)/cos(x);
76 
77 	if(flag == 1) {
78 		if(temp == 0.) {	/* check for singular "point" */
79 			errno = ERANGE;
80 			if (sign>0)
81 				return(flmax_());
82 			return(-flmax_());
83 		}
84 		temp = 1./temp;
85 	}
86 	return(sign*temp);
87 }
88 
89 #endif tahoe
90