Coverage Report

Created: 2025-07-18 06:22

/rust/registry/src/index.crates.io-6f17d22bba15001f/libm-0.2.11/src/math/sincos.rs
Line
Count
Source (jump to first uncovered line)
1
/* origin: FreeBSD /usr/src/lib/msun/src/s_sin.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
13
use super::{get_high_word, k_cos, k_sin, rem_pio2};
14
15
/// Both the sine and cosine of `x` (f64).
16
///
17
/// `x` is specified in radians and the return value is (sin(x), cos(x)).
18
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
19
0
pub fn sincos(x: f64) -> (f64, f64) {
20
0
    let s: f64;
21
0
    let c: f64;
22
0
    let mut ix: u32;
23
0
24
0
    ix = get_high_word(x);
25
0
    ix &= 0x7fffffff;
26
0
27
0
    /* |x| ~< pi/4 */
28
0
    if ix <= 0x3fe921fb {
29
        /* if |x| < 2**-27 * sqrt(2) */
30
0
        if ix < 0x3e46a09e {
31
            /* raise inexact if x!=0 and underflow if subnormal */
32
0
            let x1p120 = f64::from_bits(0x4770000000000000); // 0x1p120 == 2^120
33
0
            if ix < 0x00100000 {
34
0
                force_eval!(x / x1p120);
35
0
            } else {
36
0
                force_eval!(x + x1p120);
37
0
            }
38
0
            return (x, 1.0);
39
0
        }
40
0
        return (k_sin(x, 0.0, 0), k_cos(x, 0.0));
41
0
    }
42
0
43
0
    /* sincos(Inf or NaN) is NaN */
44
0
    if ix >= 0x7ff00000 {
45
0
        let rv = x - x;
46
0
        return (rv, rv);
47
0
    }
48
0
49
0
    /* argument reduction needed */
50
0
    let (n, y0, y1) = rem_pio2(x);
51
0
    s = k_sin(y0, y1, 1);
52
0
    c = k_cos(y0, y1);
53
0
    match n & 3 {
54
0
        0 => (s, c),
55
0
        1 => (c, -s),
56
0
        2 => (-s, -c),
57
0
        3 => (-c, s),
58
        #[cfg(debug_assertions)]
59
        _ => unreachable!(),
60
        #[cfg(not(debug_assertions))]
61
0
        _ => (0.0, 1.0),
62
    }
63
0
}
64
65
// These tests are based on those from sincosf.rs
66
#[cfg(test)]
67
mod tests {
68
    use super::sincos;
69
70
    const TOLERANCE: f64 = 1e-6;
71
72
    #[test]
73
    fn with_pi() {
74
        let (s, c) = sincos(core::f64::consts::PI);
75
        assert!(
76
            (s - 0.0).abs() < TOLERANCE,
77
            "|{} - {}| = {} >= {}",
78
            s,
79
            0.0,
80
            (s - 0.0).abs(),
81
            TOLERANCE
82
        );
83
        assert!(
84
            (c + 1.0).abs() < TOLERANCE,
85
            "|{} + {}| = {} >= {}",
86
            c,
87
            1.0,
88
            (s + 1.0).abs(),
89
            TOLERANCE
90
        );
91
    }
92
93
    #[test]
94
    fn rotational_symmetry() {
95
        use core::f64::consts::PI;
96
        const N: usize = 24;
97
        for n in 0..N {
98
            let theta = 2. * PI * (n as f64) / (N as f64);
99
            let (s, c) = sincos(theta);
100
            let (s_plus, c_plus) = sincos(theta + 2. * PI);
101
            let (s_minus, c_minus) = sincos(theta - 2. * PI);
102
103
            assert!(
104
                (s - s_plus).abs() < TOLERANCE,
105
                "|{} - {}| = {} >= {}",
106
                s,
107
                s_plus,
108
                (s - s_plus).abs(),
109
                TOLERANCE
110
            );
111
            assert!(
112
                (s - s_minus).abs() < TOLERANCE,
113
                "|{} - {}| = {} >= {}",
114
                s,
115
                s_minus,
116
                (s - s_minus).abs(),
117
                TOLERANCE
118
            );
119
            assert!(
120
                (c - c_plus).abs() < TOLERANCE,
121
                "|{} - {}| = {} >= {}",
122
                c,
123
                c_plus,
124
                (c - c_plus).abs(),
125
                TOLERANCE
126
            );
127
            assert!(
128
                (c - c_minus).abs() < TOLERANCE,
129
                "|{} - {}| = {} >= {}",
130
                c,
131
                c_minus,
132
                (c - c_minus).abs(),
133
                TOLERANCE
134
            );
135
        }
136
    }
137
}