SSE 組み込み関数を使用して、0 から 255 の範囲にクランプされ、最も近い整数に丸められた 4 つの 32 ビット浮動小数点数のベクトルを取得しました。これらの 4 つをバイトとして書き出したいと思います。
_mm_cvtps_pi8
32 ビットを 8 ビットのsigned int に変換する組み込み関数がありますが、127 を超える値はすべて 127 にクランプされるという問題があります。符号なし 8 ビット値にクランプする命令が見つかりません。
私がやりたいことは、_mm_cvtps_pi16
とそれに_mm_shuffle_pi8
続く move 命令を組み合わせて、気になる 4 バイトをメモリに入れることだという直感があります。それが最善の方法ですか?シャッフル コントロール マスクをエンコードする方法を見つけられるかどうかを確認します。
更新: 以下は、私が望むことを正確に行うようです。より良い方法はありますか?
#include <tmmintrin.h>
#include <stdio.h>
unsigned char out[8];
unsigned char shuf[8] = { 0, 2, 4, 6, 128, 128, 128, 128 };
float ins[4] = {500, 0, 120, 240};
int main()
{
__m128 x = _mm_load_ps(ins); // Load the floats
__m64 y = _mm_cvtps_pi16(x); // Convert them to 16-bit ints
__m64 sh = *(__m64*)shuf; // Get the shuffle mask into a register
y = _mm_shuffle_pi8(y, sh); // Shuffle the lower byte of each into the first four bytes
*(int*)out = _mm_cvtsi64_si32(y); // Store the lower 32 bits
printf("%d\n", out[0]);
printf("%d\n", out[1]);
printf("%d\n", out[2]);
printf("%d\n", out[3]);
return 0;
}
UPDATE2: ハロルドの回答に基づいたさらに優れたソリューションを次に示します。
#include <smmintrin.h>
#include <stdio.h>
unsigned char out[8];
float ins[4] = {10.4, 10.6, 120, 100000};
int main()
{
__m128 x = _mm_load_ps(ins); // Load the floats
__m128i y = _mm_cvtps_epi32(x); // Convert them to 32-bit ints
y = _mm_packus_epi32(y, y); // Pack down to 16 bits
y = _mm_packus_epi16(y, y); // Pack down to 8 bits
*(int*)out = _mm_cvtsi128_si32(y); // Store the lower 32 bits
printf("%d\n", out[0]);
printf("%d\n", out[1]);
printf("%d\n", out[2]);
printf("%d\n", out[3]);
return 0;
}