SSE指令集_mm_and_ps的奇怪行为

3
以下代码段:

__m128 a   = _mm_setr_ps( 1, 2, 3, 4 );
__m128 b   = _mm_set1_ps( 2 );
__m128 res = _mm_and_ps( a, b );
cout << a[0] << " " << a[1] << " " << a[2] << " " << a[3] << endl;
cout << b[0] << " " << b[1] << " " << b[2] << " " << b[3] << endl;
cout << res[0] << " " << res[1] << " " << res[2] << " " << res[3] << endl;
cout<<endl;
cout << ( 1 & 2 ) << " " << ( 2 & 2 ) << " " << ( 3 & 2 ) << " " << ( 4 & 2 ) << endl;

结果为:

1 2 3 4
2 2 2 2
0 2 2 2

0 2 2 0

SSE操作的结果难道不应该是0 2 2 0吗?因为2 = 010, 4 = 100 => 2&4 = 0。根据文档:

__m128 _mm_and_ps(__m128 a, __m128 b)

计算a和b的四个SP FP值的按位与。

R0 R1 R2 R3

a0 & b0 a1 & b1 a2 & b2 a3 & b3


为什么不显示ab的中间值? - Jonathon Reinhart
请检查编辑..... - Blue
1个回答

5
我找到的文档说:

计算 a 和 b 的四个单精度浮点数值的按位 AND。

(我强调)

2 和 4 将具有相同的尾数 (0,加上一个隐含的前导 1 位),以及分别为 128 和 129 的指数。这些的按位与是零尾数和指数为 128(== 2.0)。


编辑

如果您想对非负整数进行按位 AND 运算,则可以添加偏移量。如果您使用 8388608(== 1<<23)的偏移量,则可以像预期的那样对 0..8388607 进行位运算。

const float offset=8388608;
__m128 mm_offset = _mm_set1_ps();
__m128 a   = _mm_setr_ps( 1, 2, 3, 4 );
a =_mm_add_ps(mm_offset,a);
__m128 b   = _mm_set1_ps( 2+offset );
__m128 res = _mm_and_ps( a, b );
res = _mm_sub_ps(res,mm_offset);

如果需要的话,您也可以在整数数据上使用SSE1 andps。 (这会有轻微的性能影响)。它仍然是一个AND操作,直到您使用实际的FP指令之前,它不关心位的含义。 如果您从未这样做,并且只存储结果,则一切都没问题。 - Peter Cordes

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