Use remquo from Rug

Rug 1.27.0 exposes `remquo`; make use of it for our tests. Removing our
workaround also allows removing the direct dependency on `gmp-mpfr-sys`
This commit is contained in:
Trevor Gross 2025-01-25 01:01:24 +00:00
parent edd1289341
commit b9bd107a67
3 changed files with 5 additions and 67 deletions

View file

@ -28,7 +28,8 @@ short-benchmarks = []
[dependencies]
anyhow = "1.0.95"
gmp-mpfr-sys = { version = "1.6.4", optional = true, default-features = false, features = ["mpfr"] }
# This is not directly used but is required so we can enable `gmp-mpfr-sys/force-cross`.
gmp-mpfr-sys = { version = "1.6.4", optional = true, default-features = false }
iai-callgrind = { version = "0.14.0", optional = true }
indicatif = { version = "0.17.9", default-features = false }
libm = { path = "../..", features = ["unstable-public-internals"] }

View file

@ -4,13 +4,10 @@
//! a struct named `Operation` that implements [`MpOp`].
use std::cmp::Ordering;
use std::ffi::{c_int, c_long};
use gmp_mpfr_sys::mpfr::rnd_t;
use rug::Assign;
pub use rug::Float as MpFloat;
use rug::az::{self, Az};
use rug::float::Round;
use rug::float::Round::Nearest;
use rug::ops::{PowAssignRound, RemAssignRound};
@ -401,28 +398,20 @@ macro_rules! impl_op_for_ty {
}
impl MpOp for crate::op::[<remquo $suffix>]::Routine {
type MpTy = (MpFloat, MpFloat, MpFloat);
type MpTy = (MpFloat, MpFloat);
fn new_mp() -> Self::MpTy {
(
new_mpfloat::<Self::FTy>(),
new_mpfloat::<Self::FTy>(),
new_mpfloat::<Self::FTy>()
)
}
fn run(this: &mut Self::MpTy, input: Self::RustArgs) -> Self::RustRet {
this.0.assign(input.0);
this.1.assign(input.1);
let (ord, ql) = mpfr_remquo(&mut this.2, &this.0, &this.1, Nearest);
// `remquo` integer results are sign-magnitude representation. Transfer the
// sign bit from the long result to the int result.
let clear = !(1 << (c_int::BITS - 1));
let sign = ((ql >> (c_long::BITS - 1)) as i32) << (c_int::BITS - 1);
let q = (ql as i32) & clear | sign;
(prep_retval::<Self::FTy>(&mut this.2, ord), q)
let (ord, q) = this.0.remainder_quo31_round(&this.1, Nearest);
(prep_retval::<Self::FTy>(&mut this.0, ord), q)
}
}
@ -547,24 +536,3 @@ impl MpOp for crate::op::nextafterf::Routine {
unimplemented!("nextafter does not yet have a MPFR operation");
}
}
/// `rug` does not provide `remquo` so this exposes `mpfr_remquo`. See rug#76.
fn mpfr_remquo(r: &mut MpFloat, x: &MpFloat, y: &MpFloat, round: Round) -> (Ordering, c_long) {
let r = r.as_raw_mut();
let x = x.as_raw();
let y = y.as_raw();
let mut q: c_long = 0;
let round = match round {
Round::Nearest => rnd_t::RNDN,
Round::Zero => rnd_t::RNDZ,
Round::Up => rnd_t::RNDU,
Round::Down => rnd_t::RNDD,
Round::AwayZero => rnd_t::RNDA,
_ => unreachable!(),
};
// SAFETY: mutable and const pointers are valid and do not alias, by Rust's rules.
let ord = unsafe { gmp_mpfr_sys::mpfr::remquo(r, &mut q, x, y, round) };
(ord.cmp(&0), q)
}

View file

@ -405,15 +405,6 @@ impl MaybeOverride<(f32, f32)> for SpecialCase {
) -> CheckAction {
binop_common(input, actual, expected, ctx)
}
fn check_int<I: Int>(
_input: (f32, f32),
actual: I,
expected: I,
ctx: &CheckCtx,
) -> CheckAction {
remquo_common(actual, expected, ctx)
}
}
impl MaybeOverride<(f64, f64)> for SpecialCase {
@ -425,15 +416,6 @@ impl MaybeOverride<(f64, f64)> for SpecialCase {
) -> CheckAction {
binop_common(input, actual, expected, ctx)
}
fn check_int<I: Int>(
_input: (f64, f64),
actual: I,
expected: I,
ctx: &CheckCtx,
) -> CheckAction {
remquo_common(actual, expected, ctx)
}
}
#[cfg(f128_enabled)]
@ -496,19 +478,6 @@ fn binop_common<F1: Float, F2: Float>(
DEFAULT
}
fn remquo_common<I: Int>(actual: I, expected: I, ctx: &CheckCtx) -> CheckAction {
// FIXME: Our MPFR implementation disagrees with musl and may need to be updated.
if ctx.basis == CheckBasis::Mpfr
&& ctx.base_name == BaseName::Remquo
&& expected == I::MIN
&& actual == I::ZERO
{
return XFAIL("remquo integer mismatch");
}
DEFAULT
}
impl MaybeOverride<(i32, f32)> for SpecialCase {
fn check_float<F: Float>(
input: (i32, f32),