Skip to content

Miri: non-deterministic floating point operations in foreign_items #143906

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

LorrensP-2158466
Copy link
Contributor

@LorrensP-2158466 LorrensP-2158466 commented Jul 13, 2025

Part of rust-lang/miri/#3555, this pr does the foreign_items work.

Some things have changed since #138062 and #142514. I moved the "helpers" used for creating fixed outputs and clamping operations to their defined ranges to helpers.rs. These are now also extended to handle the floating-point operations in foreign_items. Tests in miri/tests/float.rs were changed/added.

Failing tests in std were extracted, run under miri with -Zmiri-many-seeds=0..1000 and changed accordingly. Double checked with -Zmiri-many-seeds.

I noticed that the C standard doesn't specify the output ranges for all of its mathematical operations; it just specifies them as:

Returns
The sinh functions return sinh x.

So I used Wolfram|Alpha.

@rustbot
Copy link
Collaborator

rustbot commented Jul 13, 2025

r? @tgross35

rustbot has assigned @tgross35.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jul 13, 2025
@rustbot
Copy link
Collaborator

rustbot commented Jul 13, 2025

The Miri subtree was changed

cc @rust-lang/miri

@LorrensP-2158466
Copy link
Contributor Author

LorrensP-2158466 commented Jul 13, 2025

There are some holes in the behaviour of some operations, because I did not know how I could efficiently handle them, I'll mark them and add some explanation.

Also,
r? @RalfJung

@rustbot rustbot assigned RalfJung and unassigned tgross35 Jul 13, 2025
"atan2f" | "atan2" => val.clamp(pi.neg(), pi),

// FIXME: According to Wolfram Alpha, the range of ln(gamma) is [-0.121486, +INF]. What to do?
"lgammaf_r" | "lgamma_r" => val,
Copy link
Contributor Author

@LorrensP-2158466 LorrensP-2158466 Jul 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I make a method in IeeeExt trait that gives this exact value, or?

Something like:

fn lgamma_min_output() -> IeeeFloat<S>{ ... }

/// # Note
///
/// For `powif*` operations of the form `(SNaN)^(±0)` we follow the same behaviour as `powf*`, see [`fixed_float_value`].
fn fixed_float_int_value<S: Semantics>(
Copy link
Contributor Author

@LorrensP-2158466 LorrensP-2158466 Jul 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ldexp also takes an i32 as the second argument, is this change and name good?


//atan2(±∞, −∞) = ±3π/4
("atan2f" | "atan2", [x, y]) if x.is_infinite() && y.is_neg_infinity() =>
(pi_over_4 * three).value.copy_sign(*x),
Copy link
Contributor Author

@LorrensP-2158466 LorrensP-2158466 Jul 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if this will give exactly 3π/4. Should I add a function to IeeeExt for this? These will be hex bytes...


// atan2(±∞, −∞) = ±3π/4
// assert_eq!($float_type::atan2(INFINITY, NEG_INFINITY), 3.0 * FRAC_PI_4, "atan2(+∞, −∞) = 3π/4");
// assert_eq!($float_type::atan2(NEG_INFINITY, NEG_INFINITY), -3.0 * FRAC_PI_4, "atan2(-∞, −∞) = -3π/4");
Copy link
Contributor Author

@LorrensP-2158466 LorrensP-2158466 Jul 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This 3.0 * FRAC_PI_4 will never be exactly equal to the operation mentioned in comment above. Use explicit bytes here as well, or is there a cleaner way?

Tested this repeatedly.

let pi = IeeeFloat::<S>::pi();
let pi_over_2 = IeeeFloat::<S>::frac_pi_2();

// Exclusive ranges are made using next_up/next_down.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually don't know if this is correct, but I assume so :).


// erfc(+INF) = 0
// REVIEW/HELP: for some reason the tests fail because erfc(+INF) = 1e-45. Which is weird because
// no error can be applied to 0. Checked and this does not happen without Miri.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no idea why this is, was stuck on this for like half an hour before I gave up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants