Setting Bits in C - c

I'm trying to do the following:
Write a func setbits(x,p.n,y) that returns x with n bits that begin at
position p set to the rightmost n bits of y,leaving the other bits
unchanged?
I tried it like this but not getting correct answers. Can anyone tell where I am wrong?
unsigned setbits(unsigned x,int p,int n,unsigned y)
{
return (x>>p & (y|(~0<<n)));
}

Something like:
unsigned setbits(unsigned x,int p,int n,unsigned y)
{
unsigned mask = (1U << n) - 1U; // n-bits
y &= mask; // rightmost n bits of y
y <<= p; // which begin at position p
mask <<= p; //idem
x &= ~mask; //set the 0s
x |= y; //set the 1s
return x;
}
Or if you want to do it in fewer lines, more difficult to debug, but waaaay cooler:
unsigned setbits(unsigned x,int p,int n,unsigned y)
{
unsigned mask = (1U << n) - 1U; // n-bits
return (x & ~(mask << p)) | ((y & mask) << p);
}

Kernighan and Ritchie, 2nd edition, exercise 2-6. The solution is from http://users.powernet.co.uk/eton/kandr2/krx206.html :
(x & ((~0 << (p + 1)) | (~(~0 << (p + 1 - n))))) | ((y & ~(~0 << n)) << (p + 1 - n))

You x>>() so you loose x rightmost bits and then never restore them later in you function.
One can not set bits using only & because the result depends on both operands unless you know one of them consists only of 1
(y|(~0<<n)) is supposed to cut bits from y but it's not, this time | is not the right tool, use & and appropriate second operand.
Here is the solution(I bet there is shorter one, but this is straight-forward):
(x & ~(~(~0<<n)<<p) | (y&~(~0<<n)) << p);
Left part of | clears the place in x(n bits at position p) and the right part brings y bits.

Catching the last n bits of y: (will be a number with the last n bits equal to y, and the others set to zero)
last_n_bits_of_y = y & (((1<<(n+1))-1);
then we can offset it by (32-n-p+1) (check this!)
last_n_bits_of_y_offset = last_n_bits_of_y << (32-n-p+1);
now we erase the bits of x we want to change:
new_x = x & (~( (((1<<(n+1))-1) << (32-n-p+1) ) );
and populate it with our bits:
new_x = new_x & last_n_bits_of_y_offset;
That's it! Didn't really test it, but hopefully, you'll get the idea.

Related

Do an arithmetic left shift of x by n bits (C)

Me and my group of 4 people are both completely blanking on how to correctly do an arithmetic left shift of an int x, by an amount of n bits.
It is a for a homework problem on bit manipulation for C. We are not allowed to use loops, if statements, or any operations over 15. I've attached the code given below. Also, the simple solution x << n does not work, even though I'm sure we are missing something obvious. If anyone could help or provide guidance, it would be much appreciated.
/*
* arithLeftShift - Do an arithmetic left shift of x by n bits.
* Can assume that 0 <= n <= 31
* Examples: arithLeftShift(0x87654321,4) = 0xF6543218
* Legal ops: ~ & ^ | + << >> !
* Max ops: 15
* Rating: 3
*/
int arithLeftShift(int x, int n) {
return 0;
}
Current error message:
Test arithLeftShift(-2147483648[0x80000000],1[0x1]) failed...
...Gives 0[0x0]. Should be -2147483648[0x80000000
Actually, It is not arithmetic left shift.It's your arithLeftShift with your sign bit needn't a left shift. And the high bits needed to be shifted to the low position, It looks like a cycle shift.
#include<stdio.h>
int main()
{
arithLeftShift(0x87654321,4);
}
int arithLeftShift(int x,int n)
{
int temp,i; //define two auto variables,
i=x>>(32-n);//i for x's high n bits.
temp=x<<n;//temp for x left shift n bits
if(x>0)//sign bit is 0,
{
x=temp+i;
x=x>0?x:x^0x80000000;//change the x sign bit is 0;
}
else
{//when you do right shift, there will be different with different compliers and your x.
if(i>0){//This means when you do right shift, 0 be inserted into high bits.
x=temp+i;
}
else
{
i=(0x80000000>>(32-n));
x=temp+i;
}
x=x>0?~(x^(~0x80000000)):x;//change the x sign bit is 1
printf("%x\n",x);
}
}
Your ask seems to be to "Rotate" the integer "Left", "n" number of times but retain the "Sign Bit"(MSB) if set.
One solution would be......
#include <stdio.h>
#define INT_BITS 32
int arithLeftShift(int x, int n) {
int res;
res = (x << n | (x >> (INT_BITS - n) & ~(~0 << n))) | x & (~0 << (INT_BITS - 1));
return res;
}
int main(){
int x = 0x87654321;
int n = 4;
printf("0x%x\n",arithLeftShift(x,n));
}
Explanation:
(x << n)
Left shift x, n times - the last n bits are zero.
(x >> (INT_BITS - n) & ~(~0 << n))
Right shift x (INT_BITS - n) times to put the first n bits at the correct position and "AND" it with ~(~0 << n) to set the upper bits to zero.This will take care of "sign extension", if any.
(x << n | (x >> (INT_BITS - n) & ~(~0 << n)))
"OR" them to perform the "Rotate Left" operation.
x & (~0 << (INT_BITS - 1)
Left shift "-1", 31 times and "AND" it with x to check if the MSB of x is set.
(x << n | (x >> (INT_BITS - n) & ~(~0 << n))) | x & (~0 << (INT_BITS - 1))
Finally "OR" the above expressions to get your answer.

How to interleave 2 booleans using bitwise operators?

Suppose I have two 4-bit values, ABCD and abcd. How to interleave it, so it becomes AaBbCcDd, using bitwise operators? Example in pseudo-C:
nibble a = 0b1001;
nibble b = 0b1100;
char c = foo(a,b);
print_bits(c);
// output: 0b11010010
Note: 4 bits is just for illustration, I want to do this with two 32bit ints.
This is called the perfect shuffle operation, and it's discussed at length in the Bible Of Bit Bashing, Hacker's Delight by Henry Warren, section 7-2 "Shuffling Bits."
Assuming x is a 32-bit integer with a in its high-order 16 bits and b in its low-order 16 bits:
unsigned int x = (a << 16) | b; /* put a and b in place */
the following straightforward C-like code accomplishes the perfect shuffle:
x = (x & 0x0000FF00) << 8 | (x >> 8) & 0x0000FF00 | x & 0xFF0000FF;
x = (x & 0x00F000F0) << 4 | (x >> 4) & 0x00F000F0 | x & 0xF00FF00F;
x = (x & 0x0C0C0C0C) << 2 | (x >> 2) & 0x0C0C0C0C | x & 0xC3C3C3C3;
x = (x & 0x22222222) << 1 | (x >> 1) & 0x22222222 | x & 0x99999999;
He also gives an alternative form which is faster on some CPUs, and (I think) a little more clear and extensible:
unsigned int t; /* an intermediate, temporary variable */
t = (x ^ (x >> 8)) & 0x0000FF00; x = x ^ t ^ (t << 8);
t = (x ^ (x >> 4)) & 0x00F000F0; x = x ^ t ^ (t << 4);
t = (x ^ (x >> 2)) & 0x0C0C0C0C; x = x ^ t ^ (t << 2);
t = (x ^ (x >> 1)) & 0x22222222; x = x ^ t ^ (t << 1);
I see you have edited your question to ask for a 64-bit result from two 32-bit inputs. I'd have to think about how to extend Warren's technique. I think it wouldn't be too hard, but I'd have to give it some thought. If someone else wanted to start here and give a 64-bit version, I'd be happy to upvote them.
EDITED FOR 64 BITS
I extended the second solution to 64 bits in a straightforward way. First I doubled the length of each of the constants. Then I added a line at the beginning to swap adjacent double-bytes and intermix them. In the following 4 lines, which are pretty much the same as the 32-bit version, the first line swaps adjacent bytes and intermixes, the second line drops down to nibbles, the third line to double-bits, and the last line to single bits.
unsigned long long int t; /* an intermediate, temporary variable */
t = (x ^ (x >> 16)) & 0x00000000FFFF0000ull; x = x ^ t ^ (t << 16);
t = (x ^ (x >> 8)) & 0x0000FF000000FF00ull; x = x ^ t ^ (t << 8);
t = (x ^ (x >> 4)) & 0x00F000F000F000F0ull; x = x ^ t ^ (t << 4);
t = (x ^ (x >> 2)) & 0x0C0C0C0C0C0C0C0Cull; x = x ^ t ^ (t << 2);
t = (x ^ (x >> 1)) & 0x2222222222222222ull; x = x ^ t ^ (t << 1);
From Stanford "Bit Twiddling Hacks" page:
https://graphics.stanford.edu/~seander/bithacks.html#InterleaveTableObvious
uint32_t x = /*...*/, y = /*...*/;
uint64_t z = 0;
for (int i = 0; i < sizeof(x) * CHAR_BIT; i++) // unroll for more speed...
{
z |= (x & 1U << i) << i | (y & 1U << i) << (i + 1);
}
Look at the page they propose different and faster algorithms to achieve the same.
Like so:
#include <limits.h>
typedef unsigned int half;
typedef unsigned long long full;
full mix_bits(half a,half b)
{
full result = 0;
for (int i=0; i<sizeof(half)*CHAR_BIT; i++)
result |= (((a>>i)&1)<<(2*i+1))|(((b>>i)&1)<<(2*i+0));
return result;
}
Here is a loop-based solution that is hopefully more readable than some of the others already here.
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
uint64_t interleave(uint32_t a, uint32_t b) {
uint64_t result = 0;
int i;
for (i = 0; i < 31; i++) {
result |= (a >> (31 - i)) & 1;
result <<= 1;
result |= (b >> (31 - i)) & 1;
result <<= 1;
}
// Skip the last left shift.
result |= (a >> (31 - i)) & 1;
result <<= 1;
result |= (b >> (31 - i)) & 1;
return result;
}
void printBits(uint64_t a) {
int i;
for (i = 0; i < 64; i++)
printf("%lu", (a >> (63 - i)) & 1);
puts("");
}
int main(){
uint32_t a = 0x9;
uint32_t b = 0x6;
uint64_t c = interleave(a,b);
printBits(a);
printBits(b);
printBits(c);
}
I have used the 2 tricks/operations used in this post How do you set, clear, and toggle a single bit? of setting a bit at particular index and checking the bit at particular index.
The following code is implemented using these 2 operations only.
int a = 0b1001;
int b = 0b1100;
long int c=0;
int index; //To specify index of c
int bit,i;
//Set bits in c from right to left.
for(i=32;i>=0;i--)
{
index=2*i+1; //We have to add the bit in c at this index
//Check a
bit=a&(1<<i); //Checking whether the i-th bit is set in a
if(bit)
c|=1<<index; //Setting bit in c at index
index--;
//Check b
bit=b&(1<<i); //Checking whether the i-th bit is set in b
if(bit)
c|=1<<index; //Setting bit in c at index
}
printf("%ld",c);
Output: 210 which is 0b11010010

Optimising bitwise operations in C

I had a problem in hand as this :
"Exercise 2-6. Write a function setbits(x,p,n,y) that returns x with the n bits that begin at
position p set to the rightmost n bits of y, leaving the other bits unchanged."
I've written a function for this as below. This is working as expected.
int func_setx(int x,int p,int n,int y)
{
int a_t= ~0 << (p+n);
int b_t= ~a_t >> n;
int x_t= x& (a_t | b_t); // a temporary x which has the bits to be changed as 0 , rest of the bits unchanged.
int mask= (y << p) & (~(~0 << (p+n))); // a mask which has required bits from y in positions to be set , rest all bits 0.
printf("\nCheckpoint : mask= %x x_t= %x\n",mask,x_t);
int result= mask|x_t;
return result;
}
But I somehow feel the logic is long and can be optimized, but can't think of any other way yet.
Can anyone suggest any optimization to this please?
To make an n bit mask:
mask_y = (1U << n) - 1;
To start it at bit p:
mask_x = mask_y << p;
Clear the appropriate bits in x:
x &= ~mask_x;
Extract the bits from y:
y &= mask_y;
Upshift them to position p:
y <<= p;
Put it all together:
result = x | y;
Or in a more compact form:
mask = (1U << n) - 1;
result = x & ~(mask << p);
result |= (y & mask) << p;

replace byte in 32 bit number

I have a function called replaceByte(x,n,c) that is to replace byte n in x with c with the following restrictions:
Bytes numbered from 0 (LSB) to 3 (MSB)
Examples: replaceByte(0x12345678,1,0xab) = 0x1234ab78
You can assume 0 <= n <= 3 and 0 <= c <= 255
Legal ops: ! ~ & ^ | + << >>
Max ops: 10
int replaceByte(int x, int n, int c) {
int shift = (c << (8 * n));
int mask = 0xff << shift;
return (mask & x) | shift;
}
but when I test it I get this error:
ERROR: Test replaceByte(-2147483648[0x80000000],0[0x0],0[0x0]) failed...
...Gives 0[0x0]. Should be -2147483648[0x80000000]
after realizing that * is not a legal operator I have finally figured it out...and if you are curious, this is what I did:
int replaceByte(int x, int n, int c) {
int mask = 0xff << (n << 3);
int shift = (c << (n << 3));
return (~mask & x) | shift;
}
Since this looks like homework I'm not going to post code, but list the steps you need to perform:
Cast c into a 32-bit number so you don't lose any bits while shifting
Next, shift c by the appropriate number of bits to the left (if n==0 no shifting, if n==1 shift by 8 etc.)
Create a 32-bit bitmask that will zero the lowest 8 bits of x, then shift this mask by the same amount as the last step
Perform bitwise AND of the shifted bitmask and x to zero out the appropriate bits of x
Perform bitwise OR (or addition) of the shifted c value and x to replace the masked bits of the latter
Ahh... You are almost there.
Just change
return (mask & x) | shift;
to
return (~mask & x) | shift;
The mask should contain all ones except for the region to be masked and not vice versa.
I am using this simple code and it works fine in gcc
#include<stdio.h>
int replaceByte(int x, int n, int c)
{
int shift = (c << (8 * n));
int mask = 0xff << shift;
return (~mask & x) | shift;
}
int main ()
{
printf("%X",replaceByte(0x80000000,0,0));
return 0;
}
Proper solution is for c = 0 as well:
int replaceByte(int x, int n, int c)
{
int shift = 8 * n;
int value = c << shift;
int mask = 0xff << shift;
return (~mask & x) | value;
}

retrieve byte from 32 bit integer using bitwise operators

Here is the problem and what I currently have, I just don't understand how it is wrong...
getByte - Extract byte n from word x Bytes numbered from 0 (LSB) to
3 (MSB) Examples: getByte(0x12345678,1) = 0x56 Legal ops: ! ~ &
^ | + << >> Max ops: 6 Rating: 2
int getByte(int x, int n) {
return ((x << (24 - 8 * n)) >> (8 * n));
}
Your shifting doesn't make any sense - first, you shift left by (24 - 8n) bits, then you shift back right by 8n bits. Why? Also, it's wrong. If n is 0, you shift x left by 24 bits and return that value. Try pen and paper to see that this is entirely wrong.
The correct approach would be to do:
int getByte(int x, int n) {
return (x >> 8*n) & 0xFF;
}
Unless i am totally mistaken, your code is mathematically incorrect.
getByte(0x000000ff, 0) {
24 - 8 * n = 24;
8 * n = 0;
0x000000ff << 24 = 0xff000000;
0xff000000 >> 0 = 0xff000000;
return 0xff000000; // should return 0xff
}
Not being allowed to use operators - and especially * is a problem (can't do * 8). I came up with this:
uint8_t getByte (uint32_t x, int n) {
switch (n) {
case 0:
return x & 0xff;
case 1:
return (x >> 8) & 0xff;
case 2:
return (x >> 16) & 0xff;
case 3:
return x >> 24;
}
}
Not exactly beautiful, but it conforms to the problem description: 6 operators, all of them legal.
EDIT: Just had a (pretty obvious) idea for how to avoid * 8
uint8_t getByte (uint32_t x, int n) {
return (x >> (n << 3)) & 0xff;
}
I don't understand how your function works. Try this instead:
int getByte(int x, int n)
{
return (x >> (8 * n)) & 0xFF;
}

Resources