sinf, fix constant in k_expo2f

This commit is contained in:
Andrey Zgarbul 2018-07-15 07:01:26 +03:00
parent 3b24b8ffc5
commit f8e937fa46
5 changed files with 35 additions and 5 deletions

View file

@ -108,7 +108,6 @@ pub trait F32Ext: private::Sealed {
fn ln_1p(self) -> Self;
#[cfg(todo)]
fn sinh(self) -> Self;
fn cosh(self) -> Self;
@ -284,7 +283,6 @@ impl F32Ext for f32 {
log1pf(self)
}
#[cfg(todo)]
#[inline]
fn sinh(self) -> Self {
sinhf(self)

View file

@ -2,13 +2,13 @@ use super::expf;
/* k is such that k*ln2 has minimal relative error and x - kln2 > log(FLT_MIN) */
const K: i32 = 235;
const K_LN2: f32 = 162.89; /* 0x1.45c778p+7f */
/* expf(x)/2 for x >= log(FLT_MAX), slightly better than 0.5f*expf(x/2)*expf(x/2) */
#[inline]
pub(crate) fn k_expo2f(x: f32) -> f32 {
let k_ln2 = f32::from_bits(0x4322e3bc);
/* note that k is odd and scale*scale overflows */
let scale = f32::from_bits(((0x7f + K / 2) as u32) << 23);
/* exp(x - k ln2) * 2**(k-1) */
expf(x - K_LN2) * scale * scale
expf(x - k_ln2) * scale * scale
}

View file

@ -53,6 +53,7 @@ mod scalbnf;
mod sin;
mod sinf;
mod sinh;
mod sinhf;
mod sqrt;
mod sqrtf;
mod tan;
@ -108,6 +109,7 @@ pub use self::scalbnf::scalbnf;
pub use self::sin::sin;
pub use self::sinf::sinf;
pub use self::sinh::sinh;
pub use self::sinhf::sinhf;
pub use self::sqrt::sqrt;
pub use self::sqrtf::sqrtf;
pub use self::tan::tan;

View file

@ -0,0 +1,30 @@
use super::expm1f;
use super::k_expo2f;
#[inline]
pub fn sinhf(x: f32) -> f32 {
let mut h = 0.5f32;
let mut ix = x.to_bits();
if (ix >> 31) != 0 {
h = -h;
}
/* |x| */
ix &= 0x7fffffff;
let absx = f32::from_bits(ix);
let w = ix;
/* |x| < log(FLT_MAX) */
if w < 0x42b17217 {
let t = expm1f(absx);
if w < 0x3f800000 {
if w < (0x3f800000 - (12 << 23)) {
return x;
}
return h * (2. * t - t * t / (t + 1.));
}
return h * (t + t / (t + 1.));
}
/* |x| > logf(FLT_MAX) or nan */
2. * h * k_expo2f(absx)
}

View file

@ -669,7 +669,7 @@ f32_f32! {
logf,
roundf,
sinf,
// sinhf,
sinhf,
tanf,
tanhf,
fabsf,