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

Functions to distinguish signaling from non-signaling NaN's #364

Closed
icefoxen opened this issue Mar 6, 2018 · 6 comments
Closed

Functions to distinguish signaling from non-signaling NaN's #364

icefoxen opened this issue Mar 6, 2018 · 6 comments

Comments

@icefoxen
Copy link

icefoxen commented Mar 6, 2018

It'd be nice to be able to distinguish signaling from non-signaling NaN's in some cases. In particular, writing a WebAssembly interpreter; WebAssembly disallows signaling NaN's, so one needs some way to detect and filter them out. Easy to do with bit masks, but it would be nice to be a little more abstract.

Thank you!

@icefoxen
Copy link
Author

icefoxen commented Mar 6, 2018

If you want 'em, here they are. :-P

/// Returns whether or not the float is a signaling NaN.
/// A signaling NaN has a format like:
/// `s111 1111 1nxx xxxx xxxx xxxx xxxx xxxx`
/// where the `x`'s represent a non-zero number (zero
/// would be infinity) and `n` is 0.
/// The sign bit `s` may be anything.
///
/// On some old-fashioned platforms (PA-RISC, some MIPS)
/// a signaling NaN is marked by `n=1`, but the 2008 revision of
/// IEEE754 defines it to be `n=0`.
pub fn f32_is_signaling_nan(f: f32) -> bool {
    let uf: u32 = f.to_bits();
    let signal_bit = 0b0000_0000_0100_0000_0000_0000_0000_0000;
    let signal_bit = 1 << 22;
    // signaling nan := is NAN and signal bit is clear
    let signal_bit_clear = (uf & signal_bit) == 0;
    f32::is_nan(f) && signal_bit_clear
}

/// Same as `f32_is_signaling_nan()` for `f64`'s.
/// The signaling-nan-bit is bit 51 instead of bit 22
pub fn f64_is_signaling_nan(f: f64) -> bool {
    let uf: u64 = f.to_bits();
    let signal_bit = 1 << 51;
    // signaling nan := is NAN and signal bit is clear
    let signal_bit_clear = (uf & signal_bit) == 0;
    f64::is_nan(f) && signal_bit_clear
}

@cuviper
Copy link
Member

cuviper commented Mar 6, 2018

FloatCore or Float::integer_decode can also help safely get the mantissa, if you're on a pre-1.20 Rust without to_bits(). You still have to know where to find that is_quiet bit though.

I'm not sure if there's a good way we can add a method for this without a breaking change. Standalone methods aren't really in the spirit of num-traits. A whole new trait for this would be possible, but seems rather excessive.

@icefoxen
Copy link
Author

icefoxen commented Mar 7, 2018

I was imagining it just being a method on the Float trait, really. Not sure if that would count as a breaking change though, since implementors of Float would need to add a method. Honestly maybe this belongs in std instead...

@cuviper
Copy link
Member

cuviper commented Mar 7, 2018

Not sure if that would count as a breaking change though, since implementors of Float would need to add a method.

Yes, that makes it breaking, unless we also add a default implementation for that method, but I don't know if that's possible here.

@icefoxen
Copy link
Author

icefoxen commented Mar 7, 2018

The obvious default implementation is "return false", but that's not really a correct default implementation, just a stub.

Due to that, and the fact that it is deathly platform-dependent, I think it might fit better in std. Might be something to consider for inclusion in num if/when you want to break the API anyway though.

@cuviper
Copy link
Member

cuviper commented Mar 7, 2018

This issue was moved to rust-num/num-traits#51

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants