Skip to content
This repository was archived by the owner on Apr 28, 2025. It is now read-only.

Commit 5562dd3

Browse files
committed
Introduce arch::aarch64 and use it for rint{,f}
1 parent 45af771 commit 5562dd3

File tree

5 files changed

+50
-2
lines changed

5 files changed

+50
-2
lines changed

libm/etc/function-definitions.json

+2
Original file line numberDiff line numberDiff line change
@@ -604,13 +604,15 @@
604604
"rint": {
605605
"sources": [
606606
"src/libm_helper.rs",
607+
"src/math/arch/aarch64.rs",
607608
"src/math/arch/wasm32.rs",
608609
"src/math/rint.rs"
609610
],
610611
"type": "f64"
611612
},
612613
"rintf": {
613614
"sources": [
615+
"src/math/arch/aarch64.rs",
614616
"src/math/arch/wasm32.rs",
615617
"src/math/rintf.rs"
616618
],

libm/src/math/arch/aarch64.rs

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use core::arch::aarch64::{
2+
float32x2_t, float64x1_t, vdup_n_f32, vdup_n_f64, vget_lane_f32, vget_lane_f64, vrndn_f32,
3+
vrndn_f64,
4+
};
5+
6+
pub fn rint(x: f64) -> f64 {
7+
// SAFETY: only requires target_feature=neon, ensured by `cfg_if` in parent module.
8+
let x_vec: float64x1_t = unsafe { vdup_n_f64(x) };
9+
10+
// SAFETY: only requires target_feature=neon, ensured by `cfg_if` in parent module.
11+
let result_vec: float64x1_t = unsafe { vrndn_f64(x_vec) };
12+
13+
// SAFETY: only requires target_feature=neon, ensured by `cfg_if` in parent module.
14+
let result: f64 = unsafe { vget_lane_f64::<0>(result_vec) };
15+
16+
result
17+
}
18+
19+
pub fn rintf(x: f32) -> f32 {
20+
// There's a scalar form of this instruction (FRINTN) but core::arch doesn't expose it, so we
21+
// have to use the vector form and drop the other lanes afterwards.
22+
23+
// SAFETY: only requires target_feature=neon, ensured by `cfg_if` in parent module.
24+
let x_vec: float32x2_t = unsafe { vdup_n_f32(x) };
25+
26+
// SAFETY: only requires target_feature=neon, ensured by `cfg_if` in parent module.
27+
let result_vec: float32x2_t = unsafe { vrndn_f32(x_vec) };
28+
29+
// SAFETY: only requires target_feature=neon, ensured by `cfg_if` in parent module.
30+
let result: f32 = unsafe { vget_lane_f32::<0>(result_vec) };
31+
32+
result
33+
}

libm/src/math/arch/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ cfg_if! {
1717
} else if #[cfg(target_feature = "sse2")] {
1818
mod i686;
1919
pub use i686::{sqrt, sqrtf};
20+
} else if #[cfg(all(
21+
target_arch = "aarch64", // TODO: also arm64ec?
22+
target_feature = "neon",
23+
target_endian = "little", // see https://github.com/rust-lang/stdarch/issues/1484
24+
))] {
25+
mod aarch64;
26+
pub use aarch64::{rint, rintf};
2027
}
2128
}
2229

libm/src/math/rint.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
pub fn rint(x: f64) -> f64 {
33
select_implementation! {
44
name: rint,
5-
use_arch: all(target_arch = "wasm32", intrinsics_enabled),
5+
use_arch: any(
6+
all(target_arch = "wasm32", intrinsics_enabled),
7+
all(target_arch = "aarch64", target_feature = "neon", target_endian = "little"),
8+
),
69
args: x,
710
}
811

libm/src/math/rintf.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
pub fn rintf(x: f32) -> f32 {
33
select_implementation! {
44
name: rintf,
5-
use_arch: all(target_arch = "wasm32", intrinsics_enabled),
5+
use_arch: any(
6+
all(target_arch = "wasm32", intrinsics_enabled),
7+
all(target_arch = "aarch64", target_feature = "neon", target_endian = "little"),
8+
),
69
args: x,
710
}
811

0 commit comments

Comments
 (0)