Column bit offset

How can I move a column in an 8x8 area? For example, I have this single 64-bit unsigned integer , as shown below:

#include <boost/cstdint.hpp>

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

Now I want to wrap the first vertical line, say four times, after which it becomes the following:

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

  b == 0x82828282;

Is it possible to do this relatively quickly with just bitwise operators or what?

+3
source share
5 answers

My best guess:

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

The idea is to isolate the column bits and shift only them.

+5
source

Is it possible to do this relatively quickly with just bitwise operators or what?

Yes.

How you do this will depend on how β€œgeneral” you want to make the decision. Always the first column? Always shift by 4?

Here is an idea:

  • 4 4 . , 4.
  • 0x8, , .
  • 4 (>>4), , uint64.
  • biwise-or (|) .

, , , .

+2

SIMD. V++, , , , AMD/Intel.

+1

, . , .

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

Complete the guess, since I don't have a compiler or Boost libs available:

Given b, col (1 to 8 on the right) and shift (shift distance) In your example, col will be 8 and shift will be 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;
0
source

Source: https://habr.com/ru/post/1753395/


All Articles