简体   繁体   English

反向位查找表生成背后的算法(8位)

[英]algorithm behind the generation of the reverse bits lookup table(8 bit)

I found the lookup table here.我在这里找到了查找表 The table is generated as a reverse bits table of 8 bits.该表生成为 8 位的反向位表。

I can not figure out why it works.我无法弄清楚它为什么起作用。 Please explain the theory behind it.请解释其背后的理论。 Thanks谢谢

static const unsigned char BitReverseTable256[256] = 
{
 #   define R2(n)     n,     n + 2*64,     n + 1*64,     n + 3*64
 #   define R4(n) R2(n), R2(n + 2*16), R2(n + 1*16), R2(n + 3*16)
 #   define R6(n) R4(n), R4(n + 2*4 ), R4(n + 1*4 ), R4(n + 3*4 )
     R6(0), R6(2), R6(1), R6(3)
};

First off a comment: This kind of thing is normally only done in the IOCCC .首先评论:这种事情通常只在IOCCC 中完成。 Code like this should not be used in production-environments because it is non-obvious .像这样的代码不应该在生产环境中使用,因为它是不明显的 The reason why i mention this is to remove the false impression that this has any performance- or space benefit, the compiled code will contain the same (number of) bytes you would get if writing the 256 numbers directly into the array.我之所以提到这一点是为了消除这样的错误印象,即这具有任何性能或空间优势,编译后的代码将包含与将 256 个数字直接写入数组时获得的相同(数量)字节。

Ok, now to how it works.好的,现在来看看它是如何工作的。 It works recursively of course, defining two bits at a top level R6, then two more at the next... But how in detail?当然,它以递归方式工作,在顶层 R6 定义两个位,然后在下一个定义两个位……但具体如何? Ok:行:

The first clue you get is the interesting 0->2->1->3 sequence.你得到的第一个线索是有趣的 0->2->1->3 序列。 You should ask yourself " why? ".你应该问自己“为什么? ”。 This is the building block that is required for the construction.这是构建所需的构建块。 The numbers 0 1 2 3 in binary are 00 01 10 11 and if you reverse each: 00 10 01 11 which is 0 2 1 3!二进制中的数字 0 1 2 3 是00 01 10 11 ,如果将每个数字颠倒: 00 10 01 11就是 0 2 1 3!

Now lets take a look at what we want the table to do: It should become something like this:现在让我们来看看我们希望表格做什么:它应该变成这样:

00000000 10000000 01000000 11000000 
00100000 10100000 01100000 11100000 
00010000 10010000 01010000 11010000
00110000 10110000 01110000 11110000 ...

because you want it to map index 0 to 0, index 00000001 to 10000000 and so on.因为您希望它将索引 0 映射到 0,将索引 00000001 映射到 10000000 等等。

Notice that the most significant (leftmost) 2 bits of each number: 00 10 01 11 for every line!请注意,每个数字的最高有效(最左边)2 位:每行00 10 01 11

Now notice that the second most significant 2 bits of each number increase the same way (00 10 01 11) but for the "columns".现在请注意,每个数字的第二个最重要的 2 位以相同的方式增加 (00 10 01 11),但对于“列”。

The reason why i chose to order the array in rows of length 4 is, that we found out that 2 bits are written at a time and 2 bits can create 4 patterns.我选择按长度为 4 的行对数组进行排序的原因是,我们发现一次写入 2 位,而 2 位可以创建 4 种模式。

If you then continue observing the remaining numbers of the table (256 entries total) you will see that the 3rd 2 bits can be found having the 00 10 01 11 sequence if you order the table in columns of 16 and the last 2 bits when you order it in columns of 64.如果您继续观察表的剩余数字(总共 256 个条目),您将看到如果您按 16 列和最后 2 位对表进行排序,则可以发现第 3 2 位具有00 10 01 11序列在 64 列中对其进行排序。

Now i implicitly told you where the numbers 16 and 64 in the original macro-expansion came from.现在我含蓄地告诉你原始宏扩展中的数字 16 和 64 是从哪里来的。

That are the details, and to generalize: The highest level of the recursion generates the least significant 2 bits, the middle two levels do their thing and the lowest level generates the most significant 2 bits.这就是细节,概括一下:递归的最高级别生成最低有效的 2 位,中间的两个级别执行它们的操作,最低级别生成最高有效的 2 位。

If you are working with Python and happen to end up here, this is how the lookup table would look like.如果您正在使用 Python 并且碰巧到了这里,那么查找表应该是这样的。 Nevertheless, Bernd Elkemann's explanation still stands.尽管如此, Bernd Elkemann 的解释仍然成立。

# Generating the REVERSE_BIT_LUT while pre-processing
# LUT is shorthand for lookuptable
def R2(n, REVERSE_BIT_LUT):
    REVERSE_BIT_LUT.extend([n, n + 2 * 64, n + 1 * 64, n + 3 * 64])


def R4(n, REVERSE_BIT_LUT):
    return (
        R2(n, REVERSE_BIT_LUT),
        R2(n + 2 * 16, REVERSE_BIT_LUT),
        R2(n + 1 * 16, REVERSE_BIT_LUT),
        R2(n + 3 * 16, REVERSE_BIT_LUT),
    )


def R6(n, REVERSE_BIT_LUT):
    return (
        R4(n, REVERSE_BIT_LUT),
        R4(n + 2 * 4, REVERSE_BIT_LUT),
        R4(n + 1 * 4, REVERSE_BIT_LUT),
        R4(n + 3 * 4, REVERSE_BIT_LUT),
    )


def LOOK_UP(REVERSE_BIT_LUT):
    return (
        R6(0, REVERSE_BIT_LUT),
        R6(2, REVERSE_BIT_LUT),
        R6(1, REVERSE_BIT_LUT),
        R6(3, REVERSE_BIT_LUT),
    )


# LOOK_UP is the function to generate the REVERSE_BIT_LUT
REVERSE_BIT_LUT = list()
LOOK_UP(REVERSE_BIT_LUT)

I am working on providing code snippets of Sean's bit hacks in Python here .我正致力于在此处提供Sean在 Python 中的一些技巧的代码片段。

Reverse bits table is just one of possible offline generated constants.反向位表只是可能的离线生成常量之一。 People find an algorithm to define it by using unrolling macro.人们通过使用展开宏找到一种算法来定义它。 It won't be possible to find such algorithm for another constant.不可能为另一个常数找到这样的算法。 So you will have to maintain some generators infrastructure anyway.所以无论如何你都必须维护一些发电机基础设施。

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#define BYTES_PER_LINE 16
#define BYTES_GLUE ", "
#define LINE_PREFIX "  "
#define LINE_TERMINATOR ",\n"

#define PRINT(string) fwrite(string, 1, sizeof(string), stdout)

static inline void print_reversed_byte(uint8_t byte) {
  uint8_t reversed_byte = 0;

  for (uint8_t bit_index = 0; bit_index < 8; bit_index++) {
    uint8_t bit_value = (byte >> bit_index) & 1;
    reversed_byte |= bit_value << (7 - bit_index);
  }

  printf("0x%02x", reversed_byte);
}

int main() {
  uint8_t index = 0;

  while (true) {
    if (index != 0) {
      if (index % BYTES_PER_LINE == 0) {
        PRINT(LINE_TERMINATOR);
        PRINT(LINE_PREFIX);
      } else {
        PRINT(BYTES_GLUE);
      }
    }

    print_reversed_byte(index);

    if (index == 255) {
      break;
    }
    index++;
  }

  return 0;
}

Use it in generated_constants.c.in with cmake:使用 cmake 在generated_constants.c.in使用它:

const uint8_t REVERSE_BITS_TABLE[256] = {
  @CMAKE_REVERSE_BITS_TABLE@
};

You will receive pretty and compact table.您将收到漂亮而紧凑的桌子。

See it's usage in LZWS for example.例如,查看它在LZWS 中的用法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM