This alternative produces slightly better code (no movaps
):
minsd %xmm1, %xmm0
maxsd %xmm2, %xmm0
This alternative produces slightly better code (no movaps
):
minsd %xmm1, %xmm0
maxsd %xmm2, %xmm0
Nice, it works well (With the typo of < > exchange fixed), but it has different behaviour for NaN start/end (not a useful behaviour). Thatās a legitimate design, but itās something to take into account.
Yes, I was adding a post about that and discussing the edge cases, but I realized that most of it was already in the RFC, so I wrote there
IME if youāre actually trying to use NaN for something constructive, you want it to be propagated by everything. That is, NaN.clamp(lo, hi)
should return the NaN (and so should min(NaN, x)
and max(NaN, x)
ā Iām surprised to hear that they donāt).
The behavior of NaN in the lo
and hi
arguments matters considerably less, because those are much less likely to be data.
(I do not know whether this corresponds to the behavior of the x86 instructions mentioned above.)
Hi. Since this was just merged (1 day ago), it causes a compilation error when building latest firefox (from the mercurial repo) as follows:
0:05.92 error: use of unstable library feature 'clamp' (see issue #44095)
0:05.92 --> /home/xftroxgpx/build/1packages/firefox-hg/makepkg_pacman/firefox-hg/src/firefox-hg/third_party/rust/app_units/src/app_unit.rs:192:22
0:05.92 |
0:05.92 192 | *self = self.clamp()
0:05.92 | ^^^^^
0:05.92 |
0:05.92 = help: add #![feature(clamp)] to the crate attributes to enable
0:05.92
0:05.92 error[E0061]: this function takes 2 parameters but 0 parameters were supplied
0:05.92 --> /home/xftroxgpx/build/1packages/firefox-hg/makepkg_pacman/firefox-hg/src/firefox-hg/third_party/rust/app_units/src/app_unit.rs:192:22
0:05.92 |
0:05.92 192 | *self = self.clamp()
0:05.93 | ^^^^^ expected 2 parameters
0:05.93
0:05.93 error[E0308]: mismatched types
0:05.93 --> /home/xftroxgpx/build/1packages/firefox-hg/makepkg_pacman/firefox-hg/src/firefox-hg/third_party/rust/app_units/src/app_unit.rs:192:17
0:05.93 |
0:05.93 192 | *self = self.clamp()
0:05.93 | ^^^^^^^^^^^^ expected struct `app_unit::Au`, found mutable reference
0:05.93 |
0:05.93 = note: expected type `app_unit::Au`
0:05.93 found type `&mut app_unit::Au`
0:05.93 = help: here are some functions which might fulfill your needs:
0:05.93 - .abs()
0:05.94 - .clamp()
0:05.94
0:05.95 error: aborting due to 3 previous errors
0:05.95
0:06.38 error: Could not compile `app_units`.
0:06.38
However clamp
is (re?)defined internally:
impl Au {
/// FIXME(pcwalton): Workaround for lack of cross crate inlining of newtype structs!
#[inline]
pub fn new(value: i32) -> Au {
Au(value).clamp()
}
#[inline]
fn clamp(self) -> Self {
if self.0 > MAX_AU.0 {
MAX_AU
} else if self.0 < MIN_AU.0 {
MIN_AU
} else {
self
}
}
#[inline]
fn clamp_self(&mut self) {
*self = self.clamp()
}
Iām sure this will be fixed in app_units
when the time comes, but I just wanted to mention it.
EDIT: Thanks for the fix (I have, for now, manually tested it to successfully compile latest firefox from mercurial repo; the pull for this to work auto seems on its way)
Crap this could be a huge problem for stabilizing this function. Itās going to collide with several downstream implementations because after all this is a really useful function. This proves the std library would benefit from it but itās also going to be difficult to introduce this now because itās going to collide with the downstream implementations.
What would it take to get this moved into the next epoch?
As I understand it there are no plans around how it would be possible to have varying APIs across epochs yet, from the epoch RFC:
More generally, breaking changes to the standard library are not possible.
So I guess the standard library probably just isnāt ever going to have a clamp function.
Considering how breakage around Ord::{min, max}
are resolved, the clamp
function will likely stay.
Having been hit by min/max breakage, Iād vote to not repeat that.
I donāt know if this is within my permissions or not but Iād like to run crater to see how this actually impacts downstream, and how that compares to the impact from min/max. Iāll probably do that sometime this weekend.
FWIW, thereās also num_traits::clamp
(aka num::clamp
) for any PartialOrd
type. Since this is a standalone function, it wonāt conflict with having clamp
methods on any type or trait.
Yeah I wrote that one too. It works I just think something like this could also do well in the standard library. Improvements have been made to the idea for the std library version as well. I guess at the end of the day itās not critical this make it to stable because it is already in num, I just wanted the idea to be more discoverable.
Ha! Sorry, I should have looked back to see who wrote that.
Nah youāre fine. Itās been 6 months. Both versions were initially authored sometime in February/March.
Time for num to merge: 2 days
Time for rustc to merge: 6 months.
So yeah the crate ecosystem definitely works.
Iām not always so fast with num, but yeah, generally crates have fewer constraints and can be more agile.
Pinging @aturon. Iām not really sure how we should proceed here and ultimately itās not really my decision to make anyways. You merged the PR originally, should we revert it?
@Xaeroxe, I will bring it to the libs team ASAP.
The clamp
implementation has been reverted by https://github.com/rust-lang/rust/pull/44438 today. What will be necessary steps to bring this back in the future?
Make a rule when an inference failure is considered XIB (expected-impl-breakage) (like {f32, f64}::from_bits
), and when is it unacceptable (like clamp
here).
Currently type inference change is considered acceptable by RFCs 1105 and 1122 as one could always use UFCS or other ways to force a type. But since the first try of T += &T
was closed, clamp
is reverted, and given the churn caused by PR #42496 (Ord::{min, max}
) there are clearly something that cannot be disregarded as XIB.
Whenever we add a method to a std trait, there should be a crater run to ensure the name is not already existing.
When downstream crate did not specify #![feature(clamp)]
, the candidate Ord::clamp
should never be considered (a future-compatible warning can still be issued). This will allow introduction of new trait methods not āinsta-breakingā, but the problem will still come back when stabilizing.