Is float comparison sound in const context?

When using float comparison in const fn, e.g.

const fn eq(a: f64, b: f64) -> bool {
    return a == b
}

Playground: Rust Playground

The compiler refuses with the error:

error[E0658]: floating point arithmetic is not allowed in constant functions

But it accepts the same code in a const context outside a function:


fn main() {
    const A: f64 = 1.0;
    const B: f64 = 1.0;
    const RES: bool = A == B;
    
    println!("{RES}");
}

Playground: Rust Playground

But is that code sound, with what that issue said? Tracking issue for `#![feature(const_fn_floating_point_arithmetic)]` · Issue #57241 · rust-lang/rust · GitHub

1 Like

As mentioned in the issue you linked, the problem is that a const fn can be evaluated both at compile-time and at run-time, and the results might differ.

const RES: bool = A == B; does not have this problem because it is only evaluated at compile time.

9 Likes

But it also means that if cross compiled, the result may be different from the result if compiled on the target arch (for the same reason that floating point arithmetic is not allowed in constant functions), right?

No. Compile-time evaluation uses a software implementation of floating-point arithmetic, so the results do not depend on the host hardware or the target hardware. The value of the const will be the same regardless of what machine the program is (cross-)compiled on or for.

3 Likes

NOT A CONTRIBUTION

In the context of const fns being able to return different results when evaluated at compile time vs runtime, is this a reason why?

I can imagine that while a software implementation would return the same results on every arch, different arches can give different results within some reasonably strict bounds¹.

¹ Those bounds are mainly that I'd expect any modern FP hardware implementations to adhere to some reasonably recent version of IEEE-754, rather than just providing whatever FP instructions it feels like.

1 Like

The primary notable case are NaN values, which are only loosely specified by the IEEE standard. More specifically, what the NaN payload bits are. As you note, non-NaN values should always be bit-identical, at least for the primitive arithmetic operations which are correctly rounded ±½ ULP.

2 Likes

Floating point is not even sound in non-const contexts, but these are bugs in the compiler.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.