我有一个例程,应该测试浮点数是否小于零。如果是,我应该存储标志,我得到它是绝对值。
int sign = 1;
if (x < 0)
{
sign = -1;
}
x = fabs(x);
我查看了英特尔SIMD内在函数,我发现这条指令dst = _mm_cmplt_ps(a,b)
生成一个包含(0xffffffff表示true)或(0表示false)的向量但是我被卡在那里;如何知道dst
向量的哪个元素是否为负数来构建sign_vector
。
答案 0 :(得分:3)
只有一个小异常(x == + 0.0f),您可以使用sign
指令生成整数掩码:
_mm_sign_epi32(_mm_set1_epi32(1), x)
如果x <0,这将取消1,但当x == 0时产生符号== 0。
如果不允许0,则可以通过0<mask<0x80000000
进行操作使x变为非零。
auto s=_mm_set1_epi32(1);
auto y=_mm_or_si128(x, s); // fix for x==0
s=_mm_sign_epi32(s, y);
答案 1 :(得分:2)
假设您的输入值位于向量__m128 v
:
__m128 vmask = _mm_set1_ps(-0.0f); // create sign bit mask
__m128 vsign = _mm_and_ps(v, vmask); // create vector of sign bits (MSB)
__m128i vsigni = _mm_add_epi32(_mm_srai_epi32((__m128i)vsign, 30), _mm_set1_epi32(1));
// convert sign bits to integer +1/-1 (if needed (*))
v = _mm_andnot_ps(vmask, v); // clear sign bits in v (i.e. v = fabsf(v))
(*)而不是浪费为符号生成+ 1 / -1的循环,考虑是否可以直接使用符号位,并省略此步骤。