Reputation: 49
Using only:
<< >> | ^ & +
How can I make a function that is equivalent to the logical not operator (!
)?
Right now I have:
int i = (~x + 1) >> 31;
int j = (x + 1) >> 31;
i = i | j;
i = i & 1;
return i ^ 1;
It works for everything, but -1
.
Upvotes: 4
Views: 5196
Reputation: 87406
I will assume that you are working with int
s that are 32-bit, signed, and use 2's complement notation. The unique thing about the number 0 is that neither 0 nor its negation have a 1 for the sign bits. This code would work if you were allowed to use the negation operator (-):
int not(int x)
{
return (-x | x) >> 31 & 1 ^ 1;
}
You can't use minus, but that is ok because for all x we know that -x
is equal to ~x + 1
which is equal to (x ^ -1) + 1
. That's how 2's complement notation works. So the final answer is:
int not(int x)
{
return ( (x^-1)+1 | x ) >> 31 & 1 ^ 1;
}
EDIT 1: Ok, here is the "ANSI" version of the function that makes no assumption about the size of the int and does not rely on the undefined behavior of right-shifting a signed int. It works for me in MinGW:
int not(int x)
{
unsigned int y = x;
return (( ((y^-1)+1) | y ) >> (sizeof(x)*8-1)) ^ 1;
}
Upvotes: 3
Reputation: 27201
Kind of 'cheating', but:
bool logicalNot(int i)
{
return((bool)i ^ true);
}
I'm assuming there's nothing in the rules about composition of functions/typecasting/implicit type conversions?
Upvotes: 0
Reputation: 9480
Assuming that x is a 32-bit unsigned value:
x = x | (x >> 1)
x = x | (x >> 2)
x = x | (x >> 4)
x = x | (x >> 8)
x = x | (x >> 16)
At this point, if x was 0 then it's still 0. If it had a non-zero value, it now has the bit pattern 111....111.
With a two-complement representation, you can now simply add 1 and get the desired result:
x = x + 1
This solution assumes quite a bit about integer representation, types, etc.
(The "code" above is not valid C code, of course).
Upvotes: 0