Merge rust-lang/libm#116
116: inline more functions; add more methods to F{32,64}Ext r=japaric a=japaric
Co-authored-by: Jorge Aparicio <jorge@japaric.io>
This commit is contained in:
commit
8d962a0b0b
20 changed files with 49 additions and 56 deletions
|
|
@ -14,18 +14,19 @@
|
|||
|
||||
mod math;
|
||||
|
||||
#[cfg(todo)]
|
||||
use core::{f32, f64};
|
||||
|
||||
pub use math::*;
|
||||
|
||||
/// Approximate equality with 1 ULP of tolerance
|
||||
#[doc(hidden)]
|
||||
#[inline]
|
||||
pub fn _eqf(a: u32, b: u32) -> bool {
|
||||
(a as i32).wrapping_sub(b as i32).abs() <= 1
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[inline]
|
||||
pub fn _eq(a: u64, b: u64) -> bool {
|
||||
(a as i64).wrapping_sub(b as i64).abs() <= 1
|
||||
}
|
||||
|
|
@ -33,7 +34,7 @@ pub fn _eq(a: u64, b: u64) -> bool {
|
|||
/// Math support for `f32`
|
||||
///
|
||||
/// This trait is sealed and cannot be implemented outside of `libm`.
|
||||
pub trait F32Ext: private::Sealed {
|
||||
pub trait F32Ext: private::Sealed + Sized {
|
||||
fn floor(self) -> Self;
|
||||
|
||||
fn ceil(self) -> Self;
|
||||
|
|
@ -44,20 +45,17 @@ pub trait F32Ext: private::Sealed {
|
|||
|
||||
fn fdim(self, rhs: Self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
fn fract(self) -> Self;
|
||||
|
||||
fn abs(self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
fn signum(self) -> Self;
|
||||
// NOTE depends on unstable intrinsics::copysignf32
|
||||
// fn signum(self) -> Self;
|
||||
|
||||
fn mul_add(self, a: Self, b: Self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
fn div_euc(self, rhs: Self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
fn mod_euc(self, rhs: Self) -> Self;
|
||||
|
||||
// NOTE depends on unstable intrinsics::powif32
|
||||
|
|
@ -97,9 +95,11 @@ pub trait F32Ext: private::Sealed {
|
|||
|
||||
fn atan2(self, other: Self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
#[inline]
|
||||
fn sin_cos(self) -> (Self, Self) {
|
||||
fn sin_cos(self) -> (Self, Self)
|
||||
where
|
||||
Self: Copy,
|
||||
{
|
||||
(self.sin(), self.cos())
|
||||
}
|
||||
|
||||
|
|
@ -113,13 +113,10 @@ pub trait F32Ext: private::Sealed {
|
|||
|
||||
fn tanh(self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
fn asinh(self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
fn acosh(self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
fn atanh(self) -> Self;
|
||||
}
|
||||
|
||||
|
|
@ -149,7 +146,6 @@ impl F32Ext for f32 {
|
|||
fdimf(self, rhs)
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[inline]
|
||||
fn fract(self) -> Self {
|
||||
self - self.trunc()
|
||||
|
|
@ -165,7 +161,6 @@ impl F32Ext for f32 {
|
|||
fmaf(self, a, b)
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[inline]
|
||||
fn div_euc(self, rhs: Self) -> Self {
|
||||
let q = (self / rhs).trunc();
|
||||
|
|
@ -175,7 +170,6 @@ impl F32Ext for f32 {
|
|||
q
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[inline]
|
||||
fn mod_euc(self, rhs: f32) -> f32 {
|
||||
let r = self % rhs;
|
||||
|
|
@ -296,7 +290,6 @@ impl F32Ext for f32 {
|
|||
tanhf(self)
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[inline]
|
||||
fn asinh(self) -> Self {
|
||||
if self == f32::NEG_INFINITY {
|
||||
|
|
@ -306,7 +299,6 @@ impl F32Ext for f32 {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[inline]
|
||||
fn acosh(self) -> Self {
|
||||
match self {
|
||||
|
|
@ -315,7 +307,6 @@ impl F32Ext for f32 {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[inline]
|
||||
fn atanh(self) -> Self {
|
||||
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
|
||||
|
|
@ -325,7 +316,7 @@ impl F32Ext for f32 {
|
|||
/// Math support for `f64`
|
||||
///
|
||||
/// This trait is sealed and cannot be implemented outside of `libm`.
|
||||
pub trait F64Ext: private::Sealed {
|
||||
pub trait F64Ext: private::Sealed + Sized {
|
||||
fn floor(self) -> Self;
|
||||
|
||||
fn ceil(self) -> Self;
|
||||
|
|
@ -336,20 +327,17 @@ pub trait F64Ext: private::Sealed {
|
|||
|
||||
fn fdim(self, rhs: Self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
fn fract(self) -> Self;
|
||||
|
||||
fn abs(self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
fn signum(self) -> Self;
|
||||
// NOTE depends on unstable intrinsics::copysignf64
|
||||
// fn signum(self) -> Self;
|
||||
|
||||
fn mul_add(self, a: Self, b: Self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
fn div_euc(self, rhs: Self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
fn mod_euc(self, rhs: Self) -> Self;
|
||||
|
||||
// NOTE depends on unstable intrinsics::powif64
|
||||
|
|
@ -382,7 +370,6 @@ pub trait F64Ext: private::Sealed {
|
|||
|
||||
fn tan(self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
fn asin(self) -> Self;
|
||||
|
||||
fn acos(self) -> Self;
|
||||
|
|
@ -393,9 +380,11 @@ pub trait F64Ext: private::Sealed {
|
|||
#[cfg(todo)]
|
||||
fn atan2(self, other: Self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
#[inline]
|
||||
fn sin_cos(self) -> (Self, Self) {
|
||||
fn sin_cos(self) -> (Self, Self)
|
||||
where
|
||||
Self: Copy,
|
||||
{
|
||||
(self.sin(), self.cos())
|
||||
}
|
||||
|
||||
|
|
@ -410,13 +399,10 @@ pub trait F64Ext: private::Sealed {
|
|||
|
||||
fn tanh(self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
fn asinh(self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
fn acosh(self) -> Self;
|
||||
|
||||
#[cfg(todo)]
|
||||
fn atanh(self) -> Self;
|
||||
}
|
||||
|
||||
|
|
@ -445,7 +431,7 @@ impl F64Ext for f64 {
|
|||
fn fdim(self, rhs: Self) -> Self {
|
||||
fdim(self, rhs)
|
||||
}
|
||||
#[cfg(todo)]
|
||||
|
||||
#[inline]
|
||||
fn fract(self) -> Self {
|
||||
self - self.trunc()
|
||||
|
|
@ -461,7 +447,6 @@ impl F64Ext for f64 {
|
|||
fma(self, a, b)
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[inline]
|
||||
fn div_euc(self, rhs: Self) -> Self {
|
||||
let q = (self / rhs).trunc();
|
||||
|
|
@ -471,9 +456,8 @@ impl F64Ext for f64 {
|
|||
q
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[inline]
|
||||
fn mod_euc(self, rhs: f32) -> f32 {
|
||||
fn mod_euc(self, rhs: f64) -> f64 {
|
||||
let r = self % rhs;
|
||||
if r < 0.0 {
|
||||
r + rhs.abs()
|
||||
|
|
@ -548,7 +532,6 @@ impl F64Ext for f64 {
|
|||
tan(self)
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[inline]
|
||||
fn asin(self) -> Self {
|
||||
asin(self)
|
||||
|
|
@ -597,7 +580,6 @@ impl F64Ext for f64 {
|
|||
tanh(self)
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[inline]
|
||||
fn asinh(self) -> Self {
|
||||
if self == f64::NEG_INFINITY {
|
||||
|
|
@ -607,7 +589,6 @@ impl F64Ext for f64 {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[inline]
|
||||
fn acosh(self) -> Self {
|
||||
match self {
|
||||
|
|
@ -616,7 +597,6 @@ impl F64Ext for f64 {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[inline]
|
||||
fn atanh(self) -> Self {
|
||||
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ const P_S1: f32 = -4.2743422091e-02;
|
|||
const P_S2: f32 = -8.6563630030e-03;
|
||||
const Q_S1: f32 = -7.0662963390e-01;
|
||||
|
||||
#[inline]
|
||||
fn r(z: f32) -> f32 {
|
||||
let p = z * (P_S0 + z * (P_S1 + z * P_S2));
|
||||
let q = 1. + z * Q_S1;
|
||||
|
|
|
|||
|
|
@ -55,12 +55,14 @@ const Q_S2: f64 = 2.02094576023350569471e+00; /* 0x40002AE5, 0x9C598AC8 */
|
|||
const Q_S3: f64 = -6.88283971605453293030e-01; /* 0xBFE6066C, 0x1B8D0159 */
|
||||
const Q_S4: f64 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
|
||||
|
||||
#[inline]
|
||||
fn comp_r(z: f64) -> f64 {
|
||||
let p = z * (P_S0 + z * (P_S1 + z * (P_S2 + z * (P_S3 + z * (P_S4 + z * P_S5)))));
|
||||
let q = 1.0 + z * (Q_S1 + z * (Q_S2 + z * (Q_S3 + z * Q_S4)));
|
||||
return p / q;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn asin(mut x: f64) -> f64 {
|
||||
let z: f64;
|
||||
let r: f64;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ const P_S1: f32 = -4.2743422091e-02;
|
|||
const P_S2: f32 = -8.6563630030e-03;
|
||||
const Q_S1: f32 = -7.0662963390e-01;
|
||||
|
||||
#[inline]
|
||||
fn r(z: f32) -> f32 {
|
||||
let p = z * (P_S0 + z * (P_S1 + z * P_S2));
|
||||
let q = 1. + z * Q_S1;
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ use super::{k_cos, k_sin, rem_pio2};
|
|||
// Accuracy:
|
||||
// TRIG(x) returns trig(x) nearly rounded
|
||||
//
|
||||
#[inline]
|
||||
pub fn cos(x: f64) -> f64 {
|
||||
let ix = (f64::to_bits(x) >> 32) as u32 & 0x7fffffff;
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ const Q3: f64 = -7.93650757867487942473e-05; /* BF14CE19 9EAADBB7 */
|
|||
const Q4: f64 = 4.00821782732936239552e-06; /* 3ED0CFCA 86E65239 */
|
||||
const Q5: f64 = -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */
|
||||
|
||||
#[allow(warnings)]
|
||||
#[inline]
|
||||
pub fn expm1(mut x: f64) -> f64 {
|
||||
let hi: f64;
|
||||
let lo: f64;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use super::{combine_words, exp};
|
||||
|
||||
/* exp(x)/2 for x >= log(DBL_MAX), slightly better than 0.5*exp(x/2)*exp(x/2) */
|
||||
pub(crate) fn expo2(x: f64) -> f64 {
|
||||
#[inline]
|
||||
pub fn expo2(x: f64) -> f64 {
|
||||
/* k is such that k*ln2 has minimal relative error and x - kln2 > log(DBL_MIN) */
|
||||
const K: i32 = 2043;
|
||||
let kln2 = f64::from_bits(0x40962066151add8b);
|
||||
|
|
|
|||
|
|
@ -1,33 +1,33 @@
|
|||
// src: musl/src/fenv/fenv.c
|
||||
/* Dummy functions for archs lacking fenv implementation */
|
||||
|
||||
pub(crate) const FE_UNDERFLOW: i32 = 0;
|
||||
pub(crate) const FE_INEXACT: i32 = 0;
|
||||
pub const FE_UNDERFLOW: i32 = 0;
|
||||
pub const FE_INEXACT: i32 = 0;
|
||||
|
||||
pub(crate) const FE_TONEAREST: i32 = 0;
|
||||
pub(crate) const FE_TOWARDZERO: i32 = 0;
|
||||
pub const FE_TONEAREST: i32 = 0;
|
||||
pub const FE_TOWARDZERO: i32 = 0;
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn feclearexcept(_mask: i32) -> i32 {
|
||||
pub fn feclearexcept(_mask: i32) -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn feraiseexcept(_mask: i32) -> i32 {
|
||||
pub fn feraiseexcept(_mask: i32) -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn fetestexcept(_mask: i32) -> i32 {
|
||||
pub fn fetestexcept(_mask: i32) -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn fegetround() -> i32 {
|
||||
pub fn fegetround() -> i32 {
|
||||
FE_TONEAREST
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn fesetround(_r: i32) -> i32 {
|
||||
pub fn fesetround(_r: i32) -> i32 {
|
||||
0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ const C2: f64 = -0.00138867637746099294692; /* -0x16c087e80f1e27.0p-62 */
|
|||
const C3: f64 = 0.0000243904487962774090654; /* 0x199342e0ee5069.0p-68 */
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn k_cosf(x: f64) -> f32 {
|
||||
pub fn k_cosf(x: f64) -> f32 {
|
||||
let z = x * x;
|
||||
let w = z * z;
|
||||
let r = C2 + z * C3;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ const K: i32 = 235;
|
|||
|
||||
/* 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 {
|
||||
pub 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);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ const S3: f64 = -0.000198393348360966317347; /* -0x1a00f9e2cae774.0p-65 */
|
|||
const S4: f64 = 0.0000027183114939898219064; /* 0x16cd878c3b46a7.0p-71 */
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn k_sinf(x: f64) -> f32 {
|
||||
pub fn k_sinf(x: f64) -> f32 {
|
||||
let z = x * x;
|
||||
let w = z * z;
|
||||
let r = S3 + z * S4;
|
||||
|
|
|
|||
|
|
@ -58,7 +58,8 @@ static T: [f64; 13] = [
|
|||
const PIO4: f64 = 7.85398163397448278999e-01; /* 3FE921FB, 54442D18 */
|
||||
const PIO4_LO: f64 = 3.06161699786838301793e-17; /* 3C81A626, 33145C07 */
|
||||
|
||||
pub(crate) fn k_tan(mut x: f64, mut y: f64, odd: i32) -> f64 {
|
||||
#[inline]
|
||||
pub fn k_tan(mut x: f64, mut y: f64, odd: i32) -> f64 {
|
||||
let hx = (f64::to_bits(x) >> 32) as u32;
|
||||
let big = (hx & 0x7fffffff) >= 0x3FE59428; /* |x| >= 0.6744 */
|
||||
if big {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ const T: [f64; 6] = [
|
|||
];
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn k_tanf(x: f64, odd: bool) -> f32 {
|
||||
pub fn k_tanf(x: f64, odd: bool) -> f32 {
|
||||
let z = x * x;
|
||||
/*
|
||||
* Split up the polynomial into small independent terms to give
|
||||
|
|
|
|||
|
|
@ -42,12 +42,14 @@ const PIO2_3T: f64 = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
|
|||
// use rem_pio2_large() for large x
|
||||
//
|
||||
// caller must handle the case when reduction is not needed: |x| ~<= pi/4 */
|
||||
#[inline]
|
||||
pub fn rem_pio2(x: f64) -> (i32, f64, f64) {
|
||||
let x1p24 = f64::from_bits(0x4170000000000000);
|
||||
|
||||
let sign = (f64::to_bits(x) >> 63) as i32;
|
||||
let ix = (f64::to_bits(x) >> 32) as u32 & 0x7fffffff;
|
||||
|
||||
#[inline]
|
||||
fn medium(x: f64, ix: u32) -> (i32, f64, f64) {
|
||||
/* rint(x/(pi/2)), Assume round-to-nearest. */
|
||||
let f_n = x as f64 * INV_PIO2 + TO_INT - TO_INT;
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ const PIO2: [f64; 8] = [
|
|||
/// more accurately, = 0 mod 8 ). Thus the number of operations are
|
||||
/// independent of the exponent of the input.
|
||||
#[inline]
|
||||
pub(crate) fn rem_pio2_large(x: &[f64], y: &mut [f64], e0: i32, prec: usize) -> i32 {
|
||||
pub fn rem_pio2_large(x: &[f64], y: &mut [f64], e0: i32, prec: usize) -> i32 {
|
||||
let x1p24 = f64::from_bits(0x4170000000000000); // 0x1p24 === 2 ^ 24
|
||||
let x1p_24 = f64::from_bits(0x3e70000000000000); // 0x1p_24 === 2 ^ (-24)
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ const PIO2_1T: f64 = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */
|
|||
/// use double precision for everything except passing x
|
||||
/// use __rem_pio2_large() for large x
|
||||
#[inline]
|
||||
pub(crate) fn rem_pio2f(x: f32) -> (i32, f64) {
|
||||
pub fn rem_pio2f(x: f32) -> (i32, f64) {
|
||||
let x64 = x as f64;
|
||||
|
||||
let mut tx: [f64; 1] = [0.];
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ use super::{k_cos, k_sin, rem_pio2};
|
|||
//
|
||||
// Accuracy:
|
||||
// TRIG(x) returns trig(x) nearly rounded
|
||||
#[inline]
|
||||
pub fn sin(x: f64) -> f64 {
|
||||
let x1p120 = f64::from_bits(0x4770000000000000); // 0x1p120f === 2 ^ 120
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use super::{expm1, expo2};
|
|||
// = (exp(x)-1 + (exp(x)-1)/exp(x))/2
|
||||
// = x + x^3/6 + o(x^5)
|
||||
//
|
||||
#[inline]
|
||||
pub fn sinh(x: f64) -> f64 {
|
||||
// union {double f; uint64_t i;} u = {.f = x};
|
||||
// uint32_t w;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ use super::{k_tan, rem_pio2};
|
|||
//
|
||||
// Accuracy:
|
||||
// TRIG(x) returns trig(x) nearly rounded
|
||||
#[inline]
|
||||
pub fn tan(x: f64) -> f64 {
|
||||
let x1p120 = f32::from_bits(0x7b800000); // 0x1p120f === 2 ^ 120
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use super::expm1;
|
|||
* = (exp(2*x) - 1)/(exp(2*x) - 1 + 2)
|
||||
* = (1 - exp(-2*x))/(exp(-2*x) - 1 + 2)
|
||||
*/
|
||||
#[inline]
|
||||
pub fn tanh(mut x: f64) -> f64 {
|
||||
let mut uf: f64 = x;
|
||||
let mut ui: u64 = f64::to_bits(uf);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue