这个函数如何通过NOT和and操作来计算浮点数的绝对值

How does this function compute the absolute value of a float through a NOT and AND operation?

本文关键字:操作 计算 浮点数 绝对值 and 函数 何通过 NOT      更新时间:2023-10-16

我试图理解下面的代码片段是如何工作的。该程序使用SIMD矢量指令(Intel SSE)来计算4个浮点数的绝对值(因此,基本上是一个矢量化的"fabs()"函数)。

下面是代码片段:
#include <iostream>
#include "xmmintrin.h"
template <typename T>
struct alignas(16) sse_t
{
    T data[16/sizeof(T)];
};
int main()
{
    sse_t<float> x;
    x.data[0] = -4.;
    x.data[1] = -20.;
    x.data[2] = 15.;
    x.data[3] = -143.;
    __m128 a = _mm_set_ps1(-0.0); // ???
    __m128 xv = _mm_load_ps(x.data);
    xv = _mm_andnot_ps(a,xv); // <-- Computes absolute value
    sse_t<float> result;
    _mm_store_ps(result.data, xv);
    std::cout << "x[0]: " << result.data[0] << std::endl;
    std::cout << "x[1]: " << result.data[1] << std::endl;
    std::cout << "x[2]: " << result.data[2] << std::endl;
    std::cout << "x[3]: " << result.data[3] << std::endl;
}

现在,我知道它是有效的,因为我自己运行了程序来测试它。当使用g++ 4.8.2编译时,结果是:

x[0]: 4
x[1]: 20
x[2]: 15
x[3]: 143

三个(相关的)问题困扰着我:

首先,怎么可能把一个按位函数应用到浮点数上?如果我在普通的c++中尝试这个,它告诉我这只适用于整型(这是有意义的)。

但是,第二,也是更重要的:它到底是怎么工作的?做NOT和and有什么用呢?在Python中尝试使用整数类型只会给你预期的结果:任何整数与-1(不是0),只是给你那个数字,但不改变符号。那么它是如何工作的呢?

第三,我注意到,如果我改变用于NAND操作的浮点数的值(用3标记),从-0.0到0.0,程序不再给我绝对值。但是-0.0怎么可能存在,它又有什么用呢?

有用的参考:

Intel intrinsic guide

-0.0表示为1000...000 1。因此,_mm_andnot_ps(-0.0, x) 2等价于0111...111 & x。这将强制MSB(即符号位)为0。


<子> 1。在IEEE-754中,

<子> 2。_mm_andnot_ps本征并不意味着"NAND";参见http://msdn.microsoft.com/en-us/library/68h7wd02(v=vs.90).aspx。