How to de-interleave bits (UnMortonizing?)

笑着哭i 提交于 2019-11-26 22:21:57

问题


What is the most efficient way to de-interleave bits from a 32 bit int? For this particular case, I'm only concerned about the odd bits, although I'm sure it's simple to generalize any solution to both sets.

For example, I want to convert 0b01000101 into 0b1011. What's the quickest way?

EDIT:

In this application, I can guarantee that the even bits are all zeros. Can I take advantage of that fact to improve speed or reduce space?


回答1:


Given that you know that every other bit is 0 in your application, you can do it like this:

x = (x | (x >> 1)) & 0x33333333;
x = (x | (x >> 2)) & 0x0f0f0f0f;
x = (x | (x >> 4)) & 0x00ff00ff;
x = (x | (x >> 8)) & 0x0000ffff;

The first step looks like this:

  0a0b0c0d0e0f0g0h0i0j0k0l0m0n0o0p   x
| 00a0b0c0d0e0f0g0h0i0j0k0l0m0n0o0   x >> 1
  --------------------------------
= 0aabbccddeeffgghhiijjkkllmmnnoop   x | (x >> 1)
& 00110011001100110011001100110011   0x33333333
  --------------------------------
= 00ab00cd00ef00gh00ij00kl00mn00op   (x | (x >> 1)) & 0x33333333

Then the second step works with two bits at a time, and so on.




回答2:


In terms of speed, a lookup table 16 bits wide with 2^32 entries will be hard to beat! But if you don't have that much memory to spare, four lookups in a 256-entry table, plus a few shifts and ANDs to stitch them together, might be a better choice. Or perhaps the sweet spot is somewhere in between...it depends on the resources you have available, and how the cost of initializing the lookup table will be amortized over the number of lookups you need to perform.




回答3:


I'm not sure how quick it would be, but you could do something like

int a = 0b01000101;
int b = 0;
int i = 0;
while (a > 0) {
    b |= (a & 1) << i;
    a >>= 2;
}

Which would pull all the odd bits off of a and put them on b.



来源:https://stackoverflow.com/questions/3137266/how-to-de-interleave-bits-unmortonizing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!