我有一些代码,最初是由MSVC工作人员给我的,而我正试图让它在Clang上工作。这是我遇到问题的功能:
float vectorGetByIndex( __m128 V, unsigned int i )
{
assert( i <= 3 );
return V.m128_f32[i];
}
我得到的错误如下:
Member reference has base type '__m128' is not a structure or union.
我环顾四周,发现Clang(也许是GCC)在将__m128视为结构或联合时遇到了问题。但是我还没有找到一个直接的答案,我怎么能得到这些价值。我已经尝试使用下标运算符而无法做到这一点,我已经浏览了大量的SSE内在函数列表并且尚未找到合适的函数。
答案 0 :(得分:18)
联盟可能是最便携的方式:
union {
__m128 v; // SSE 4 x float vector
float a[4]; // scalar array of 4 floats
} U;
float vectorGetByIndex(__m128 V, unsigned int i)
{
U u;
assert(i <= 3);
u.v = V;
return u.a[i];
}
答案 1 :(得分:17)
即使SSE4.1可用且i
是编译时常量,也不能以这种方式使用pextract
等:
// broken code starts here
template<unsigned i>
float vectorGetByIndex( __m128 V) {
return _mm_extract_epi32(V, i);
}
// broken code ends here
我不删除它,因为它是一个有用的提示,如何不做事情,让它成为公众羞辱。
更好地使用
template<unsigned i>
float vectorGetByIndex( __m128 V) {
union {
__m128 v;
float a[4];
} converter;
converter.v = V;
return converter.a[i];
}
无论可用的指令集如何都可以使用。
答案 2 :(得分:15)
作为对hirschhornsalz解决方案的修改,如果i
是编译时常量,则可以通过使用shuffle / store完全避免联合路径:
template<unsigned i>
float vectorGetByIndex( __m128 V)
{
#ifdef __SSE4_1__
return _mm_extract_epi32(V, i);
#else
float ret;
// shuffle V so that the element that you want is moved to the least-
// significant element of the vector (V[0])
V = _mm_shuffle_ps(V, V, _MM_SHUFFLE(i, i, i, i));
// return the value in V[0]
return _mm_cvtss_f32(V);
#endif
}
答案 3 :(得分:4)
我使用的方式是
union vec { __m128 sse, float f[4] };
float accessmember(__m128 v, int index)
{
vec v.sse = v;
return v.f[index];
}
似乎很适合我。
答案 4 :(得分:0)
参加晚会但发现这在 MSVC 中对我有用,其中 z 是 __m128 类型的变量。
#define _mm_extract_f32(v, i) _mm_cvtss_f32(_mm_shuffle_ps(v, v, i))
__m128 z = _mm_setr_ps(1.0, 2.0, 3.0, 4.0);
float f = _mm_extract_f32(z, 2);
或者更简单
__m128 z;
float f = z.m128_f32[2]; // to get the 3rd float value in the vector