Como essa função calcula o valor absoluto de um float por meio de uma operação NOT e AND?
Estou tentando entender como o seguinte trecho de código funciona. Este programa usa instruções vetoriais SIMD (Intel SSE) para calcular o valor absoluto de 4 flutuadores (portanto, basicamente, uma função "fabs ()" vetorizada).
Aqui está o trecho:
#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;
}
Agora, eu sei que funciona, desde que eu mesmo executei o programa para testá-lo. Quando compilado com g ++ 4.8.2, o resultado é:
x[0]: 4
x[1]: 20
x[2]: 15
x[3]: 143
Três questões (relacionadas) me intrigam:
Primeiro, como é possível pegar uma função bit a bit e aplicá-la em um flutuador? Se eu tentar isso em baunilha C ++, ele me informa que isso funciona apenas para tipos integrais (o que faz sentido).
Mas, segundo, e mais importante: como isso funciona? Como tirar um NÃO e um AND até ajuda você aqui? Tentar isso no Python com um tipo integral apenas fornece o resultado esperado: qualquer número integral AND -1 (que NÃO é 0), simplesmente devolve esse número, mas não altera o sinal. Então, como isso funciona aqui?
Terceiro, notei que se eu alterar o valor do float usado para a operação NAND (marcado com três ???), de -0,0 a 0,0, o programa não me fornecerá mais o valor absoluto. Mas como pode existir um -0.0 e como isso ajuda?
Referências úteis: