2016-11-17 3 views
1

비트 마스크를 가로로 뒤집을 수있는 쉬운 방법이 있습니까? 그것은 다음을 수행해야 더 우아한 방법이 있나요가로로 비트 마스크를 뒤집기

uint16 flipUint16Horizontally(uint16 bitmask) 
{ 
    uint16 flippedMask = 0; 
    for(unsigned int bit = 0; bit < 16; ++bit) 
    { 
     uint16 currentBit = (bitmask & (1 << bit)) >> bit; 
     flippedMask |= currentBit << (15 - bit); 
    } 
    return flippedMask; 
} 

:

0b1010101111001101 -> 0b1011001111010101 

직선 앞으로 솔루션은 조금만 비트 일을 할 것인가?

+0

우아함을 정의하십시오. – 2501

+0

@ 2501 : 어리석은 방법이 아닙니다 .-) – m47h

+0

여기에는 여러 가지 접근법이 있습니다 (https://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious); 그러나, 아이디어의 아무도는 "one-liner"에게 불릴 수 없다. – Codor

답변

0

거기에 uint16이 있으면 룩업 테이블이 있습니다. 그건 반대쪽에 대한 하나의 라이너, 물론 초기화가 좀 더 걸립니다. 반드시 큰 테이블이기 때문에 가장 빠른 방법은 아닙니다. 아마도 캐시 무효를 야기 할 가능성이있는 무작위로 색인을 생성 할 것입니다. 또한 여전히 간단하고 공간을 많이 차지하지 않는 바이트 : 바이트를 역순으로 바꾸는 룩업 테이블. 확실한 방법으로 사용하십시오 :

return (bitreverse[x & 0xFF] << 8) | bitreverse[x >> 8]; 

물론 초기화를 처리해야하지만 속도는 중요하지 않습니다.

제 생각에는 약간의 비트 연산 (그리고 전혀 이해할 수없는 나머지 연산이나 그와 같은 것)을 사용하지 않고 좀 더 복잡하지만 처음에는 인접한 비트를 뒤집은 다음 인접한 2 비트 조각을 뒤집는 것이 더 멋지지만, 마지막으로 모든 비트가 "전역 적으로"역전 될 때까지 매 단계마다 역전 된 것의 너비를 두 배로 늘립니다. 이러한 단계를 순서대로 재정렬 할 수 있으며 한 번의 작업으로 ILP를 적게 쓸 수 있습니다.

x = ((x & 0x5555) << 1) | ((x >> 1) & 0x5555); // swap bits 
x = ((x & 0x3333) << 2) | ((x >> 2) & 0x3333); // swap 2-bit pieces 
x = ((x & 0x0f0f) << 4) | ((x >> 4) & 0x0f0f); // swap nibbles 
return (x >> 8) | (x << 8); // optimized last step