位调整重新排序

发布于 2024-07-14 15:22:30 字数 701 浏览 8 评论 0原文

我需要对 7 位值进行任意重新排序(是的,我知道我应该使用表格),并且想知道是否有任何位黑客可以做到这一点。

示例:

// <b0, b1, b2, b3, b4, b5, b6> -> <b3, b2, b4, b1, b5, b0, b6>

// the naive way
out =
   (0x020 & In) << 5 |
   (0x008 & In) << 2 |
   (0x040 & In)      |
   (0x012 & In) >> 1 |
   (0x004 & In) >> 2 |
   (0x001 & In) >> 3;

// 6 ANDs, 5 ORs, 5 shifts = 16 ops

编辑: 我正在考虑类似 this

只是为了好玩,因为我是 AFTK,所以我正在尝试强力搜索以下形式的解决方案:

((In * C1) >> C2) & 0x7f

未找到解决方案。

I need to do an arbitrary reorder of a 7 bit value (Yes I know I should be using a table) and am wondering if there are any bit hacks to do this.

Example:

// <b0, b1, b2, b3, b4, b5, b6> -> <b3, b2, b4, b1, b5, b0, b6>

// the naive way
out =
   (0x020 & In) << 5 |
   (0x008 & In) << 2 |
   (0x040 & In)      |
   (0x012 & In) >> 1 |
   (0x004 & In) >> 2 |
   (0x001 & In) >> 3;

// 6 ANDs, 5 ORs, 5 shifts = 16 ops

edit:
I was thinking of something along the lines of this

Just for kicks and because I was AFTK I'm trying a brute force search for solutions of the form:

((In * C1) >> C2) & 0x7f

No solutions found.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

仅此而已 2024-07-21 15:22:30

第一步似乎是理解数学解决方案并对其进行优化。

请参阅此处的位黑客

The first step seems to be to understand a mathematical solution and optimize that.

see here of bit hacks

耳钉梦 2024-07-21 15:22:30

看看你的“天真的”代码的编译器输出,它可能会让你感到惊讶。 我曾经做过类似的事情,编译器(VC++2005)完全改变了我所有的 and 和移位的值,使它们更有效,例如我确信它会删除你的“(0x001 & In)> ;>3”。

但是,是的,如果重新洗牌是固定功能,那么表格可能是最好的。

更新

为了一笑,我查看了 VC++ 2005 的编译器输出......

首先,我尝试为“In”使用常量值,但编译器并没有被愚弄,它生成了以下代码:

mov eax,469h

即。 它完全优化了它。

所以......我尝试了一个正确的输入并得到了这个:

00401D4F  mov         eax,ecx 
00401D51  and         eax,20h 
00401D54  shl         eax,3 
00401D57  mov         edx,ecx 
00401D59  and         edx,8 
00401D5C  or          eax,edx 
00401D5E  mov         edx,ecx 
00401D60  sar         edx,1 
00401D62  and         edx,2 
00401D65  or          edx,ecx 
00401D67  sar         edx,1 
00401D69  shl         eax,2 
00401D6C  and         edx,9 
00401D6F  or          eax,edx 
00401D71  and         ecx,40h 
00401D74  or          eax,ecx 

这是四个移位操作,五个AND,四个OR - 对于六个输入来说还不错。 可能比大多数人手工做的要好。

它可能还针对乱序执行进行了优化,因此时钟周期比看起来要少。 :-)

Have a look at the compiler output of your "naive" code, it might surprise you. I once did something like that and the compiler (VC++2005) completely changed the values of all the ands and shifts for me to make them more efficient, eg I'm sure it would remove your "(0x001 & In) >> 3".

But yes, if the reshuffle is a fixed function then a table is probably best.

Update

For a laugh I looked at the compiler output from VC++ 2005....

First I tried a constant value for "In" but the compiler wasn't fooled one bit, it produced this code:

mov eax,469h

ie. it completely optimized it away.

So ... I tried a proper input and got this:

00401D4F  mov         eax,ecx 
00401D51  and         eax,20h 
00401D54  shl         eax,3 
00401D57  mov         edx,ecx 
00401D59  and         edx,8 
00401D5C  or          eax,edx 
00401D5E  mov         edx,ecx 
00401D60  sar         edx,1 
00401D62  and         edx,2 
00401D65  or          edx,ecx 
00401D67  sar         edx,1 
00401D69  shl         eax,2 
00401D6C  and         edx,9 
00401D6F  or          eax,edx 
00401D71  and         ecx,40h 
00401D74  or          eax,ecx 

That's four shift operations, five ANDs, four ORs - not bad for six inputs. Probably better than most people could do by hand.

It's probably also optimized for out-of-order execution so it'll be less clock cycles than it seems. :-)

旧时模样 2024-07-21 15:22:30

对于常见操作,有很多位旋转技巧,即反转 32 位字中的位顺序(移位、AND 和 OR 各 10 个,AFAICR)。

在这种情况下,从输入到输出的映射显然是完全任意的,我看不到任何清理它的方法。

使用查找表:)

There are plenty of bit-twiddling hacks for common operations, i.e. to reverse the order of the bits in a 32-bit word (10 each of shift, AND and OR, AFAICR).

In this case, with an apparently completely arbitrary mapping from input to output, I can't see any way of cleaning this up.

Use a lookup table :)

当爱已成负担 2024-07-21 15:22:30

在优化之前,您应该确保您的“天真的”方式正在按照您的意图进行。 如果我将您的代码放入一个函数并运行此循环:

for (b=0;b<7;b++)
{
    i=1<<b;
    printf("%d: %02x -> %02x\n", b, i, shuffle(i));
}

它会产生此输出,这与注释相矛盾。 事实上,它会丢失比特。

0: 01 -> 00
1: 02 -> 01
2: 04 -> 01
3: 08 -> 20
4: 10 -> 08
5: 20 -> 00
6: 40 -> 40

为了获得您描述的随机播放,我会像这样编码:

   //    0 1 2 3 4 5 6 
   //-> 3 2 4 1 5 0 6
   (0x001 & In) << 3 |
   (0x004 & In) << 2 |
   (0x020 & In)      |
   (0x012 & In) << 1 |
   (0x008 & In) >> 2 |
   (0x020 & In) >> 5 ;

Before you optimize, you should make sure your 'naive' way is doing what you intend. If I make your code into a function and run this loop:

for (b=0;b<7;b++)
{
    i=1<<b;
    printf("%d: %02x -> %02x\n", b, i, shuffle(i));
}

It produces this output, which contradicts the comments. In fact, it loses bits.

0: 01 -> 00
1: 02 -> 01
2: 04 -> 01
3: 08 -> 20
4: 10 -> 08
5: 20 -> 00
6: 40 -> 40

In order to get the shuffle you describe, I would code it like this:

   //    0 1 2 3 4 5 6 
   //-> 3 2 4 1 5 0 6
   (0x001 & In) << 3 |
   (0x004 & In) << 2 |
   (0x020 & In)      |
   (0x012 & In) << 1 |
   (0x008 & In) >> 2 |
   (0x020 & In) >> 5 ;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文