2010-07-06 68 views
3

如何移動8x8區域的列?例如,我有這個一個64位無符號整數如下:位列移位

#include <boost/cstdint.hpp> 

int main() 
{ 
    /** In binary: 
     * 
     * 10000000 
     * 10000000 
     * 10000000 
     * 10000000 
     * 00000010 
     * 00000010 
     * 00000010 
     * 00000010 
     */ 
    boost::uint64_t b = 0x8080808002020202; 
} 

現在,我想移後的第一縱行讓說四次,之後就變成這樣:

/** In binary: 
    * 
    * 00000000 
    * 00000000 
    * 00000000 
    * 00000000 
    * 10000010 
    * 10000010 
    * 10000010 
    * 10000010 
    */ 

    b == 0x82828282; 

只有按位運算符纔可以做到這一點,或者是什麼?

回答

5

我最好的猜測是:

(((b & 0x8080808080808080) >> 4 * 8) | (b & ~0x8080808080808080) 

的想法是隔離柱位,只有將它們轉移。

2

只有按位運算符才能完成這項工作,還是比較快?

是的。

你是如何做到這一點將取決於你想如何「通用」的解決方案。總是第一列?總是移動4?

這裏的一個想法:

  • 前4個字節表示頂部4行。利用該技術,循環訪問前4位。
  • 使用0x8屏蔽掉第一列,查看該位是否已設置。
  • 將該位移過4個字節(>>4),當然它需要在uint64中才能做到這一點。
  • biwise-或(|)它違背了新的字節。

通過避免循環和編寫更多的代碼,你可以做得更好。

1

可能有一個SIMD指令。你必須在你的VC++設置中打開這些指令,當然它們不能在除AMD/Intel處理器之外的架構上工作。

0

在這種情況下,您希望將值分成兩部分,即第一列和其他列。將第一列移入適當的數量,然後將它們組合在一起。

b = ((b & 0x8080808080808080)) >> (8*4) | (b & 0x7f7f7f7f7f7f7f7f) 
0

完整的猜測,因爲我沒有一個編譯器和升壓可用庫:

鑑於B,山坳(右起計1〜8),和shift(移位距離) 在你的榜樣,col將是8並且移位將是4.

boost::uint64_t flags = 0x0101010101010101; 
boost::uint64_t mask = flags << (col -1); 
boost::int64_t eraser = -1^flags; 
boost::uint64_t data = b & mask; 
data = data >> (8*shift) 
b = (b & eraser) | data;