4 ms·
I am sorry, I am missing something here... are you saying that you are using a smaller type "int" so that it wraps sooner? AFAIK, the compiler is going to use t
by saurik 2y ago
I am sorry, I am missing something here... are you saying that you are using a smaller type "int" so that it wraps sooner? AFAIK, the compiler is going to use the fact that wrap is undefined to promote that int to a native type and make it not wrap until the same place ssize_t would!
OK, and yeah: based on your godbolt example, I do feel like you still don't understand all the ramifications, as you are relying on a bunch of undefined behavior to make your loop sort of work just because you want to avoid working with field arithmetic. Fixing the code is just as fast:
int f(unsigned long n)
{
int sum = 0;
for (unsigned long k = n; k != n + 4; ++k)
sum += k;
return sum;
}
f(unsigned long):
lea eax, [6+rdi*4]
ret
(Of course this is still a bit awkward, as this function should also clearly return an unsigned long. I am just trying to show you the minimal patch to the loop to demonstrate why you aren't buying anything... there is no benefit to this quirk of the compiler: please fix the code.)
(edit: BTW, I just looked at your about, and the fact that you are or were on the C WG is demoralizing, as I'd have thought this kind of confusion would be reason to rid this behavior from the spec... but C developers really seem to love doing signed inequalities on field elements :/.)
- uecker 2y agoYes, I want "int" to wrap sooner, except not that it wraps but to get an error message to find the bug. Your use of the term "field" might indicate that you are confused a bit. That you can rewrite the example seems irrelevant to the point.
- saurik 2y agoBut using int doesn't wrap sooner or cause any errors at all, because it is automatically promoted to the native size due to this all being undefined behavior. Your example even directly demonstrates that, as the code had no chance of erroring in any way as it just returned the sum directly... the sum is even overflowing the int it is being stored into, that's how crazy the behavior of the code you wrote is. And like, in addition to undermining your argument, that is also distressing, right? The code you wrote can be interpreted in a ton of different ways and the only reason the fast one makes any sense is if you squint hard enough so as to lose the details of the sizes and behaviors of all of the types that were declared... if you actually had to make the wrapping or errors you wish to see happen you'd have to have the slow code. In contrast, the code using a native-sized unsigned type and != means only one thing, and that one thing is the fast code you said wanted to get... that makes it the correct code. It isn't optimized to that code due to undefined behavior: mathematically that lea multiplication is identical, and if you simulated all of the steps--including the wrap (and if we fixed the output type, the truncation)--you'd always get that result. (And the reason I keep using the term "field" is because these types are elements of a modular finite field, and once you see them for what they are it becomes a lot easier to write correct code using them. There are even some modern languages where the native algebraic type is an element of a prime field, at which point confusing it for some kind of integer is extremely problematic.)
- uecker 2y agoLet's start with something simple: Those types are not fields but quotient rings. If you have learned enough math to understand this, please come back.