How to compare __m128 types?

__m128 a; __m128 b; 

How to encode a != b ?

what to use: _mm_cmpneq_ps or _mm_cmpneq_ss ?

How to process the result?

Cannot find matching documents.

+7
source share
3 answers

You should _mm_cmpneq_ps use _mm_cmpneq_ps . However, interpretation of comparisons is slightly different from SIMD code than with scalar code. Do you want to check if any matching item matches? Or are all the relevant elements not equal?

To check the results of 4 comparisons with _mm_cmpneq_ps , you can use _mm_movemask_epi8 .

Note that comparing floating point values ​​for equality or inequality is usually a bad idea, except in special cases.

 __m128i vcmp = (__m128i)_mm_cmpneq_ps(a, b); // compare a, b for inequality uint16_t test = _mm_movemask_epi8(vcmp); // extract results of comparison if (test == 0xffff) // *all* elements not equal else if (test != 0) // *some* elements not equal else // no elements not equal, ie all elements equal 

For documentation, you need these two volumes from Intel:

Intel® 64 and IA-32 Software Developer Guide Volume 2A: Instruction Manual Reference, AM

Intel® 64 and IA-32 Software Developer's Guide Volume 2B: Instruction Set Reference, NZ

+14
source

Consider using the SSE4.1 ptest instruction

 if(_mm_testc_si128(_mm_castps_si128(a), _mm_castps_si128(b))) { /* equal */ } else { /* not equal */ } 

This is one instruction.

+1
source

The answer to this question also depends on whether you want the actual inequality, where you will use something according to what @PaulR shows:

 bool fneq128_a (__m128 const& a, __m128 const& b) { // returns true if at least one element in a is not equal to // the corresponding element in b return _mm_movemask_ps(_mm_cmpeq_ps(a, b)) != 0xF; } 

or do you want to use some epsilon to indicate that the elements are still considered "equal" if they do not differ from each other beyond the threshold:

 bool fneq128_b (__m128 const& a, __m128 const& b, float epsilon = 1.e-8f) { // epsilon vector auto eps = _mm_set1_ps(epsilon); // absolute of difference of a and b auto abd = _mm_andnot_ps(_mm_set1_ps(-0.0f), _mm_sub_ps(a, b)); // compare abd to eps // returns true if one of the elements in abd is not less than // epsilon return _mm_movemask_ps(_mm_cmplt_ps(abd, eps)) != 0xF; } 

Example:

 auto a = _mm_set_ps(0.0, 0.0, 0.0, 0.0); auto b = _mm_set_ps(0.0, 0.0, 0.0, 1.e-15); std::cout << fneq128_a(a, b) << ' ' << fneq128_b(a, b) << "\n"; 

Print

  1 0 
0
source

All Articles