From 6430351e7457649d7b6cb50c33a4ab83e33944f8 Mon Sep 17 00:00:00 2001 From: Vinzent Steinberg Date: Tue, 10 Apr 2018 15:26:14 +0200 Subject: [PATCH] =?UTF-8?q?Use=20constant=20for=20180/=CF=80=20in=20f32::t?= =?UTF-8?q?o=5Fdegrees?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current `f32::to_degrees` implementation uses a division to calculate 180/π, which causes a loss of precision. Using a constant is still not perfect (implementing a maximally-precise algorithm would come with a high performance cost), but improves precision with a minimal change. This is a backport from [`std`]. [`std`]: https://github.com/rust-lang/rust/pull/47919/commits/e34c31bf02eb0f0ff4dd43ae72e0eae53f2ac519 --- src/float.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/float.rs b/src/float.rs index 072a91b..dbd11d4 100644 --- a/src/float.rs +++ b/src/float.rs @@ -771,7 +771,9 @@ impl FloatCore for f32 { #[inline] #[cfg(not(feature = "std"))] fn to_degrees(self) -> Self { - self * (180.0 / f32::consts::PI) + // Use a constant for better precision. + const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32; + self * PIS_IN_180 } #[inline] @@ -841,6 +843,9 @@ impl FloatCore for f64 { #[inline] #[cfg(not(feature = "std"))] fn to_degrees(self) -> Self { + // The division here is correctly rounded with respect to the true + // value of 180/π. (This differs from f32, where a constant must be + // used to ensure a correctly rounded result.) self * (180.0 / f64::consts::PI) } @@ -2008,4 +2013,9 @@ mod tests { assert!((Float::to_radians(deg) - rad).abs() < 1e-5); } } + + #[test] + fn to_degrees_rounding() { + assert_eq!(1_f32.to_degrees(), 57.2957795130823208767981548141051703); + } }