Calculation of Bit wise NOT - c

How to calculate ~a manually? I am seeing these types of questions very often.
#include <stdio.h>
int main()
{
unsigned int a = 10;
a = ~a;
printf("%d\n", a);
}

The result of the ~ operator is the bitwise complement of its (promoted) operand
C11dr §6.5.3.3
When used with unsigned, it is sufficient to mimic ~ with exclusive-or with UINT_MAX which is the same type and value as (unsigned) -1. #EOF
unsigned int a = 10;
// a = ~a;
a ^= -1;

You could XOR it with a bitmask of all 1's.
unsigned int a = 10, mask = 0xFFFFFFFF;
a = a ^ mask;
This is assuming of course that an int is 32 bits. That's why it makes more sense to just use ~.

Just convert the number to binary form, and change '1' by '0' and '0' by '1'.
That is:
10 (decimal)
Converted to binary (32 bits as usual in an int) gives us:
0000 0000 0000 0000 0000 0000 0000 1010
Then apply the ~ operator:
1111 1111 1111 1111 1111 1111 1111 0101
Now you have a number that could be interpreted as an unsigned 32 bit number, or signed one. As you are using %d in your printf and a is an int, signed it is.
To find out the value in decimal from a signed (2-complement) number do as this:
If the most significant bit (the leftmost) is 0, then just convert back the binary number to decimal as usual.
if the most significant bit is 1 (our case here), then change '1' by '0' and '0' by '1', add '1' and convert to decimal prepending a minus sign to the result.
So it is:
1111 1111 1111 1111 1111 1111 1111 0101
^
|
Its most significant bit is 1, so first we change 0 and 1
0000 0000 0000 0000 0000 0000 0000 1010
And then, we add 1
0000 0000 0000 0000 0000 0000 0000 1010
1
---------------------------------------
0000 0000 0000 0000 0000 0000 0000 1011
Take this number and convert back to decimal prepending a minus sign to the result. The converted value is 11. With the minus sign, is -11

This function shows the binary representation of an int and swaps the 0's and 1's:
void not(unsigned int x)
{
int i;
for(i=(sizeof(int)*8)-1; i>=0; i--)
(x&(1u<<i))?putchar('0'):putchar('1');
printf("\n");
}
Source: https://en.wikipedia.org/wiki/Bitwise_operations_in_C#Right_shift_.3E.3E

Related

Decide if X is at most half as long as Y, in binary, for unsigned ints in C

I have two unsigned ints X and Y, and I want to efficiently decide if X is at most half as long as Y, where the length of X is k+1, where 2^k is the largest power of 2 that is no larger than X.
i.e., X=0000 0101 has length 3, Y=0111 0000 is more than twice as long as X.
Obviously we can check by looking at individual bits in X and Y, for example by shifting right and counting in a loop, but is there an efficient, bit-twiddling (and loop-less) solution?
The (toy) motivation comes from the fact that I want to divide the range RAND_MAX either into range buckets or RAND_MAX/range buckets, plus some remainder, and I prefer use the larger number of buckets. If range is (approximately) at most the square root of RAND_MAX (i.e., at most half as long), than I prefer using RAND_MAX/range buckets, and otherwise I want to use range buckets.
It should be noted, therefore, that X and Y might be large, where possibly Y=1111 1111, in the 8-bit example above. We certainly don't want to square X.
Edit, post-answer: The answer below mentions the built-in count leading zeros function (__builtin_clz()), and that is probably the fastest way to compute the answer. If for some reason this is unavailable, the lengths of X and Y can be obtained through some well-known bit twiddling.
First, smear the bits of X to the right (filling X with 1s except its leading 0s), and then do a population count. Both of these operations involve O(log k) operations, where k is the number of bits that X occupies in memory (my examples are for uint32_t, 32 bit unsigned integers). There are various implementations, but I put the ones that are easiest to understand below:
//smear
x = x | x>>1;
x = x | x>>2;
x = x | x>>4;
x = x | x>>8;
x = x | x>>16;
//population count
x = ( x & 0x55555555 ) + ( (x >> 1 ) & 0x55555555 );
x = ( x & 0x33333333 ) + ( (x >> 2 ) & 0x33333333 );
x = ( x & 0x0F0F0F0F ) + ( (x >> 4 ) & 0x0F0F0F0F );
x = ( x & 0x00FF00FF ) + ( (x >> 8 ) & 0x00FF00FF );
x = ( x & 0x0000FFFF ) + ( (x >> 16) & 0x0000FFFF );
The idea behind the population count is to divide and conquer. For example with
01 11, I first count the 1-bits in 01: there is 1 1-bit on the right, and
there are 0 1-bits on the left, so I record that as 01 (in place). Similarly,
11 becomes 10, so the updated bit-string is 01 10, and now I will add the
numbers in buckets of size 2, and replace the pair of them with the result;
1+2=3, so the bit string becomes 0011, and we are done. The original
bit-string is replaced with the population count.
There are faster ways to do the pop count given in Hacker's Delight, but this
one is easier to explain, and seems to be the basis for most of the others. You
can get my code as a
Gist here..
X=0000 0000 0111 1111 1000 1010 0010 0100
Set every bit that is 1 place to the right of a 1
0000 0000 0111 1111 1100 1111 0011 0110
Set every bit that is 2 places to the right of a 1
0000 0000 0111 1111 1111 1111 1111 1111
Set every bit that is 4 places to the right of a 1
0000 0000 0111 1111 1111 1111 1111 1111
Set every bit that is 8 places to the right of a 1
0000 0000 0111 1111 1111 1111 1111 1111
Set every bit that is 16 places to the right of a 1
0000 0000 0111 1111 1111 1111 1111 1111
Accumulate pop counts of bit buckets size 2
0000 0000 0110 1010 1010 1010 1010 1010
Accumulate pop counts of bit buckets size 4
0000 0000 0011 0100 0100 0100 0100 0100
Accumulate pop counts of bit buckets size 8
0000 0000 0000 0111 0000 1000 0000 1000
Accumulate pop counts of bit buckets size 16
0000 0000 0000 0111 0000 0000 0001 0000
Accumulate pop counts of bit buckets size 32
0000 0000 0000 0000 0000 0000 0001 0111
The length of 8358436 is 23 bits
Y=0000 0000 0000 0000 0011 0000 1010 1111
Set every bit that is 1 place to the right of a 1
0000 0000 0000 0000 0011 1000 1111 1111
Set every bit that is 2 places to the right of a 1
0000 0000 0000 0000 0011 1110 1111 1111
Set every bit that is 4 places to the right of a 1
0000 0000 0000 0000 0011 1111 1111 1111
Set every bit that is 8 places to the right of a 1
0000 0000 0000 0000 0011 1111 1111 1111
Set every bit that is 16 places to the right of a 1
0000 0000 0000 0000 0011 1111 1111 1111
Accumulate pop counts of bit buckets size 2
0000 0000 0000 0000 0010 1010 1010 1010
Accumulate pop counts of bit buckets size 4
0000 0000 0000 0000 0010 0100 0100 0100
Accumulate pop counts of bit buckets size 8
0000 0000 0000 0000 0000 0110 0000 1000
Accumulate pop counts of bit buckets size 16
0000 0000 0000 0000 0000 0000 0000 1110
Accumulate pop counts of bit buckets size 32
0000 0000 0000 0000 0000 0000 0000 1110
The length of 12463 is 14 bits
So now I know that 12463 is significantly larger than the square root of
8358436, without taking square roots, or casting to floats, or dividing or
multiplying.
See also
Stackoverflow
and Haacker's Delight (it's
a book, of course, but I linked to some snippets on their website).
If you are dealing with unsigned int and sizeof(unsigned long long) >= sizeof(unsigned int), you can just use the square method after casting:
(unsigned long long)X * (unsigned long long)X <= (unsigned long long)Y
If not, you can still use the square method if X is less than the square root of UINT_MAX+1, which you may need to hard code in the function.
Otherwise, you could use floating point calculation:
sqrt((double)Y) >= (double)X
On modern CPUs, this would be quite fast anyway.
If you are OK with gcc extensions, you can use __builtin_clz() to compute the length of X and Y:
int length_of_X = X ? sizeof(X) * CHAR_BIT - __builtin_clz(X) : 0;
int length_of_Y = Y ? sizeof(Y) * CHAR_BIT - __builtin_clz(Y) : 0;
return length_of_X * 2 <= length_of_Y;
__buitin_clz() compiles to a single instruction on modern Intel CPUs.
Here is a discussion on more portable ways to count leading zeroes you could use to implement your length function: Counting leading zeros in a 32 bit unsigned integer with best algorithm in C programming or this one: Implementation of __builtin_clz

Bitwise addition of opposite signs

int main(){
int a = 10, b = -2;
printf("\n %d \n",a^b);
return 0;
}
This program outputs -12. I could not understand how. Please explain.
0111 1110 -> 2's complement of -2
0000 1010 -> 10
---------
0111 0100
This no seems to be greater than -12 and is +ve. But how did I get the o/p as -12 ?
To find the two's complement of a negative integer, first find the binary representation of its magnitude. Then flip all its bits, i.e., apply the bitwise NOT operator !. Then add 1 to it. Therefore, we have
2 --> 0000 0000 0000 0010
~2 --> 1111 1111 1111 1101 // flip all the bits
~2 + 1 --> 1111 1111 1111 1110 // add 1
Therefore, the binary representation of -2 in two's complement is
1111 1111 1111 1110
Now, assuming the size of int is 4, the representation of a and b in two's complement is -
a --> 0000 0000 0000 1010 --> 10
b --> 1111 1111 1111 1110 --> -2
a^b --> 1111 1111 1111 0100 --> -12
The operator ^ is the bitwise XOR, or exclusive OR operator. If operates on the corresponding bits of a and b and evaluates to 1 only when the bits are not both 0 or both 1, else it evaluate to 0.
Seems legit!
1111 1110 (-2)
xor
0000 1010 (10)
=
1111 0100 (-12)
^ is the bitwise XOR, not power
a = 10 = 0000 1010
b = -2 = 1111 1110
──────────────────
a^b = 1111 0100 = -12
(int) -2 = 0xfffffffe
(int) 10 = 0x0000000a
0xfffffffe ^ 0x0000000a = fffffff4 = (int) -12

bitwise operations in c explanation

I have the following code in c:
unsigned int a = 60; /* 60 = 0011 1100 */
int c = 0;
c = ~a; /*-61 = 1100 0011 */
printf("c = ~a = %d\n", c );
c = a << 2; /* 240 = 1111 0000 */
printf("c = a << 2 = %d\n", c );
The first output is -61 while the second one is 240. Why the first printf computes the two's complement of 1100 0011 while the second one just converts 1111 0000 to its decimal equivalent?
You have assumed that an int is only 8 bits wide. This is probably not the case on your system, which is likely to use 16 or 32 bits for int.
In the first example, all the bits are inverted. This is actually a straight inversion, not two's complement:
1111 1111 1111 1111 1111 1111 1100 0011 (32-bit)
1111 1111 1100 0011 (16-bit)
In the second example, when you shift it left by 2, the highest-order bit is still zero. You have misled yourself by depicting the numbers as 8 bits in your comments.
0000 0000 0000 0000 0000 0000 1111 0000 (32-bit)
0000 0000 1111 0000 (16-bit)
Try to avoid doing bitwise operations with signed integers -- often it'll lead you into undefined behavior.
The situation here is that you're taking unsigned values and assigning them to a signed variable. For ~60 this is undefined behavior. You see it as -61 because the bit pattern ~60 is also the two's-complement representation of -61. On the other hand 60 << 2 comes out correct because 240 has the same representation both as a signed and unsigned integer.

Type conversion: signed int to unsigned long in C

I'm currently up to chapter 2 in The C Programming Language (K&R) and reading about bitwise operations.
This is the example that sparked my curiosity:
x = x & ~077
Assuming a 16-bit word length and 32-bit long type, what I think would happen is 077 would first be converted to:
0000 0000 0011 1111 (16 bit signed int).
This would then be complemented to:
1111 1111 1100 0000.
My question is what would happen next for the different possible types of x? If x is a signed int the answer is trivial. But, if x is a signed long I'm assuming ~077 would become:
1111 1111 1111 1111 1111 1111 1100 0000
following 2s complement to preserve the sign. Is this correct?
Also, if x is an unsigned long will ~077 become:
0000 0000 0000 0000 1111 1111 1100 0000
Or, will ~077 be converted to a signed long first:
1111 1111 1111 1111 1111 1111 1100 0000
...after which it is converted to an unsigned long (no change to bits)?
Any help would help me clarify whether or not this operation will always set only the last 6 bits to zero.
Whatever data-type you choose, ~077 will set the rightmost 6 bits to 0 and all others to 1.
Assuming 16-bit ints and 32-bit longs, there are 4 cases:
Case 1
unsigned int x = 077; // x = 0000 0000 0011 1111
x = ~x; // x = 1111 1111 1100 0000
unsigned long y = ~x; // y = 0000 0000 0000 0000 1111 1111 1100 0000
Case 2
unsigned int x = 077; // x = 0000 0000 0011 1111
x = ~x; // x = 1111 1111 1100 0000
long y = ~x; // y = 0000 0000 0000 0000 1111 1111 1100 0000
Case 3
int x = 077; // x = 0000 0000 0011 1111
x = ~x; // x = 1111 1111 1100 0000
unsigned long y = ~x; // y = 1111 1111 1111 1111 1111 1111 1100 0000
Case 4
int x = 077; // x = 0000 0000 0011 1111
x = ~x; // x = 1111 1111 1100 0000
long y = ~x; // y = 1111 1111 1111 1111 1111 1111 1100 0000
See code here. This means the sign extension is done when the source is signed. When the source is unsigned, sign bit is not extended and the left bits are set to 0.
x = x & ~077 //~077=11111111111111111111111111000000(not in every case)
~077 is a constant evaluated at the complie time so its value will be casted according to the value of x at the compile time so the AND operation will always yield to last 6 bits of x to 0 and the remaining bits will remain whatever they were before the AND operation. Like
//let x=256472--> Binary--> 0000 0000 0000 0011 1110 1001 1101 1000
x = x & ~077;
// now x = 0000 0000 0000 0011 1110 1001 1100 0000 Decimal--> 256448
So the last 6 bits are changed to 0 irrespective of the data type during the compile time remaining bits remain same. And in knr it is written there The portable form
involves no extra cost, since ~077 is a constant expression that can be evaluated at compile time.

Sign-extend a number in C

I am having trouble trying to sign-extend a number by extracting part of a bit-string. This has trouble when it is a negative number, it wraps the number around to the positive side.
Here is my code:
// printf("add1 \n");
unsigned short r1 = (instruction>>6)&7;
signed short amount = (instruction& 31); //right here! i am trying to get the last 5 bits and store it in a register but i can't figure out how to make it negative if it is negative
// printf("\namount is %d \n", amount);
unsigned short dest = (instruction>>9)&7;
state->regs[dest] = state->regs[r1]+amount;
setCC(state,state->regs[r1]+amount);
For bit patterns, it's often easier to use hex constants instead of decimal.
signed short amount = (instruction & 0x1F);
Then to sign-extend the number, check the sign-bit (assuming the sign-bit here is the left-most of the 5 extracted bits). If it's set, do a binary inversion and add 1. Take the 2's-complement of the 5-bit value (invert and add one), then take the 2's-complement of the full-width result (invert and add 1).
if (amount & 0x10)
amount = ~(amount^0x1F + 1) + 1;
Eg.
5-bit "bitfield"
X XXXX
0000 0000 0001 1111
0000 0000 0000 0000 invert x ^ 0x1F (= 1 1111)
0000 0000 0000 0001 add 1
1111 1111 1111 1110 invert ~
1111 1111 1111 1111 add 1
0000 0000 0001 0000
0000 0000 0000 1111 invert x ^ 0x1F (= 1 1111)
0000 0000 0001 0000 add 1
1111 1111 1110 1111 invert ~
1111 1111 1111 0000 add 1
Ooops. Even simpler:
-(x^0x1F + 1) Assuming the machine operates with 2's-complement
0000 0000 0001 0110
0000 0000 0000 1001 invert
0000 0000 0000 1010 add 1 (yielding the full-width absolute value)
1111 1111 1111 0110 negate
use bitfields:
union {
int a;
struct {
int a:5;
int b:3;
unsigned int c:20;
} b;
} u = 0xdeadbeef;
int b = u.b.b; // should sign extend the 3-bit bitfield starting from bit 5
Here is how you can sign extend a 5-bit two's complement value portably without tests:
int amount = (instruction & 31) - ((instruction & 16) << 1);
More generally, it the field width is n, non zero and less than the number of bits in an int, you can write:
int amount = (instruction & ~(~1U << (n - 1) << 1)) -
((instruction & (1U << (n - 1)) << 1);
From Hacker's Delight 2-6. Assuming 5 bits of data that must be sign extended (sign bit has value 16).
Best case: If the upper bits are all zeros:
(i ^ 16) - 16
Next best case (as with OP's instruction): If the upper bits contain data that must be discarded:
(i & 15) - (i & 16)
You can check the sign-bit and fix-up the result accordingly:
int width_of_field = 5;
signed short amount = (instruction& 31);
if (amount & (1 << width_of_field >> 1)) // look at the sign bit
{
amount -= 1 << width_of_field; // fix the result
}
Alternatively, use a left-shift followed by a right shift:
width_of_field = 5;
signed short amount = (instruction& 31);
// It is possible to omit the "& 31", because of the left shift below
amount <<= 16 - width_of_field;
amount >>= 16 - width_of_field;
Note: must use two statements to avoid effects of promotion to int (which presumably has 32 bits).

Resources