繁体   English   中英

有人可以帮忙解释一下此C one班轮做什么吗?

[英]Could someone help explain what this C one liner does?

我通常可以弄清楚大多数C代码,但这是我的头。

#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))

用法示例如下:

int x = 57;
kroundup32(x);
//x is now 64

其他一些示例是:

一对一
2比2
7至8
31至32
60至64
3000至4096

我知道它会将一个整数四舍五入为最接近的2的幂,但是据我所知,这是差不多的。

任何解释将不胜感激。

谢谢

(--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
  1. 将x减1
  2. 或x与(x / 2)。
  3. 或x与(x / 4)。
  4. 或x与(x / 16)。
  5. 或x与(x / 256)。
  6. 或x与(x / 65536)。
  7. x增加1。

对于32位无符号整数,这应将值向上移动到等于或大于2的最接近的幂。 “或”部分将所有低位设置在最高位以下,因此它的最终幂为2减1,然后再加一个。 看起来似乎已经过优化,因此不太可读; 可以通过按位操作和位移位单独进行操作,也可以作为宏进行操作(因此无需调用函数)。

按位或和移位操作实质上是将最高位和零位之间的每个位设置。 这将产生2^n - 1形式的数字。 最后的增量加1得到2^n形式的数字。 初始递减可确保您不会将已经是2的幂的数字四舍五入到下一个幂,例如2048不会变成4096。

在我的机器上, kroundup32提供了6.000m发/秒
下一个功能给出7.693m发/秒

inline int scan_msb(int x)
{
#if defined(__i386__) || defined(__x86_64__)
    int y;
    __asm__("bsr %1, %0"
            : "=r" (y)
            : "r" (x)
            : "flags"); /* ZF */
    return y;
#else
#error "Implement me for your platform"
#endif
}

inline int roundup32(int x)
{
    if (x == 0) return x;
    else {
        const int bit = scan_msb(x);
        const int mask = ~((~0) << bit);
        if (x & mask) return (1 << (bit+1));
        else return (1 << bit);
    }
}

因此,@ thomasrutter我不会说它是“高度优化的”。

和适当的(仅有意义的部分)组装(对于GCC 4.4.4):

kroundup32:
    subl    $1, %edi
    movl    %edi, %eax
    sarl    %eax
    orl %edi, %eax
    movl    %eax, %edx
    sarl    $2, %edx
    orl %eax, %edx
    movl    %edx, %eax
    sarl    $4, %eax
    orl %edx, %eax
    movl    %eax, %edx
    sarl    $8, %edx
    orl %eax, %edx
    movl    %edx, %eax
    sarl    $16, %eax
    orl %edx, %eax
    addl    $1, %eax
    ret

roundup32:
    testl   %edi, %edi
    movl    %edi, %eax
    je  .L6
    movl    $-1, %edx
    bsr %edi, %ecx
    sall    %cl, %edx
    notl    %edx
    testl   %edi, %edx
    jne .L10
    movl    $1, %eax
    sall    %cl, %eax
.L6:
    rep
    ret
.L10:
    addl    $1, %ecx
    movl    $1, %eax
    sall    %cl, %eax
    ret

由于某种原因,我没有在GCC的标准标头(仅__TBB_machine_lg / __TBB_Log2 )中找到适当的scan_msb实现(例如#define scan_msb(x) if (__builtin_constant_p (x)) ... )。

暂无
暂无

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

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