coshf tanhf and atan2f
This commit is contained in:
parent
802f6a2b46
commit
b61b0046c0
7 changed files with 169 additions and 11 deletions
|
|
@ -96,7 +96,6 @@ pub trait F32Ext: private::Sealed {
|
|||
|
||||
fn atan(self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
fn atan2(self, other: Self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
|
|
@ -112,10 +111,8 @@ pub trait F32Ext: private::Sealed {
|
|||
#[cfg(todo)]
|
||||
fn sinh(self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
fn cosh(self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
fn tanh(self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
|
|
@ -272,7 +269,6 @@ impl F32Ext for f32 {
|
|||
atanf(self)
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[inline]
|
||||
fn atan2(self, other: Self) -> Self {
|
||||
atan2f(self, other)
|
||||
|
|
@ -294,13 +290,11 @@ impl F32Ext for f32 {
|
|||
sinhf(self)
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[inline]
|
||||
fn cosh(self) -> Self {
|
||||
coshf(self)
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[inline]
|
||||
fn tanh(self) -> Self {
|
||||
tanhf(self)
|
||||
|
|
|
|||
71
library/compiler-builtins/libm/src/math/atan2f.rs
Normal file
71
library/compiler-builtins/libm/src/math/atan2f.rs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
use super::atanf;
|
||||
use super::fabsf;
|
||||
|
||||
const PI: f32 = 3.1415927410e+00; /* 0x40490fdb */
|
||||
const PI_LO: f32 = -8.7422776573e-08; /* 0xb3bbbd2e */
|
||||
|
||||
#[inline]
|
||||
pub fn atan2f(y: f32, x: f32) -> f32 {
|
||||
if x.is_nan() || y.is_nan() {
|
||||
return x + y;
|
||||
}
|
||||
let mut ix = x.to_bits();
|
||||
let mut iy = y.to_bits();
|
||||
|
||||
if ix == 0x3f800000 {
|
||||
/* x=1.0 */
|
||||
return atanf(y);
|
||||
}
|
||||
let m = ((iy >> 31) & 1) | ((ix >> 30) & 2); /* 2*sign(x)+sign(y) */
|
||||
ix &= 0x7fffffff;
|
||||
iy &= 0x7fffffff;
|
||||
|
||||
/* when y = 0 */
|
||||
if iy == 0 {
|
||||
return match m {
|
||||
0 | 1 => y, /* atan(+-0,+anything)=+-0 */
|
||||
2 => PI, /* atan(+0,-anything) = pi */
|
||||
3 | _ => -PI, /* atan(-0,-anything) =-pi */
|
||||
};
|
||||
}
|
||||
/* when x = 0 */
|
||||
if ix == 0 {
|
||||
return if m & 1 != 0 { -PI / 2. } else { PI / 2. };
|
||||
}
|
||||
/* when x is INF */
|
||||
if ix == 0x7f800000 {
|
||||
return if iy == 0x7f800000 {
|
||||
match m {
|
||||
0 => PI / 4., /* atan(+INF,+INF) */
|
||||
1 => -PI / 4., /* atan(-INF,+INF) */
|
||||
2 => 3. * PI / 4., /* atan(+INF,-INF)*/
|
||||
3 | _ => -3. * PI / 4., /* atan(-INF,-INF)*/
|
||||
}
|
||||
} else {
|
||||
match m {
|
||||
0 => 0., /* atan(+...,+INF) */
|
||||
1 => -0., /* atan(-...,+INF) */
|
||||
2 => PI, /* atan(+...,-INF) */
|
||||
3 | _ => -PI, /* atan(-...,-INF) */
|
||||
}
|
||||
};
|
||||
}
|
||||
/* |y/x| > 0x1p26 */
|
||||
if (ix + (26 << 23) < iy) || (iy == 0x7f800000) {
|
||||
return if m & 1 != 0 { -PI / 2. } else { PI / 2. };
|
||||
}
|
||||
|
||||
/* z = atan(|y/x|) with correct underflow */
|
||||
let z = if (m & 2 != 0) && (iy + (26 << 23) < ix) {
|
||||
/*|y/x| < 0x1p-26, x < 0 */
|
||||
0.
|
||||
} else {
|
||||
atanf(fabsf(y / x))
|
||||
};
|
||||
match m {
|
||||
0 => z, /* atan(+,+) */
|
||||
1 => -z, /* atan(-,+) */
|
||||
2 => PI - (z - PI_LO), /* atan(+,-) */
|
||||
_ => (z - PI_LO) - PI, /* case 3 */ /* atan(-,-) */
|
||||
}
|
||||
}
|
||||
33
library/compiler-builtins/libm/src/math/coshf.rs
Normal file
33
library/compiler-builtins/libm/src/math/coshf.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
use super::expf;
|
||||
use super::expm1f;
|
||||
use super::k_expo2f;
|
||||
|
||||
#[inline]
|
||||
pub fn coshf(mut x: f32) -> f32 {
|
||||
let x1p120 = f32::from_bits(0x7b800000); // 0x1p120f === 2 ^ 120
|
||||
|
||||
/* |x| */
|
||||
let mut ix = x.to_bits();
|
||||
ix &= 0x7fffffff;
|
||||
x = f32::from_bits(ix);
|
||||
let w = ix;
|
||||
|
||||
/* |x| < log(2) */
|
||||
if w < 0x3f317217 {
|
||||
if w < (0x3f800000 - (12 << 23)) {
|
||||
force_eval!(x + x1p120);
|
||||
return 1.;
|
||||
}
|
||||
let t = expm1f(x);
|
||||
return 1. + t * t / (2. * (1. + t));
|
||||
}
|
||||
|
||||
/* |x| < log(FLT_MAX) */
|
||||
if w < 0x42b17217 {
|
||||
let t = expf(x);
|
||||
return 0.5 * (t + 1. / t);
|
||||
}
|
||||
|
||||
/* |x| > log(FLT_MAX) or nan */
|
||||
k_expo2f(x)
|
||||
}
|
||||
14
library/compiler-builtins/libm/src/math/k_expo2f.rs
Normal file
14
library/compiler-builtins/libm/src/math/k_expo2f.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
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 {
|
||||
/* 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
|
||||
}
|
||||
|
|
@ -10,12 +10,14 @@ mod acos;
|
|||
mod acosf;
|
||||
mod asin;
|
||||
mod asinf;
|
||||
mod atan2f;
|
||||
mod atanf;
|
||||
mod cbrt;
|
||||
mod cbrtf;
|
||||
mod ceil;
|
||||
mod ceilf;
|
||||
mod cosf;
|
||||
mod coshf;
|
||||
mod exp;
|
||||
mod exp2;
|
||||
mod exp2f;
|
||||
|
|
@ -50,6 +52,7 @@ mod sinf;
|
|||
mod sqrt;
|
||||
mod sqrtf;
|
||||
mod tanf;
|
||||
mod tanhf;
|
||||
mod trunc;
|
||||
mod truncf;
|
||||
|
||||
|
|
@ -58,12 +61,14 @@ pub use self::acos::acos;
|
|||
pub use self::acosf::acosf;
|
||||
pub use self::asin::asin;
|
||||
pub use self::asinf::asinf;
|
||||
pub use self::atan2f::atan2f;
|
||||
pub use self::atanf::atanf;
|
||||
pub use self::cbrt::cbrt;
|
||||
pub use self::cbrtf::cbrtf;
|
||||
pub use self::ceil::ceil;
|
||||
pub use self::ceilf::ceilf;
|
||||
pub use self::cosf::cosf;
|
||||
pub use self::coshf::coshf;
|
||||
pub use self::exp::exp;
|
||||
pub use self::exp2::exp2;
|
||||
pub use self::exp2f::exp2f;
|
||||
|
|
@ -98,18 +103,20 @@ pub use self::sinf::sinf;
|
|||
pub use self::sqrt::sqrt;
|
||||
pub use self::sqrtf::sqrtf;
|
||||
pub use self::tanf::tanf;
|
||||
pub use self::tanhf::tanhf;
|
||||
pub use self::trunc::trunc;
|
||||
pub use self::truncf::truncf;
|
||||
|
||||
mod k_cosf;
|
||||
mod k_expo2f;
|
||||
mod k_sinf;
|
||||
mod k_tanf;
|
||||
mod rem_pio2_large;
|
||||
mod rem_pio2f;
|
||||
|
||||
use self::{
|
||||
k_cosf::k_cosf, k_sinf::k_sinf, k_tanf::k_tanf, rem_pio2_large::rem_pio2_large,
|
||||
rem_pio2f::rem_pio2f,
|
||||
k_cosf::k_cosf, k_expo2f::k_expo2f, k_sinf::k_sinf, k_tanf::k_tanf,
|
||||
rem_pio2_large::rem_pio2_large, rem_pio2f::rem_pio2f,
|
||||
};
|
||||
|
||||
#[inline]
|
||||
|
|
|
|||
39
library/compiler-builtins/libm/src/math/tanhf.rs
Normal file
39
library/compiler-builtins/libm/src/math/tanhf.rs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
use super::expm1f;
|
||||
|
||||
#[inline]
|
||||
pub fn tanhf(mut x: f32) -> f32 {
|
||||
/* x = |x| */
|
||||
let mut ix = x.to_bits();
|
||||
let sign = (ix >> 31) != 0;
|
||||
ix &= 0x7fffffff;
|
||||
x = f32::from_bits(ix);
|
||||
let w = ix;
|
||||
|
||||
let tt = if w > 0x3f0c9f54 {
|
||||
/* |x| > log(3)/2 ~= 0.5493 or nan */
|
||||
if w > 0x41200000 {
|
||||
/* |x| > 10 */
|
||||
1. + 0. / x
|
||||
} else {
|
||||
let t = expm1f(2. * x);
|
||||
1. - 2. / (t + 2.)
|
||||
}
|
||||
} else if w > 0x3e82c578 {
|
||||
/* |x| > log(5/3)/2 ~= 0.2554 */
|
||||
let t = expm1f(2. * x);
|
||||
t / (t + 2.)
|
||||
} else if w >= 0x00800000 {
|
||||
/* |x| >= 0x1p-126 */
|
||||
let t = expm1f(-2. * x);
|
||||
-t / (t + 2.)
|
||||
} else {
|
||||
/* |x| is subnormal */
|
||||
force_eval!(x * x);
|
||||
x
|
||||
};
|
||||
if sign {
|
||||
-tt
|
||||
} else {
|
||||
tt
|
||||
}
|
||||
}
|
||||
|
|
@ -659,7 +659,7 @@ f32_f32! {
|
|||
cbrtf,
|
||||
cosf,
|
||||
ceilf,
|
||||
// coshf,
|
||||
coshf,
|
||||
exp2f,
|
||||
expf,
|
||||
expm1f,
|
||||
|
|
@ -671,14 +671,14 @@ f32_f32! {
|
|||
sinf,
|
||||
// sinhf,
|
||||
tanf,
|
||||
// tanhf,
|
||||
tanhf,
|
||||
fabsf,
|
||||
sqrtf,
|
||||
}
|
||||
|
||||
// With signature `fn(f32, f32) -> f32`
|
||||
f32f32_f32! {
|
||||
// atan2f,
|
||||
atan2f,
|
||||
fdimf,
|
||||
hypotf,
|
||||
fmodf,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue