我想将浮点值转换为 16 位无符号整数而不饱和(改为环绕/溢出)。
#include <iostream>
#include <xmmintrin.h>
void satur_wrap()
{
const float bigVal = 99000.f;
const __m128 bigValVec = _mm_set1_ps(bigVal);
const __m64 outVec64 =_mm_cvtps_pi16(bigValVec);
#if 0
const __m128i outVec = _mm_movpi64_epi64(outVec64);
#else
#if 1
const __m128i outVec = _mm_packs_epi32(_mm_cvttps_epi32(bigValVec), _mm_cvttps_epi32(bigValVec));
#else
const __m128i outVec = _mm_cvttps_epi32(bigValVec);
#endif
#endif
uint16_t *outVals = NULL;
posix_memalign((void **) &outVals, sizeof(__m128i), sizeof(__m128i));
_mm_store_si128(reinterpret_cast<__m128i *>(outVals), outVec);
for (int i = 0; i < sizeof(outVec) / sizeof(*outVals); i++)
{
std::cout << "outVals[" << i << "]: " << outVals[i] << std::endl;
}
std::cout << std::endl
<< "\tbigVal: " << bigVal << std::endl
<< "\t(unsigned short) bigVal: " << ((unsigned short) bigVal) << std::endl
<< "\t((unsigned short)((int) bigVal)): " << ((unsigned short)((int) bigVal)) << std::endl
<< std::endl;
}
示例执行:
$ ./row
outVals[0]: 32767
outVals[1]: 32767
outVals[2]: 32767
outVals[3]: 32767
outVals[4]: 32767
outVals[5]: 32767
outVals[6]: 32767
outVals[7]: 32767
bigVal: 99000
(unsigned short) bigVal: 65535
((unsigned short)((int) bigVal)): 33464
该((unsigned short)((int) bigVal))
表达式按需要工作(但它可能是 UB,对吗?)。但我找不到与 SSE 非常相似的东西。我一定遗漏了一些东西,但我找不到将四个 32-bit 转换为四个 32-bitfloat
的原语int
。
编辑:糟糕,我认为 32 位整数 -> 16 位无符号整数转换使用环绕是“正常的”。但我从那以后了解到_mm_packs_epi32
使用有符号饱和(并且似乎没有 a _mm_packus_epi32
)。有没有办法设置模式,或者除此之外的其他原语_mm_packus_epi32
?