]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libc/port/tan.c
libregexp: improve the transition to next available thread, instruction, and generation
[plan9front.git] / sys / src / libc / port / tan.c
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 <u.h>
9 #include <libc.h>
10
11 static double p0         = -0.1306820264754825668269611177e+5;
12 static double p1          = 0.1055970901714953193602353981e+4;
13 static double p2         = -0.1550685653483266376941705728e+2;
14 static double p3          = 0.3422554387241003435328470489e-1;
15 static double p4          = 0.3386638642677172096076369e-4;
16 static double q0         = -0.1663895238947119001851464661e+5;
17 static double q1          = 0.4765751362916483698926655581e+4;
18 static double q2         = -0.1555033164031709966900124574e+3;
19
20 double
21 tan(double arg)
22 {
23         double temp, e, x, xsq;
24         int flag, sign, i;
25
26         flag = 0;
27         sign = 0;
28         if(arg < 0){
29                 arg = -arg;
30                 sign++;
31         }
32         arg = 2*arg/PIO2;   /* overflow? */
33         x = modf(arg, &e);
34         i = e;
35         switch(i%4) {
36         case 1:
37                 x = 1 - x;
38                 flag = 1;
39                 break;
40
41         case 2:
42                 sign = !sign;
43                 flag = 1;
44                 break;
45
46         case 3:
47                 x = 1 - x;
48                 sign = !sign;
49                 break;
50
51         case 0:
52                 break;
53         }
54
55         xsq = x*x;
56         temp = ((((p4*xsq+p3)*xsq+p2)*xsq+p1)*xsq+p0)*x;
57         temp = temp/(((xsq+q2)*xsq+q1)*xsq+q0);
58
59         if(flag) {
60                 if(temp == 0)
61                         return NaN();
62                 temp = 1/temp;
63         }
64         if(sign)
65                 temp = -temp;
66         return temp;
67 }