-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Tracking issue for RFC 2169: Euclidean Modulo #49048
Comments
@fanzier had expressed interest in implementing this RFC as a good starter issue (most of the details are included in the RFC), so I'd be happy to mentor this issue if they want to tackle it! |
A question came up in the initial implementation PR about shifting the euclidean modulo methods for |
|
@sdroege See conversations in the RFC, such as rust-lang/rfcs#2169 (comment) |
@huonw made this argument for a longer name, which I find convincing:
|
@sdroege, @lfairy: I think the plan was to take another look at the method names during the FCP for these methods (which won't be for a while at least) — because there was some disagreement about what to prioritise for the naming here. With some actual usage statistics, it might be easier to form arguments one way or the other. |
Just my 2c: the suffix |
There is an issue about the future compatibility lint of this: #50232 |
@pietroalbini: I think that was an issue about the lint in general, rather than specifically about |
I really like the short name (I've been using this function a lot in my code, also had named it |
I didn't follow the original RFC, but I think that the methods should be |
Another thing to note: while it has been mentioned before that having a Although I don't know how far down the rabbit hole we'd want to go with that, considering how adding every combination of |
Regarding terminology, I believe that |
@demurgos Haskell uses the distinction quot/rem for the Euclidean versions and div/mod for the non-euclidean versions. I personally don't like this distinction and find it hard to remember, which is why I accept Rust's decision to simply append But if we're going to change rem to mod and not div to quot, that seems too odd to me. And besides, the ship has sailed and Rust is stuck with |
Also, I messed around with the code and let (q, r) = (self / rhs, self % rhs);
if r < 0 {
if rhs > 0 {
(q - 1, r - rhs)
} else {
(q + 1, r + rhs)
}
} else {
(q, r)
} versus the existing: let q = self / rhs;
let q = if self % rhs < 0 {
if rhs > 0 { q - 1 } else { q + 1 }
} else {
q
};
let r = self % rhs;
let r = if r < 0 {
if rhs < 0 {
r - rhs
} else {
r + rhs
}
} else {
r
};
(q, r) And I haven't run any benchmarks, but it seems pretty clear that even if LLVM can combine the existing division and remainder into one operation, it probably won't be smart enough to combine the branches. But, if we can write the latter in a way that optimises to the former, I think it'd be reasonable to say that a divrem method isn't necessary. |
I don't think it should be hard for LLVM to find the common subexpressions. In fact, I get the same assembly for pub fn div_mod_euc(lhs: i32, rhs: i32) -> (i32, i32) {
let (q, r) = (lhs / rhs, lhs % rhs);
if r < 0 {
if rhs > 0 {
(q - 1, r - rhs)
} else {
(q + 1, r + rhs)
}
} else {
(q, r)
}
} pub fn separate_div_mod_euc(lhs: i32, rhs: i32) -> (i32, i32) {
(div_euc(lhs, rhs), mod_euc(lhs, rhs))
}
pub fn div_euc(lhs: i32, rhs: i32) -> i32 {
let (q, r) = (lhs / rhs, lhs % rhs);
if r < 0 {
if rhs > 0 {
q - 1
} else {
q + 1
}
} else {
q
}
}
pub fn mod_euc(lhs: i32, rhs: i32) -> i32 {
let r = lhs % rhs;
if r < 0 {
if rhs > 0 {
r - rhs
} else {
r + rhs
}
} else {
r
}
} |
Even though it can be annoying to have to remember the distinction, it's more helpful to follow convention and at least be unambiguous than mix terminology confusingly. Rust originally used
I was under the impression LLVM doesn't optimise this as much as it could, but I haven't checked in a while, so that may be outdated. I think it could be worth having a dedicated method for this, and it's worth proposing (it wasn't part of the original RFC just to avoid too much bloat).
Yeah, this method propagation is unfortunate, and it's unclear how to completely avoid it. Maybe just by adding the simplest methods first and then adding the others if/when people request them? |
I would like to work on stabilizing this. One question: would it be stable since 1.27.1 or the next version? |
You should use the current nightly version when stabilizing (at the moment 1.29.0). |
OK, thanks! I'll open a PR soon. |
I've closed my PR because there is still discussion about naming the functions. |
@clarcharr do you think you could elaborate on your concerns in #52547 (comment)? It seems to me that the consensus in the general programming community is for There's was already quite a bit of discussion in rust-lang/rfcs#2169 that came up with the current names, |
@demurgos This is not a "mod operation", mathematically, this is a remainder operation. "mod operation" doesn't make sense - modular arithmetic is about equivalences, not operators.
Notably, also - |
Also, the names are too short - |
There is such a thing as a mod(ulo) operation. It's analogous to modular arithmetic, but it's a distinct concept.
This is exactly the point under discussion. Personally, I find the full |
@varkor note the first paragraph - "In computing, the modulo operation". Note also the ambiguity around sign - calling it "modulo" doesn't make it positive. Remainder is what the rest of the ecosystem calls it, we should continue calling it remainder. @daboross Afaict, only languages like Haskell make this distinction - C still calls it the modulo operator, but |
I'm not sure why the mathematics versus programming distinction should be made, but even then, the definition for programming languages seems like the most appropriate anyway. As you say, the precise definition is language-specific anyway, but:
Rust chose the name "remainder" specifically because it produced negative results for negative dividends. This is either described in the commit history or the mailing list, but I don't have time to dig it up right now. (If I recall correctly, it used to be called "modulo" until it was changed for this reason.) |
@varkor that doesn't change the fact that even in CS, "mod" does not imply positive. It's only used that way, afaict, in Haskell - other languages use You'll note, for example, that C++'s |
I personally think that As far as the distinction between "modulo" and "remainder," I feel like the most important distinction is that Rust currently uses "rem" to refer to the remainder of truncated division, rather than "mod." Because So to clarify, I think we should name the methods to That way, we have truncated division + remainder and Euclidean divison + remainder, rather than truncated division + remainder and Euclidean division + modulo. |
Side note-- I really think that Rust should have somewhere in the documentation for |
Can I fix the names of these functions? Will that be accepted? |
rename div_euc -> div_euclid, and mod_euc -> rem_euclid logic is written up in rust-lang#49048 Also, update the documentation slightly. cc @alexcrichton @clarcharr @varkor
rename div_euc -> div_euclid, and mod_euc -> rem_euclid logic is written up in rust-lang#49048 Also, update the documentation slightly. cc @alexcrichton @clarcharr @varkor
What about a modulus operator, perhaps
The rule is that the output wraps around the second argument on a range |
I just noticed that the naming discussion is not closed (my build failed due to the renaming), so here are my 2 cents:
I agree with the choice of |
I think as of #56936, consensus was reached.
As mentioned in the RFC, flooring division/modulo is different from Euclidean division/modulo (as described in this paper), which is why the name was chosen. I'd rather avoid any more bikeshedding and put the functions forward for stabilisation. |
Ah, I see, I missed that it behaves differently for negative divisors. |
This required a fair bit of faffing, and I'm not completely sure I know what I'm really doing with the boxing. However! My first polymorphism and traits. I should probably read the book properly, but who's got time for that. Some fun also since rust modulo arithmetic seems to be non-intuitive, and the euclidean versions aren't stable yet. https://github.com/rust-lang/rfcs/blob/master/text/2169-euclidean-modulo.md rust-lang/rust#49048
I think this is a good candidate for stabilization? Could any one propose a fcp for it? @SimonSapin @alexcrichton |
@crlf0710 you can just file a PR for stabilization, should speed up the process. |
…ntril Stablize Euclidean Modulo (feature euclidean_division) Closes rust-lang#49048
Is there a trait for |
I don't think so. The general policy for |
Tracking issue for rust-lang/rfcs#2169, euclidean modulo methods on numbers
Steps:
The text was updated successfully, but these errors were encountered: