Kirill Lykov - 1 year ago 123
C Question

# Difference in converting unsigned/signed integer into float

In SSE there is a function

`_mm_cvtepi32_ps(__m128i input)`
which takes input vector of signed integers and converts them into float. Now, I want to interpret input integers as not signed. But there is no function
`_mm_cvtepu32_ps`
and I could not find an implementation of one. Do you know where I can find such a function or at least give a hint on the implementation?
To illustrate the the difference in results:

``````unsigned int a = 2480160505; // 10010011 11010100 00111110 11111001
float a1 = a; // 01001111 00010011 11010100 00111111;
float a2 = (signed int)a; // 11001110 11011000 01010111 10000010
``````

This functionality exists in AVX-512, but if you can't wait until then the only thing I can suggest is to convert the `unsigned int` input values into pairs of smaller values, convert these, and then add them together again, e.g.

``````inline __m128 _mm_cvtepu32_ps(const __m128i v)
{
__m128i v2 = _mm_srli_epi32(v, 1);     // v2 = v / 2
__m128i v1 = _mm_sub_epi32(v, v2);     // v1 = v - (v / 2)
__m128 v2f = _mm_cvtepi32_ps(v2);
__m128 v1f = _mm_cvtepi32_ps(v1);
}
``````

UPDATE

As noted by @wim in his answer, the above solution fails for an input value of `UINT_MAX`. Here is a more robust, but slightly less efficient solution, which should work for the full `uint32_t` input range:

``````inline __m128 _mm_cvtepu32_ps(const __m128i v)
{
__m128i v2 = _mm_srli_epi32(v, 1);                 // v2 = v / 2
__m128i v1 = _mm_and_si128(v, _mm_set1_epi32(1));  // v1 = v & 1
__m128 v2f = _mm_cvtepi32_ps(v2);
__m128 v1f = _mm_cvtepi32_ps(v1);