1 | /* @(#)k_tan.c 1.5 04/04/22 SMI */
|
---|
2 |
|
---|
3 | /*
|
---|
4 | * ====================================================
|
---|
5 | * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
|
---|
6 | *
|
---|
7 | * Permission to use, copy, modify, and distribute this
|
---|
8 | * software is freely granted, provided that this notice
|
---|
9 | * is preserved.
|
---|
10 | * ====================================================
|
---|
11 | */
|
---|
12 |
|
---|
13 | /* INDENT OFF */
|
---|
14 | #ifndef lint
|
---|
15 | static char rcsid[] = "$FreeBSD: src/lib/msun/src/k_tan.c,v 1.10 2005/02/04 18:26:06 das Exp $";
|
---|
16 | #endif
|
---|
17 |
|
---|
18 | /* __kernel_tan( x, y, k )
|
---|
19 | * kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854
|
---|
20 | * Input x is assumed to be bounded by ~pi/4 in magnitude.
|
---|
21 | * Input y is the tail of x.
|
---|
22 | * Input k indicates whether tan (if k = 1) or -1/tan (if k = -1) is returned.
|
---|
23 | *
|
---|
24 | * Algorithm
|
---|
25 | * 1. Since tan(-x) = -tan(x), we need only to consider positive x.
|
---|
26 | * 2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0.
|
---|
27 | * 3. tan(x) is approximated by a odd polynomial of degree 27 on
|
---|
28 | * [0,0.67434]
|
---|
29 | * 3 27
|
---|
30 | * tan(x) ~ x + T1*x + ... + T13*x
|
---|
31 | * where
|
---|
32 | *
|
---|
33 | * |tan(x) 2 4 26 | -59.2
|
---|
34 | * |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2
|
---|
35 | * | x |
|
---|
36 | *
|
---|
37 | * Note: tan(x+y) = tan(x) + tan'(x)*y
|
---|
38 | * ~ tan(x) + (1+x*x)*y
|
---|
39 | * Therefore, for better accuracy in computing tan(x+y), let
|
---|
40 | * 3 2 2 2 2
|
---|
41 | * r = x *(T2+x *(T3+x *(...+x *(T12+x *T13))))
|
---|
42 | * then
|
---|
43 | * 3 2
|
---|
44 | * tan(x+y) = x + (T1*x + (x *(r+y)+y))
|
---|
45 | *
|
---|
46 | * 4. For x in [0.67434,pi/4], let y = pi/4 - x, then
|
---|
47 | * tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y))
|
---|
48 | * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
|
---|
49 | */
|
---|
50 |
|
---|
51 | #include "math.h"
|
---|
52 | #include "math_private.h"
|
---|
53 | static const double xxx[] = {
|
---|
54 | 3.33333333333334091986e-01, /* 3FD55555, 55555563 */
|
---|
55 | 1.33333333333201242699e-01, /* 3FC11111, 1110FE7A */
|
---|
56 | 5.39682539762260521377e-02, /* 3FABA1BA, 1BB341FE */
|
---|
57 | 2.18694882948595424599e-02, /* 3F9664F4, 8406D637 */
|
---|
58 | 8.86323982359930005737e-03, /* 3F8226E3, E96E8493 */
|
---|
59 | 3.59207910759131235356e-03, /* 3F6D6D22, C9560328 */
|
---|
60 | 1.45620945432529025516e-03, /* 3F57DBC8, FEE08315 */
|
---|
61 | 5.88041240820264096874e-04, /* 3F4344D8, F2F26501 */
|
---|
62 | 2.46463134818469906812e-04, /* 3F3026F7, 1A8D1068 */
|
---|
63 | 7.81794442939557092300e-05, /* 3F147E88, A03792A6 */
|
---|
64 | 7.14072491382608190305e-05, /* 3F12B80F, 32F0A7E9 */
|
---|
65 | -1.85586374855275456654e-05, /* BEF375CB, DB605373 */
|
---|
66 | 2.59073051863633712884e-05, /* 3EFB2A70, 74BF7AD4 */
|
---|
67 | /* one */ 1.00000000000000000000e+00, /* 3FF00000, 00000000 */
|
---|
68 | /* pio4 */ 7.85398163397448278999e-01, /* 3FE921FB, 54442D18 */
|
---|
69 | /* pio4lo */ 3.06161699786838301793e-17 /* 3C81A626, 33145C07 */
|
---|
70 | };
|
---|
71 | #define one xxx[13]
|
---|
72 | #define pio4 xxx[14]
|
---|
73 | #define pio4lo xxx[15]
|
---|
74 | #define T xxx
|
---|
75 | /* INDENT ON */
|
---|
76 |
|
---|
77 | double
|
---|
78 | __kernel_tan(double x, double y, int iy) {
|
---|
79 | double z, r, v, w, s;
|
---|
80 | int32_t ix, hx;
|
---|
81 |
|
---|
82 | GET_HIGH_WORD(hx,x);
|
---|
83 | ix = hx & 0x7fffffff; /* high word of |x| */
|
---|
84 | if (ix < 0x3e300000) { /* x < 2**-28 */
|
---|
85 | if ((int) x == 0) { /* generate inexact */
|
---|
86 | u_int32_t low;
|
---|
87 | GET_LOW_WORD(low,x);
|
---|
88 | if (((ix | low) | (iy + 1)) == 0)
|
---|
89 | return one / fabs(x);
|
---|
90 | else {
|
---|
91 | if (iy == 1)
|
---|
92 | return x;
|
---|
93 | else { /* compute -1 / (x+y) carefully */
|
---|
94 | double a, t;
|
---|
95 |
|
---|
96 | z = w = x + y;
|
---|
97 | SET_LOW_WORD(z, 0);
|
---|
98 | v = y - (z - x);
|
---|
99 | t = a = -one / w;
|
---|
100 | SET_LOW_WORD(t, 0);
|
---|
101 | s = one + t * z;
|
---|
102 | return t + a * (s + t * v);
|
---|
103 | }
|
---|
104 | }
|
---|
105 | }
|
---|
106 | }
|
---|
107 | if (ix >= 0x3FE59428) { /* |x| >= 0.6744 */
|
---|
108 | if (hx < 0) {
|
---|
109 | x = -x;
|
---|
110 | y = -y;
|
---|
111 | }
|
---|
112 | z = pio4 - x;
|
---|
113 | w = pio4lo - y;
|
---|
114 | x = z + w;
|
---|
115 | y = 0.0;
|
---|
116 | }
|
---|
117 | z = x * x;
|
---|
118 | w = z * z;
|
---|
119 | /*
|
---|
120 | * Break x^5*(T[1]+x^2*T[2]+...) into
|
---|
121 | * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
|
---|
122 | * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
|
---|
123 | */
|
---|
124 | r = T[1] + w * (T[3] + w * (T[5] + w * (T[7] + w * (T[9] +
|
---|
125 | w * T[11]))));
|
---|
126 | v = z * (T[2] + w * (T[4] + w * (T[6] + w * (T[8] + w * (T[10] +
|
---|
127 | w * T[12])))));
|
---|
128 | s = z * x;
|
---|
129 | r = y + z * (s * (r + v) + y);
|
---|
130 | r += T[0] * s;
|
---|
131 | w = x + r;
|
---|
132 | if (ix >= 0x3FE59428) {
|
---|
133 | v = (double) iy;
|
---|
134 | return (double) (1 - ((hx >> 30) & 2)) *
|
---|
135 | (v - 2.0 * (x - (w * w / (w + v) - r)));
|
---|
136 | }
|
---|
137 | if (iy == 1)
|
---|
138 | return w;
|
---|
139 | else {
|
---|
140 | /*
|
---|
141 | * if allow error up to 2 ulp, simply return
|
---|
142 | * -1.0 / (x+r) here
|
---|
143 | */
|
---|
144 | /* compute -1.0 / (x+r) accurately */
|
---|
145 | double a, t;
|
---|
146 | z = w;
|
---|
147 | SET_LOW_WORD(z,0);
|
---|
148 | v = r - (z - x); /* z+v = r+x */
|
---|
149 | t = a = -1.0 / w; /* a = -1.0/w */
|
---|
150 | SET_LOW_WORD(t,0);
|
---|
151 | s = 1.0 + t * z;
|
---|
152 | return t + a * (s + t * v);
|
---|
153 | }
|
---|
154 | }
|
---|