I have a byte, whose value in binary is 11111111. I have to extend my byte to 16 bits 0101010101010101 according to these rules: if bit = 1, now is 01. If bit = 0, now is 10.
For example:
00001111 -> 1010101001010101
00000101 -> 1010101010011001
What is the operation to do this?
First, convert your byte to an int:
int x = (int)byte_value;
Then, extend to 16 bits, by shifting bits 4 at a time, then 2, then 1, then doubling each bit with a shift and bitwise OR:
x = ((x << 4) | x) & 0b0000111100001111;
x = ((x << 2) | x) & 0b0011001100110011;
x = ((x << 1) | x) & 0b0101010101010101;
x = (x << 1) | x;
Then, mask the bits so that the even bit positions are 1 if the bit is 1, and the odd positions are 1 if the bit is 0 (using bitwise NOT):
x = (x & 0b0101010101010101) | (~x & 0b1010101010101010);
I don't think that there is an operator for "expanding" bits as described.
But you could do it in a loop together with shifting and testing bits as follows:
unsigned char b = 0xff;
unsigned int result = 0x0;
for (int i=0; i<8; i++) {
result <<= 2; // make place for the next 2 bits
int isSet = b & 0x80; // check highest significant bit of b
if (isSet) {
result |= 0x01; // in bits: 01
}
else {
result |= 0x02; // in bits: 10
}
b <<= 1;
}
Hope it helps.
Related
I am trying to practice bit manipulation with this problem. I attempted to solve this question by using an 8 bit integer. For example, if you have an input of 1101 1110, the output will be 1011 1110. I will show the steps I took to arrive to this output.
Input: 1101 1110
Save less significant half of integer: (1101 1110) & 0x0f = 0000 1110
Reverse the more significant half of integer: (1101 1110) >> 4 = 0000 1101
int mostSigHalf = 0b00001101;
int result = 0;
for(int i=0; i<8; i++)
{
result = (result<<1) | (mostSigHalf&1);
mostSigHalf = mostSigHalf>>1;
}
The reversed part is now 1011 0000
Lastly, XOR the reversed most significant half of the integer with the least significant half that got saved:
(1011 0000) ^ (0000 1110) = 1011 1110
How can I extend this method of only reversing the bits of the most significant half of an integer of any size (not just limited to 8 bits)? If anyone has any suggestions or other methods to solve this problem than what I came up with, please do share!
You need a series of masks and shifts. There is more than one way to come up with a sequence that does what you need. One way to approach it would be:
#include <stdio.h>
int main (void) {
unsigned char u = 0xde,
v = u >> 4, /* high nibble as v */
w = v & 0x3, /* bottom 2 bits */
x = (v & 0xc) >> 2, /* top 2 bits */
y = ((w >> 1) | ((w & 1) << 1)) << 2, /* rev bot/shift */
z = (x >> 1) | ((x & 1) << 1); /* rev top */
/* form high-nibble shift by 4, or with original bottom nibble */
printf ("orig: 0x%02hhx\nrevd: 0x%02hhx\n", u, ((y | z) << 4) | (u & 0xf));
}
Example Use/Output
$ ./bin/bitrevhighnibble
orig: 0xde
revd: 0xbe
Put Together In a Function
Since you are looking to extend your current function, you can simply write another short function that takes a byte and performs the same series of shifts and masks and returns the results you need:
unsigned char swaphighnibblepairs (unsigned char u) {
unsigned char v = u >> 4, /* high nibble as v */
w = v & 0x3, /* bottom 2 bits */
x = (v & 0xc) >> 2, /* top 2 bits */
y = ((w >> 1) | ((w & 1) << 1)), /* rev bottom */
z = (x >> 1) | ((x & 1) << 1); /* rev top */
/* form high-nibble shift by 4, OR with original bottom nibble */
return (((y << 2) | z) << 4) | (u & 0xf);
}
Explanation
Looking further that the sequence beginning with u = 0xde; (your bit sequence 1101 1110), you start by isolating the top 4-bits (the high-nibble),
unsigned char v = u >> 4, /* high nibble as v */
With the high-nibble in v, you can then mask and isolate the bottom 2-bits and mask and shift top 2-bits, e.g.
w = v & 0x3, /* bottom 2 bits */
x = (v & 0xc) >> 2, /* top 2 bits */
What is left is revering each bit in w and x:
y = ((w >> 1) | ((w & 1) << 1)), /* rev bottom */
z = (x >> 1) | ((x & 1) << 1); /* rev top */
The final result is arrived at by OR'ing (y << 2) | z and shifting that nibble by 4 to the left to become the new high-nibble and OR'ing that with the original low-nibble isolated by a simple mask of the original high-nibble: (((y << 2) | z) << 4) | (u & 0xf)
You can re-arrange the order of the masks and shifts and probably come up with a shorter route, or combine more of the operations together, but for the cost of a few extra bytes, spreading them out may make it easier to think through.
Let me know if you have further questions.
Suppose you have an integer a = 0x12345678 & a short b = 0xabcd
What i wanna do is replace the given nibbles in integer a with nibbles from short b
Eg: Replace 0,2,5,7th nibbles in a = 0x12345678 (where 8 = 0th nibble, 7=1st nibble, 6=2nd nibble and so on...) with nibbles from b = 0xabcd (where d = 0th nibble, c=1st nibble, b=2nd nibble & so on...)
My approach is -
Clear the bits we're going to replace from a.
like a = 0x02045070
Create the mask from the short b like mask = 0xa0b00c0d
bitwise OR them to get the result. result = a| mask i.e result = 0xa2b45c7d hence nibbles replaced.
My problem is I don't know any efficient way to create the desired mask (like in step 2) from the given short b
If you can give me an efficient way of doing so, it would be a great help to me and I thank you for that in advance ;)
Please ask if more info needed.
EDIT:
My code to solve the problem (not good enough though)
Any improvement is highly appreciated.
int index[4] = {0,1,5,7}; // Given nibbles to be replaced in integer
int s = 0x01024300; // integer mask i.e. cleared nibbles
int r = 0x0000abcd; // short (converted to int )
r = ((r & 0x0000000f) << 4*(index[0]-0)) |
((r & 0x000000f0) << 4*(index[1]-1)) |
((r & 0x00000f00) << 4*(index[2]-2)) |
((r & 0x0000f000) << 4*(index[3]-3));
s = s|r;
Nibble has 4 bits, and according to your indexing scheme, the zeroth nibble is represented by least significant bits at positions 0-3, the first nibble is represented by least significant bits at positions 4-7, and so on.
Simply shift the values the necessary amount. This will set the nibble at position set by the variable index:
size_t index = 5; //6th nibble is at index 5
size_t shift = 4 * index; //6th nibble is represented by bits 20-23
unsigned long nibble = 0xC;
unsigned long result = 0x12345678;
result = result & ~( 0xFu << shift ); //clear the 6th nibble
result = result | ( nibble << shift ); //set the 6th nibble
If you want to set more than one value, put this code in a loop. The variable index should be changed to an array of values, and variable nibble could also be an array of values, or it could contain more than one nibble, in which case you extract them one by one by shifting values to the right.
A lot depends on how your flexible you are in accepting the "nibble list" index[4] in your case.
You mentioned that you can replace anywhere from 0 to 8 nibbles. If you take your nibble bits as an 8-bit bitmap, rather than as a list, you can use the bitmap as a lookup in a 256-entry table, which maps from bitmap to a (fixed) mask with 1s in the nibble positions. For example, for the nibble list {1, 3}, you'd have the bitmap 0b00001010 which would map to the mask 0x0000F0F0.
Then you can use pdep which has intrinsics on gcc, clang, icc and MSVC on x86 to expand the bits in your short to the right position. E.g., for b == 0xab you'd have _pdep_u32(b, mask) == 0x0000a0b0.
If you aren't on a platform with pdep, you can accomplish the same thing with multiplication.
To be able to change easy the nibbles assignment, a bit-field union structure could be used:
Step 1 - create a union allowing to have nibbles access
typedef union u_nibble {
uint32_t dwValue;
uint16_t wValue;
struct sNibble {
uint32_t nib0: 4;
uint32_t nib1: 4;
uint32_t nib2: 4;
uint32_t nib3: 4;
uint32_t nib4: 4;
uint32_t nib5: 4;
uint32_t nib6: 4;
uint32_t nib7: 4;
} uNibble;
} NIBBLE;
Step 2 - assign two NIBBLE items with your integer a and short b
NIBBLE myNibbles[2];
uint32_t a = 0x12345678;
uint16_t b = 0xabcd;
myNibbles[0].dwValue = a;
myNibbles[1].wValue = b;
Step 3 - initialize nibbles of a by nibbles of b
printf("a = %08x\n",myNibbles[0].dwValue);
myNibbles[0].uNibble.nib0 = myNibbles[1].uNibble.nib0;
myNibbles[0].uNibble.nib2 = myNibbles[1].uNibble.nib1;
myNibbles[0].uNibble.nib5 = myNibbles[1].uNibble.nib2;
myNibbles[0].uNibble.nib7 = myNibbles[1].uNibble.nib3;
printf("a = %08x\n",myNibbles[0].dwValue);
Output will be:
a = 12345678
a = a2b45c7d
If I understand your goal, the fun you are having comes from the reversal of the order of your fill from the upper half to the lower half of your final number. (instead of 0, 2, 4, 6, you want 0, 2, 5, 7) It isn't any more difficult, but it does make you count where the holes are in the final number. If I understood, then you could mask with 0x0f0ff0f0 and then fill in the zeros with shifts of 16, 12, 4 and 0. For example:
#include <stdio.h>
int main (void) {
unsigned a = 0x12345678, c = 0, mask = 0x0f0ff0f0;
unsigned short b = 0xabcd;
/* mask a, fill in the holes with the bits from b */
c = (a & mask) | (((unsigned)b & 0xf000) << 16);
c |= (((unsigned)b & 0x0f00) << 12);
c |= (((unsigned)b & 0x00f0) << 4);
c |= (unsigned)b & 0x000f;
printf (" a : 0x%08x\n b : 0x%0hx\n c : 0x%08x\n", a, b, c);
return 0;
}
Example Use/Output
$ ./bin/bit_swap_nibble
a : 0x12345678
b : 0xabcd
c : 0xa2b45c7d
Let me know if I misunderstood, I'm happy to help further.
With nibble = 4 bits and unsigned int = 32 bits, a nibble inside a unsigned int can be found as follows:
x = 0x00a0b000, find 3rd nibble in x i.e locate 'b'. Note nibble index starts with 0.
Now 3rd nibble is from 12th bit to 15th bit.
3rd_nibble can be selected with n = 2^16 - 2^12. So, in n all the bits in 3rd nibble will be 1 and all the bits in other nibbles will be 0. That is, n=0x00001000
In general, suppose if you want to find a continuous sequence of 1 in binary representation in which sequence starts from Xth bit to Yth bit then formula is 2^(Y+1) - 2^X.
#include <stdio.h>
#define BUF_SIZE 33
char *int2bin(int a, char *buffer, int buf_size)
{
int i;
buffer[BUF_SIZE - 1] = '\0';
buffer += (buf_size - 1);
for(i = 31; i >= 0; i--)
{
*buffer-- = (a & 1) + '0';
a >>= 1;
}
return buffer;
}
int main()
{
unsigned int a = 0;
unsigned int b = 65535;
unsigned int b_nibble;
unsigned int b_at_a;
unsigned int a_nibble_clear;
char replace_with[8];
unsigned int ai;
char buffer[BUF_SIZE];
memset(replace_with, -1, sizeof(replace_with));
replace_with[0] = 0; //replace 0th nibble of a with 0th nibble of b
replace_with[2] = 1; //replace 2nd nibble of a with 1st nibble of b
replace_with[5] = 2; //replace 5th nibble of a with 2nd nibble of b
replace_with[7] = 3; //replace 7th nibble of a with 3rd nibble of b
int2bin(a, buffer, BUF_SIZE - 1);
printf("a = %s, %08x\n", buffer, a);
int2bin(b, buffer, BUF_SIZE - 1);
printf("b = %s, %08x\n", buffer, b);
for(ai = 0; ai < 8; ++ai)
{
if(replace_with[ai] != -1)
{
b_nibble = (b & (1LL << ((replace_with[ai] + 1)*4)) - (1LL << (replace_with[ai]*4))) >> (replace_with[ai]*4);
b_at_a = b_nibble << (ai * 4);
a_nibble_clear = (a & ~(a & (1LL << ((ai + 1) * 4)) - (1LL << (ai * 4))));
a = a_nibble_clear | b_at_a;
}
}
int2bin(a, buffer, BUF_SIZE - 1);
printf("a = %s, %08x\n", buffer, a);
return 0;
}
Output:
a = 00000000000000000000000000000000, 00000000
b = 00000000000000001111111111111111, 0000ffff
a = 11110000111100000000111100001111, f0f00f0f
How would I go about implementing a sign extend from 16 bits to 32 bits in C code?
I am supposed to be using bitwise operators. I also need to add and subtract; can anyone point me in the right direction? I did the first 4 but am confused on the rest. I have to incorporate a for loop somewhere as well for 1 of the cases.
I am not allowed to use any arithmetic operators (+, -, /, *) and no if statements.
Here is the code for the switch statement I am currently editing:
unsigned int csc333ALU(const unsigned int opcode,
const unsigned int argument1,
const unsigned int argument2) {
unsigned int result;
switch(opcode) {
case(0x01): // result = NOT argument1
result = ~(argument1);
break;
case(0x02): // result = argument 1 OR argument 2
result = argument1 | argument2;
break;
case(0x03): // result = argument 1 AND argument 2
result = argument1 & argument2;
break;
case(0x04): // result = argument 1 XOR argument 2
result = argument1 ^ argument2;
break;
case(0x05): // result = 16 bit argument 1 sign extended to 32 bits
result = 0x00000000;
break;
case(0x06): // result = argument1 + argument2
result = 0x00000000;
break;
case(0x07): // result = -argument1. In two's complement, negate and add 1.
result = 0x00000000;
break;
default:
printf("Invalid opcode: %X\n", opcode);
result = 0xFFFFFFFF;
}
partial answer for sign extension:
result = (argument1 & 0x8000) == 0x8000 ? 0xFFFF0000 | argument1 : argument1;
To sign-extend a 16 bit number to 32 bit, you need to copy bit 15 to the upper bits. The naive way to do this is with 16 instructions, copying bit 15 to bit 16, then 17, then 18, and so on. But you can do it more efficiently by using previously copied bits and doubling the number of bits you've copied each time like this:
unsigned int ext = (argument1 & 0x8000U) << 1;
ext |= ext << 1;
ext |= ext << 2;
ext |= ext << 4;
ext |= ext << 8;
result = (argument1 & 0xffffU) | ext;
To add two 32 bit numbers "manually" then you can simply do it bit by bit.
unsigned carry = 0;
result = 0;
for (int i = 0; i < 32; i++) {
// Extract the ith bit from argument1 and argument 2.
unsigned a1 = (argument1 >> i) & 1;
unsigned a2 = (argument2 >> i) & 1;
// The ith bit of result is set if 1 or 3 of a1, a2, carry is set.
unsigned v = a1 ^ a2 ^ carry;
result |= v << i;
// The new carry is 1 if at least two of a1, a2, carry is set.
carry = (a1 & a2) | (a1 & carry) | (a2 & carry);
}
Subtraction works with almost exactly the same code: a - b is the same as a + (~b+1) in two's complement arithmetic. Because you aren't allowed to simply add 1, you can achieve the same by initialising carry to 1 instead of 0.
unsigned carry = 1;
result = 0;
for (int i = 0; i < 32; i++) {
unsigned a1 = (argument1 >> i) & 1;
unsigned a2 = (~argument2 >> i) & 1;
unsigned v = a1 ^ a2 ^ carry;
result |= v << i;
carry = (a1 & a2) | (a1 & carry) | (a2 & carry);
}
To find two's complement without doing the negation, similar ideas apply. Bitwise negate and then add 1. Adding 1 is simpler than adding argument2, so the code is correspondingly simpler.
result = ~argument1;
unsigned carry = 1;
for (int i = 0; i < 32 && carry; i++) {
carry &= (result >> i);
result |= (1 << i);
}
to get sign extension from short int to int....
short int iShort = value;
int i = iShort; // compiler automatically creates code that performs sign extension
Note: going from i to iShort will generate a compiler waring.
however, for other situations...
no need to make comparison, the & will result in a single bit being either 0 or 1 and be sure to cast the parts of the calculation as int
int i = (short int argument&0x8000)? (int)(0xFFFF000 | (int)argument) : (int)argument;
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;
I have the following function
int sign(int x) {
int sign = (x >> 31);
sign = sign | 1;
return sign;
}
I wish for the following:
return -1 for a negative number (first line)
return 1 for a positive number (second line)
return 0 for zero
I'm stuck on this last item. How can I use the bitwise operators only to return zero if x is zero?
Nice little puzzle. Assume you have 32 bit ints:
int sign( int x )
{
// if any bit is on, all bits are on. else zero.
int lowBit = x;
lowBit |= lowBit >> 16;
lowBit |= lowBit >> 8;
lowBit |= lowBit >> 4;
lowBit |= lowBit >> 2;
lowBit |= lowBit >> 1;
lowBit &= 1;
int signBit = x & 0x80000000;
signBit |= signBit >> 16;
signBit |= signBit >> 8;
signBit |= signBit >> 4;
signBit |= signBit >> 2;
signBit |= signBit >> 1;
signBit &= 0xFFFFFFFE;
return signBit | lowBit;
}
Here is how it works. I'll explain with 4 bit numbers, but the explanation generalizes. You have to make a mapping from three categories of bit patterns:
0000 -> 0000
0xxx -> 0001
1yyy -> 1111
where x can be anything except 000, and yyy can be anything.
So first you want a bit that is 1 if any bit in the register is 1, and 0 otherwise. So we 'smear' the register, such that if any bit is high all bits are high, and we keep that bit for the value of the low bit in our result.
Then we 'smear' the sign bit. Finally we 'or' them together.
Exercise for the reader: If you have 32 bit ints, but 64 bit registers, you can cut the number of operations in half.
update: It can always be done better (untested):
int sign( int x )
{
int lowBit = !!x; // double ! operator, wtf? yes...
int signBit = x & 0x80000000;
signBit |= signBit >> 16;
signBit |= signBit >> 8;
signBit |= signBit >> 4;
signBit |= signBit >> 2;
signBit |= signBit >> 1;
signBit &= 0xFFFFFFFE;
return signBit | lowBit;
}
Use this
int sign(int x) {
int sign = (x >> 31);
sign = sign | (~(1<<((x|(x>>5)|(x>>10)|(x>>15)|(x>>20)|(x>>25)|(x>>30))&0x1F))&0x1);
return sign;
}
The idea is to left shift 1 with x count.
So if x==0 then the first bit will be kept 1
and if x!=0 then the first bit will be changed to 0
and then the sign = sign | (~(First bit))
it's equivalent to
sign = sign | (~(1<<x) & 0x1);
but we have to be careful when we left shift 1 with x, because x could be >= to the size of the type format (32) and the x could be negatif and for both cases it is undefined behavior.
so to avoid the above problem I split our 32 bits (the x) to 7 blocs each bloc contains 5 bits except the last one it contains 2 bits and then I made a | for all the blok
y=(bloc1|bloc2|bloc3|bloc4|bloc5|bloc6|bloc7)
so if x!= 0 then y!=0
and if x==0 then y==0
and we have to take only the first 5 bits of y (&0x1F). here I m sure that y is not negatif and y<32
and then instead of shifting with x I can shift with y to avoid the undefined behavior
you can use also this. it has the same logic with my previous answer
int sign(int x) {
int y = x;
y |= y >> 16;
y |= y >> 8;
y |= y >> 4;
y &= 0xF;
int sign = (x >> 31);
sign = sign | (~(1<<y) & 0x1);
return sign;
}