tan.c 1.9 KB
Newer Older
R
Rich Felker 已提交
1
/* origin: FreeBSD /usr/src/lib/msun/src/s_tan.c */
R
Rich Felker 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * ====================================================
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
 *
 * Developed at SunPro, a Sun Microsystems, Inc. business.
 * Permission to use, copy, modify, and distribute this
 * software is freely granted, provided that this notice
 * is preserved.
 * ====================================================
 */
/* tan(x)
 * Return tangent function of x.
 *
 * kernel function:
R
Rich Felker 已提交
16 17
 *      __tan           ... tangent function on [-pi/4,pi/4]
 *      __rem_pio2      ... argument reduction routine
R
Rich Felker 已提交
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
 *
 * Method.
 *      Let S,C and T denote the sin, cos and tan respectively on
 *      [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
 *      in [-pi/4 , +pi/4], and let n = k mod 4.
 *      We have
 *
 *          n        sin(x)      cos(x)        tan(x)
 *     ----------------------------------------------------------
 *          0          S           C             T
 *          1          C          -S            -1/T
 *          2         -S          -C             T
 *          3         -C           S            -1/T
 *     ----------------------------------------------------------
 *
 * Special cases:
 *      Let trig be any of sin, cos, or tan.
 *      trig(+-INF)  is NaN, with signals;
 *      trig(NaN)    is that NaN;
 *
 * Accuracy:
 *      TRIG(x) returns trig(x) nearly rounded
 */

R
Rich Felker 已提交
42
#include "libm.h"
R
Rich Felker 已提交
43

R
Rich Felker 已提交
44
double tan(double x)
R
Rich Felker 已提交
45
{
S
Szabolcs Nagy 已提交
46 47 48
	double y[2];
	uint32_t ix;
	unsigned n;
R
Rich Felker 已提交
49

R
Rich Felker 已提交
50
	GET_HIGH_WORD(ix, x);
S
Szabolcs Nagy 已提交
51
	ix &= 0x7fffffff;
R
Rich Felker 已提交
52

R
Rich Felker 已提交
53 54
	/* |x| ~< pi/4 */
	if (ix <= 0x3fe921fb) {
S
Szabolcs Nagy 已提交
55 56 57 58 59 60
		if (ix < 0x3e400000) { /* |x| < 2**-27 */
			/* raise inexact if x!=0 and underflow if subnormal */
			FORCE_EVAL(ix < 0x00100000 ? x/0x1p120f : x+0x1p120f);
			return x;
		}
		return __tan(x, 0.0, 0);
R
Rich Felker 已提交
61
	}
R
Rich Felker 已提交
62

R
Rich Felker 已提交
63 64 65
	/* tan(Inf or NaN) is NaN */
	if (ix >= 0x7ff00000)
		return x - x;
R
Rich Felker 已提交
66

S
Szabolcs Nagy 已提交
67
	/* argument reduction */
R
Rich Felker 已提交
68
	n = __rem_pio2(x, y);
S
Szabolcs Nagy 已提交
69
	return __tan(y[0], y[1], n&1);
R
Rich Felker 已提交
70
}