]> git.nega.tv - josh/narcissus/commitdiff
Improve error rate on sin_pi
authorJoshua Simmons <josh@nega.tv>
Sat, 22 Oct 2022 14:25:44 +0000 (16:25 +0200)
committerJoshua Simmons <josh@nega.tv>
Sat, 22 Oct 2022 14:25:44 +0000 (16:25 +0200)
Similarly to our tan implementation, use a 48 bit leading coefficient.
Reduces the percentage of faithfully rounded results from 17.4% to 1.3%.

narcissus-maths/doc/sincostan.sollya
narcissus-maths/src/sin_cos_pi.rs
narcissus-maths/tests/exhaustive_f32.rs

index eb3d5176a7756a0a7cc01fee37764e4e875b2df2..ef8280b37774f6ba792071b26893fc27c82c71e3 100644 (file)
@@ -121,6 +121,8 @@ procedure f32_data_write(name,a,f,r)
 
 // Actual start of building polynomial
 
+B = [|D,SG...|];
+
 print("sin(pi x) in binary32");
 I = [|1,3,5,7|];
 F = sin(pi*x);
@@ -129,6 +131,8 @@ f32_data_write("F32_SIN_PI_7", P,F,R);
 f32_write_list("F32_SIN_PI_7", list_of_odd_coeff(P));
 print("\n");
 
+B = [|SG...|];
+
 print("cos(pi x) in binary32");
 I = [|0,2,4,6,8|];
 F = cos(pi*x);
index 0f1450f7bc61a95c091db2ce3c5193062e623bac..e9912cba95c8fc93dcd3ef71d7e57716e530e0d4 100644 (file)
@@ -3,12 +3,11 @@
 // Sollya code for generating these polynomials is in `doc/sincostan.sollya`
 
 // constants for sin(pi x), cos(pi x) for x on [-1/4,1/4]
-const F32_SIN_PI_7_K: [f32; 4] = unsafe {
-    std::mem::transmute::<[u32; 4], _>([
-        0x40490fdb, // 0x1.921fb6p1
-        0xc0a55df6, // -0x1.4abbecp2
-        0x40233590, // 0x1.466b2p1
-        0xbf17acc9, // -0x1.2f5992p-1
+const F32_SIN_PI_7_K: [f32; 3] = unsafe {
+    std::mem::transmute::<[u32; 3], _>([
+        0xc0a55ddd, // -0x1.4abbbap2
+        0x40232f6e, // 0x1.465edcp1
+        0xbf16cf2d, // -0x1.2d9e5ap-1
     ])
 };
 
@@ -42,7 +41,7 @@ fn mulsign_f32(x: f32, s: u32) -> f32 {
 /// assert_eq!(cos, 1.0);
 /// ```
 pub fn sin_cos_pi_f32(a: f32) -> (f32, f32) {
-    const S: [f32; 4] = F32_SIN_PI_7_K;
+    const S: [f32; 3] = F32_SIN_PI_7_K;
     const C: [f32; 4] = F32_COS_PI_8_K;
 
     // cos_pi(a) = 1.0f for |a| > 2^24, but cos_pi(Inf) = NaN
@@ -67,11 +66,10 @@ pub fn sin_cos_pi_f32(a: f32) -> (f32, f32) {
     let c = c.mul_add(r2, 1.0);
     let c = mulsign_f32(c, sx);
 
-    let r3 = r2 * r;
-    let s = S[3];
-    let s = s.mul_add(r2, S[2]);
+    let s = S[2];
     let s = s.mul_add(r2, S[1]);
-    let s = r.mul_add(S[0], r3 * s);
+    let s = s.mul_add(r2, S[0]);
+    let s = r.mul_add(std::f32::consts::PI, r * r2.mul_add(s, -8.742278e-8));
 
     let (s, c) = if i & 1 != 0 { (c, s) } else { (s, c) };
 
index ce723a9e761d798c90463635201a71896bb366b6..3d392f4b1b6a4861034a0aaca8fb67fb3e95b678 100644 (file)
@@ -424,7 +424,7 @@ pub fn exhaustive_sin_pi() {
     let errors = check_exhaustive_f32(ref_sin_pi_f32, |a| sin_cos_pi_f32(a).0, false);
     println!("SIN: {:?}", errors);
     assert_eq!(errors.max_error_ulp, 1);
-    assert_eq!(errors.num_errors, 744_496_052);
+    assert_eq!(errors.num_errors, 55_943_962);
 }
 
 #[test]