使用饱和加法对32位字进行相加

3

你知道使用MMX/SSE汇编指令添加饱和的32位有符号单词的方法吗?我能找到8/16位版本,但没有32位版本。


请查看Agner Fog的vectorclass库以获取使用C++内置函数实现加法和减法的方法。此外,GPL源文件的副本在此处,使用XOR检查相同/不同的符号,并使用移位、PANDN和PADDD来修正结果。 - Peter Cordes
2个回答

2
您可以通过以下步骤模拟饱和有符号加法:
int saturated_add(int a, int b)
{
    int sum = a + (unsigned)b;                // avoid signed-overflow UB
    if (a >= 0 && b >= 0)
        return sum > 0 ? sum : INT32_MAX;     // catch positive wraparound
    else if (a < 0 && b < 0)
        return sum > 0 ? INT32_MIN : sum;     // catch negative wraparound
    else
        return sum;                           // sum of pos + neg always fits
}

对于无符号数,更加简单,参见这个stackoverflow帖子

在SSE2中,上述操作映射为一系列并行比较和AND / ANDN操作。不幸的是,硬件中没有单个操作可用。


2
在C语言中进行位饱和加法(HW)可能可以更好地进行向量化,使用一些pxor来进行sum^asum^b,以及pcmpgt(0, v)psrad - Peter Cordes

1

饱和无符号减法很容易,因为对于 `a -= b',我们可以执行

    asm (
        "pmaxud %1, %0\n\t" // a = max (a,b)
        "psubd %1, %0" // a -= b
        : "+x" (a)
        : "xm" (b)
    );

使用SSE。

我正在寻找无符号加法,但可能唯一的方法是将其转换为饱和无符号减法,执行它,然后再转换回来。对于有符号变量也是同样的。

编辑:使用无符号加法,您可以通过这种方式获得min(a, ~b) + b,这当然有效。对于有符号加法和减法,您有两个饱和边界,这使得事情变得复杂。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接