This question already has answers here:
Need help understanding "getbits()" method in Chapter 2 of K&R C
(6 answers)
Closed 6 years ago.
In the K&R book in chapter 2.9, I am stuck on understanding this sample function getbits()
getbits(x,p,n)
Returns the (right-adjusted) n-bit field of x that begins at position p. Here's the function body
/* getbits: get n bits from from position p */
unsigned getbits(unsigned x, int p, int n)
{
return (x >> (p+1-n)) & ~(~0 << n);
}
I am actually not facing problems with the bitwise operators but I can't actually get the question. I am stuck on understanding the question mainly not solving it.
Ultimately "What do we need to find in this function".
It just shifts the bits right by p+1-n bits (to make the required field right-justified), then masks out all but the bottom n bits. Here is an expanded version, which may be easier to understand:
unsigned getbits(unsigned x, int p, int n)
{
unsigned x_right = (x >> (p+1-n)); // shift right to make required bits right-justified
unsigned mask = ~(~0 << n); // create n bit mask
return x_right & mask; // return required bits
}
Drawing a binary representation usually helps for such cases.
For example: taking 3 bits from position 5:
X: 101010101
--^
p
It shifts:
X: 1010
^
p
And then masks:
X: 010
--^
p
Related
Assume that I have:
unsigned int x = 883621;
which in binary is :
00000000000011010111101110100101
I need the fastest way to swap the two lowest bits:
00000000000011010111101110100110
Note: To clarify: If x is 7 (0b111), the output should be still 7.
If you have few bytes of memory to spare, I would start with a lookup table:
constexpr unsigned int table[]={0b00,0b10,0b01,0b11};
unsigned int func(unsigned int x){
auto y = (x & (~0b11)) |( table[x&0b11]);
return y;
}
Quickbench -O3 of all the answers so far.
Quickbench -Ofast of all the answers so far.
(Plus my ifelse naive idea.)
[Feel free to add yourself and edit my answer].
Please do correct me if you believe the benchmark is incorrect, I am not an expert in reading assembly. So hopefully volatile x prevented caching the result between loops.
I'll ignore the top bits for a second - there's a trick using multiplication. Multiplication is really a convolution operation, and you can use that to shuffle bits.
In particular, assume the two lower bits are AB. Multiply that by 0b0101, and you get ABAB. You'll see that the swapped bits BA are the middle bits.
Hence,
x = (x & ~3U) | ((((x&3)*5)>>1)&3)
[edit] The &3 is needed to strip the top A bit, but with std::uint_32_t you can use overflow to lose that bit for free - multiplication then gets you the result BAB0'0000'0000'0000'0000'0000'0000'0000'0000' :
x = (x & ~3U) | ((((x&3)*0xA0000000)>>30));
I would use
x = (x & ~0b11) | ((x & 0b10) >> 1) | ((x & 0b01) << 1);
Inspired by the table idea, but with the table as a simple constant instead of an array. We just need mask(00)==00, mask(01)==11, mask(10)=11, masK(11)==11.
constexpr unsigned int table = 0b00111100;
unsigned int func(unsigned int x) {
auto xormask = (table >> ((x&3) * 2)) &3;
x ^= xormask;
return x;
}
This also uses the xor-trick from dyungwang to avoid isolating the top bits.
Another idea, to avoid stripping the top bits. Assume x has the bits XXXXAB, then we want to x-or it with 0000(A^B)(A^B). Thus
auto t = x^(x>>1); // Last bit is now A^B
t &=1; // take just that bit
t *= 3; // Put in the last two positions
x ^= t; // Change A to B and B to A.
Just looking from a mathematical point of view, I would start with a rotate_left() function, which rotates a list of bits one place to the left (011 becomes 110, then 101, and then back 011), and use this as follows:
int func(int input){
return rotate_left(rotate_left((input / 4))) + rotate_left(input % 4);
}
Using this on the author's example 11010111101110100101:
input = 11010111101110100101;
input / 4 = 110101111011101001;
rotate_left(input / 4) = 1101011110111010010;
rotate_left(rotate_left(input / 4) = 11010111101110100100;
input % 4 = 01;
rotate_left(input % 4) = 10;
return 11010111101110100110;
There is also a shift() function, which can be used (twice!) for replacing the integer division.
This question already has answers here:
Minimum number of bits to represent a given `int`
(9 answers)
Closed 4 months ago.
How would I scan an integer (in binary) from left to right instead of right to left? I know that I can start from the left and try every bit, and then record the leftmost bit, but is there a faster way? Is there a built-in function that can instantly find the leftmost active bit (that is a 1) in an integer?
I know that for right to left, I can do something like
int myInt = 1234;
for(int i = 0; i < 32; i++) {
int curr_bit = myInt & (1 << i);
// do something with curr_bit
}
But, I want to start off at the leftmost available bit, and I want its number "x" so that 1 << x will point to that exact digit
(Just as a side note, I am trying to implement repeated squaring, and I need this in my code).
Any help would be greatly appreciated!
If you're interested in the actual fastest answer (at least on a desktop), here it is: use the _bit_scan_reverse intrinsic supported by Intel Compiler and Clang (maybe Visual Studio and GCC as well).
#include "immintrin.h"
int main() { printf("%i", _bit_scan_reverse(9)); }
Result: 3 (because 1<<3 = 8 is the highest bit set in 9).
Documentation
If you're worried about portability (as you should be with all proprietary extensions like this one), just include a fallback function and use the preprocessor to select the implementation you need:
#ifdef __SSE__ // All SSE processors support bsf/bsr
#include "immintrin.h"
static inline int bit_scan_reverse(int n) { return _bit_scan_reverse(n); }
#else
// Fallback implementation here
#endif
Note that the _bit_scan_reverse returns an unspecified value for n=0. If this is a problem you can add a ternary to the code in bit_scan_reverse: return n == 0 ? 0 : _bit_scan_reverse(n);.
This is called Find first set and most modern architectures have an instruction to do that quickly. In C++20 it can be done with std::countl_zero in the <bit> header
int left_most_bit_pos = sizeof(myInt)*CHAR_BIT - std::countl_zero(myInt);
int left_most_bit = myInt & (1 << left_most_bit_pos)
Java has a method in the Integer class called highestOneBit(int value) which returns an int value with at most a single one-bit, in the position of the most significant (left most) bit that is set in the specified int value. It is implemented like this:
int highestOneBit(int value)
{
value |= (value >> 1);
value |= (value >> 2);
value |= (value >> 4);
value |= (value >> 8);
value |= (value >> 16);
return value - (value >> 1);
}
iBug's answer is very interesting, and I had never thought of doing it this way. If you're doing huge calculations where you want to find the leftmost digit many many times, I would recomment __builtin_clz in c++11. If you perform the snippet
for(int i = 31 - __builtin_clz; i >= 0; i--) {
int left_most_bit = myInt & (1 << i);
}
This will start from the left_most_bit and work it's way to the right. Hope this helps!
Implementation of __builtin_clz
Use this:
int left_most_bit = myInt & (1 << (sizeof myInt * CHAR_BIT - 1));
How does it work?
sizeof myInt returns the size of the variable myInt in bytes
CHAR_BIT is a (possibly) platform-dependent macro that tells you how many bits are there in a byte, which is typically 8
Shift 1 left by that gets the leftmost bit.
Works great in O(1) time because both sizeof myInt and CHAR_BIT are compile-time constants, so the whole expression (1 << (sizeof myInt * CHAR_BIT - 1)) is a compile-time constant, too. The compiler can then apply maximum optimization to it.
To answer this question, I read this source code on github and found a problem with the second function.
The challenge is to write C code with various restrictions in terms of operators and language constructions to perform given tasks.
/*
* fitsShort - return 1 if x can be represented as a
* 16-bit, two's complement integer.
* Examples: fitsShort(33000) = 0, fitsShort(-32768) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 8
* Rating: 1
*/
int fitsShort(int x) {
/*
* after left shift 16 and right shift 16, the left 16 of x is 00000..00 or 111...1111
* so after shift, if x remains the same, then it means that x can be represent as 16-bit
*/
return !(((x << 16) >> 16) ^ x);
}
Left shifting a negative value or a number whose shifted value is beyond the range of int has undefined behavior, right shifting a negative value is implementation defined, so the above solution is incorrect (although it is probably the expected solution).
Is there a solution to this problem that only assumes 32-bit two's complement representation?
The following only assumes 2's complement with at least 16 bits:
int mask = ~0x7FFF;
return !(x&mask)|!(~x&mask);
That uses a 15-bit constant; if that is too big, you can construct it from three smaller constants, but that will push it over the 8-operator limit.
An equivalent way of writing that is:
int m = 0x7FFF;
return !(x&~m)|!~(x|m);
But it's still 7 operations, so int m = (0x7F<<8)|0xFF; would still push it to 9. (I only added it because I don't think I've ever before found a use for !~.)
This question already has answers here:
How to align a pointer in C
(6 answers)
Closed 6 years ago.
When I browsing c++ header files of opencv, It happened to see the construct (ptr + n-1) & -n in alignPtr function. The complete function as follows
/*!
Aligns pointer by the certain number of bytes
This small inline function aligns the pointer by the certain number of bytes by shifting
it forward by 0 or a positive offset.
*/
template<typename _Tp> static inline _Tp* alignPtr(_Tp* ptr, int n=(int)sizeof(_Tp))
{
return (_Tp*)(((size_t)ptr + n-1) & -n);
}
Can you explain how it works?
In this expression its implicit that n is a power of 2 such as 2, 4, 8 etc. Lets say that n is 2^m
In a twos complement binary system:
-2 is ...11110
-4 is ...11100
-8 is ...11000
In general, n = -2^m has a representation with exactly the m rightmost digits being zero.
This means, if we take any number and & it with -2^m then it will be returned with the m rightmost digits being zero, and the other digits retained, which makes the answer a multiple of 2^m.
This means the expression x & -2^m will effectively "floor" the number to the largest multiple of 2^m that is less than or equal to x.
The addition of (n - 1) that is being done:
(x + (n-1)) & -2^m
effectively changes this from a "floor" to a "rounding".
Hello is have a question for a school assignment i need to :
Read a round number, and with the internal binaire code with bit 0 on the right and bit 7 on the left.
Now i need to change:
bit 0 with bit 7
bit 1 with bit 6
bit 2 with bit 5
bit 3 with bit 4
by example :
if i use hex F703 becomes F7C0
because 03 = 0000 0011 and C0 = 1100 0000
(only the right byte (8 bits) need to be switched.
The lession was about bitmanipulation but i can't find a way to make it correct for al the 16 hexnumbers.
I`am puzzling for a wile now,
i am thinking for using a array for this problem or can someone say that i can be done with only bitwise ^,&,~,<<,>>, opertors ???
Study the following two functions:
bool GetBit(int value, int bit_position)
{
return value & (1 << bit_position);
}
void SetBit(int& value, int bit_position, bool new_bit_value)
{
if (new_bit_value)
value |= (1 << bit_position);
else
value &= ~(1 << bit_position);
}
So now we can read and write arbitrary bits just like an array.
1 << N
gives you:
000...0001000...000
Where the 1 is in the Nth position.
So
1 << 0 == 0000...0000001
1 << 1 == 0000...0000010
1 << 2 == 0000...0000100
1 << 3 == 0000...0001000
...
and so on.
Now what happens if I BINARY AND one of the above numbers with some other number Y?
X = 1 << N
Z = X & Y
What is Z going to look like? Well every bit apart from the Nth is definately going to be 0 isnt it? because those bits are 0 in X.
What will the Nth bit of Z be? It depends on the value of the Nth bit of Y doesn't it? So under what circumstances is Z zero? Precisely when the Nth bit of Y is 0. So by converting Z to a bool we can seperate out the value of the Nth bit of Y. Take another look at the GetBit function above, this is exactly what it is doing.
Now thats reading bits, how do we set a bit? Well if we want to set a bit on we can use BINARY OR with one of the (1 << N) numbers from above:
X = 1 << N
Z = Y | X
What is Z going to be here? Well every bit is going to be the same as Y except the Nth right? And the Nth bit is always going to be 1. So we have set the Nth bit on.
What about setting a bit to zero? What we want to do is take a number like 11111011111 where just the Nth bit is off and then use BINARY AND. To get such a number we just use BINARY NOT:
X = 1 << N // 000010000
W = ~X // 111101111
Z = W & Y
So all the bits in Z apart from the Nth will be copies of Y. The Nth will always be off. So we have effectively set the Nth bit to 0.
Using the above two techniques is how we have implemented SetBit.
So now we can read and write arbitrary bits. Now we can reverse the bits of the number just like it was an array:
int ReverseBits(int input)
{
int output = 0;
for (int i = 0; i < N; i++)
{
bool bit = GetBit(input, i); // read ith bit
SetBit(output, N-i-1, bit); // write (N-i-1)th bit
}
return output;
}
Please make sure you understand all this. Once you have understood this all, please close the page and implement and test them without looking at it.
If you enjoyed this than try some of these:
http://graphics.stanford.edu/~seander/bithacks.html
And/or get this book:
http://www.amazon.com/exec/obidos/ASIN/0201914654/qid%3D1033395248/sr%3D11-1/ref%3Dsr_11_1/104-7035682-9311161
This does one quarter of the job, but I'm not going to give you any more help than that; if you can work out why I said that, then you should be able to fill in the rest of the code.
if ((i ^ (i >> (5 - 2))) & (1 >> 2))
i ^= (1 << 2) | (1 << 5);
Essentially you need to reverse the bit ordering.
We're not going to solve this for you.. but here's a hint:
What if you had a 2-bit value. How would you reverse these bits?
A simple swap would work, right? Think about how to code this swap with operators that are available to you.
Now let's say you had a 4-bit value. How would you reverse these bits?
Could you split it into two 2-bit values, reverse each one, and then swap them? Would that give you the right result? Now code this.
Generalizing that solution to the 8-bit value should be trivial now.
Good luck!