1 | //! Sine approximation, implemented in terms of `cos(x)`. |
2 | |
3 | use super::F32; |
4 | use core::f32::consts::PI; |
5 | |
6 | impl F32 { |
7 | /// Approximates `sin(x)` in radians with a maximum error of `0.002`. |
8 | pub fn sin(self) -> Self { |
9 | (self - PI / 2.0).cos() |
10 | } |
11 | } |
12 | |
13 | #[cfg (test)] |
14 | mod tests { |
15 | use super::F32; |
16 | use crate::float::cos::tests::MAX_ERROR; |
17 | |
18 | /// Sine test vectors - `(input, output)` |
19 | const TEST_VECTORS: &[(f32, f32)] = &[ |
20 | (0.000, 0.000), |
21 | (0.140, 0.139), |
22 | (0.279, 0.276), |
23 | (0.419, 0.407), |
24 | (0.559, 0.530), |
25 | (0.698, 0.643), |
26 | (0.838, 0.743), |
27 | (0.977, 0.829), |
28 | (1.117, 0.899), |
29 | (1.257, 0.951), |
30 | (1.396, 0.985), |
31 | (1.536, 0.999), |
32 | (1.676, 0.995), |
33 | (1.815, 0.970), |
34 | (1.955, 0.927), |
35 | (2.094, 0.866), |
36 | (2.234, 0.788), |
37 | (2.374, 0.695), |
38 | (2.513, 0.588), |
39 | (2.653, 0.469), |
40 | (2.793, 0.342), |
41 | (2.932, 0.208), |
42 | (3.072, 0.070), |
43 | (3.211, -0.070), |
44 | (3.351, -0.208), |
45 | (3.491, -0.342), |
46 | (3.630, -0.469), |
47 | (3.770, -0.588), |
48 | (3.910, -0.695), |
49 | (4.049, -0.788), |
50 | (4.189, -0.866), |
51 | (4.328, -0.927), |
52 | (4.468, -0.970), |
53 | (4.608, -0.995), |
54 | (4.747, -0.999), |
55 | (4.887, -0.985), |
56 | (5.027, -0.951), |
57 | (5.166, -0.899), |
58 | (5.306, -0.829), |
59 | (5.445, -0.743), |
60 | (5.585, -0.643), |
61 | (5.725, -0.530), |
62 | (5.864, -0.407), |
63 | (6.004, -0.276), |
64 | (6.144, -0.139), |
65 | (6.283, 0.000), |
66 | ]; |
67 | |
68 | #[test ] |
69 | fn sanity_check() { |
70 | for &(x, expected) in TEST_VECTORS { |
71 | let sin_x = F32(x).sin(); |
72 | let delta = (sin_x - expected).abs(); |
73 | |
74 | assert!( |
75 | delta <= MAX_ERROR, |
76 | "delta {} too large: {} vs {}" , |
77 | delta, |
78 | sin_x, |
79 | expected |
80 | ); |
81 | } |
82 | } |
83 | } |
84 | |