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

Implementation of std::f64::powi function gives inconsistent answers in multiple Rust tool-chains #73920

Closed
hansieodendaal opened this issue Jul 1, 2020 · 5 comments
Labels
A-floating-point Area: Floating point numbers and arithmetic A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@hansieodendaal
Copy link

Problem code

I tried this code (also in Rust playpen here):

fn main() {
    let base = 0.999_999_560_409_038_5f64;
    let i = [
        9182i32, 9430i32, 10855i32, 10856i32, 10857i32, 11708i32, 30335i32, 33923i32, 34947i32,
    ];
    // Reference results from:
    // - stable-x86_64-unknown-linux-gnu  (Debug)
    // - stable-x86_64-pc-windows-gnu     (Debug, Release)
    // - stable-x86_64-pc-windows-msvc    (Debug)
    // - nightly-x86_64-unknown-linux-gnu (Debug)
    // - nightly-x86_64-pc-windows-gnu    (Debug, Release)
    let result = [
        0.9959718099156295f64, 
        0.9958632363991619f64, 
        0.9952396058283226f64, 
        0.9952391683299874f64, 
        0.9952387308318444f64, 
        0.9948664896246138f64, 
        0.9867535223990311f64, 
        0.9851983894664985f64, 
        0.9847550108373471f64, 
    ];
    let iter = i.iter().zip(&result);
    for item in iter {
        let v = base.powi(*item.0);
        assert_eq!(v, *item.1)
    }
}

I expected to see this happen:

  • The code should always give consistent answers in Windows and Linux, either in release or debug mode, using stable or nightly.
  • The code should always give consistent answers in Rust playpen, either in release or debug mode, using stable, beta or nightly.

Instead, this happened:

Toolchains tested (Windows 10)

# Tool-chain (Windows) Debug/Release Pass/Fail
1 stable-x86_64-pc-windows-gnu Debug Pass
[1.44.1 (c7087fe 2020-06-17)] Release Pass
-- ----------------------------------------- ------------- ---------
2 stable-x86_64-pc-windows-msvc Debug Pass
[1.44.1 (c7087fe 2020-06-17)] Release Fail
-- ----------------------------------------- ------------- ---------
3 nightly-x86_64-pc-windows-gnu Debug Pass
[1.46.0-nightly (16957bd 2020-06-30)] Release Pass
-- ----------------------------------------- ------------- ---------
4 nightly-x86_64-pc-windows-msvc Debug Fail
[1.46.0-nightly (16957bd 2020-06-30)] Release Fail
-- ----------------------------------------- -------------- ---------
5 nightly-2019-05-12-x86_64-pc-windows-msvc Debug Pass
[1.36.0-nightly (af98304 2019-05-11)] Release Fail
-- ----------------------------------------- ------------- ---------
6 nightly-2019-07-31-x86_64-pc-windows-msvc Debug Pass
[1.38.0-nightly (dddb7fc 2019-07-30)] Release Fail
-- ------------------------------------------ ------------- ---------
7 nightly-2019-10-04-x86_64-pc-windows-msvc Debug Pass
[1.40.0-nightly (032a53a 2019-10-03)] Release Fail
-- ----------------------------------------- ------------- ---------
8 nightly-2020-01-08-x86_64-pc-windows-msvc Debug Pass
[1.42.0-nightly (8597644 2020-01-07)] Release Fail
-- ----------------------------------------- ------------- ---------
9 nightly-2020-02-23-x86_64-pc-windows-msvc Debug Pass
[1.43.0-nightly (436494b 2020-02-22)] Release Fail
-- ----------------------------------------- ------------- ---------
10 nightly-2020-06-10-x86_64-pc-windows-msvc Debug Fail
[1.46.0-nightly (feb3536 2020-06-09)] Release Fail

Toolchains tested (Linux Ubuntu)

# Tool-chain (Linux) Debug/Release Pass/Fail
1 stable-x86_64-unknown-linux-gnu Debug Pass
[1.44.1 (c7087fe 2020-06-17)] Release Fail
-- ------------------------------------------- ------------- ---------
2 nightly-2019-07-31-x86_64-unknown-linux-gnu Debug Pass
[1.38.0-nightly (dddb7fc 2019-07-30)] Release Fail
-- ------------------------------------------- ------------- ---------
3 nightly-2020-01-08-x86_64-unknown-linux-gnu Debug Pass
[1.42.0-nightly (8597644 2020-01-07)] Release Fail
-- ------------------------------------------- ------------- ---------
4 nightly-2020-06-10-x86_64-unknown-linux-gnu Debug Pass
[1.46.0-nightly (feb3536 2020-06-09)] Release Fail
-- ------------------------------------------- ------------- ---------
5 nightly-x86_64-unknown-linux-gnu Debug Pass
[1.46.0-nightly (16957bd 2020-06-30)] Release Fail

Rust playpen

# Tool-chain (Rust playpen) Debug/Release Pass/Fail
1 Stable channel Debug Pass
[Stable version: 1.44.1] Release Fail
-- --------------------------------------- ------------- ---------
2 Beta channel Debug Pass
[1.45.0-beta.3 (2020-06-27 8196407)] Release Fail
-- -------------------------------------- ------------- ---------
3 Nightly channel Debug Pass
[1.46.0-nightly (2020-06-30 16957bd)] Release Fail
-- --------------------------------------- ------------- ---------

Meta

rustc --version --verbose:
See detail information in the tables above.

Backtrace

C:\Code\f64_powi_issue>cargo run --release
warning: unused config key `build.RUSTFLAGS` in `C:\Users\.cargo\config`
    Finished release [optimized] target(s) in 0.05s
     Running `target\release\f64_powi_issue.exe`
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `0.9959718099154268`,
 right: `0.9959718099156295`', src\main.rs:22:9
stack backtrace:
   0: backtrace::backtrace::trace_unsynchronized
             at C:\Users\VssAdministrator\.cargo\registry\src\gh.neting.cc-1ecc6299db9ec823\backtrace-0.3.46\src\backtrace\mod.rs:66
   1: std::sys_common::backtrace::_print_fmt
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\sys_common\backtrace.rs:78
   2: std::sys_common::backtrace::_print::{{impl}}::fmt
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\sys_common\backtrace.rs:59
   3: core::fmt::write
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libcore\fmt\mod.rs:1069
   4: std::io::Write::write_fmt<std::sys::windows::stdio::Stderr>
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\io\mod.rs:1504
   5: std::sys_common::backtrace::_print
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\sys_common\backtrace.rs:62
   6: std::sys_common::backtrace::print
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\sys_common\backtrace.rs:49
   7: std::panicking::default_hook::{{closure}}
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\panicking.rs:198
   8: std::panicking::default_hook
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\panicking.rs:218
   9: std::panicking::rust_panic_with_hook
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\panicking.rs:511
  10: std::panicking::begin_panic_handler
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\panicking.rs:419
  11: std::panicking::begin_panic_fmt
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\panicking.rs:373
  12: __ImageBase
  13: __ImageBase
  14: std::rt::lang_start_internal::{{closure}}
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\rt.rs:52
  15: std::panicking::try::do_call
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\panicking.rs:331
  16: std::panicking::try
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\panicking.rs:274
  17: std::panic::catch_unwind
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\panic.rs:394
  18: std::rt::lang_start_internal
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\rt.rs:51
  19: main
  20: invoke_main
             at d:\agent\_work\5\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
  21: __scrt_common_main_seh
             at d:\agent\_work\5\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
  22: BaseThreadInitThunk
  23: RtlUserThreadStart
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
error: process didn't exit successfully: `target\release\f64_powi_issue.exe` (exit code: 101)

C:\Code\f64_powi_issue>rustc --version --verbose
rustc 1.44.1 (c7087fe00 2020-06-17)
binary: rustc
commit-hash: c7087fe00d2ba919df1d813c040a5d47e43b0fe7
commit-date: 2020-06-17
host: x86_64-pc-windows-msvc
release: 1.44.1
LLVM version: 9.0

@hansieodendaal hansieodendaal added the C-bug Category: This is a bug. label Jul 1, 2020
@hansieodendaal hansieodendaal changed the title Implementation of std::f64::powi function in Rust tool-chain nightly-2020-06-10 broken for Windows Implementation of std::f64::powi function gives inconsistent answers in multiple Rust tool-chains Jul 1, 2020
@ehuss
Copy link
Contributor

ehuss commented Jul 1, 2020

There is a bit of discussion about this in #71355 and #73420, which I think is pretty much the same.

@ecstatic-morse ecstatic-morse added A-floating-point Area: Floating point numbers and arithmetic A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. labels Jul 1, 2020
@mati865
Copy link
Contributor

mati865 commented Jul 2, 2020

Quite interesting that #73420 affects both windows-gnu and windows-msvc targets but here only msvc output changed in the nightly.
#71355 on the other hand works fine on both Windows targets:

$ rustc -vV
rustc 1.46.0-nightly (16957bd4d 2020-06-30)
binary: rustc
commit-hash: 16957bd4d3a5377263f76ed74c572aad8e4b7e59
commit-date: 2020-06-30
host: x86_64-pc-windows-gnu
release: 1.46.0-nightly
LLVM version: 10.0

$ rustc powi2.rs && ./powi2
5e-324
5e-324
5e-324

$ rustc powi2.rs -O && ./powi2
5e-324
5e-324
5e-324

$ rustc powi2.rs --target x86_64-pc-windows-msvc && ./powi2
5e-324
5e-324
5e-324

$ rustc powi2.rs --target x86_64-pc-windows-msvc -O && ./powi2
5e-324
5e-324
5e-324

@workingjubilee
Copy link
Member

Because LLVM generally turns powi into a call to libm, powi consistency is not possible without Rust bypassing this and shipping its own powi.

@Noratrieb Noratrieb added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Apr 5, 2023
@RalfJung
Copy link
Member

RalfJung commented Jan 6, 2024

This should be closed as a duplicate of #71355 or vice versa.

So far it's not even clear to me that there is a bug here. Where is the exact rounding behavior of powi specified? Float operations behaving different across platforms and build modes is not unexpected; the exact precision of these operations is often left unspecified and hence should be considered non-deterministic. See rust-lang/rfcs#3514 for another source of non-determinism in float operations (the representation bits of a NaN value).

@ehuss
Copy link
Contributor

ehuss commented Jan 6, 2024

Closing as a duplicate of #71355.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-floating-point Area: Floating point numbers and arithmetic A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

7 participants