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

Expose float from_bits and to_bits in libcore. #46931

Merged
merged 2 commits into from
Jan 24, 2018

Conversation

clarfonthey
Copy link
Contributor

These methods have no dependencies on libm and thus should be offered in libcore.

@rust-highfive
Copy link
Collaborator

r? @bluss

(rust_highfive has picked a reviewer for you, use r? to override)

@est31
Copy link
Member

est31 commented Dec 22, 2017

Not sure why I didn't do it back in #39271. You should probably copy over the tests from std as well as the docs.

@hanna-kruppe
Copy link
Contributor

It makes sense to have these operations in core, but note that we currently don't have a good way to expose those to end users. The Float trait is perma-unstable and doc(hidden), as it's mostly for internal purposes. Inherent methods can't work, as the inherent impl block is in std. Free functions in core::fN modules are unidiomatic.

This PR shouldn't/doesn't have to address that, I'm just saying this will not really be usable by anyone except other code in the standard library. There are indeed places in core that could use these methods (float parsing, and probably formatting too), so I'm in favor of this change.

@est31
Copy link
Member

est31 commented Dec 22, 2017

@rkruppe thanks for explaining, probably that's why I didnt do it in my PR :). As this is for internal use only, the single line of docs that we have now is probably enough.

@kennytm kennytm added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Dec 22, 2017
@clarfonthey
Copy link
Contributor Author

Isn't the Float trait still in the core prelude? Similarly to the StrExt and SliceExt traits I just assumed that methods are available to use and the trait itself is not.

Long term I assume that the goal is to have multiple inherent impl blocks, so that core, alloc, and std could all have their own.

Regardless, I'm going to proceed with this and replace the existing unions that are used with to_bits and from_bits.

@hanna-kruppe
Copy link
Contributor

Isn't the Float trait still in the core prelude? Similarly to the StrExt and SliceExt traits I just assumed that methods are available to use and the trait itself is not.

Nope: https://play.rust-lang.org/?gist=6b061936c1e1e0d872210e120f6d0ae3&version=stable

@clarfonthey clarfonthey force-pushed the float_bits_core branch 3 times, most recently from 0cbe181 to 80d5bbf Compare December 23, 2017 01:18
@clarfonthey
Copy link
Contributor Author

@rkruppe I noticed! :(

Regardless, it appears that these methods would be useful in dec2flt, so, I converted that module to using the trait. It seems a bit messy with the associated const, but it works.

@@ -363,8 +337,7 @@ pub fn next_float<T: RawFloat>(x: T) -> T {
// too is exactly what we want!
// Finally, f64::MAX + 1 = 7eff...f + 1 = 7ff0...0 = f64::INFINITY.
Zero | Subnormal | Normal => {
let bits: u64 = x.transmute();
T::from_bits(bits + 1)
T::from_bits(x.to_bits() + T::Bits::from(1u8))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This technically changes the overflow behaviour on release, but I don't think it should be a problem, as this function isn't expected to ever trigger the assert that was originally in from_bits here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah this can't overflow. If x was the all-ones bit pattern, it'd be a NaN and we wouldn't enter this branch.

@@ -2872,6 +2872,10 @@ pub enum FpCategory {
reason = "stable interface is via `impl f{32,64}` in later crates",
issue = "32110")]
pub trait Float: Sized {
/// Type used by `to_bits` and `from_bits`.
#[stable(feature = "core_float_bits", since = "1.24.0")]
type Bits: ops::Add<Output = Self::Bits> + From<u8> + TryFrom<u64>;
Copy link
Contributor

@hanna-kruppe hanna-kruppe Dec 23, 2017

Choose a reason for hiding this comment

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

These bounds are pretty arbitrary. I guess it's okay for an internal trait, but alternatively you could move them to RawFloat (assuming that's the only place where they are needed).

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 made this work by duplicating the associated type in the RawFloat trait.

@bluss
Copy link
Member

bluss commented Dec 31, 2017

To be clear -- they are not really offered as anything but doc(hidden) and unstable in libcore even with this PR, right? It seems we have no stable float methods with just libcore.

@ollie27
Copy link
Member

ollie27 commented Dec 31, 2017

Marking the methods as stable in the Float trait will technically make them available in stable Rust. For example the following does compile on stable Rust:

#![no_std]
#![crate_type="lib"]

pub fn foo() -> bool {
    ::core::num::Float::is_nan(0f32)
}

@hanna-kruppe
Copy link
Contributor

hanna-kruppe commented Dec 31, 2017

Oh, right, that damn stability hole =/ Well, since this already applies to some existing methods, this PR doesn't really make it worse.

@bluss
Copy link
Member

bluss commented Dec 31, 2017

ugh. It's very unfortunate that in no_std, 0f32.is_nan() suggests use core::num::Float, but that use line is unstable.

@bluss
Copy link
Member

bluss commented Dec 31, 2017

I hope that we can reach the best kind of solution by providing inherent methods for f32, f64 in libcore (composable with the additional inherent methods in std)

@shepmaster
Copy link
Member

Happy new year from triage, @bluss! Will you be able to check this out sometime?

@shepmaster shepmaster added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Jan 13, 2018
@shepmaster
Copy link
Member

Ping from triage, @bluss! It's been over 6 days since we've heard from you, maybe @rust-lang/libs could assign a new reviewer?

}

/// Construct a subnormal. A mantissa of 0 is allowed and constructs zero.
pub fn encode_subnormal<T: RawFloat>(significand: u64) -> T {
assert!(significand < T::MIN_SIG, "encode_subnormal: not actually subnormal");
// Encoded exponent is 0, the sign bit is 0, so we just have to reinterpret the bits.
T::from_bits(significand)
T::from_bits(significand.try_into().unwrap_or_else(|_| unreachable!()))
Copy link
Member

Choose a reason for hiding this comment

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

This seems to be a step back, isn't there a way to keep this using just from_bits? Do you know if it has any performance impact?

The assertion assert!(bits < u32::MAX as u64, "f32::from_bits: too many bits"); from the old code has been lost, but I suppose it is unreachable here.

Copy link
Contributor

@hanna-kruppe hanna-kruppe Jan 17, 2018

Choose a reason for hiding this comment

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

I wouldn't worry about performance impact, this is only called near the end of the slowest of slow paths. Edit: The other instance of this pattern, in encode_normal above, is also called in the slightly-less-slow-path, Algorithm R, but that path is still really slow in absolute terms. So I stand by my assesment.

It's still ugly as hell but that ugliness will have to be somewhere unless all the dec2flt code is restructured to work with the Bits associated type instead of u64 (which would probably not be pretty either). Maybe it could move into RawFloat::from_bits? (But if so, it should gain a nicer panic message than unreachable)

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'll try seeing what needs to be done to use Bits instead of u64 here.

Copy link
Contributor

Choose a reason for hiding this comment

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

That's probably far too big a refactor to be worthwhile for this PR.

Copy link
Contributor

@hanna-kruppe hanna-kruppe Jan 17, 2018

Choose a reason for hiding this comment

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

Moving the try_into to from_bits seems more fruitful.

@bluss
Copy link
Member

bluss commented Jan 13, 2018

@shepmaster sure, that seems like a good idea

@kennytm
Copy link
Member

kennytm commented Jan 17, 2018

Review ping for @rust-lang/libs! Randomly reassigning to another team member due to #46931 (comment).

r? @BurntSushi

Also @clarcharr could you address @bluss's comment in #46931 (review)?

@BurntSushi
Copy link
Member

@rfcbot fcp merge

@rfcbot
Copy link

rfcbot commented Jan 17, 2018

Team member @BurntSushi has proposed to merge this. The next step is review by the rest of the tagged teams:

No concerns currently listed.

Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@rfcbot rfcbot added the proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. label Jan 17, 2018
@kennytm kennytm added S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 17, 2018
@carols10cents
Copy link
Member

Ping for ticky boxes here @Kimundi @dtolnay @sfackler!

@rfcbot
Copy link

rfcbot commented Jan 23, 2018

🔔 This is now entering its final comment period, as per the review above. 🔔

1 similar comment
@rfcbot
Copy link

rfcbot commented Jan 23, 2018

🔔 This is now entering its final comment period, as per the review above. 🔔

@rfcbot rfcbot added final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. and removed proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. labels Jan 23, 2018
@rfcbot
Copy link

rfcbot commented Jan 23, 2018

🔔 This is now entering its final comment period, as per the review above. 🔔

@alexcrichton
Copy link
Member

@bors: r+

@bors
Copy link
Contributor

bors commented Jan 23, 2018

📌 Commit 556fb02 has been approved by alexcrichton

@bors
Copy link
Contributor

bors commented Jan 24, 2018

⌛ Testing commit 556fb02 with merge a538fe7...

bors added a commit that referenced this pull request Jan 24, 2018
Expose float from_bits and to_bits in libcore.

These methods have no dependencies on libm and thus should be offered in libcore.
@bors
Copy link
Contributor

bors commented Jan 24, 2018

☀️ Test successful - status-appveyor, status-travis
Approved by: alexcrichton
Pushing a538fe7 to master...

@bors bors merged commit 556fb02 into rust-lang:master Jan 24, 2018
@clarfonthey clarfonthey deleted the float_bits_core branch April 15, 2018 20:31
@dhardy
Copy link
Contributor

dhardy commented Jul 10, 2018

Did this really land in 1.25.0? Because I still get a compiler error with that version:

$ rustc -V
rustc 1.25.0 (84203cac6 2018-03-25)
$ cargo test --tests --no-default-features
   Compiling serde v1.0.70
   Compiling rand v0.5.3 (file:///home/dhardy/rust/rand)
error[E0599]: no function or associated item named `from_bits` found for type `f32` in the current scope
   --> src/distributions/float.rs:98:22
    |
98  |                 $ty::from_bits(self | exponent_bits)
    |                      ^^^^^^^^^ function or associated item not found in `f32`
...
149 | float_impls! { f32, u32, f32, u32, 23, 127 }
    | -------------------------------------------- in this macro invocation
    |
    = help: items from traits can only be used if the trait is in scope
    = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
            candidate #1: `use core::num::Float;`

error[E0599]: no function or associated item named `from_bits` found for type `f64` in the current scope

Strangely I don't get warnings about conflicting keywords, which I got with older compilers (at least 1.22 and 1.23).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.