Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions etc/function-definitions.json
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,7 @@
"rint": {
"sources": [
"libm/src/math/arch/aarch64/rounding.rs",
"libm/src/math/arch/i586/rounding.rs",
"libm/src/math/arch/wasm32/rounding.rs",
"libm/src/math/generic/rint.rs",
"libm/src/math/rint.rs"
Expand Down
9 changes: 0 additions & 9 deletions libm-test/src/precision.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,15 +297,6 @@ impl MaybeOverride<(f32,)> for SpecialCase {

impl MaybeOverride<(f64,)> for SpecialCase {
fn check_float<F: Float>(input: (f64,), actual: F, expected: F, ctx: &CheckCtx) -> CheckAction {
if cfg!(x86_no_sse2)
&& (ctx.base_name == BaseName::Rint || ctx.base_name == BaseName::Roundeven)
&& (expected - actual).abs() <= F::ONE
&& (expected - actual).abs() > F::ZERO
{
// Our rounding mode is incorrect.
return XFAIL("i586 rint rounding mode");
}

if ctx.base_name == BaseName::J0 && input.0 < -1e300 {
// Errors get huge close to -inf
return XFAIL_NOCHECK;
Expand Down
2 changes: 1 addition & 1 deletion libm/src/math/arch/i586/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ mod exp_all;
mod rounding;

pub use exp_all::{x87_exp, x87_exp2, x87_exp2f, x87_exp10, x87_exp10f, x87_expf};
pub use rounding::{ceil, floor};
pub use rounding::{ceil, floor, rint};
50 changes: 50 additions & 0 deletions libm/src/math/arch/i586/rounding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,53 @@ pub fn floor(mut x: f64) -> f64 {
}
x
}

/// Note that this respects rounding mode. Because it is UB to have a non-default rounding
/// mode in Rust, this acts as roundeven.
pub fn rint(mut x: f64) -> f64 {
unsafe {
core::arch::asm!(
"fld qword ptr [{x}]",
"frndint",
"fstp qword ptr [{x}]",
x = in(reg) &mut x,
// All the x87 FPU stack is used, all registers must be clobbered
out("st(0)") _, out("st(1)") _,
out("st(2)") _, out("st(3)") _,
out("st(4)") _, out("st(5)") _,
out("st(6)") _, out("st(7)") _,
options(nostack),
);
}
x
}

/* FIXME(msrv): after 1.82, the below can be used to compute control words using `asm_const`:

#[derive(Clone, Copy, Debug, PartialEq)]
enum Precision {
Single,
Double,
Extended,
}

/// See: Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 1:
/// Basic Architecture, section 8.1.5 x87 FPU Control Word.
const fn make_fpcw(round: Round, prec: Precision) -> u16 {
let exceptions = 0b111111; // Disable all 6 exceptions
let misc = 0b1000000; // reserved field usually set by default
let pc = match prec {
Precision::Single => 0b00,
Precision::Double => 0b10,
Precision::Extended => 0b11,
};
let rc = match round {
Round::Nearest => 0b00,
Round::Negative => 0b01,
Round::Positive => 0b10,
Round::Zero => 0b11,
};
(rc << 10) | (pc << 8) | misc | exceptions
}

*/
1 change: 1 addition & 0 deletions libm/src/math/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ cfg_if! {
pub use i586::{
ceil,
floor,
rint,
x87_exp,
x87_exp10,
x87_exp10f,
Expand Down
1 change: 1 addition & 0 deletions libm/src/math/rint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub fn rint(x: f64) -> f64 {
all(target_arch = "aarch64", target_feature = "neon"),
all(target_arch = "wasm32", intrinsics_enabled),
),
use_arch_required: x86_no_sse2,
args: x,
}

Expand Down
Loading