asdasdqwer
asdasdqwer

Reputation: 53

Reverse nibbles of a hexadecimal number in C++

What would be the fastest way possible to reverse the nibbles (e.g digits) of a hexadecimal number in C++?

Here's an example of what I mean : 0x12345 -> 0x54321

Here's what I already have:

unsigned int rotation (unsigned int hex) {
    unsigned int result = 0;

    while (hex) {
        result = (result << 4) | (hex & 0xF);
        hex >>= 4;
    }

    return result;
}

Upvotes: 2

Views: 459

Answers (2)

user555045
user555045

Reputation: 64904

This problem can be split into two parts:

  • Reverse the nibbles of an integer. Reverse the bytes, and swap the nibble within each byte.
  • Shift the reversed result right by some amount to adjust for the "variable length". There are std::countl_zero(x) & -4 (number of leading zeroes, rounded down to a multiple of 4) leading zero bits that are part of the leading zeroes in hexadecimal, shifting right by that amount makes them not participate in the reversal.

For example, using some of the new functions from <bit>:

#include <stdint.h>
#include <bit>

uint32_t reverse_nibbles(uint32_t x) {
    // reverse bytes
    uint32_t r = std::byteswap(x);
    // swap adjacent nibbles
    r = ((r & 0x0F0F0F0F) << 4) | ((r >> 4) & 0x0F0F0F0F);
    // adjust for variable-length of input
    int len_of_zero_prefix = std::countl_zero(x) & -4;
    return r >> len_of_zero_prefix;
}

That requires C++23 for std::byteswap which may be a bit optimistic, you can substitute it with some other byteswap.

Easily adaptable to uint64_t too.

Upvotes: 2

pm100
pm100

Reputation: 50190

i would do it without loops based on the assumption that the input is 32 bits

  result = (hex & 0x0000000f) << 28
         | (hex & 0x000000f0) << 20
         | (hex & 0x00000f00) << 12  
  ....

dont know if faster, but I find it more readable

Upvotes: 1

Related Questions