Если вы ищете функцию поворота, вы можете попробовать следующее.
Во-первых, у вас есть мета-функция для получения количества битов значения, которое должно быть повернуто (примечание: 8*sizeof(T)
не будет переносимым; стандарт требует только 8 бит):
#include <climits>
template <typename T>
struct bits { enum { value = CHAR_BIT * sizeof(T) }; };
Далее определите функцию для вращения вправо. Он делает это, применяя сдвиг вправо, как и ожидалось, и сдвиг влево, чтобы сдвинуть вверх то, что было бы отменено в противном случае:
template <unsigned int N, typename T>
T rotate_right (T value)
{
enum { left = bits<T>::value - N };
return (value>>N) | (value<<left);
}
Имеют функцию диагностики для тестирования и проверки:
#include <iostream>
template <typename T>
void print_bits (std::ostream &os, T value)
{
for (unsigned int i=bits<T>::value; i!=0; --i)
os << ((value>>(i-1))&1);
}
int main () {
char c = 1,
c_ = rotate_right<1>(c);
unsigned long long ull = 0xF0F0C0C050503030,
ull_ = rotate_right<63>(ull);
std::cout << "c ="; print_bits(std::cout, c); std::cout << '\n';
std::cout << "c'="; print_bits(std::cout, c_); std::cout << '\n';
std::cout << "ull ="; print_bits(std::cout, ull); std::cout << '\n';
std::cout << "ull'="; print_bits(std::cout, ull_); std::cout << '\n';
}
Выход:
c =00000001
c'=10000000
ull =1111000011110000110000001100000001010000010100000011000000110000
ull'=1110000111100001100000011000000010100000101000000110000001100001
Поворот влево может быть реализован аналогично или с точки зрения поворота вправо.
Что касается производительности, g ++ обнаруживает идиому и использует инструкцию поворота на x86 и amd64.
g++ -std=c++0x -S main.cc
cat main.s
...
sarl %eax
...