我目前正在使用intel SIMD函数:_mm_cmplt_ps( V1, V2 )
。函数返回一个向量,其中包含每个组件测试的结果。基于V1分量是否小于V2分量,例如:
XMVECTOR Result;
Result.x = (V1.x < V2.x) ? 0xFFFFFFFF : 0;
Result.y = (V1.y < V2.y) ? 0xFFFFFFFF : 0;
Result.z = (V1.z < V2.z) ? 0xFFFFFFFF : 0;
Result.w = (V1.w < V2.w) ? 0xFFFFFFFF : 0;
return Result;
但是,有没有像这样的函数会返回1或0?一个使用SIMD并且没有变通方法的函数,因为它应该被优化+矢量化。
您可以自己编写该函数。只有两条指令:
// 1.0 for lanes where a < b, zero otherwise
inline __m128 compareLessThan_01( __m128 a, __m128 b )
{
const __m128 cmp = _mm_cmplt_ps( a, b );
return _mm_and_ps( cmp, _mm_set1_ps( 1.0f ) );
}
这里有一个更通用的版本,它返回两个值中的任何一个。它需要SSE 4.1,到目前为止,它几乎在97.94%的用户中普遍可用,如果您必须仅支持SSE2,请使用_mm_and_ps、_mm_andnot_ps和_mm_or_ps进行模拟。
// y for lanes where a < b, x otherwise
inline __m128 compareLessThan_xy( __m128 a, __m128 b, float x, float y )
{
const __m128 cmp = _mm_cmplt_ps( a, b );
return _mm_blendv_ps( _mm_set1_ps( x ), _mm_set1_ps( y ), cmp );
}
_mm_cmplt_ps
的DirectXMath非内部版本实际上是:
XMVECTORU32 Control = { { {
(V1.vector4_f32[0] < V2.vector4_f32[0]) ? 0xFFFFFFFF : 0,
(V1.vector4_f32[1] < V2.vector4_f32[1]) ? 0xFFFFFFFF : 0,
(V1.vector4_f32[2] < V2.vector4_f32[2]) ? 0xFFFFFFFF : 0,
(V1.vector4_f32[3] < V2.vector4_f32[3]) ? 0xFFFFFFFF : 0
} } };
return Control.v;
XMVECTOR
与__m128
相同,后者是4个浮点值,因此它需要别名来确保它正在写入整数。
我使用CCD_ 5作为";控制寄存器";DirectXMath函数的版本。它只是收集每个SIMD值的最高位。
int result = _mm_movemask_ps(_mm_cmplt_ps( V1, V2 ));
result
的下半字节将包含比特模式。每一个通过测试的值都有一个1位,每一个失败的值都是0位。这可用于重建1与0之间的关系。