- _mm_cvtps_epi32 :Converts the four single-precision, floating-point values of a to signed 32-bit integer values. 意思是: 把四个float变量强转为四个int变量。其中需要注意的是他的截断规则:四舍五入,在进位后末位是偶数的进,否则不进位。
- _mm_cvttps_epi32: Converts the four single-precision, floating-point values of a to signed 32-bit integer values using truncate. 这里就多了using truncate,意思是直接截断。与C/C++中的 r = (int)a 一样。
使用案例:
__m128 test1 = _mm_set_ps(3.4f, 3.5f, 3.6f, 4.5f);
__m128i test2 = _mm_cvtps_epi32(test1);
__m128i test3 = _mm_cvttps_epi32(test1);
输出结果分别: 3(高位),4,4,4(低位) 和 3(高位),3,3,4(低位)
但是需要注意的是一个浮点数和int32数的表示范围的问题:因为浮点数的表示范围大于int32, float型数据的绝对值在2^128(近似10^38)级,而int32在 -2147483648~2147483647,所以,若:
__m128 test1 = _mm_set_ps(3.4f, 3.5f, 3.6f, 2147483647.5f);
__m128i test2 = _mm_cvtps_epi32(test1);
__m128i test3 = _mm_cvttps_epi32(test1);
则,输出结果分别为:3(高位),3,3, -2147483648(低位) 和 3(高位),4,4, -2147483648(低位)
若set 2147483646.5f, 对应的仍为-2147483648(低位),甚至2147483640.5f也是-2147483648(低位)
但是,若set 1999999999.3f
__m128 test1 = _mm_set_ps(3.4f, 3.5f, 3.6f, 1999999999.3f);
输出结果:3(高位),3,3, 2000000000(低位)和3(高位),4,4, 2000000000(低位); 小数点后为3,不管是_mm_cvtps_epi32还是截断版_mm_cvttps_epi32都进了以为得到2000000000.
有点诡异,这或许与浮点数本身的精度有关吧
所以综上测试,个人认为_mm_cvtps_epi32 以及_mm_cvttps_epi32的结果与浮点数的表示范围以及精度都有关系,但一般情况下,不set这么大的数,使用起来应该没有问题
- _mm_cvtepi32_ps
//_mm_cvtepi32_ps
__m128i test1 = _mm_set_epi32(223, 2147483647, 2147483646, -2147483647);
__m128 test2 = _mm_cvtepi32_ps(test1);
输出:223.000000(高位), 2.14748365e+009, 2.14748365e+009, -2.14748365e+009(低位)
由于浮点数的表示范围大于int32,所以,_mm_cvtepi32_ps可以正常转换.(-2147483648编译不过去)
**以上实验只是为了研究下边界条件,但是一般情况下,正确的做法是考虑所处理问题的数据范围,再来决定使用什么类型的数据以及数据类型的转换**
- _mm_cvtepu32_epi64: Zero extend packed unsigned 32-bit integers in a to packed 64-bit integers, and store the results in dst.
__m128i test1 = _mm_set_epi32(223, 8088, 2147483646, 2147483647);
__m128i test2 = _mm_cvtepu32_epi64(test1);
输出:2147483646(高位), 2147483647(低位)
---------------------------------------------------------------------
//intValues:A 128-bit parameter that contains two unsigned 32-bit integers
//in the lower 64 bits, intValues=(a0, a1, a2, a3)
/*则r0 = a0
r1 = 0
r2 = a1
r3 = 0*/
extern __m128i _mm_cvtepu32_epi64(__m128i intValues);
- _mm_cvtepi32_epi64: Sign extend packed 32-bit integers in a to packed 64-bit integers, and store the results in dst.
extern __m128i _mm_cvtepi8_epi64 (__m128i byteValues);
//intValues: A 128-bit parameter that contains two signed 32-bit
//integers in the lower 64 bits, intValues=(a0, a1, a2, a3)
/*则r0 := a0
r1 := (a0 < 0) ? 0xffffffff : 0
r2 := a1
r3 := (a1 < 0) ? 0xffffffff : 0*/
extern __m128i _mm_cvtepi32_epi64(__m128i intValues);
貌似没有 epixx To epuxx 的 inrinsic 函数
- int _mm_cvtsi128_si32 (__m128i a) : Copy the lower 32-bit integer in a to dst. 只取低位32-bits进行转换,也只返回低位32-bits.