I am trying to implement a rotate left function that rotates an integer x left by n bits
The best way is:
int rotateLeft(int x, int n)
{
_asm
{
mov eax, dword ptr [x]
mov ecx, dword ptr [n]
rol eax, cl
}
}
If you need to rotate an int
variable right in your code, then the fastest way is:
#define rotl( val, shift ) _asm mov eax, dword ptr[val] _asm mov ecx, dword ptr [shift] _asm rol eax, cl _asm mov dword ptr [val], eax
val
is the value you rotate, shift
is the length of the rotation.
Can you define 'rotate left' for a signed int
?
I would simply cast x
to an unsigned int
and perform the rotation the way you have it right now.
On another note: does your code need to work on different architectures (not just 32-bit)? You may want to avoid hardcoding the int
bitsize.
I find a way for doing a rotate that can be useful when you work with some bit who the size is fixed and you knew it:
int rotate_bit_left(int bit_rotating){
int LastMax = 64;
bit_rotating = (bit_rotating>=LastMax)? ((bit_rotating << 1 ) | 0x01) : bit_rotating << 1 ;
return bit_rotating;
/*
Here LastMax is 64 because in the exemple I work in the Ascii table where the max is 0111 1111 and this value can be adapted with the value of the last one bit in decimale
*/
}
This function can be changed to a right rotate
int rotate_bit_right(int bit_rotating){
bit_rotating = ((bit_rotating%2)==1)? ((bit_rotating >> 1)| 0x80 ): bit_rotating >> 1 ;
return bit_rotating;
/*
Because if is a odd number then the last bit is one and we have to put it in the first place
*/
}
Notice that 0x01 and 0x80 must be changed if your worked in an other case than Ascii table to Hexa number with a pattern like this : 0...0001 for the left rotate 100....0 for the right rotate
int rotateLeft(int x, int n) {
return (x << n) | (x >> (32 - n)) & ~((-1 >> n) << n);
}
UPDATE:(thanks a lot @George)
int rotateLeft(int x, int n) {
return (x << n) | (x >> (32 - n)) & ~(-1 << n);
}
not use '-' version.
int rotateLeft(int x, int n) {
return (x << n) | (x >> (0x1F & (32 + ~n + 1))) & ~(0xFFFFFFFF << n);
}
//test program
int main(void){
printf("%x\n",rotateLeft(0x87654321,4));
printf("%x\n",rotateLeft(0x87654321,8));
printf("%x\n",rotateLeft(0x80000000,1));
printf("%x\n",rotateLeft(0x78123456,4));
printf("%x\n",rotateLeft(0xFFFFFFFF,4));
return 0;
}
/* result : GCC 4.4.3 and Microsoft(R) 32-bit C 16.00.40219.01
76543218
65432187
1
81234567
ffffffff
*/
Current best practice for compiler-friendly rotates is this community-wiki Q&A. The code from wikipedia doesn't produce very good asm with clang, or gcc older than 5.1.
There's a very good, detailed explanation of bit rotation a.k.a. circular shift on Wikipedia.
Quoting from there:
unsigned int _rotl(const unsigned int value, int shift) {
if ((shift &= sizeof(value)*8 - 1) == 0)
return value;
return (value << shift) | (value >> (sizeof(value)*8 - shift));
}
unsigned int _rotr(const unsigned int value, int shift) {
if ((shift &= sizeof(value)*8 - 1) == 0)
return value;
return (value >> shift) | (value << (sizeof(value)*8 - shift));
In your case, since you don't have access to the multiplication operator, you can replace *8
with << 3
.
EDIT You can also remove the if
statements given your statement that you cannot use if
. That is an optimization, but you still get the correct value without it.
Note that, if you really intend to rotate bits on a signed
integer, the interpretation of the rotated result will be platform dependent. Specifically, it will depend on whether the platform uses Two's Complement or One's Complement. I can't think of an application where it is meaningful to rotate the bits of a signed integer.
In ISO C (no idea if this is your implementation language or not, but it sure looks like it), shift-right on a signed integer that’s negative is implementation-defined and should thus be avoided.
If you’re doing bitops anyway, you really should cast to unsigned integers first.