I'm trying to find an efficient way to check if an integer is zero without jumping.
I have two integer variables in and out. If in is zero, I want out to be zero. If in is not zero, I want out to be one.
If it may help, I know that in will be zero or a power of two (only one set bit). I also know that the most significant and the less significant bits are never set.
I could do the obvious : out = (in == 0 ? 0 : 1); But that implies a jump which is costly.
I could do something like this out = (in * 0xFFFFFFFF) >> 63;. This implies a multiplication and shift that I would like to avoid, but I can't find a way. Maybe it's not possible.
Any other way I could do this without jump and only using bit-wise operators and arithmetic?
Thanks
This will differ with architecture but the code doesn't compile to a jump on Intel CPUs.
This code:
int square(int in) {
int out = (in != 0);
return out;
}
is compiled to:
square(int):
xor eax, eax
test edi, edi
setne al
ret
or:
square, COMDAT PROC
xor eax, eax
test ecx, ecx
setne al
ret 0
square ENDP
by msvc, clang and gcc with O2:
It is only a jump with no optimization which you would never do anyway.
I've also found the need to do this, to index a length-2 array at 0 for zero values and 1 for non-zero values.
Cast the int to bool, and then back to int. This does not jump on almost every compiler I've tried (gcc, clang, recent MSVC) except MSVC pre-2018. I recommend you check the assembly code to make sure on your platform.
int one_if_nonzero_else_zero(int value) { return (bool) value; }
EDIT: This does not satisfy your constraint "only using bit-wise operators and arithmetic" but this cast takes advantage of assembly optimization and will be very efficient.
EDIT: Your "obvious" solution out = (in == 0 ? 0 : 1); results in identical assembly code as solutions posted by Jerry Jeremiah and myself on gcc, clang, and msvc. No jump after optimization! I suggest you use it for clarity.
I have two integer variables
inandout. Ifinis zero, I wantoutto be zero. Ifinis not zero, I wantoutto be one.
Try this:
int in = ...;
int out = !!in;
C++ has an implicit conversion defined from int to bool, so in as a bool will be false when in is 0, and will be true otherwise.
Then !false will be true, and !true will be false.
Then !true will be false, and !false will be true.
Then there is also an implicit conversion defined from bool to int, so true as an int will be 1, and false will be 0.
Thus, out will be 0 when in is 0, and will be 1 otherwise.
User contributions licensed under CC BY-SA 3.0