Skip to content

Enable Non-determinism of float operations in Miri and change std tests #138062

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

Merged
merged 2 commits into from
Jun 10, 2025

Conversation

LorrensP-2158466
Copy link
Contributor

@LorrensP-2158466 LorrensP-2158466 commented Mar 5, 2025

Links to #4208 and #3555 in Miri.

Non-determinism of floating point operations was disabled in #137594 because it breaks the tests and doc-tests in core/coretests and std. This PR enables some of them.

This pr includes the following changes:

  • Enables the float non-determinism but with a lower relative error of 4ULP instead of 16ULP
  • These operations now have a fixed output based on the C23 standard, except the pow operations, this is tracked in #4286
  • Changes tests that made incorrect assumptions about the operations, not to make that assumption anymore (from assert_eq! to assert_approx_eq!.
  • Changed the doctests of the stdlib of these operations to compare against fixed constants instead of f*::EPSILON, which now succeed with Miri and -Zmiri-many-seeds
  • Added a constant APPROX_DELTA in std/tests/floats/f32.rs which is used for approximation tests, but with a different value when run in Miri. This is to make these tests succeed.
  • Added tests in the float tests of Miri to test the C23 behaviour.

Fixes rust-lang/miri#4208

@rustbot
Copy link
Collaborator

rustbot commented Mar 5, 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 Mar 5, 2025
@rustbot
Copy link
Collaborator

rustbot commented Mar 5, 2025

The Miri subtree was changed

cc @rust-lang/miri

@LorrensP-2158466 LorrensP-2158466 changed the title Enable Non-determinism of float operations and change std tests Enable Non-determinism of float operations in Miri and change std tests Mar 5, 2025
@tgross35
Copy link
Contributor

tgross35 commented Mar 5, 2025

The library changes lgtm, for the rest

r? @RalfJung

@rustbot rustbot assigned RalfJung and unassigned tgross35 Mar 5, 2025
@LorrensP-2158466
Copy link
Contributor Author

I didn't touch the doc tests because I do not know nearly enough to come near them :)

I should have clarified: the doc tests fail when running ./x miri --doc --no-fail-fast core coretests std -- f64 f32 because of the extra 4ULP error.

2, // log2(4)
);

// Clamp values to the output range defined in IEEE 754 9.1.
Copy link
Member

Choose a reason for hiding this comment

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

We said we're going to follow the C standard, which is more permissive than the IEEE spec. Is there a reference for this in the C standard?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes and no...

For some operations it specifies it like this:

The atan functions return arctan x in the interval [−π/2, +π/2] radians

But for sin and cos like this:

The sin functions return sin x

If I read "returns sin x", I understand it as "the output is [-1, +1]", but maybe that's just me.

let fixed_res = match (f1.category(), f2.category()) {
// 1^y = 1 for any y even a NaN.
// TODO: C Standard says any NaN, IEEE says not a Signaling NaN
(Category::Normal, _) if f1 == 1.0f32.to_soft() => Some(1.0f32.to_soft()),
Copy link
Member

Choose a reason for hiding this comment

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

Can you avoid using soft floats here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the miri issue you said this:

except that the logic for fixed_res and clamp has to be done with soft-floats.

Did I misunderstand what you meant?

Copy link
Member

Choose a reason for hiding this comment

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

Argh sorry, I meant "avoid using hard floats" :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

alright!

Comment on lines 416 to 419
let fixed_res = match (f1.category(), f2.category()) {
// 1^y = 1 for any y even a NaN.
// TODO: C says any NaN, IEEE says no a Sign NaN
(Category::Normal, _) if f1 == 1.0f64.to_soft() => Some(1.0f64.to_soft()),
Copy link
Member

Choose a reason for hiding this comment

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

Please do not duplicate the same logic 4 times. We were a bit lazy here so far as the boilerplate for making the code generic was bigger than the code, but with all this special-case handling that is no longer the case.

// accept up to 64ULP (16ULP for host floats and 16ULP for miri artificial error and 32 for any rounding errors)
assert_approx_eq!($a, $b, 64);
// accept up to 52ULP (16ULP for host floats, 4ULP for miri artificial error and 32 for any rounding errors)
assert_approx_eq!($a, $b, 52);
Copy link
Member

Choose a reason for hiding this comment

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

Do we really still need 52 ULP? I would have hoped that 32 works now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed 32 works, don't know why I didn't tried it.

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 tried lower but got some ULP differences of 27.

Comment on lines 1011 to 1012
// TODO: How to test NaN inputs? f*::NAN is not guaranteed
// to be any specific bit pattern (in std).
Copy link
Member

Choose a reason for hiding this comment

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

It is guaranteed to be a NaN though. Why do you want a specific bit pattern?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IEEE is not as permissive as C, so it doesn't matter much now, just one case: C standard says for pown(powi) the following:

pown(x, 0) returns 1 for all x not a signaling NaN

And since std doesn't guarantee the specific bit pattern of NaN, I'm not quite sure how to test it.

Copy link
Member

Choose a reason for hiding this comment

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

Oh, since NAN might be signaling? That'd be quite bad.^^

Please rely on it being not signalling, I'll see if we can fix the docs.

@RalfJung
Copy link
Member

RalfJung commented Mar 9, 2025

I should have clarified: the doc tests fail when running ./x miri --doc --no-fail-fast core coretests std -- f64 f32 because of the extra 4ULP error.

it is failing the tests that use f32::EPSILON, right? Can you change that to 4.0 * f32::EPSILON (or maybe more if needed)? Once we know the change that makes the tests pass, we can ask the libs folks if that is reasonable.

macro_rules! assert_approx_eq {
($a:expr, $b:expr) => {{ assert_approx_eq!($a, $b, 1.0e-6) }};
($a:expr, $b:expr) => {{ assert_approx_eq!($a, $b, 1.0e-4) }};
Copy link
Member

Choose a reason for hiding this comment

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

I think I'd rather not change this for all tests, and in particular not for f64.

An alternative would be to just set this precision with the affected tests in library/std/tests/floats/f32.rs.

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe the precision should be only loosened only with cfg!(miri) as well. I think it is beneficial to learn which platforms, if any, have worse precision than we expect and address that on a case-by-case basis.

@LorrensP-2158466
Copy link
Contributor Author

LorrensP-2158466 commented Mar 10, 2025

So I:

  • only used 1e-4 on failed tests in std, so 1e-6 is back.
  • increased epsilon threshold in the failed doctests to 4.0 or 8.0
  • used a macro instead of the duplicate logic in the pow intrinsic. I didn't find another way to cleanly do this + I don't know where I should put this macro.

@RalfJung
Copy link
Member

No, a macro is not right. The way to avoid this duplication is to add a function that is generic over the apfloat float type.

I'd say just remove pow from the PR for now, let's use sin/cos to test out the waters. Already there the code duplication bothers me but it's less bad.

@LorrensP-2158466
Copy link
Contributor Author

Yeah Sorry, I was confused with your comment: avoid using soft floats. It should be easier with soft floats. I can try deduplicating sin/cos and pow, and if it isn't what you're looking for, I'll remove them.

@RalfJung
Copy link
Member

RalfJung commented Mar 10, 2025 via email

@LorrensP-2158466
Copy link
Contributor Author

No problems! This float stuff it getting to me too :)

@LorrensP-2158466
Copy link
Contributor Author

So I extended the fixed_float_value to accept powf, but this required accepting a slice of arguments and matching on the size. This pattern matching is getting extensive, but I don't find it confusing atm. powi accepts i32, so I made a separate function to handle that one.

There is still some repetitiveness, like applying the error or adjust_nan, but that's not the focus of this pr.

@@ -522,3 +572,121 @@ fn apply_random_float_error_to_imm<'tcx>(

interp_ok(ImmTy::from_scalar_int(res, val.layout))
}

// TODO(lorrens): This can be moved to `helpers` when we implement the other intrinsics.
Copy link
Member

Choose a reason for hiding this comment

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

No please only but things in helpers that are widely useful across Miri. Specific functionality should remain in its specific file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Alright, I thought that this would be the case when implementing the foreign_itmes, since they probably will share this functionality, like asin and such.

Copy link
Member

Choose a reason for hiding this comment

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

Ah yeah... we'll figure that out when we get there.

// x^(±0) = 1 for any x, even a NaN
("powf32" | "powf64", [_, exp]) if exp.is_zero() => Some(one),

// C standard doesn't specify or invalid combination
Copy link
Member

Choose a reason for hiding this comment

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

This is not a sentence...?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, now that I am reading that again... I'll update it, excuse me for my bad English :)

Comment on lines 590 to 592
// TODO: not sure about this pattern matching stuff. It's definitly cleaner than if-else chains
// Error code 0158 explains this: https://doc.rust-lang.org/stable/error_codes/E0158.html
// The only reason I did this is to use the same function for powf as for sin/cos/exp/log
Copy link
Member

Choose a reason for hiding this comment

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

I don't understand the comment. The code looks nice though :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, I should have explained why the error code applies here.
Consider this arm:

// sin(+- 0) = +- 0.
("sinf32" | "sinf64", [input]) if input.is_zero() => Some(*input),

I still have to put an if-guard on it to check that input is Zero, but in my opinion, it would be a lot nicer if I could do the following:

// sin(+- 0) = +- 0.
("sinf32" | "sinf64", [IeeeFloat::<S>::Zero]) => Some(*input),

If I then were able to make a constant for 1 and maybe other values, I wouldn't need those if-guards. But unfortunately, the compiler doesn't try to see if this can work; it just assumes this to be non-exhaustive, regardless of a _ => ... arm.

Luckily, you like the code :)

Copy link
Member

Choose a reason for hiding this comment

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

You can't use consts that depend on generics in patterns like that, that is expected.

Comment on lines 1011 to 1012
// TODO: How to test NaN inputs? f*::NAN is not guaranteed
// to be any specific bit pattern (in std).
Copy link
Member

Choose a reason for hiding this comment

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

Oh, since NAN might be signaling? That'd be quite bad.^^

Please rely on it being not signalling, I'll see if we can fix the docs.

@RalfJung
Copy link
Member

RalfJung commented Mar 19, 2025

Regarding the library tests, I suggested a plan above for the doc tests. Have you tried that?

EDIT: Ah, yes seems you did. :) I assume all tests pass now in the current state of the PR?

Also:

probably change the assert_approx_eq to use the same technique as Miri (i.e., using ULP instead of EPSILON)

I am not convinced we want to do that, so unless @tgross35 asks for it I'd say please stick to the current approach.

@RalfJung
Copy link
Member

@tgross35 could you have a look at the library diff again?
If you prefer, instead of hard-coding 1e-4 I guess we could also have a constant like

// Miri adds some extra error to float functions, make sure the tests still pass.
const APPROX_DETLA: f32 = if cfg!(miri) { 1e-4 } else { 1e-6 };

@LorrensP-2158466
Copy link
Contributor Author

EDIT: Ah, yes seems you did. :) I assume all tests pass now in the current state of the PR?

Yes, they indeed pass now.

On the topic of doc and doctests, for example, powf:

// part of powf doctest
let x = 2.0_f32;
let abs_difference = (x.powf(2.0) - (x * x)).abs();
assert!(abs_difference <= 8.0 * f32::EPSILON);

This is not wrong, but shouldn't it be noted that this only works with small values?
And I think this applies to a lot of operations.

@RalfJung
Copy link
Member

r? @tgross35

to reflect the current status. Feel free to re-assign to me if the libs changes are fine.

@LorrensP-2158466
Copy link
Contributor Author

@RalfJung should this PR also alter the algebraic operations that were mentioned in #136457?

@RalfJung
Copy link
Member

RalfJung commented Apr 2, 2025

Let's avoid a conflict with the other in-flight PR, #136457. So let's deal with the algebraic and fast-math operations separately.

@RalfJung
Copy link
Member

RalfJung commented Jun 9, 2025

Wut?
@bors retry

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 9, 2025
@RalfJung
Copy link
Member

RalfJung commented Jun 9, 2025

@bors2 try jobs=aarch64-apple

@rust-bors
Copy link

rust-bors bot commented Jun 9, 2025

⌛ Trying commit 00452bd with merge b009e21

To cancel the try build, run the command @bors2 try cancel.

rust-bors bot added a commit that referenced this pull request Jun 9, 2025
…<try>

Enable Non-determinism of float operations in Miri and change std tests

<!-- homu-ignore:start -->
<!--
If this PR is related to an unstable feature or an otherwise tracked effort,
please link to the relevant tracking issue here. If you don't know of a related
tracking issue or there are none, feel free to ignore this.

This PR will get automatically assigned to a reviewer. In case you would like
a specific user to review your work, you can assign it to them by using

    r? <reviewer name>
-->
<!-- homu-ignore:end -->

Links to [#4208](rust-lang/miri#4208) and [#3555](rust-lang/miri#3555) in Miri.

Non-determinism of floating point operations was disabled in #137594 because it breaks the tests and doc-tests in core/coretests and std. This PR enables some of them.

This pr includes the following changes:

- Enables the float non-determinism but with a lower relative error of 4ULP instead of 16ULP
- These operations now have a fixed output based on the C23 standard, except the pow operations, this is tracked in [#4286](rust-lang/miri#4286 (comment))
- Changes tests that made incorrect assumptions about the operations, not to make that assumption anymore (from `assert_eq!` to `assert_approx_eq!`.
- Changed the doctests of the stdlib of these operations to compare against fixed constants instead of `f*::EPSILON`, which now succeed with Miri and `-Zmiri-many-seeds`
- Added a constant `APPROX_DELTA` in `std/tests/floats/f32.rs` which is used for approximation tests, but with a different value when run in Miri. This is to make these tests succeed.
- Added tests in the float tests of Miri to test the C23 behaviour.

Fixes rust-lang/miri#4208
try-job: aarch64-apple
@rust-bors
Copy link

rust-bors bot commented Jun 9, 2025

💔 Test failed

@tgross35
Copy link
Contributor

tgross35 commented Jun 9, 2025

With #142241 merged

@bors2 try jobs=aarch64-apple

@rust-bors
Copy link

rust-bors bot commented Jun 9, 2025

⌛ Trying commit 00452bd with merge 369075d

To cancel the try build, run the command @bors2 try cancel.

rust-bors bot added a commit that referenced this pull request Jun 9, 2025
…<try>

Enable Non-determinism of float operations in Miri and change std tests

<!-- homu-ignore:start -->
<!--
If this PR is related to an unstable feature or an otherwise tracked effort,
please link to the relevant tracking issue here. If you don't know of a related
tracking issue or there are none, feel free to ignore this.

This PR will get automatically assigned to a reviewer. In case you would like
a specific user to review your work, you can assign it to them by using

    r? <reviewer name>
-->
<!-- homu-ignore:end -->

Links to [#4208](rust-lang/miri#4208) and [#3555](rust-lang/miri#3555) in Miri.

Non-determinism of floating point operations was disabled in #137594 because it breaks the tests and doc-tests in core/coretests and std. This PR enables some of them.

This pr includes the following changes:

- Enables the float non-determinism but with a lower relative error of 4ULP instead of 16ULP
- These operations now have a fixed output based on the C23 standard, except the pow operations, this is tracked in [#4286](rust-lang/miri#4286 (comment))
- Changes tests that made incorrect assumptions about the operations, not to make that assumption anymore (from `assert_eq!` to `assert_approx_eq!`.
- Changed the doctests of the stdlib of these operations to compare against fixed constants instead of `f*::EPSILON`, which now succeed with Miri and `-Zmiri-many-seeds`
- Added a constant `APPROX_DELTA` in `std/tests/floats/f32.rs` which is used for approximation tests, but with a different value when run in Miri. This is to make these tests succeed.
- Added tests in the float tests of Miri to test the C23 behaviour.

Fixes rust-lang/miri#4208
try-job: aarch64-apple
@rust-bors
Copy link

rust-bors bot commented Jun 9, 2025

☀️ Try build successful (CI)
Build commit: 369075d (369075d7cc9b5ccad68cd6b324ad64244ae12054)

@bors
Copy link
Collaborator

bors commented Jun 9, 2025

⌛ Testing commit 00452bd with merge c6768de...

@bors
Copy link
Collaborator

bors commented Jun 10, 2025

☀️ Test successful - checks-actions
Approved by: RalfJung
Pushing c6768de to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Jun 10, 2025
@bors bors merged commit c6768de into rust-lang:master Jun 10, 2025
20 checks passed
@rustbot rustbot added this to the 1.89.0 milestone Jun 10, 2025
Copy link
Contributor

What is this? This is an experimental post-merge analysis report that shows differences in test outcomes between the merged PR and its parent PR.

Comparing d13a431 (parent) -> c6768de (this PR)

Test differences

No test diffs found

Test dashboard

Run

cargo run --manifest-path src/ci/citool/Cargo.toml -- \
    test-dashboard c6768de2d63de7a41124a0fb8fc78f9e26111c01 --output-dir test-dashboard

And then open test-dashboard/index.html in your browser to see an overview of all executed tests.

Job duration changes

  1. dist-apple-various: 6087.9s -> 9413.9s (54.6%)
  2. dist-x86_64-apple: 8482.7s -> 11889.8s (40.2%)
  3. x86_64-apple-2: 5966.9s -> 3710.7s (-37.8%)
  4. x86_64-apple-1: 7300.2s -> 8548.4s (17.1%)
  5. mingw-check-2: 2222.6s -> 1922.5s (-13.5%)
  6. i686-gnu-2: 6163.5s -> 5360.4s (-13.0%)
  7. x86_64-rust-for-linux: 2958.8s -> 2587.0s (-12.6%)
  8. arm-android: 5947.6s -> 5249.8s (-11.7%)
  9. dist-ohos-armv7: 3890.6s -> 4338.5s (11.5%)
  10. i686-gnu-nopt-1: 8182.9s -> 7317.2s (-10.6%)
How to interpret the job duration changes?

Job durations can vary a lot, based on the actual runner instance
that executed the job, system noise, invalidated caches, etc. The table above is provided
mostly for t-infra members, for simpler debugging of potential CI slow-downs.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (c6768de): comparison URL.

Overall result: no relevant changes - no action needed

@rustbot label: -perf-regression

Instruction count

This benchmark run did not return any relevant results for this metric.

Max RSS (memory usage)

Results (secondary 2.9%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
2.9% [2.9%, 2.9%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Cycles

This benchmark run did not return any relevant results for this metric.

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 754.509s -> 755.17s (0.09%)
Artifact size: 372.30 MiB -> 372.30 MiB (-0.00%)

tautschnig pushed a commit to model-checking/verify-rust-std that referenced this pull request Jun 17, 2025
…ondet, r=RalfJung

Enable Non-determinism of float operations in Miri and change std tests

Links to [rust-lang#4208](rust-lang/miri#4208) and [rust-lang#3555](rust-lang/miri#3555) in Miri.

Non-determinism of floating point operations was disabled in rust-lang#137594 because it breaks the tests and doc-tests in core/coretests and std. This PR enables some of them.

This pr includes the following changes:

- Enables the float non-determinism but with a lower relative error of 4ULP instead of 16ULP
- These operations now have a fixed output based on the C23 standard, except the pow operations, this is tracked in [rust-lang#4286](rust-lang/miri#4286 (comment))
- Changes tests that made incorrect assumptions about the operations, not to make that assumption anymore (from `assert_eq!` to `assert_approx_eq!`.
- Changed the doctests of the stdlib of these operations to compare against fixed constants instead of `f*::EPSILON`, which now succeed with Miri and `-Zmiri-many-seeds`
- Added a constant `APPROX_DELTA` in `std/tests/floats/f32.rs` which is used for approximation tests, but with a different value when run in Miri. This is to make these tests succeed.
- Added tests in the float tests of Miri to test the C23 behaviour.

Fixes rust-lang/miri#4208
@LorrensP-2158466 LorrensP-2158466 deleted the miri-enable-float-nondet branch June 26, 2025 14:34
rust-bors bot added a commit that referenced this pull request Jun 27, 2025
Miri: handling of SNaN inputs in `f*::pow` operations

<!-- homu-ignore:start -->
<!--
If this PR is related to an unstable feature or an otherwise tracked effort,
please link to the relevant tracking issue here. If you don't know of a related
tracking issue or there are none, feel free to ignore this.

This PR will get automatically assigned to a reviewer. In case you would like
a specific user to review your work, you can assign it to them by using

    r? <reviewer name>
-->
<!-- homu-ignore:end -->

fixes [miri/#4286](rust-lang/miri#4286) and related to #138062 and [miri/#4208](rust-lang/miri#4208 (comment)).

For the following cases of the powf or powi operations, Miri returns either `1.0` or an arbitrary `NaN`:
- `powf(SNaN, 0.0)`
- `powf(1.0, SNaN)`
- `powi(SNaN, 0)`

Also added a macro in `miri/tests/pass/float.rs` which conveniently checks if both are indeed returned from such an operation.

Made these changes in the rust repo so I could test against stdlib, since these were impacted some time ago and were fixed in #138062. Tested with:
```fish
env MIRIFLAGS=-Zmiri-many-seeds ./x miri --no-fail-fast std core coretests -- f32 f64
```
This was successful. This does take a while, so I recommend using `--no-doc` and separate use of `f32` or `f64`

The pr is somewhat split up into 3 main commits, which implement the cases described above. The first commit also introduces the macro, and the last commit is just a global refactor of some things.

r? `@RalfJung`
try-job: x86_64-gnu-aux
dianqk added a commit to dianqk/rust that referenced this pull request Jun 30, 2025
…-pow, r=RalfJung

Miri: handling of SNaN inputs in `f*::pow` operations

fixes [miri/rust-lang#4286](rust-lang/miri#4286) and related to rust-lang#138062 and [miri/rust-lang#4208](rust-lang/miri#4208 (comment)).

For the following cases of the powf or powi operations, Miri returns either `1.0` or an arbitrary `NaN`:
- `powf(SNaN, 0.0)`
- `powf(1.0, SNaN)`
- `powi(SNaN, 0)`

Also added a macro in `miri/tests/pass/float.rs` which conveniently checks if both are indeed returned from such an operation.

Made these changes in the rust repo so I could test against stdlib, since these were impacted some time ago and were fixed in rust-lang#138062. Tested with:
```fish
env MIRIFLAGS=-Zmiri-many-seeds ./x miri --no-fail-fast std core coretests -- f32 f64
```
This was successful. This does take a while, so I recommend using `--no-doc` and separate use of `f32` or `f64`

The pr is somewhat split up into 3 main commits, which implement the cases described above. The first commit also introduces the macro, and the last commit is just a global refactor of some things.

r? `@RalfJung`
rust-timer added a commit that referenced this pull request Jun 30, 2025
Rollup merge of #142514 - LorrensP-2158466:miri-float-nondet-pow, r=RalfJung

Miri: handling of SNaN inputs in `f*::pow` operations

fixes [miri/#4286](rust-lang/miri#4286) and related to #138062 and [miri/#4208](rust-lang/miri#4208 (comment)).

For the following cases of the powf or powi operations, Miri returns either `1.0` or an arbitrary `NaN`:
- `powf(SNaN, 0.0)`
- `powf(1.0, SNaN)`
- `powi(SNaN, 0)`

Also added a macro in `miri/tests/pass/float.rs` which conveniently checks if both are indeed returned from such an operation.

Made these changes in the rust repo so I could test against stdlib, since these were impacted some time ago and were fixed in #138062. Tested with:
```fish
env MIRIFLAGS=-Zmiri-many-seeds ./x miri --no-fail-fast std core coretests -- f32 f64
```
This was successful. This does take a while, so I recommend using `--no-doc` and separate use of `f32` or `f64`

The pr is somewhat split up into 3 main commits, which implement the cases described above. The first commit also introduces the macro, and the last commit is just a global refactor of some things.

r? `@RalfJung`
github-actions bot pushed a commit to rust-lang/miri that referenced this pull request Jul 1, 2025
…alfJung

Miri: handling of SNaN inputs in `f*::pow` operations

fixes [miri/#4286](#4286) and related to rust-lang/rust#138062 and [miri/#4208](#4208 (comment)).

For the following cases of the powf or powi operations, Miri returns either `1.0` or an arbitrary `NaN`:
- `powf(SNaN, 0.0)`
- `powf(1.0, SNaN)`
- `powi(SNaN, 0)`

Also added a macro in `miri/tests/pass/float.rs` which conveniently checks if both are indeed returned from such an operation.

Made these changes in the rust repo so I could test against stdlib, since these were impacted some time ago and were fixed in rust-lang/rust#138062. Tested with:
```fish
env MIRIFLAGS=-Zmiri-many-seeds ./x miri --no-fail-fast std core coretests -- f32 f64
```
This was successful. This does take a while, so I recommend using `--no-doc` and separate use of `f32` or `f64`

The pr is somewhat split up into 3 main commits, which implement the cases described above. The first commit also introduces the macro, and the last commit is just a global refactor of some things.

r? `@RalfJung`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. 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.

Miri float ops are less precise than what the standard library expects