Skip to content
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

f64 NaN conversion to f32 maintains sign in Debug, not in Release #120898

Closed
starkat99 opened this issue Feb 10, 2024 · 3 comments
Closed

f64 NaN conversion to f32 maintains sign in Debug, not in Release #120898

starkat99 opened this issue Feb 10, 2024 · 3 comments
Labels
C-discussion Category: Discussion or questions that doesn't represent real issues. T-lang Relevant to the language team, which will review and decide on the PR/issue. T-opsem Relevant to the opsem team

Comments

@starkat99
Copy link
Contributor

I tried this code:

https://play.rust-lang.org/?version=nightly&mode=release&edition=2021&gist=ca495022488c872fb3addd969e8d705e

fn main() {
    {
        // This code works in both Debug & Release
        let nan64 = f64::from_bits(0x7FF0_0000_0000_0001u64);
        let nan32_from_64 = nan64 as f32;

        assert!(nan64.is_nan() && nan64.is_sign_positive());
        assert!(nan32_from_64.is_nan() && nan32_from_64.is_sign_positive());
    }

    {
        // Runs without errors in Debug. Fails in Release.
        let neg_nan64 = f64::from_bits(0xFFF0_0000_0000_0001u64);
        let neg_nan32_from_64 = neg_nan64 as f32;

        assert!(neg_nan64.is_nan() && neg_nan64.is_sign_negative());
        assert!(neg_nan32_from_64.is_nan() && neg_nan32_from_64.is_sign_negative());
    }
}

I expected to see this happen:

f64 to f32 conversion of a NaN value has the same behavior between Debug and Release mode. Hardware may or may not be preserving sign of NaN casts, so this may differ on different hardware with different standards support, but same behavior between compile modes would be expected

Instead, this happened:

Casting a negative-signed NaN f64 to a f32 maintains the negative-sign in Debug mode but not in Release mode. This behavior has been occurring since 1.75 according to starkat99/half-rs#103 and still exists in nightly. Interestingly, when using miri, the float sign changes in both debug & release, but for positive-signed floats.

Meta

rustc --version --verbose:

rustc 1.76.0 (07dca489a 2024-02-04)
binary: rustc
commit-hash: 07dca489ac2d933c78d3c5158e3f43beefeb02ce
commit-date: 2024-02-04
host: x86_64-unknown-linux-gnu
release: 1.76.0
LLVM version: 17.0.6
Backtrace

Running `target/release/playground`
thread 'main' panicked at src/main.rs:17:9:
assertion failed: neg_nan32_from_64.is_nan() && neg_nan32_from_64.is_sign_negative()
stack backtrace:
   0: rust_begin_unwind
             at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/std/src/panicking.rs:645:5
   1: core::panicking::panic_fmt
             at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/panicking.rs:72:14
   2: core::panicking::panic
             at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/panicking.rs:144:5
   3: playground::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

@starkat99 starkat99 added the C-bug Category: This is a bug. label Feb 10, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Feb 10, 2024
@saethlin
Copy link
Member

I'm pretty sure this is intentional, albiet grudgingly so: rust-lang/rfcs#3514

@saethlin saethlin added T-lang Relevant to the language team, which will review and decide on the PR/issue. C-discussion Category: Discussion or questions that doesn't represent real issues. T-opsem Relevant to the opsem team and removed C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Feb 11, 2024
@RalfJung
Copy link
Member

Yes, the sign of NaNs returned by a cast is non-deterministic and hence behavior may differ between debug and release builds and depending on optimizer behavior, compiler flags, or the target architecture. Even running the same cast with the same inputs in different circumstances can lead to different results.

Closing as a duplicate of #73328.

@RalfJung
Copy link
Member

when using miri, the float sign changes in both debug & release, but for positive-signed floats.

If you run this in Miri in a loop, you will notice that the sign sometimes changes and sometimes does not change. This reflects the non-determinism. We make no guarantee for when and whether this happens.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-discussion Category: Discussion or questions that doesn't represent real issues. T-lang Relevant to the language team, which will review and decide on the PR/issue. T-opsem Relevant to the opsem team
Projects
None yet
Development

No branches or pull requests

4 participants