1 | //! Tangent approximation for a single-precision float. |
2 | |
3 | use super::F32; |
4 | |
5 | impl F32 { |
6 | /// Approximates `tan(x)` in radians with a maximum error of `0.6`. |
7 | pub fn tan(self) -> Self { |
8 | self.sin() / self.cos() |
9 | } |
10 | } |
11 | |
12 | #[cfg (test)] |
13 | mod tests { |
14 | use super::F32; |
15 | |
16 | /// Maximum error in radians |
17 | // TODO(tarcieri): this is kinda bad, find a better approximation? |
18 | const MAX_ERROR: f32 = 0.6; |
19 | |
20 | /// Tangent test vectors - `(input, output)` |
21 | const TEST_VECTORS: &[(f32, f32)] = &[ |
22 | (0.000, 0.000), |
23 | (0.140, 0.141), |
24 | (0.279, 0.287), |
25 | (0.419, 0.445), |
26 | (0.559, 0.625), |
27 | (0.698, 0.839), |
28 | (0.838, 1.111), |
29 | (0.977, 1.483), |
30 | (1.117, 2.050), |
31 | (1.257, 3.078), |
32 | (1.396, 5.671), |
33 | (1.536, 28.636), |
34 | (1.676, -9.514), |
35 | (1.815, -4.011), |
36 | (1.955, -2.475), |
37 | (2.094, -1.732), |
38 | (2.234, -1.280), |
39 | (2.374, -0.966), |
40 | (2.513, -0.727), |
41 | (2.653, -0.532), |
42 | (2.793, -0.364), |
43 | (2.932, -0.213), |
44 | (3.072, -0.070), |
45 | (3.211, 0.070), |
46 | (3.351, 0.213), |
47 | (3.491, 0.364), |
48 | (3.630, 0.532), |
49 | (3.770, 0.727), |
50 | (3.910, 0.966), |
51 | (4.049, 1.280), |
52 | (4.189, 1.732), |
53 | (4.328, 2.475), |
54 | (4.468, 4.011), |
55 | (4.608, 9.514), |
56 | (4.747, -28.636), |
57 | (4.887, -5.671), |
58 | (5.027, -3.078), |
59 | (5.166, -2.050), |
60 | (5.306, -1.483), |
61 | (5.445, -1.111), |
62 | (5.585, -0.839), |
63 | (5.725, -0.625), |
64 | (5.864, -0.445), |
65 | (6.004, -0.287), |
66 | (6.144, -0.141), |
67 | (6.283, 0.000), |
68 | ]; |
69 | |
70 | #[test ] |
71 | fn sanity_check() { |
72 | for &(x, expected) in TEST_VECTORS { |
73 | let tan_x = F32(x).tan(); |
74 | let delta = (tan_x - expected).abs(); |
75 | |
76 | assert!( |
77 | delta <= MAX_ERROR, |
78 | "delta {} too large: {} vs {}" , |
79 | delta, |
80 | tan_x, |
81 | expected |
82 | ); |
83 | } |
84 | } |
85 | |
86 | #[test ] |
87 | fn zero() { |
88 | assert_eq!(F32::ZERO.tan(), F32::ZERO); |
89 | } |
90 | |
91 | #[test ] |
92 | fn nan() { |
93 | assert!(F32::NAN.tan().is_nan()); |
94 | } |
95 | } |
96 | |