3 ms·
> Compute the sign of an integer > On the other hand, if you prefer the result be either -1, 0, or +1, then use: > sign = (v != 0) | -(int)((unsigned int)((i
by mike_hock 2y ago
> Compute the sign of an integer
> On the other hand, if you prefer the result be either -1, 0, or +1, then use:
> sign = (v != 0) | -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
> // Or, for more speed but less portability:
> sign = (v != 0) | (v >> (sizeof(int) * CHAR_BIT - 1)); // -1, 0, or +1
> // Or, for portability, brevity, and (perhaps) speed:
> sign = (v > 0) - (v < 0); // -1, 0, or +1
Or if you prefer portability, speed, and readability at the same time:
int sign(int i) {
if(i > 0)
return 1;
else if(i < 0)
return -1;
else
return 0;
}
gets compiled to
mov ecx, edi
sar ecx, 31
test edi, edi
mov eax, 1
cmovle eax, ecx
ret
which is the bit shift hack.
(still useful as a reference for implementing an optimizer, to be read as pseudo code)
- jimbobthrowawy 2y agoI think a bunch of compilers nowadays are smart enough to see these kinds of hacks and compile them to an equivalent on the target that runs best. Favourite example of this is writing a duff's device to unroll a loop, and then gcc completely ignores it and replaces it with a vectorised loop.