0
votes

I'm using the following to extract the sign bit of an __mm128:

const int sign_mask = _mm_movemask_ps(a);

I now want to use the following to blend two vectors:

v_add = _mm_blendv_ps(a, v_add_neg, _mm_castsi128_ps(v_mask));

v_mask needs to come from sign_mask but I cannot find an intrinsic that does this.

The code's purpose is to change the signs of a vector's elements based on the signs in another vector's corresponding elements.

1
You could store all the possible v_masks in an array, indexed by the sign_mask. But I don't see why you want to go through sign_mask, you should stick to vectors. - Marc Glisse
I subsequently figured it's easier to use vector AND and OR to do this. There isn't an intrinsic (that I know of) that extracts the sign into a vector. - IamIC
I'm not sure if you need such an intrinsic, because _mm_blendv_ps (a, b,c) uses the sign bits of c to choose between the elements of a and b. Probably that is just want you want? - wim

1 Answers

4
votes

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.