You could use _mm_blendv_ps(a, v_add_neg, a)
. blendvps
takes a vector input, and uses the sign bit of each element as the blend condition for that element.
You only need movemask if you need it as an integer, not a vector, e.g. to use it as an index for a lookup table, or to branch on all vector elements having some property for example.
The code's purpose is to change the signs of a vector's elements based on the signs in another vector's corresponding elements.
Use booleans to manipulate sign bits:
// pick your favourite way to express a 0x80000000 FP constant: just the sign bit set.
__m128 sign_v = _mm_and_ps(v, _mm_set1_ps(-0.0));
__m128 a_times_sign_v = _mm_xor_ps(a, sign_v);
The flips the sign of elements in a
where v
had its sign bit set.
Note that it treats -0.0
as negative, not zero, and -NaN
is also treated as a normal negative. If you don't want that, use _mm_cmplt_ps
and left-shift or AND that compare-mask to get a sign-bit mask for xorps
.