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