Research V7 development
[unix-history] / usr / src / libm / tan.c
CommitLineData
5d130d40
RM
1/*
2 floating point tangent
3
4 A series is used after range reduction.
5 Coefficients are #4285 from Hart & Cheney. (19.74D)
6*/
7
8#include <errno.h>
9#include <math.h>
10
11int errno;
12static double invpi = 1.27323954473516268;
13static double p0 = -0.1306820264754825668269611177e+5;
14static double p1 = 0.1055970901714953193602353981e+4;
15static double p2 = -0.1550685653483266376941705728e+2;
16static double p3 = 0.3422554387241003435328470489e-1;
17static double p4 = 0.3386638642677172096076369e-4;
18static double q0 = -0.1663895238947119001851464661e+5;
19static double q1 = 0.4765751362916483698926655581e+4;
20static double q2 = -0.1555033164031709966900124574e+3;
21
22double
23tan(arg)
24double arg;
25{
26 double modf();
27 double sign, temp, e, x, xsq;
28 int flag, i;
29
30 flag = 0;
31 sign = 1.;
32 if(arg < 0.){
33 arg = -arg;
34 sign = -1.;
35 }
36 arg = arg*invpi; /*overflow?*/
37 x = modf(arg,&e);
38 i = e;
39 switch(i%4) {
40 case 1:
41 x = 1. - x;
42 flag = 1;
43 break;
44
45 case 2:
46 sign = - sign;
47 flag = 1;
48 break;
49
50 case 3:
51 x = 1. - x;
52 sign = - sign;
53 break;
54
55 case 0:
56 break;
57 }
58
59 xsq = x*x;
60 temp = ((((p4*xsq+p3)*xsq+p2)*xsq+p1)*xsq+p0)*x;
61 temp = temp/(((1.0*xsq+q2)*xsq+q1)*xsq+q0);
62
63 if(flag == 1) {
64 if(temp == 0.) {
65 errno = ERANGE;
66 if (sign>0)
67 return(HUGE);
68 return(-HUGE);
69 }
70 temp = 1./temp;
71 }
72 return(sign*temp);
73}