I was trying to make some code in C++ about “bitwise rotation” and I would like to make this by the left shif. I didn’t know how to code this, but I found a little code in “
C++20 provides std::rotl
and std::rotr
in the <bit>
header. An example from cppreference.com:
#include <bit>
#include <bitset>
#include <cstdint>
#include <iostream>
int main()
{
std::uint8_t i = 0b00011101;
std::cout << "i = " << std::bitset<8>(i) << '\n';
std::cout << "rotl(i,0) = " << std::bitset<8>(std::rotl(i,0)) << '\n';
std::cout << "rotl(i,1) = " << std::bitset<8>(std::rotl(i,1)) << '\n';
std::cout << "rotl(i,4) = " << std::bitset<8>(std::rotl(i,4)) << '\n';
std::cout << "rotl(i,9) = " << std::bitset<8>(std::rotl(i,9)) << '\n';
std::cout << "rotl(i,-1) = " << std::bitset<8>(std::rotl(i,-1)) << '\n';
}
I believe std::bitset
is only used in this example for its stream formatting.
It's because you're using an int
which is 32 bits, so it worked as expected by wrapping the most significant bits to the front. Use a smaller data structure like an unsigned char
to make this more managable.
You have more than 4 bits in your integer, most likely 32, but could theoretically be 64 or 16. So your bits for the value 12 are 00000000000000000000000000001100. Doing a left rotation by 1 would naturally give you the value 00000000000000000000000000011000 (=24).
if you want bitwise rotation over an arbitrary number of bits (for example 4), simply add a parameter to your function:
unsigned int rotl(unsigned int value, int shift, unsigned int width) {
return ((value << shift) & (UINT_MAX >> (sizeof(int) * CHAR_BIT - width))) | (value >> (width - shift));
}
Following code works great
#include <cstdint>
std::uint32_t rotl(std::uint32_t v, std::int32_t shift) {
std::int32_t s = shift>=0? shift%32 : -((-shift)%32);
return (v<<s) | (v>>(32-s));
}
std::uint32_t rotr(std::uint32_t v, std::int32_t shift) {
std::int32_t s = shift>=0? shift%32 : -((-shift)%32);
return (v>>s) | (v<<(32-s));
}
and of course the test for it.
#include <iostream>
int main(){
using namespace std;
cout<<rotr(8,1)<<endl; // 4
cout<<rotr(8,-1)<<endl; //16
cout<<rotl(8,1)<<endl; //16
cout<<rotl(8,-1)<<endl; //4
cout<<rotr(4,60)<<endl; //64
cout<<rotr(4,61)<<endl; //32
cout<<rotl(4,3)<<endl; //32
cout<<rotl(4,4)<<endl; //64
return 0;
}
maybe I not provided the fastest implementation, but a portable and stable one for sure
Generic version
#include <cstdint>
template< class T>
inline T rotl( T v, std::int32_t shift){
std::size_t m = sizeof(v)*std::numeric_limits<T>::digits;
T s = shift>=0? shift%m: -((-shift)%m)
return (v<<s) | (v>>(m-s));
}
template< class T>
inline T rotr( T v, std::int32_t shift){
std::size_t m = sizeof(v)*std::numeric_limits<T>::digits;
T s = shift>=0? shift%m: -((-shift)%m)
return (v>>s) | (v<<(m-s));
}
Cheers :)