-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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 clamp RFC #1961
Add clamp RFC #1961
Conversation
0000-clamp.md
Outdated
/// Returns the upper bound of the range if input is greater than the range, and the lower bound of | ||
/// the range if input is less than the range. Otherwise this will return input. | ||
#[inline] | ||
pub fn clamp<T: Ord>(input: T, range: RangeInclusive<T>) -> T { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if we should tie the stability of this RFC with #1192 (rust-lang/rust#28237) here by using range: RangeInclusive<T>
instead of min: T, max: T
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After messing around with the playground a bit and doing some thinking I actually agree with you. I much prefer the RangeInclusive syntax but the instability of it is too much of a drawback.
My two concerns:
|
I think the RFC and docstring should explicitly describe what happens if |
@pornel my first thought is that we ought to optimize the @bluetech agreed, I'll add something for that as soon as I can. |
@Xaeroxe please note that I think use of SSE dictates that if any of the operands is NaN, then NaN is returned. http://www.felixcloutier.com/x86/MAXSD.html |
@pornel No,
i.e. The definition of |
text/0000-clamp.md
Outdated
input | ||
} | ||
} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An alternative implementation which results in better code is:
pub fn clamp(input:f32, min: f32, max: f32) -> f32 {
let mut x = input;
if !(x < min) { x = min; }
if !(x > max) { x = max; }
x
}
It conveniently preserves the source when it is NaN
, as required in the edge cases listed below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Looks great!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... but it incorrectly returns NaN
when max == NaN || min == NaN
(EDIT: this is pseudocode... as crazy as it looks, the check for NaN
would be max != max || min != min
).
I am unsure if this is good or bad: while the infinity corresponding to no enforcement is straightforward, it is not obvious to me what is the desirable behaviour for NaN
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You know honestly that might be better behavior than what I proposed. It assumes a NaN is unintentional which they often are. If someone explicitly wants no bounds enforced they should provide infinity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ranma42 I think you mean if !(x >= min)
etc.
Should we mention the expected behaviour for |
@ranma42 I think so yes. max and min may not be constant values so it's not that far out to say a user could accidentally provide a max < min |
So I think the behavior for max < min should be explicitly defined but I don't really know what that behavior should be. My first thought is to just add a line at the top of the function: assert!(max >= min); I worry about |
If If they are not statically known, and the function is marked inline, then if it is called inside of a loop and So IMO panic is the safe way to go. |
@Xaeroxe that assert would also forbid passing |
Thanks @bluetech ! I learned some cool stuff about the optimizer today. |
Personally I prefer panic, as more harsh consequences for invalid input are more likely to make the programmer make sure to account for the possibility of invalid input. Of course if anyone has counter points to that I'd love to hear them. |
@kennytm Good catch. How about this? pub fn clamp(input:f32, min: f32, max: f32) -> f32 {
assert!(max >= min);
let mut x = input;
if x < min { x = min; }
if x > max { x = max; }
x
} |
@kennytm sorry, you're right, I was misled by the documentation mentioning the first/second operand in Intel syntax vs the playground showing the GNU syntax. My bad. |
Changes made, requesting feedback. Good work, I think we're getting closer to a final. |
For other languages/libraries having
Behaviors of different algorithms
|
The shepherds for this RFC have signaled readiness for full team review, so here we go! @rfcbot fcp merge |
Team member @aturon 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. |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
Tracking issue: rust-lang/rust#44095 |
The final comment period is now complete. |
Implementation PR is ready, it can be merged as soon as this is merged I believe. |
Merged! Thanks, @Xaeroxe, for sticking this one out. |
Add clamp functions Implementation of clamp feature: Tracking issue: rust-lang#44095 RFC: rust-lang/rfcs#1961
Add clamp functions Implementation of clamp feature: Tracking issue: rust-lang#44095 RFC: rust-lang/rfcs#1961
Clamp was implemented then shortly reverted due to concerns about breaking downstream code. It's unlikely this RFC will be implemented. See this: rust-lang/rust#44095 |
The rendered link on top is broken. I was looking this up to find out what clamp even is. Now I still don't know. |
All accepted RFCs are visible on the website: https://rust-lang.github.io/rfcs/1961-clamp.html
https://doc.rust-lang.org/std/primitive.f32.html#method.clamp
|
Congrats, @Xaeroxe, on this finally getting to stable! |
🎉 Thank you!! I'm very excited! 🎉 |
RFC for feature discussed at https://internals.rust-lang.org/t/clamp-function-for-primitive-types/4999
Tracking issue: rust-lang/rust#44095
Implementation PR: rust-lang/rust#44097