Merge pull request rust-lang/libm#430 from hanna-kruppe/rint-arch
wasm32 and aarch64 intrinsics for rint and rintf
This commit is contained in:
commit
d73a7452c5
6 changed files with 73 additions and 1 deletions
|
|
@ -604,12 +604,16 @@
|
|||
"rint": {
|
||||
"sources": [
|
||||
"src/libm_helper.rs",
|
||||
"src/math/arch/aarch64.rs",
|
||||
"src/math/arch/wasm32.rs",
|
||||
"src/math/rint.rs"
|
||||
],
|
||||
"type": "f64"
|
||||
},
|
||||
"rintf": {
|
||||
"sources": [
|
||||
"src/math/arch/aarch64.rs",
|
||||
"src/math/arch/wasm32.rs",
|
||||
"src/math/rintf.rs"
|
||||
],
|
||||
"type": "f32"
|
||||
|
|
|
|||
33
library/compiler-builtins/libm/src/math/arch/aarch64.rs
Normal file
33
library/compiler-builtins/libm/src/math/arch/aarch64.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
use core::arch::aarch64::{
|
||||
float32x2_t, float64x1_t, vdup_n_f32, vdup_n_f64, vget_lane_f32, vget_lane_f64, vrndn_f32,
|
||||
vrndn_f64,
|
||||
};
|
||||
|
||||
pub fn rint(x: f64) -> f64 {
|
||||
// SAFETY: only requires target_feature=neon, ensured by `cfg_if` in parent module.
|
||||
let x_vec: float64x1_t = unsafe { vdup_n_f64(x) };
|
||||
|
||||
// SAFETY: only requires target_feature=neon, ensured by `cfg_if` in parent module.
|
||||
let result_vec: float64x1_t = unsafe { vrndn_f64(x_vec) };
|
||||
|
||||
// SAFETY: only requires target_feature=neon, ensured by `cfg_if` in parent module.
|
||||
let result: f64 = unsafe { vget_lane_f64::<0>(result_vec) };
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn rintf(x: f32) -> f32 {
|
||||
// There's a scalar form of this instruction (FRINTN) but core::arch doesn't expose it, so we
|
||||
// have to use the vector form and drop the other lanes afterwards.
|
||||
|
||||
// SAFETY: only requires target_feature=neon, ensured by `cfg_if` in parent module.
|
||||
let x_vec: float32x2_t = unsafe { vdup_n_f32(x) };
|
||||
|
||||
// SAFETY: only requires target_feature=neon, ensured by `cfg_if` in parent module.
|
||||
let result_vec: float32x2_t = unsafe { vrndn_f32(x_vec) };
|
||||
|
||||
// SAFETY: only requires target_feature=neon, ensured by `cfg_if` in parent module.
|
||||
let result: f32 = unsafe { vget_lane_f32::<0>(result_vec) };
|
||||
|
||||
result
|
||||
}
|
||||
|
|
@ -11,10 +11,19 @@
|
|||
cfg_if! {
|
||||
if #[cfg(all(target_arch = "wasm32", intrinsics_enabled))] {
|
||||
mod wasm32;
|
||||
pub use wasm32::{ceil, ceilf, fabs, fabsf, floor, floorf, sqrt, sqrtf, trunc, truncf};
|
||||
pub use wasm32::{
|
||||
ceil, ceilf, fabs, fabsf, floor, floorf, rint, rintf, sqrt, sqrtf, trunc, truncf,
|
||||
};
|
||||
} else if #[cfg(target_feature = "sse2")] {
|
||||
mod i686;
|
||||
pub use i686::{sqrt, sqrtf};
|
||||
} else if #[cfg(all(
|
||||
target_arch = "aarch64", // TODO: also arm64ec?
|
||||
target_feature = "neon",
|
||||
target_endian = "little", // see https://github.com/rust-lang/stdarch/issues/1484
|
||||
))] {
|
||||
mod aarch64;
|
||||
pub use aarch64::{rint, rintf};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,14 @@ pub fn floorf(x: f32) -> f32 {
|
|||
core::arch::wasm32::f32_floor(x)
|
||||
}
|
||||
|
||||
pub fn rint(x: f64) -> f64 {
|
||||
core::arch::wasm32::f64_nearest(x)
|
||||
}
|
||||
|
||||
pub fn rintf(x: f32) -> f32 {
|
||||
core::arch::wasm32::f32_nearest(x)
|
||||
}
|
||||
|
||||
pub fn sqrt(x: f64) -> f64 {
|
||||
core::arch::wasm32::f64_sqrt(x)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,14 @@
|
|||
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
|
||||
pub fn rint(x: f64) -> f64 {
|
||||
select_implementation! {
|
||||
name: rint,
|
||||
use_arch: any(
|
||||
all(target_arch = "wasm32", intrinsics_enabled),
|
||||
all(target_arch = "aarch64", target_feature = "neon", target_endian = "little"),
|
||||
),
|
||||
args: x,
|
||||
}
|
||||
|
||||
let one_over_e = 1.0 / f64::EPSILON;
|
||||
let as_u64: u64 = x.to_bits();
|
||||
let exponent: u64 = (as_u64 >> 52) & 0x7ff;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,14 @@
|
|||
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
|
||||
pub fn rintf(x: f32) -> f32 {
|
||||
select_implementation! {
|
||||
name: rintf,
|
||||
use_arch: any(
|
||||
all(target_arch = "wasm32", intrinsics_enabled),
|
||||
all(target_arch = "aarch64", target_feature = "neon", target_endian = "little"),
|
||||
),
|
||||
args: x,
|
||||
}
|
||||
|
||||
let one_over_e = 1.0 / f32::EPSILON;
|
||||
let as_u32: u32 = x.to_bits();
|
||||
let exponent: u32 = (as_u32 >> 23) & 0xff;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue