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

Add a copysign function to f32 and f64 #55169

Merged
merged 3 commits into from
Oct 19, 2018
Merged

Conversation

raphlinus
Copy link
Contributor

This patch adds a copysign function to the float primitive types. It is an exceptionally useful function for writing efficient numeric code, as it often avoids branches, is auto-vectorizable, and there are efficient intrinsics for most platforms.

I think this might work as-is, as the relevant copysign intrinsic is already used internally for the implementation of signum. It's possible that an implementation might be needed in japaric/libm for portability across all platforms, in which case I'll do that also.

Part of the work towards #55107

This patch adds a `copysign` function to the float primitive types.
It is an exceptionally useful function for writing efficient numeric
code, as it often avoids branches, is auto-vectorizable, and there
are efficient intrinsics for most platforms.

I think this might work as-is, as the relevant `copysign` intrinsic
is already used internally for the implementation of `signum`. It's
possible that an implementation might be needed in japaric/libm for
portability across all platforms, in which case I'll do that also.

Part of the work towards rust-lang#55107
@rust-highfive
Copy link
Collaborator

r? @joshtriplett

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

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Oct 18, 2018
@joshtriplett
Copy link
Member

The two versions have doc comments that explain the NAN behavior differently. Could you please make them match? I found the explanation on the f32 version much clearer; could you copy that to the f64 version?

I improved the f32 version and made a copy-paste error for f64.
@raphlinus
Copy link
Contributor Author

Definitely, and good catch. Was just a copy-paste error.

Who is a good person to look into the question of whether this might break exotic targets because llvm might generate a call to a (possibly unimplemented) library function for the general copysign intrinsic. Maybe @japaric?

@nikic
Copy link
Contributor

nikic commented Oct 18, 2018

Instead of a.copysign(b) something like a.with_sign_of(b) might make it more explicit which of the signs is being applied to which of the operands. On the other hand, copysign is standard terminology.

@raphlinus
Copy link
Contributor Author

@nikic Good point, and I'm open to that. In this case, I'm going to suggest sticking with standard terminology, because I think the target user is much more likely to be studying or adapting numerical algorithms from other languages, rather than than writing Rust-only numerical algorithms. Also I think when studying asm output (especially wasm), it reduces the translation, understanding that copysign in the source should translate into the copysign intrinsic.

But if people strongly prefer a more explicit name, I'll change it.

@joshtriplett
Copy link
Member

I think keeping the standard name copysign makes sense. And you've kept the order of arguments: a.copysign(b) matches copysign(a, b).

You could make it copysign_of for clarity, but even that divergence from the standard function might do more harm than good. I'll leave that up to you.

However, that brings to mind another thought. To prevent someone from thinking that this might modify the value in place, please add #[must_use] to require using the return value.

Added a #[must_use] annotation on copysign, per review feedback.
@raphlinus
Copy link
Contributor Author

@joshtriplett Done. I agree with the rationale but will point out it's not consistent with the rest of the module. I think we can chalk that up to must_use not being available when the base library was done.

@joshtriplett
Copy link
Member

LGTM. If you would like to seek feedback to confirm that this will work on obscure architectures, please feel free to do so and r=me afterward. You could also go ahead, on the theory that we already use many other intrinsics and this one doesn't seem drastically less likely to work.

@raphlinus
Copy link
Contributor Author

I'm comfortable going ahead and seeing what breaks. If we get a failure on a specific architecture because of a missing _copysign, it should be pretty clear what to do next to fix it.

@joshtriplett
Copy link
Member

@bors r+

@bors
Copy link
Contributor

bors commented Oct 18, 2018

📌 Commit f08db6b has been approved by joshtriplett

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 18, 2018
kennytm added a commit to kennytm/rust that referenced this pull request Oct 19, 2018
Add a `copysign` function to f32 and f64

This patch adds a `copysign` function to the float primitive types. It is an exceptionally useful function for writing efficient numeric code, as it often avoids branches, is auto-vectorizable, and there are efficient intrinsics for most platforms.

I think this might work as-is, as the relevant `copysign` intrinsic is already used internally for the implementation of `signum`. It's possible that an implementation might be needed in japaric/libm for portability across all platforms, in which case I'll do that also.

Part of the work towards rust-lang#55107
bors added a commit that referenced this pull request Oct 19, 2018
Rollup of 7 pull requests

Successful merges:

 - #54300 (Updated RELEASES.md for 1.30.0)
 - #55013 ([NLL] Propagate bounds from generators)
 - #55071 (Fix ICE and report a human readable error)
 - #55144 (Cleanup resolve)
 - #55166 (Don't warn about parentheses on `match (return)`)
 - #55169 (Add a `copysign` function to f32 and f64)
 - #55178 (Stabilize slice::chunks_exact(), chunks_exact_mut(), rchunks(), rchunks_mut(), rchunks_exact(), rchunks_exact_mut())
@bors bors merged commit f08db6b into rust-lang:master Oct 19, 2018
/// another.
///
/// Equal to `self` if the sign of `self` and `y` are the same, otherwise
/// equal to `-y`. If `self` is a `NAN`, then a `NAN` with the sign of `y`
Copy link
Member

Choose a reason for hiding this comment

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

"otherwise equal to -self", and not "-y", right? Or am I confused now?

Also: I'd rephrase the first sentence to "Returns a number composed of the magnitude of self and the sign of y". That's more explicit.

And yes, I know the PR is already merged, but I guess we should fix this in a new PR, if I'm right about this typo.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@LukasKalbertodt You're absolutely right. I'm happy to fix this in a followup PR. Good catch!

@raphlinus raphlinus deleted the copysign branch October 24, 2018 22:16
kennytm pushed a commit to kennytm/rust that referenced this pull request Oct 25, 2018
Thanks to @LukasKalbertodt for catching this. Addresses a comment
raised in rust-lang#55169 after it was merged.
kennytm added a commit to kennytm/rust that referenced this pull request Oct 25, 2018
…lett

Fix doc for new copysign functions

Thanks to \@LukasKalbertodt for catching this. Addresses a comment raised in rust-lang#55169 after it was merged.
pietroalbini added a commit to pietroalbini/rust that referenced this pull request Oct 25, 2018
…lett

Fix doc for new copysign functions

Thanks to @LukasKalbertodt for catching this. Addresses a comment raised in rust-lang#55169 after it was merged.
@crlf0710
Copy link
Member

crlf0710 commented Dec 1, 2018

Well, it seems this is actually the tracking issue for copysign feature gate? Or is a separate tracking issue needed?

@raphlinus
Copy link
Contributor Author

@crlf0710 I was told on IRC that this issue could serve as the tracking issue, for such a small feature. But I am not expert on the ways of Rust stabilization.

@crlf0710
Copy link
Member

crlf0710 commented Dec 1, 2018

@raphlinus The tracking issue should be an issue, not a PR, i think... @Centril

@Centril
Copy link
Contributor

Centril commented Dec 1, 2018

@crlf0710 is correct; there should be an open issue for it; take a look at https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AC-tracking-issue+label%3AT-libs for inspiration.

@raphlinus
Copy link
Contributor Author

Ok, will do. One reason I've been holding back is that was also planning on adding "round to nearest even" function as part of the same motivating work, but now I see that could take a long time (honestly, the motivation I have for it has somewhat stalled out), so no reason that should block this.

@crlf0710
Copy link
Member

crlf0710 commented Dec 2, 2018

Well i've just finished seeking for solutions of "round with ties to positive infinity" when i come to this issue yesterday. :)

Centril added a commit to Centril/rust that referenced this pull request Mar 29, 2019
…Sapin

Stablize {f32,f64}::copysign().

Stablization PR for rust-lang#55169/rust-lang#58046. Please check if i'm doing it correctly. Is 1.35.0 good to go?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants