1 /*
2  * Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 /* tan(x)
27  * Return tangent function of x.
28  *
29  * kernel function:
30  *      __kernel_tan            ... tangent function on [-pi/4,pi/4]
31  *      __ieee754_rem_pio2      ... argument reduction routine
32  *
33  * Method.
34  *      Let S,C and T denote the sin, cos and tan respectively on
35  *      [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
36  *      in [-pi/4 , +pi/4], and let n = k mod 4.
37  *      We have
38  *
39  *          n        sin(x)      cos(x)        tan(x)
40  *     ----------------------------------------------------------
41  *          0          S           C             T
42  *          1          C          -S            -1/T
43  *          2         -S          -C             T
44  *          3         -C           S            -1/T
45  *     ----------------------------------------------------------
46  *
47  * Special cases:
48  *      Let trig be any of sin, cos, or tan.
49  *      trig(+-INF)  is NaN, with signals;
50  *      trig(NaN)    is that NaN;
51  *
52  * Accuracy:
53  *      TRIG(x) returns trig(x) nearly rounded
54  */
55 
56 #include "fdlibm.h"
57 
58 #ifdef __STDC__
tan(double x)59         double tan(double x)
60 #else
61         double tan(x)
62         double x;
63 #endif
64 {
65         double y[2],z=0.0;
66         int n, ix;
67 
68     /* High word of x. */
69         ix = __HI(x);
70 
71     /* |x| ~< pi/4 */
72         ix &= 0x7fffffff;
73         if(ix <= 0x3fe921fb) return __kernel_tan(x,z,1);
74 
75     /* tan(Inf or NaN) is NaN */
76         else if (ix>=0x7ff00000) return x-x;            /* NaN */
77 
78     /* argument reduction needed */
79         else {
80             n = __ieee754_rem_pio2(x,y);
81             return __kernel_tan(y[0],y[1],1-((n&1)<<1)); /*   1 -- n even
82                                                         -1 -- n odd */
83         }
84 }
85