Coverage Report

Created: 2024-09-10 12:50

/build/cargo-vendor-dir/libm-0.2.8/src/math/tan.rs
Line
Count
Source (jump to first uncovered line)
1
// origin: FreeBSD /usr/src/lib/msun/src/s_tan.c */
2
//
3
// ====================================================
4
// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5
//
6
// Developed at SunPro, a Sun Microsystems, Inc. business.
7
// Permission to use, copy, modify, and distribute this
8
// software is freely granted, provided that this notice
9
// is preserved.
10
// ====================================================
11
12
use super::{k_tan, rem_pio2};
13
14
// tan(x)
15
// Return tangent function of x.
16
//
17
// kernel function:
18
//      k_tan           ... tangent function on [-pi/4,pi/4]
19
//      rem_pio2        ... argument reduction routine
20
//
21
// Method.
22
//      Let S,C and T denote the sin, cos and tan respectively on
23
//      [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
24
//      in [-pi/4 , +pi/4], and let n = k mod 4.
25
//      We have
26
//
27
//          n        sin(x)      cos(x)        tan(x)
28
//     ----------------------------------------------------------
29
//          0          S           C             T
30
//          1          C          -S            -1/T
31
//          2         -S          -C             T
32
//          3         -C           S            -1/T
33
//     ----------------------------------------------------------
34
//
35
// Special cases:
36
//      Let trig be any of sin, cos, or tan.
37
//      trig(+-INF)  is NaN, with signals;
38
//      trig(NaN)    is that NaN;
39
//
40
// Accuracy:
41
//      TRIG(x) returns trig(x) nearly rounded
42
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
43
0
pub fn tan(x: f64) -> f64 {
44
0
    let x1p120 = f32::from_bits(0x7b800000); // 0x1p120f === 2 ^ 120
45
0
46
0
    let ix = (f64::to_bits(x) >> 32) as u32 & 0x7fffffff;
47
0
    /* |x| ~< pi/4 */
48
0
    if ix <= 0x3fe921fb {
49
0
        if ix < 0x3e400000 {
50
            /* |x| < 2**-27 */
51
            /* raise inexact if x!=0 and underflow if subnormal */
52
0
            force_eval!(if ix < 0x00100000 {
53
0
                x / x1p120 as f64
54
            } else {
55
0
                x + x1p120 as f64
56
            });
57
0
            return x;
58
0
        }
59
0
        return k_tan(x, 0.0, 0);
60
0
    }
61
0
62
0
    /* tan(Inf or NaN) is NaN */
63
0
    if ix >= 0x7ff00000 {
64
0
        return x - x;
65
0
    }
66
0
67
0
    /* argument reduction */
68
0
    let (n, y0, y1) = rem_pio2(x);
69
0
    k_tan(y0, y1, n & 1)
70
0
}