Created
July 19, 2018 00:05
-
-
Save porglezomp/3ec824f07d15ba5383992f573e6be120 to your computer and use it in GitHub Desktop.
Sin/Cos error ULPs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Sin functions | |
// | |
const S1: f64 = -0.166666666416265235595; /* -0x15555554cbac77.0p-55 */ | |
const S2: f64 = 0.0083333293858894631756; /* 0x111110896efbb2.0p-59 */ | |
const S3: f64 = -0.000198393348360966317347; /* -0x1a00f9e2cae774.0p-65 */ | |
const S4: f64 = 0.0000027183114939898219064; /* 0x16cd878c3b46a7.0p-71 */ | |
pub fn k_sinf(x: f64) -> f32 { | |
let z = x * x; | |
let w = z * z; | |
let r = S3 + z * S4; | |
let s = z * x; | |
((x + s * (S1 + z * S2)) + s * w * r) as f32 | |
} | |
const S1_F32: f32 = -0.166666666416265235595; /* -0x15555554cbac77.0p-55 */ | |
const S2_F32: f32 = 0.0083333293858894631756; /* 0x111110896efbb2.0p-59 */ | |
const S3_F32: f32 = -0.000198393348360966317347; /* -0x1a00f9e2cae774.0p-65 */ | |
const S4_F32: f32 = 0.0000027183114939898219064; /* 0x16cd878c3b46a7.0p-71 */ | |
fn k_sinf_f32(x: f32) -> f32 { | |
let z = x * x; | |
let w = z * z; | |
let r = S3_F32 + z * S4_F32; | |
let s = z * x; | |
((x + s * (S1_F32 + z * S2_F32)) + s * w * r) | |
} | |
// Cos functinos | |
const C0: f64 = -0.499999997251031003120; /* -0x1ffffffd0c5e81.0p-54 */ | |
const C1: f64 = 0.0416666233237390631894; /* 0x155553e1053a42.0p-57 */ | |
const C2: f64 = -0.00138867637746099294692; /* -0x16c087e80f1e27.0p-62 */ | |
const C3: f64 = 0.0000243904487962774090654; /* 0x199342e0ee5069.0p-68 */ | |
pub fn k_cosf(x: f64) -> f32 { | |
let z = x * x; | |
let w = z * z; | |
let r = C2 + z * C3; | |
(((1.0 + z * C0) + w * C1) + (w * z) * r) as f32 | |
} | |
const C0_F32: f32 = -0.499999997251031003120; /* -0x1ffffffd0c5e81.0p-54 */ | |
const C1_F32: f32 = 0.0416666233237390631894; /* 0x155553e1053a42.0p-57 */ | |
const C2_F32: f32 = -0.00138867637746099294692; /* -0x16c087e80f1e27.0p-62 */ | |
const C3_F32: f32 = 0.0000243904487962774090654; /* 0x199342e0ee5069.0p-68 */ | |
pub fn k_cosf_f32(x: f32) -> f32 { | |
let z = x * x; | |
let w = z * z; | |
let r = C2_F32 + z * C3_F32; | |
(((1.0 + z * C0_F32) + w * C1_F32) + (w * z) * r) as f32 | |
} | |
use std::f32::consts::PI; | |
fn main() { | |
let mut sin_err = 0; | |
let mut cos_err = 0; | |
for n in 0..=f32::to_bits(PI / 4.0) { | |
let input = f32::from_bits(n); | |
sin_err = sin_err.max({ | |
let high_prec_sin = k_sinf(input as f64); | |
let low_prec_sin = k_sinf_f32(input); | |
(f32::to_bits(high_prec_sin) as i32) | |
.wrapping_sub(f32::to_bits(low_prec_sin) as i32) | |
.abs() as u32 | |
}).max({ | |
let high_prec_sin = k_sinf(-input as f64); | |
let low_prec_sin = k_sinf_f32(-input); | |
(f32::to_bits(high_prec_sin) as i32) | |
.wrapping_sub(f32::to_bits(low_prec_sin) as i32) | |
.abs() as u32 | |
}); | |
cos_err = cos_err.max({ | |
let high_prec_cos = k_cosf(input as f64); | |
let low_prec_cos = k_cosf_f32(input); | |
(f32::to_bits(high_prec_cos) as i32) | |
.wrapping_sub(f32::to_bits(low_prec_cos) as i32) | |
.abs() as u32 | |
}).max({ | |
let high_prec_cos = k_cosf(-input as f64); | |
let low_prec_cos = k_cosf_f32(-input); | |
(f32::to_bits(high_prec_cos) as i32) | |
.wrapping_sub(f32::to_bits(low_prec_cos) as i32) | |
.abs() as u32 | |
}); | |
} | |
println!("Sin error (ULPs): {}", sin_err); | |
println!("Cos error (ULPs): {}", cos_err); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment