简体   繁体   中英

How do I clamp __m128i signed integers into non-negative unsigned integers in SSE

I can't figure out how to convert 4 x 32 bit signed integers stored in a single __m128i into "unsigned" counterparts. The conversion should be done with value truncation, clamping negative numbers to 0 but leaving non-negative numbers unchanged.

Eg: -100 should turn into 0, while 100 should remain 100

#include <stdio.h>
#include <cstdint>
#include <emmintrin.h>

int main()
{    
    alignas(16) uint32_t out32u[4];
    __m128i my = _mm_setr_epi32 (100, -200, 0, -500);
    <....missing code....>
    _mm_store_si128(reinterpret_cast<__m128i *>(out32u), my);
    printf("%u %u %u %u\n", out32u[0], out32u[1], out32u[2], out32u[3]);
}

So given the <....missing code....> additions the result of the code above should become:

100 0 0 0

Use SSE4.1 _mm_max_epi32 as:

my = _mm_max_epi32(my, _mm_setzero_si128());

Or without that, @chtz's elegant a & ~(a >> 31) can be implemented using SSE2 as follows:

my = _mm_andnot_si128(_mm_srai_epi32(my, 31), my);

Replace <....missing code....> with the above line.

Generated assembly for both methods .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM