/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 | | } |