Search code examples
c++csseintrinsicsavx

How to check inf for AVX intrinsic __m256


What is the best way to check whether a AVX intrinsic __m256 (vector of 8 float) contains any inf? I tried

__m256 X=_mm256_set1_ps(1.0f/0.0f);
_mm256_cmp_ps(X,X,_CMP_EQ_OQ);

but this compares to true. Note that this method will find nan (which compare to false). So one way is to check for X!=nan && 0*X==nan:

__m256 Y=_mm256_mul_ps(X,_mm256_setzero_ps());   // 0*X=nan if X=inf
_mm256_andnot_ps(_mm256_cmp_ps(Y,Y,_CMP_EQ_OQ),
                 _mm256_cmp_ps(X,X,_CMP_EQ_OQ));

However, this appears somewhat lengthy. Is there a faster way?


Solution

  • If you want to check if a vector has any infinities:

    #include <limits>
    
    bool has_infinity(__m256 x){
        const __m256 SIGN_MASK = _mm256_set1_ps(-0.0);
        const __m256 INF = _mm256_set1_ps(std::numeric_limits<float>::infinity());
    
        x = _mm256_andnot_ps(SIGN_MASK, x);
        x = _mm256_cmp_ps(x, INF, _CMP_EQ_OQ);
        return _mm256_movemask_ps(x) != 0;
    }
    

    If you want a vector mask of the values that are infinity:

    #include <limits>
    
    __m256 is_infinity(__m256 x){
        const __m256 SIGN_MASK = _mm256_set1_ps(-0.0);
        const __m256 INF = _mm256_set1_ps(std::numeric_limits<float>::infinity());
    
        x = _mm256_andnot_ps(SIGN_MASK, x);
        x = _mm256_cmp_ps(x, INF, _CMP_EQ_OQ);
        return x;
    }