When bitwise and & operation is greater or equal to bitwise xor ^ operation? - bit-manipulation

When bitwise & operation is greater or equal to bitwise ^ operation?
For example, 4&7 >= 4^7 is true.
How do we know when it will be true?
The one way is to do manually what will be hidden trick?

If we just talk about the set bits. This condition will be true when the highest common set bit is also the highest set bit in each of the numbers.
Why? Because when the highest set bit in both numbers is also a common bit, then that bit will be set in the result of the AND operation. And it will not be set in the result of the XOR operation.
And if the highest set bit in the largest number is not also set in the lower number, then necessarily that bit will be set in the XOR operation and not set in the AND operation.

You can create a quick String image like so:
for i in 1...25 {
var foo = ""
for j in 1...25 {
foo += i&j >= i^j ? "•" : " "
}
print(foo)
}
•
••
••
••••
••••
••••
••••
••••••••
••••••••
••••••••
••••••••
••••••••
••••••••
••••••••
••••••••
••••••••••
••••••••••
••••••••••
••••••••••
••••••••••
••••••••••
••••••••••
••••••••••
••••••••••
••••••••••
Notice how the squares are growing quadratically.
From this you can see that when i == j == true it always returns true.

Related

Why is a bit-wise AND necessary to check if a bit is set?

I am learning a backtrack problem with memoization using bit-mask.
When checking if the i'th bit is set in a bit-mask, all the solutions I have come across are doing (mask >> i) & 1. I was wondering, why is the & 1 necessary? Isn't (mask >> i) a 1 when the i'th bit is set, and a 0 when the bit is not set? That already translate into true and false.
(mask >> i) cannot eliminate the higher bits.
For example, when mask = 5 (101 in binary) and i = 1, the value of (mask >> i) is 2. This evaluated as true, but the 2nd lowest bit is 0, so you fail to check the bit correctly.
Therefore, & 1 is necessary to eliminate the higher bits and check one specified bit correctly.
For example, if you want to check bit 0 for the mask 0b10 then the expression mask >> 0 yields the same value 0b10, that is not equal to 0. However, its bit 0 is equal to 0. So you need to write ( mask >> 0 ) & 1, or in general ( mask >> i ) & 1.
That is, higher bits that precede the i-th bit can be 1. Thus the expression mask >> i does not change their values. So the value of the expression can be unequal to 0 though the i-th bit itself is equal to 0.
The expression (mask >> i) keeps all the bits from the i-th. That means, if either the i-th, (i+1)-th, etc. is set, then it'll evaluate to true in an if-expression.

Comparing the Most Significant Bit of two numbers: ==, <, <=

Is there a quick bit operation to implement msb_equal: a function to check if two numbers have the same most significant bit?
For example, 0b000100 and 0b000111 both have 4 as their most significant bit value, so they are most msb_equal. In contrast 0b001111 has 8 as the MSB value, and 0b010000 has 16 as it's MSB value, so the pair are not msb_equal.
Similarly, are there fast ways to compute <, and <=?
Examples:
msb_equal(0, 0) => true
msb_equal(2, 3) => true
msb_equal(0, 1) => false
msb_equal(1, 2) => false
msb_equal(3, 4) => false
msb_equal(128, 255) => true
A comment asks why 0 and 1 are not msb_equal. My view on this is that if I write out two numbers in binary, they are msb_equal when the most significant 1 bit in each is the same bit.
Writing out 2 & 3:
2 == b0010
3 == b0011
In this case, the top most 1 is the same in each number
Writing out 1 & 0:
1 == b0001
0 == b0000
Here, the top most 1s are not the same.
It could be said that as 0 has no top most set bit, msb_equal(0,0) is ambiguous. I'm defining it as true: I feel this is helpful and consistent.
Yes, there are fast bit based operations to compute MSB equality and inequalities.
Note on syntax
I'll provide implementations using c language syntax for bitwise and logical operators:
| – bitwise OR. || – logical OR.
& – bitwise AND. && – logical AND.
^ – bitwise XOR.
==
msb_equal(l, r) -> bool
{
return (l^r) <= (l&r)
}
<
This is taken from the Wikipedia page on the Z Order Curve (which is awesome):
msb_less_than(l, r) -> bool
{
(l < r) && (l < l^r)
}
<=
msb_less_than_equal(l, r) -> bool
{
(l < r) || (l^r <= l&r)
}
If you know which number is the smallest/biggest one, there is a very fast way to check whether the MSBs are equal. The following code is written in C:
bool msb_equal(unsigned small, unsigned big) {
assert(small <= big);
return (small ^ big) <= small;
}
This can be useful in cases like when you add numbers to a variable and you want to know when you reached a new power of 2.
Explanation
The trick here is that if the two numbers have the same most significant bit, it will disappear since 1 xor 1 is 0; that makes the xor result smaller than both numbers. If they have different most significant bits, the biggest number's MSB will remain because the smallest number has a 0 in that place and therefore the xor result will be bigger than the smallest number.
When both input numbers are 0, the xor result will be 0 and the function will return true. If you want 0 and 0 to count as having different MSBs then you can replace <= with <.

Please explain in detail the logic behind the output of x &(~0 << n)

I have doubt in logic behind x &(~0 <<n).
First of all I could not get the meaning of ~0. When I tried this in Java it showed -1. How
can we represent -1 in binary and differentiate it from the positive numbers?
The most common way (and the way that Java uses) to represent negative numbers, is called Two's Complement. As mentioned in my comment, one way to calculate the negative in this system is -x = ~(x - 1). An other, equivalent way, is -x = ~x + 1.
For example, in 8bit,
00000001 // 1
00000000 // 1 - 1
11111111 // ~(1 - 1) = ~0 = -1
Adding one to 11111111 would wrap to zero - it makes sense to call "the number such that adding one to it result in zero" minus one.
The numbers with the highest bit set are regarded as negative.
The wikipedia article I linked to contains more information.
As for x & (~0 << n), ~0 is just a way to represent "all ones" (which also happens to be -1, which is irrelevant for this use really). For most n, "all ones" shifted left by n is a bunch of ones followed by n zeroes.
In total, that expression clears the lower n bits of x.
At least, for 0 <= n <= 31.
a << n in Java, where a is an int, is equivalent to a << (n & 31).
Every bit of the byte 0 is 0, and every bit of -1 is 1, so the bitwise negation of 0 is -1.
Hence ~0 is -1.
As for the rest of the question: what are you actually asking?

How is this size alignment working

I am not able to understand the below code with respect to the comment provided. What does this code does, and what would be the equivalent code for 8-aligned?
/* segment size must be 4-aligned */
attr->options.ssize &= ~3;
Here, ssize is of unsigned int type.
Since 4 in binary is 100, any value aligned to 4-byte boundaries (i.e. a multiple of 4) will have the last two bits set to zero.
3 in binary is 11, and ~3 is the bitwise negation of those bits, i.e., ...1111100. Performing a bitwise AND with that value will keep every bit the same, except the last two which will be cleared (bit & 1 == bit, and bit & 0 == 0). This gives us a the next lower or equal value that is a multiple of 4.
To do the same operation for 8 (1000 in binary), we need to clear out the lowest three bits. We can do that with the bitwise negation of the binary 111, i.e., ~7.
All powers of two (1, 2, 4, 8, 16, 32...) can be aligned by simple a and operation.
This gives the size rounded down:
size &= ~(alignment - 1);
or if you want to round up:
size = (size + alignment-1) & ~(alignment-1);
The "alignment-1", as long as it's a value that is a power of two, will give you "all ones" up to the bit just under the power of two. ~ inverts all the bits, so you get ones for zeros and zeros for ones.
You can check that something is a power of two by:
bool power_of_two = !(alignment & (alignment-1))
This works because, for example 4:
4 = 00000100
4-1 = 00000011
& --------
0 = 00000000
or for 16:
16 = 00010000
16-1 = 00001111
& --------
0 = 00000000
If we use 5 instead:
5 = 00000101
4-1 = 00000100
& --------
4 = 00000100
So not a power of two!
Perhaps more understandable comment would be
/* make segment size 4-aligned
by zeroing two least significant bits,
effectively rounding down */
Then at least for me, immediate question pops to my mind: should it really be rounded down, when it is size? Wouldn't rounding up be more appropriate:
attr->options.ssize = (attr->options.ssize + 3) & ~3;
As already said in other answers, to make it 8-aligned, 3 bits need to be zeroed, so use 7 instead of 3. So, we might make it into a function:
unsigned size_align(unsigned size, unsigned bit_count_to_zero)
{
unsigned bits = (1 << bit_count_to_zero) - 1;
return (size + bits) & ~bits;
}
~3 is the bit pattern ...111100. When you do a bitwise AND with that pattern, it clears the bottom two bits, i.e. rounds down to the nearest multiple of 4.
~7 does the same thing for 8-aligned.
The code ensures the bottom two bits of ssize are cleared, guaranteeing that ssize is a multiple of 4. Equivalent code for 8-aligned would be
attr->options.ssize &= ~7;
number = number & ~3
The number is rounded off to the nearest multiple of 4 that is lesser than number
Ex:
if number is 0,1,2 or 3, the `number` is rounded off to 0
similarly if number is 4,5,6,or 7,numberis rounded off to 4
But if this is related to memory alignment, the memory must be aligned upwards and not downwards.

Detecting two numbers with same/matching bit pattern in their lower order bits

We've two numbers with same bit patterns in their lower order.
For ex: 01001110110 and 10110 are the two numbers, they match with their lower order.
Is there a simple way to find this out ?
I've a solution with shifting the bits and then comparing, Is there a better way ?
You can XOR them together and check if the last N lower order bits are all zero (where N is the number of bits in the smaller of the two numbers).
For eg: using the sample numbers you gave, 01001110110 and 10110:
01001110110 XOR 10110 = 01001100000
Notice that the last 5 bits are all zero in the result.
In C/C++/Java you can use the ^ operator for this purpose and then extract the last N bits with a mask like so:
int a = 0x276; // 01001110110
int b = 0x16; // 10110
if (((a ^ b) & 0x1F) == 0) { // Mask 0x1F assumes least significant 5 bits for match
// match!
}
If course, this assumes you know the number of significant bits in each number (5 in this example). If instead the number of matching bits is unspecified, you will need to count the number of consecutive trailing 0s to figure out how many bits match. There may be some other trickery you could perform in this case.
Mask the numbers with &:
if (number1 & 0x1f == number2 & 0x1f)