|
|
1.1 root 1: /* @(#)r_tan.c 1.0 10/01/82 */
2:
3: /*
4: SINGLE PRECISION floating point tangent
5:
6: sin/cos is used after argument reduction to [0,pi/4] range.
7: since x is in this range, tan(x) is in [0,1] range and
8: no overflow can occur here.
9: */
10:
11: #include <errno.h>
12:
13: int errno;
14: static double invpi = 1.27323954473516268; /* 4/pi */
15:
16: float
17: r_tan(parg)
18: float *parg;
19: {
20: double arg;
21: fortran float sin(), cos();
22: double modf();
23: float flmax_();
24: double temp, e, x, xsq;
25: int sign;
26: int flag, i;
27:
28: arg = *parg;
29: flag = 0;
30: sign = 1.;
31: if(arg < 0.){ /* tan(-arg) = -tan(arg) */
32: arg = -arg;
33: sign = -1.;
34: }
35: arg = arg*invpi; /*overflow?*/
36: x = modf(arg,&e);
37: i = e;
38: switch(i%4) {
39: case 1: /* 2nd octant: tan(x) = 1/tan(1-x) */
40: x = 1. - x;
41: flag = 1;
42: break;
43:
44: case 2: /* 3rd octant: tan(x) = -1/tan(x) */
45: sign = - sign;
46: flag = 1;
47: break;
48:
49: case 3: /* 4th octant: tan(x) = -tan(1-x) */
50: x = 1. - x;
51: sign = - sign;
52: break;
53:
54: case 0: /* 1st octant */
55: break;
56: }
57: x = x/invpi;
58:
59: temp = sin(x)/cos(x);
60:
61: if(flag == 1) {
62: if(temp == 0.) { /* check for singular "point" */
63: errno = ERANGE;
64: if (sign>0)
65: return(flmax_());
66: return(-flmax_());
67: }
68: temp = 1./temp;
69: }
70: return(sign*temp);
71: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.