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

Various improvements to FloatCore #41

Merged
merged 15 commits into from
Mar 1, 2018
Merged

Various improvements to FloatCore #41

merged 15 commits into from
Mar 1, 2018

Conversation

cuviper
Copy link
Member

@cuviper cuviper commented Feb 28, 2018

@cuviper
Copy link
Member Author

cuviper commented Feb 28, 2018

cc #32 @vks - I'd really appreciate a review on this, if only to make sure I didn't butcher your work. 😅

Copy link
Contributor

@vks vks left a comment

Choose a reason for hiding this comment

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

The changes look good to me. I have a few comments:

  • What is the motivation behind adding NumCast to FloatCore? Just symmetry with Float? I think the traits are kind of orthogonal. It seems like you need NumCast for the implementation of round.
  • Should we use associated constants rather than static methods? Would that raise our minimal supported Rust version?
  • Are the implementations of the rounding functions canonical? I don't know enough about the properties of floats to vouch for their correctness. It seems like tests for them are missing?

src/float.rs Outdated
self = self.recip();
}
// It should always be possible to convert a positive `i32` to a `usize`.
super::pow(self, exp.to_usize().unwrap())
super::pow(self, exp as u32 as usize)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why was this changed?

Copy link
Member Author

Choose a reason for hiding this comment

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

To handle i32::MIN. See above that I switched it to wrapping_neg, which will leave MIN the same. We want that to become an unsigned positive 0x80000000, but to_usize() would just fail.

Copy link
Member Author

Choose a reason for hiding this comment

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

I compromised -- added a comment why the as u32 is needed, but went back to using to_usize() so we won't be surprised here by a platform with 16-bit usize (although that will panic).

assert!((FloatCore::to_degrees(rad) - deg).abs() < 1e-6);
assert!((FloatCore::to_radians(deg) - rad).abs() < 1e-6);
assert!((FloatCore::to_degrees(rad) - deg).abs() < 1e-5);
assert!((FloatCore::to_radians(deg) - rad).abs() < 1e-5);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why was this necessary?

Copy link
Member Author

Choose a reason for hiding this comment

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

After I made it forward to std's f32::to_degrees, it started failing on nightly. I suspect rust-lang/rust#47919, which tried to be more accurate, actually made things less accurate for these inputs, but I haven't investigated yet. I will probably file an upstream bug.

Copy link
Member Author

Choose a reason for hiding this comment

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

src/float.rs Outdated
@@ -164,14 +505,54 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
}

/// Returns `true` if `self` is positive, including `+0.0` and
/// `FloatCore::infinity()`.
/// `FloatCore::infinity()`, and with newer versions of Rust
/// even `FloatCore::nan()`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we be explicit about the Rust version?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I'll look that up.

Copy link
Member Author

Choose a reason for hiding this comment

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

Changed the comment to mention that this was Rust 1.20.

@cuviper
Copy link
Member Author

cuviper commented Feb 28, 2018

What is the motivation behind adding NumCast to FloatCore? Just symmetry with Float? I think the traits are kind of orthogonal. It seems like you need NumCast for the implementation of round.

For symmetry, yes. I thought it made sense to keep Float and FloatCore as similar as possible. Do you see any situation where it's a problem to have it?

I did end up using NumCast for round, but just for a simple 0.5 -- we could avoid that with one() / (one() + one()) if necessary. Or we could move that implementation of round directly to f32 and f64 (no_std only), leaving no default.

Should we use associated constants rather than static methods? Would that raise our minimal supported Rust version?

It would raise it a lot -- associated consts were only made stable in 1.20.

Are the implementations of the rounding functions canonical? I don't know enough about the properties of floats to vouch for their correctness. It seems like tests for them are missing?

I implemented them independently based on their description and observed behavior. I'm fairly confident in them, but not 100% sure. They do have doctests where I tried to exercise interesting cases, and note this gets tested both with and without forwarding to std, so I know we're at least consistent for the inputs I selected.

@cuviper
Copy link
Member Author

cuviper commented Mar 1, 2018

I'm going to merge this so we can publish. The rounding parts that I'm less confident about can always be bug-fixed later. Thanks for reviewing!

bors r=vks

bors bot added a commit that referenced this pull request Mar 1, 2018
41: Various improvements to FloatCore r=vks a=cuviper

- New macros simplify forwarding method implementations.
  - `Float` and `Real` use this to compact their implementations.
  - `FloatCore` now forwards `std` implementations when possible.
- `FloatCore` now requires `NumCast`, like `Float does.
- New additions to `FloatCore`:
  - Constants like `min_value()` -> `f64::MIN`
  - Rounding methods `floor`, `ceil`, `round`, `trunc`, `fract`
  - `integer_decode` matching `Float`'s
- Fix NAN sign handling in `FloatCore` (rust-num/num#312, rust-lang/rust#42425)
- Fix overflow in `FloatCore::powi` exponent negation.
- Add doctests to all `FloatCore` methods.
@bors
Copy link
Contributor

bors bot commented Mar 1, 2018

Build succeeded

@bors bors bot merged commit 04a3f2a into rust-num:master Mar 1, 2018
@cuviper cuviper deleted the floater branch February 8, 2024 01:02
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

Successfully merging this pull request may close these issues.

None yet

2 participants