1

I need to implement a function that rotates left the last 10 bits of an int.

So if an int has value

0b 1111 0000 0000 0000 0000 1100 1100 0000

a left rotation by 2 would give us

0b 1111 0000 0000 0000 0000 1111 0000 0000

A further left rotation by 1 would give

0b 1111 0000 0000 0000 0000 1110 0000 0001
  • ptr - pointer to given int that we want to rotate
  • n - how many times we want to rotate
void leftRotateLast10Digits(int * ptr, int n) {

}

I understand how to do it if we wanted to rotate the whole int, but I'm not sure how to do it for the last 10 digits only. I think to left rotate an int, it would look something like below. But still, I don't understand how to only rotate the last 10 digits.

void leftRotate(int * ptr, int n) {
    int DROPPED_MSB;
    int INT_BITS = sizeof(int) * 8 - 1;
    int num = *ptr;

    // The effective rotation
    n %= INT_BITS;

    while(n) {
        DROPPED_MSB = (num >> INT_BITS) & 1; 

        // Left rotate num by 1 and set its dropped MSB as new LSB
        num = (num << 1) | DROPPED_MSB;
        n--;
    }
    *ptr = num;
}
Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39
scy17
  • 61
  • 4
  • 1
    You could take the starting number and & it with 0b1111111111111111111110000000000. Now you have the bits that must not change. You can do the inverse and & the starting number with 0b1111111111. Those 10 bits need to rotate. You know how to do that. Finally | the both numbers together. – Cheatah Jul 09 '20 at 20:49
  • 1) so the rotation involves only the 10 least significant bits, did I understand correctly? 2) `int INT_BITS = sizeof(int) * 8 - 1;` seem to build a general function working for every architecture. Is it a requirement? Would the assumption of a 4byte integer acceptable? – Roberto Caboni Jul 09 '20 at 20:50
  • scy17, do you want this rotation to work for `n > 9`, for `n < 0`? – chux - Reinstate Monica Jul 09 '20 at 21:19
  • scy17 Note: `int INT_BITS = sizeof(int) * 8 - 1; n %= INT_BITS;` is questionable code. I'd expect `n %= INT_BITS + 1;` and more to handle `n < 0`. – chux - Reinstate Monica Jul 09 '20 at 21:22

2 Answers2

5

I'm not sure how to do it for the last 10 digits only

Isolate the 10 bits from the rest.

Rotate the 10 bits (I'd skip the while loop).

"Or" the 10 bits back into the int.


(Let us use "least" rather than "last")

void leftRotateLeast10Digits(int *ptr, int n) {
  int value = *ptr;
  int ls10bits = value & 0x3FF;
  value ^= ls10bits;  // zero out the 10 LS bits.
  
  // If `n` outside [0...9] range needed
  n %= 10;
  if (n < 0) n += 10;

  // move LS bits left `n` times` and MS bits right `10-n` times.
  int rotated = (ls10bits << n) | (ls10bits >> (10-n));
  rotated &= 0x3FF;

  value |= rotated;
  *ptr = value;
}

Some additional work needed to support 16-bit int. int ls10bits --> int_least32_t ls10bits to easily handle the <<.
I'd suggest this also works for rare non-2's complement when the result is not a trap.


Tip: bit manipulations and shifts are best done with unsigned types and math rather than signed ones like int.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

A relatively easy way to do this would be to separate the integer into two parts: the 10 bits that should be rotated and the other (upper) bits that shouldn't be rotated. Then, after rotating the appropriate part, restore the other bits using a bitwise OR operation:

void leftRotate(int* ptr, int n)
{
    int mask = 0x03FF; // Mask for lower 10 bits;
    int DROPPED_MSB;
    int INT_BITS = 10; // Only work with 10 bits
    int num = *ptr & mask; // Extract JUST low 10 bits
    int top = *ptr & ~mask; // Save all the OTHER bits
    n %= INT_BITS; // The effective rotation
    while (n) {
        DROPPED_MSB = (num >> INT_BITS) & 1;
        // Left rotate num by 1 and set its dropped MSB as new LSB
        num = (num << 1) | DROPPED_MSB;
        n--;
    }
    *ptr = num | top; // Restore the saved upper bits
}
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83